package handlers import ( "net/http" "runtime" "time" "visiona-local/server/internal/deps" "github.com/gin-gonic/gin" ) type SystemHandler struct { startTime time.Time version string buildTime string pythonBin string // 由 main.go 傳入,InstallDriver 會用到 shutdownFn func() depsCache []deps.Dependency } func NewSystemHandler(version, buildTime, pythonBin string, shutdownFn func()) *SystemHandler { return &SystemHandler{ startTime: time.Now(), version: version, buildTime: buildTime, pythonBin: pythonBin, shutdownFn: shutdownFn, depsCache: deps.CheckAll(), } } func (h *SystemHandler) HealthCheck(c *gin.Context) { c.JSON(200, gin.H{"status": "ok"}) } func (h *SystemHandler) Info(c *gin.Context) { c.JSON(200, gin.H{ "success": true, "data": gin.H{ "version": h.version, "platform": runtime.GOOS + "/" + runtime.GOARCH, "uptime": time.Since(h.startTime).Seconds(), "goVersion": runtime.Version(), }, }) } func (h *SystemHandler) Metrics(c *gin.Context) { var ms runtime.MemStats runtime.ReadMemStats(&ms) c.JSON(200, gin.H{ "success": true, "data": gin.H{ "version": h.version, "buildTime": h.buildTime, "platform": runtime.GOOS + "/" + runtime.GOARCH, "goVersion": runtime.Version(), "uptimeSeconds": time.Since(h.startTime).Seconds(), "goroutines": runtime.NumGoroutine(), "memHeapAllocMB": float64(ms.HeapAlloc) / 1024 / 1024, "memSysMB": float64(ms.Sys) / 1024 / 1024, "memHeapObjects": ms.HeapObjects, "gcCycles": ms.NumGC, "nextGcMB": float64(ms.NextGC) / 1024 / 1024, }, }) } func (h *SystemHandler) Deps(c *gin.Context) { c.JSON(200, gin.H{ "success": true, "data": gin.H{"deps": h.depsCache}, }) } // InstallDriver 安裝 Kneron WinUSB driver(僅 Windows 有意義)。 // 呼叫 platform-specific 實作(見 system_driver_windows.go / system_driver_other.go)。 func (h *SystemHandler) InstallDriver(c *gin.Context) { if runtime.GOOS != "windows" { c.JSON(400, gin.H{ "success": false, "error": gin.H{ "code": "DRIVER_NOT_NEEDED", "message": runtime.GOOS + " 不需要安裝 WinUSB driver", }, }) return } pyBin := h.pythonBin if pyBin == "" { c.JSON(500, gin.H{ "success": false, "error": gin.H{ "code": "PYTHON_NOT_AVAILABLE", "message": "Python interpreter 未就緒,請確認 bundled Python runtime 初始化完成", }, }) return } if err := installKneronWinUSBDriverHandler(pyBin); err != nil { c.JSON(500, gin.H{ "success": false, "error": gin.H{ "code": "DRIVER_INSTALL_FAILED", "message": err.Error(), }, }) return } c.JSON(200, gin.H{ "success": true, "data": gin.H{"message": "WinUSB driver 安裝完成,請重新插拔裝置或直接點擊連線。"}, }) } func (h *SystemHandler) Restart(c *gin.Context) { c.JSON(200, gin.H{"success": true, "data": gin.H{"message": "restarting"}}) if f, ok := c.Writer.(http.Flusher); ok { f.Flush() } go func() { time.Sleep(200 * time.Millisecond) // shutdownFn signals the main goroutine to perform exec after server shutdown if h.shutdownFn != nil { h.shutdownFn() } }() }