This commit is contained in:
[Valentino Heman Budiarto] 2026-06-12 18:20:16 +07:00
parent ff02b00055
commit dad3d4f519

View File

@ -35,7 +35,7 @@ var DeviceStatusCache = map[string]string{
} }
// ========================================================================= // =========================================================================
// FUNGSI 1: VERIFIKASI TOKEN (Dan Buka Gembok Relay) // FUNGSI 1: VERIFIKASI TOKEN (Bisa Master & Mahasiswa)
// ========================================================================= // =========================================================================
func VerifyHardwareCode(c *gin.Context) { func VerifyHardwareCode(c *gin.Context) {
var req VerifyRequest var req VerifyRequest
@ -47,38 +47,33 @@ func VerifyHardwareCode(c *gin.Context) {
tokenInput := req.Token tokenInput := req.Token
sekarang := time.Now() sekarang := time.Now()
sisaMenit := 0
// 1. Token Master CS (Cleaning Service)
if tokenInput == "CS2026" {
fmt.Printf("[VERIFY] Master Token CS digunakan\n")
c.JSON(http.StatusOK, gin.H{
"status": "success", "message": "Token CS Valid", "duration_minutes": 60,
})
return
}
// 2. Token Master Admin
if tokenInput == "ADM999" {
fmt.Printf("[VERIFY] Master Token Admin digunakan\n")
c.JSON(http.StatusOK, gin.H{
"status": "success", "message": "Token Admin Valid", "duration_minutes": 999,
})
return
}
// -------------------------------------------------------------
// TARIK DATA START_TIME & END_TIME MENGGUNAKAN time.Time
// -------------------------------------------------------------
var jamMulai time.Time
var jamSelesai time.Time
isTokenValid := false isTokenValid := false
// =========================================================
// 1. PENGECEKAN KELOMPOK TOKEN MASTER (Tanpa Cek Waktu)
// =========================================================
if tokenInput == "CS2026" {
fmt.Printf("[VERIFY] Master Token CS digunakan\n")
sisaMenit = 60
isTokenValid = true
} else if tokenInput == "ADM999" {
fmt.Printf("[VERIFY] Master Token Admin digunakan\n")
sisaMenit = 999
isTokenValid = true
} else {
// =========================================================
// 2. PENGECEKAN KELOMPOK TOKEN MAHASISWA (Cek Database & Waktu)
// =========================================================
var jamMulai time.Time
var jamSelesai time.Time
type ResultTime struct { type ResultTime struct {
JamMulai time.Time `gorm:"column:start_time"` JamMulai time.Time `gorm:"column:start_time"`
JamSelesai time.Time `gorm:"column:end_time"` JamSelesai time.Time `gorm:"column:end_time"`
} }
var result ResultTime var result ResultTime
// Cek Bookings
errBooking := config.DB.Table("bookings"). errBooking := config.DB.Table("bookings").
Select("start_time, end_time"). Select("start_time, end_time").
Where("redeem_code = ?", tokenInput). Where("redeem_code = ?", tokenInput).
@ -89,6 +84,7 @@ func VerifyHardwareCode(c *gin.Context) {
jamSelesai = result.JamSelesai jamSelesai = result.JamSelesai
isTokenValid = true isTokenValid = true
} else { } else {
// Cek Jadwal Kelas Tetap
errSchedule := config.DB.Table("class_schedules"). errSchedule := config.DB.Table("class_schedules").
Select("start_time, end_time"). Select("start_time, end_time").
Where("kode_mk = ?", tokenInput). Where("kode_mk = ?", tokenInput).
@ -106,44 +102,32 @@ func VerifyHardwareCode(c *gin.Context) {
return return
} }
// Ekstrak Jam, Menit, Detik langsung dari objek Time (Sangat Aman & Akurat)
jamMulaiHariIni := time.Date(sekarang.Year(), sekarang.Month(), sekarang.Day(), jamMulaiHariIni := time.Date(sekarang.Year(), sekarang.Month(), sekarang.Day(),
jamMulai.Hour(), jamMulai.Minute(), jamMulai.Second(), 0, sekarang.Location()) jamMulai.Hour(), jamMulai.Minute(), jamMulai.Second(), 0, sekarang.Location())
jamSelesaiHariIni := time.Date(sekarang.Year(), sekarang.Month(), sekarang.Day(), jamSelesaiHariIni := time.Date(sekarang.Year(), sekarang.Month(), sekarang.Day(),
jamSelesai.Hour(), jamSelesai.Minute(), jamSelesai.Second(), 0, sekarang.Location()) jamSelesai.Hour(), jamSelesai.Minute(), jamSelesai.Second(), 0, sekarang.Location())
// -------------------------------------------------------------
// LOGIKA PENOLAKAN TOKEN MASA DEPAN
// -------------------------------------------------------------
// Toleransi masuk: Hanya bisa masuk 15 menit sebelum jadwal.
batasMasukAwal := jamMulaiHariIni.Add(-15 * time.Minute) batasMasukAwal := jamMulaiHariIni.Add(-15 * time.Minute)
if sekarang.Before(batasMasukAwal) { if sekarang.Before(batasMasukAwal) {
fmt.Printf("[VERIFY] Ditolak: Kelas %s belum mulai\n", tokenInput)
c.JSON(http.StatusForbidden, gin.H{"error": "Jadwal kelas belum dimulai"}) c.JSON(http.StatusForbidden, gin.H{"error": "Jadwal kelas belum dimulai"})
return return
} }
// -------------------------------------------------------------
// LOGIKA PENOLAKAN TOKEN KADALUARSA
// -------------------------------------------------------------
selisihWaktu := jamSelesaiHariIni.Sub(sekarang) selisihWaktu := jamSelesaiHariIni.Sub(sekarang)
sisaMenit := int(selisihWaktu.Minutes()) sisaMenit = int(selisihWaktu.Minutes())
if sisaMenit <= 0 { if sisaMenit <= 0 {
fmt.Printf("[VERIFY] Ditolak: Waktu kelas %s sudah habis\n", tokenInput)
c.JSON(http.StatusForbidden, gin.H{"error": "Waktu peminjaman sudah habis"}) c.JSON(http.StatusForbidden, gin.H{"error": "Waktu peminjaman sudah habis"})
return return
} }
}
// ------------------------------------------------------------- // =========================================================
// JIKA LOLOS SEMUA UJIAN: IZINKAN MASUK & BUKA GEMBOK // 3. JIKA VALID (Master / Mahasiswa), BUKA GEMBOK VIA MQTT
// ------------------------------------------------------------- // =========================================================
DeviceStatusCache["lampu1"] = "on" DeviceStatusCache["lampu1"] = "on"
DeviceStatusCache["lampu2"] = "on" DeviceStatusCache["lampu2"] = "on"
// --- START BLOK MQTT UNLOCK ---
broker := os.Getenv("MQTT_BROKER") broker := os.Getenv("MQTT_BROKER")
user := os.Getenv("MQTT_USER") user := os.Getenv("MQTT_USER")
pass := os.Getenv("MQTT_PASSWORD") pass := os.Getenv("MQTT_PASSWORD")
@ -156,19 +140,18 @@ func VerifyHardwareCode(c *gin.Context) {
client := mqtt.NewClient(opts) client := mqtt.NewClient(opts)
if tokenMQTT := client.Connect(); tokenMQTT.Wait() && tokenMQTT.Error() == nil { if tokenMQTT := client.Connect(); tokenMQTT.Wait() && tokenMQTT.Error() == nil {
// 1. Mengirim sinyal otorisasi "UNLOCK" ke Relay dengan retain=true // Buka Gembok Relay
client.Publish("sclass/d101/auth", 0, true, "UNLOCK").Wait() client.Publish("sclass/d101/auth", 0, true, "UNLOCK").Wait()
// 2. Opsional: otomatis nyalakan lampu saat token dimasukkan // Opsional: Nyalakan Lampu Otomatis saat login
client.Publish("sclass/d101/lampu1", 0, false, "on").Wait() client.Publish("sclass/d101/lampu1", 0, false, "on").Wait()
client.Publish("sclass/d101/lampu2", 0, false, "on").Wait() client.Publish("sclass/d101/lampu2", 0, false, "on").Wait()
client.Disconnect(250) client.Disconnect(250)
fmt.Printf("[MQTT] Perintah UNLOCK dan ON berhasil dikirim ke Relay D101\n") fmt.Printf("[MQTT] Perintah UNLOCK dan ON dikirim (Sisa Menit: %d)\n", sisaMenit)
} else { } else {
fmt.Printf("[MQTT ERROR] Gagal menghubungi broker: %v\n", tokenMQTT.Error()) fmt.Printf("[MQTT ERROR] Gagal menghubungi broker: %v\n", tokenMQTT.Error())
} }
// --- END BLOK MQTT UNLOCK ---
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"status": "success", "status": "success",
@ -177,9 +160,6 @@ func VerifyHardwareCode(c *gin.Context) {
}) })
} }
// =========================================================================
// FUNGSI 2: KONTROL DEVICE VIA HOME ASSISTANT & MQTT
// =========================================================================
// ========================================================================= // =========================================================================
// FUNGSI 2: KONTROL DEVICE VIA HOME ASSISTANT & MQTT // FUNGSI 2: KONTROL DEVICE VIA HOME ASSISTANT & MQTT
// ========================================================================= // =========================================================================
@ -246,9 +226,17 @@ func ControlHardware(c *gin.Context) {
switch req.Device { switch req.Device {
case "ac": case "ac":
if req.Action == "on" { entityID = "scene.ac_d101_on" } else { entityID = "scene.ac_d101_off" } if req.Action == "on" {
entityID = "scene.ac_d101_on"
} else {
entityID = "scene.ac_d101_off"
}
case "projector": case "projector":
if req.Action == "on" { entityID = "scene.projector_d101_on" } else { entityID = "scene.projector_d101_off" } if req.Action == "on" {
entityID = "scene.projector_d101_on"
} else {
entityID = "scene.projector_d101_off"
}
} }
apiURL := fmt.Sprintf("%s/api/services/scene/turn_on", haURL) apiURL := fmt.Sprintf("%s/api/services/scene/turn_on", haURL)
@ -261,7 +249,9 @@ func ControlHardware(c *gin.Context) {
reqHA.Header.Set("Content-Type", "application/json") reqHA.Header.Set("Content-Type", "application/json")
httpClient := &http.Client{Timeout: 5 * time.Second} httpClient := &http.Client{Timeout: 5 * time.Second}
resp, _ := httpClient.Do(reqHA) resp, _ := httpClient.Do(reqHA)
if resp != nil { resp.Body.Close() } if resp != nil {
resp.Body.Close()
}
} }
DeviceStatusCache[req.Device] = req.Action DeviceStatusCache[req.Device] = req.Action