package m9zApi import ( "encoding/json" "os" "path/filepath" "sync" g "tgk-touch/internal/global" "github.com/towgo/towgo/lib/system" "github.com/towgo/towgo/towgo" ) const defaultAlarmDisplayEnabled = true type ScanConfigManager struct { mu sync.RWMutex loopCount int alarmDisplayEnabled bool } type ScanConfigData struct { LoopCount int `json:"loop_count"` AlarmDisplayEnabled *bool `json:"alarm_display_enabled,omitempty"` } var scanConfigManager = &ScanConfigManager{alarmDisplayEnabled: defaultAlarmDisplayEnabled} func getScanConfigFilePath() string { return filepath.Join(system.GetPathOfProgram(), "data", "scanConfig.json") } func (m *ScanConfigManager) GetLoopCount() int { m.mu.RLock() defer m.mu.RUnlock() return normalizeLoopCount(m.loopCount) } func (m *ScanConfigManager) GetAlarmDisplayEnabled() bool { m.mu.RLock() defer m.mu.RUnlock() return m.alarmDisplayEnabled } func (m *ScanConfigManager) SetLoopCount(loopCount int) error { m.mu.Lock() defer m.mu.Unlock() m.loopCount = normalizeLoopCount(loopCount) if err := m.saveToFile(); err != nil { return err } g.GVA_Config.DeviceInfo.LoopCount = m.loopCount return nil } func (m *ScanConfigManager) SetConfig(loopCount int, alarmDisplayEnabled *bool) error { m.mu.Lock() defer m.mu.Unlock() if loopCount > 0 { m.loopCount = normalizeLoopCount(loopCount) g.GVA_Config.DeviceInfo.LoopCount = m.loopCount } if alarmDisplayEnabled != nil { m.alarmDisplayEnabled = *alarmDisplayEnabled } if err := m.saveToFile(); err != nil { return err } return nil } func (m *ScanConfigManager) loadFromFile() error { m.mu.Lock() defer m.mu.Unlock() filePath := getScanConfigFilePath() jsonData, err := os.ReadFile(filePath) if err != nil { if os.IsNotExist(err) { m.loopCount = normalizeLoopCount(g.Config().DeviceInfo.LoopCount) m.alarmDisplayEnabled = defaultAlarmDisplayEnabled return m.saveToFile() } return err } var data ScanConfigData if err := json.Unmarshal(jsonData, &data); err != nil { return err } m.loopCount = normalizeLoopCount(data.LoopCount) if data.AlarmDisplayEnabled == nil { m.alarmDisplayEnabled = defaultAlarmDisplayEnabled } else { m.alarmDisplayEnabled = *data.AlarmDisplayEnabled } g.GVA_Config.DeviceInfo.LoopCount = m.loopCount return nil } func (m *ScanConfigManager) saveToFile() error { filePath := getScanConfigFilePath() dir := filepath.Dir(filePath) if err := os.MkdirAll(dir, 0755); err != nil { return err } jsonData, err := json.Marshal(ScanConfigData{ LoopCount: normalizeLoopCount(m.loopCount), AlarmDisplayEnabled: boolPtr(m.alarmDisplayEnabled), }) if err != nil { return err } return os.WriteFile(filePath, jsonData, 0600) } func getScanConfig(rpcConn towgo.JsonRpcConnection) { rpcConn.WriteResult(map[string]interface{}{ "loop_count": scanConfigManager.GetLoopCount(), "alarm_display_enabled": scanConfigManager.GetAlarmDisplayEnabled(), "max_loop_count": maxLoopCount, "min_loop_count": 1, }) } type SetScanConfigReq struct { LoopCount int `json:"loop_count"` AlarmDisplayEnabled *bool `json:"alarm_display_enabled"` } func setScanConfig(rpcConn towgo.JsonRpcConnection) { var req SetScanConfigReq rpcConn.ReadParams(&req) if req.LoopCount != 0 && (req.LoopCount < 1 || req.LoopCount > maxLoopCount) { rpcConn.WriteError(400, "loop_count must be between 1 and 10") return } if req.LoopCount == 0 && req.AlarmDisplayEnabled == nil { rpcConn.WriteError(400, "loop_count or alarm_display_enabled is required") return } if err := scanConfigManager.SetConfig(req.LoopCount, req.AlarmDisplayEnabled); err != nil { rpcConn.WriteError(500, "save scan config failed: "+err.Error()) return } rpcConn.WriteResult(map[string]interface{}{ "success": true, "loop_count": scanConfigManager.GetLoopCount(), "alarm_display_enabled": scanConfigManager.GetAlarmDisplayEnabled(), "max_loop_count": maxLoopCount, "min_loop_count": 1, }) } func boolPtr(value bool) *bool { return &value }