.
This commit is contained in:
parent
0a8ced6490
commit
16075c670a
@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings" // TAMBAHAN: Untuk membersihkan spasi/enter gaib
|
|
||||||
"s-class-backend/models"
|
"s-class-backend/models"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"s-class-backend/config" // IMPORT WAJIB UNTUK KONEKSI DATABASE
|
||||||
|
|
||||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@ -18,7 +20,6 @@ type DeviceControlRequest struct {
|
|||||||
Action string `json:"action"`
|
Action string `json:"action"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Struct baru untuk menangkap input Token dari layar ESP32
|
|
||||||
type VerifyRequest struct {
|
type VerifyRequest struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
@ -29,7 +30,6 @@ type VerifyRequest struct {
|
|||||||
func VerifyHardwareCode(c *gin.Context) {
|
func VerifyHardwareCode(c *gin.Context) {
|
||||||
var req VerifyRequest
|
var req VerifyRequest
|
||||||
|
|
||||||
// 1. Tangkap JSON { "token": "..." } dari ESP32
|
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Format token tidak valid"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Format token tidak valid"})
|
||||||
return
|
return
|
||||||
@ -37,41 +37,64 @@ func VerifyHardwareCode(c *gin.Context) {
|
|||||||
|
|
||||||
tokenInput := req.Token
|
tokenInput := req.Token
|
||||||
sekarang := time.Now()
|
sekarang := time.Now()
|
||||||
|
var jamSelesai time.Time
|
||||||
|
isTokenValid := false
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// Struktur penampung jam selesai dari database
|
||||||
// 2. LOGIKA DATABASE PENGGANTI (Silakan sesuaikan dengan model GORM-mu)
|
type ResultTime struct {
|
||||||
// ---------------------------------------------------------------------
|
JamSelesai time.Time `gorm:"column:end_time"` // PASTIKAN NAMA KOLOM 'end_time' SESUAI DENGAN YANG ADA DI DATABASE
|
||||||
/* // CONTOH ASLI JIKA SUDAH MENGHUBUNGKAN KE DATABASE:
|
}
|
||||||
var jadwal models.Booking
|
var result ResultTime
|
||||||
if err := db.Where("token = ?", tokenInput).First(&jadwal).Error; err != nil {
|
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token salah atau tidak ditemukan"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
jamSelesai := jadwal.JamSelesai
|
|
||||||
*/
|
|
||||||
|
|
||||||
// SIMULASI SEMENTARA (Hapus bagian ini jika query DB di atas sudah aktif):
|
// 1. Cek di tabel bookings (Redeem Code)
|
||||||
// Mengatur jam selesai kelas pada jam 19:00:00 di hari ini sebagai sampel waktu
|
errBooking := config.DB.Table("bookings").
|
||||||
jamSelesai := time.Date(sekarang.Year(), sekarang.Month(), sekarang.Day(), 19, 0, 0, 0, sekarang.Location())
|
Select("end_time").
|
||||||
|
Where("redeem_code = ?", tokenInput).
|
||||||
|
Scan(&result).Error
|
||||||
|
|
||||||
// Tampilkan log di terminal backend
|
if errBooking == nil && !result.JamSelesai.IsZero() {
|
||||||
fmt.Printf("[VERIFY] Token masuk: %s | Jam Selesai: %v\n", tokenInput, jamSelesai)
|
jamSelesai = result.JamSelesai
|
||||||
// ---------------------------------------------------------------------
|
isTokenValid = true
|
||||||
|
fmt.Println("[VERIFY] Token ditemukan di tabel bookings!")
|
||||||
|
} else {
|
||||||
|
// 2. Cek di tabel class_schedules (Kode MK)
|
||||||
|
errSchedule := config.DB.Table("class_schedules").
|
||||||
|
Select("end_time").
|
||||||
|
Where("kode_mk = ?", tokenInput).
|
||||||
|
Scan(&result).Error
|
||||||
|
|
||||||
|
if errSchedule == nil && !result.JamSelesai.IsZero() {
|
||||||
|
jamSelesai = result.JamSelesai
|
||||||
|
isTokenValid = true
|
||||||
|
fmt.Println("[VERIFY] Token ditemukan di tabel class_schedules!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika token tidak ditemukan di kedua tabel (Token Acak/Salah)
|
||||||
|
if !isTokenValid {
|
||||||
|
fmt.Printf("[VERIFY] Token %s SALAH atau tidak ditemukan.\n", tokenInput)
|
||||||
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token salah atau tidak ditemukan"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Kalkulasi Selisih Waktu
|
// 3. Kalkulasi Selisih Waktu
|
||||||
selisihWaktu := jamSelesai.Sub(sekarang)
|
// Gabungkan tanggal hari ini dengan jam dari database
|
||||||
|
jamSelesaiHariIni := time.Date(sekarang.Year(), sekarang.Month(), sekarang.Day(),
|
||||||
|
jamSelesai.Hour(), jamSelesai.Minute(), jamSelesai.Second(), 0, sekarang.Location())
|
||||||
|
|
||||||
|
selisihWaktu := jamSelesaiHariIni.Sub(sekarang)
|
||||||
sisaMenit := int(selisihWaktu.Minutes())
|
sisaMenit := int(selisihWaktu.Minutes())
|
||||||
|
|
||||||
// 4. Proteksi Jika Waktu Sudah Habis / Kelas Selesai
|
// 4. Proteksi Jika Waktu Sudah Habis (Lebih dari jam selesai)
|
||||||
if sisaMenit <= 0 {
|
if sisaMenit <= 0 {
|
||||||
c.JSON(http.StatusForbidden, gin.H{"error": "Waktu peminjaman sudah habis"})
|
c.JSON(http.StatusForbidden, gin.H{"error": "Waktu peminjaman sudah habis"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Kirim balasan ke ESP32 beserta nilai duration_minutes
|
// 5. Kirim balasan sukses ke ESP32 beserta durasinya
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"message": "Token Valid, Akses Diberikan",
|
"message": "Token Valid",
|
||||||
"duration_minutes": sisaMenit,
|
"duration_minutes": sisaMenit,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -86,13 +109,11 @@ func ControlHardware(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- SKENARIO 1: KONTROL LAMPU (Via MQTT ke ESP32 Relay) ---
|
|
||||||
if req.Device == "lampu1" || req.Device == "lampu2" {
|
if req.Device == "lampu1" || req.Device == "lampu2" {
|
||||||
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")
|
||||||
|
|
||||||
// Setup Konfigurasi Klien MQTT Golang
|
|
||||||
opts := mqtt.NewClientOptions()
|
opts := mqtt.NewClientOptions()
|
||||||
opts.AddBroker(broker)
|
opts.AddBroker(broker)
|
||||||
opts.SetUsername(user)
|
opts.SetUsername(user)
|
||||||
@ -106,10 +127,7 @@ func ControlHardware(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
defer client.Disconnect(250)
|
defer client.Disconnect(250)
|
||||||
|
|
||||||
// Tentukan Topik
|
|
||||||
topic := fmt.Sprintf("sclass/d101/%s", req.Device)
|
topic := fmt.Sprintf("sclass/d101/%s", req.Device)
|
||||||
|
|
||||||
// Publish Pesan
|
|
||||||
token := client.Publish(topic, 0, false, req.Action)
|
token := client.Publish(topic, 0, false, req.Action)
|
||||||
token.Wait()
|
token.Wait()
|
||||||
|
|
||||||
@ -120,7 +138,6 @@ func ControlHardware(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- SKENARIO 2: KONTROL AC & PROYEKTOR (Via Home Assistant) ---
|
|
||||||
if req.Device == "ac" || req.Device == "projector" {
|
if req.Device == "ac" || req.Device == "projector" {
|
||||||
haURL := os.Getenv("HA_URL")
|
haURL := os.Getenv("HA_URL")
|
||||||
haToken := os.Getenv("HA_TOKEN")
|
haToken := os.Getenv("HA_TOKEN")
|
||||||
@ -169,7 +186,6 @@ func ControlHardware(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jika device tidak dikenali
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Device tidak dikenali sistem"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Device tidak dikenali sistem"})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +196,6 @@ func GetPowerStatus(c *gin.Context) {
|
|||||||
haURL := os.Getenv("HA_URL")
|
haURL := os.Getenv("HA_URL")
|
||||||
haToken := os.Getenv("HA_TOKEN")
|
haToken := os.Getenv("HA_TOKEN")
|
||||||
|
|
||||||
// Ganti dengan Entity ID sensor daya kamu di Home Assistant
|
|
||||||
entityID := "sensor.kwh_meter_power"
|
entityID := "sensor.kwh_meter_power"
|
||||||
apiURL := fmt.Sprintf("%s/api/states/%s", haURL, entityID)
|
apiURL := fmt.Sprintf("%s/api/states/%s", haURL, entityID)
|
||||||
|
|
||||||
@ -199,7 +214,6 @@ func GetPowerStatus(c *gin.Context) {
|
|||||||
var result map[string]interface{}
|
var result map[string]interface{}
|
||||||
json.NewDecoder(resp.Body).Decode(&result)
|
json.NewDecoder(resp.Body).Decode(&result)
|
||||||
|
|
||||||
// Ambil nilai state (angka watt)
|
|
||||||
powerStr, ok := result["state"].(string)
|
powerStr, ok := result["state"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
c.JSON(http.StatusOK, gin.H{"power": 0})
|
c.JSON(http.StatusOK, gin.H{"power": 0})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user