diff --git a/backend/controllers/hardwarecontroller.go b/backend/controllers/hardwarecontroller.go index 54d9d58..8d7b53d 100644 --- a/backend/controllers/hardwarecontroller.go +++ b/backend/controllers/hardwarecontroller.go @@ -177,6 +177,9 @@ func VerifyHardwareCode(c *gin.Context) { }) } +// ========================================================================= +// FUNGSI 2: KONTROL DEVICE VIA HOME ASSISTANT & MQTT +// ========================================================================= // ========================================================================= // FUNGSI 2: KONTROL DEVICE VIA HOME ASSISTANT & MQTT // ========================================================================= @@ -187,7 +190,27 @@ func ControlHardware(c *gin.Context) { return } - // --- BLOK KONTROL LAMPU --- + // 🌟 BLOK 1: KONTROL GEMBOK / OTORISASI RELAY (SANGAT PENTING) + if req.Device == "auth" { + broker := os.Getenv("MQTT_BROKER") + user := os.Getenv("MQTT_USER") + pass := os.Getenv("MQTT_PASSWORD") + + opts := mqtt.NewClientOptions().AddBroker(broker).SetUsername(user).SetPassword(pass).SetClientID(fmt.Sprintf("Golang-Lock-%d", time.Now().Unix())) + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() == nil { + // Retain = true untuk menimpa status UNLOCK lama di server MQTT + client.Publish("sclass/d101/auth", 0, true, req.Action).Wait() + client.Disconnect(250) + fmt.Println("[MQTT] Status Gembok Relay diubah menjadi:", req.Action) + } else { + fmt.Println("[MQTT ERROR] Gagal terhubung saat mencoba mengunci relay.") + } + c.JSON(http.StatusOK, gin.H{"status": "success", "message": "Gembok " + req.Action}) + return + } + + // --- BLOK 2: KONTROL LAMPU --- if req.Device == "lampu1" || req.Device == "lampu2" { broker := os.Getenv("MQTT_BROKER") user := os.Getenv("MQTT_USER") @@ -210,17 +233,12 @@ func ControlHardware(c *gin.Context) { token := client.Publish(topic, 0, false, req.Action) token.Wait() - // ⭐ SIMPAN STATUS TERBARU LAMPU KE MEMORI GOLANG DeviceStatusCache[req.Device] = req.Action - - c.JSON(http.StatusOK, gin.H{ - "status": "success", - "message": fmt.Sprintf("Berhasil mengirim perintah %s ke %s", req.Action, req.Device), - }) + c.JSON(http.StatusOK, gin.H{"status": "success", "message": fmt.Sprintf("Berhasil %s ke %s", req.Action, req.Device)}) return } - // --- BLOK KONTROL AC & PROYEKTOR --- + // --- BLOK 3: KONTROL AC & PROYEKTOR --- if req.Device == "ac" || req.Device == "projector" { haURL := os.Getenv("HA_URL") haToken := os.Getenv("HA_TOKEN") @@ -228,19 +246,9 @@ func ControlHardware(c *gin.Context) { switch req.Device { case "ac": - switch req.Action { - case "on": - entityID = "scene.ac_d101_on" - default: - entityID = "scene.ac_d101_off" - } + if req.Action == "on" { entityID = "scene.ac_d101_on" } else { entityID = "scene.ac_d101_off" } case "projector": - switch req.Action { - case "on": - entityID = "scene.projector_d101_on" - case "off": - 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) @@ -248,33 +256,20 @@ func ControlHardware(c *gin.Context) { jsonPayload, _ := json.Marshal(payload) reqHA, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonPayload)) - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Gagal membuat request ke HA"}) - return + if err == nil { + reqHA.Header.Set("Authorization", "Bearer "+haToken) + reqHA.Header.Set("Content-Type", "application/json") + httpClient := &http.Client{Timeout: 5 * time.Second} + resp, _ := httpClient.Do(reqHA) + if resp != nil { resp.Body.Close() } } - reqHA.Header.Set("Authorization", "Bearer "+haToken) - reqHA.Header.Set("Content-Type", "application/json") - - httpClient := &http.Client{Timeout: 5 * time.Second} - resp, err := httpClient.Do(reqHA) - if err != nil { - c.JSON(http.StatusGatewayTimeout, gin.H{"error": "Gagal menghubungi Home Assistant"}) - return - } - defer resp.Body.Close() - - // ⭐ SIMPAN STATUS TERBARU AC/PROYEKTOR KE MEMORI GOLANG DeviceStatusCache[req.Device] = req.Action - - c.JSON(http.StatusOK, gin.H{ - "status": "success", - "message": fmt.Sprintf("Berhasil memicu scene %s", entityID), - }) + c.JSON(http.StatusOK, gin.H{"status": "success", "message": "Scene dipicu: " + entityID}) return } - c.JSON(http.StatusBadRequest, gin.H{"error": "Device tidak dikenali sistem"}) + c.JSON(http.StatusBadRequest, gin.H{"error": "Device tidak dikenali"}) } // =========================================================================