diff --git a/internal/module/m9zTtyApi/read.go b/internal/module/m9zTtyApi/read.go index 8777029..d8d62ad 100644 --- a/internal/module/m9zTtyApi/read.go +++ b/internal/module/m9zTtyApi/read.go @@ -135,8 +135,9 @@ type DeviceStatusLoop struct { } type DeviceStatus struct { m9z.DeviceStatus - ScanDeviceCount int `json:"scan_device_count"` - Loops []DeviceStatusLoop `json:"Loops"` + ScanDeviceCount int `json:"scan_device_count"` + AlarmDisplayEnabled bool `json:"alarm_display_enabled"` + Loops []DeviceStatusLoop `json:"Loops"` } // 实时监控数据 @@ -158,6 +159,7 @@ func getDeviceStatus2Real(rpc towgo.JsonRpcConnection) { scanLoopCount := configuredLoopCount() displayLoopCount := monitorDisplayLoopCount() d.ScanDeviceCount = scanLoopCount + d.AlarmDisplayEnabled = scanConfigManager.GetAlarmDisplayEnabled() loops := make([]DeviceStatusLoop, displayLoopCount) var wg sync.WaitGroup for i := 0; i < displayLoopCount; i++ { @@ -206,8 +208,9 @@ func buildDemoDeviceStatus2() *DeviceStatus { displayLoopCount := monitorDisplayLoopCount() scanLoopCount := configuredLoopCount() d := &DeviceStatus{ - ScanDeviceCount: scanLoopCount, - Loops: make([]DeviceStatusLoop, displayLoopCount), + ScanDeviceCount: scanLoopCount, + AlarmDisplayEnabled: scanConfigManager.GetAlarmDisplayEnabled(), + Loops: make([]DeviceStatusLoop, displayLoopCount), } d.Mode = 0 d.DeviceTime = time.Now().UTC() diff --git a/internal/module/m9zTtyApi/scan_config.go b/internal/module/m9zTtyApi/scan_config.go index 60961ff..439cbc0 100644 --- a/internal/module/m9zTtyApi/scan_config.go +++ b/internal/module/m9zTtyApi/scan_config.go @@ -12,16 +12,20 @@ import ( "github.com/towgo/towgo/towgo" ) +const defaultAlarmDisplayEnabled = true + type ScanConfigManager struct { - mu sync.RWMutex - loopCount int + mu sync.RWMutex + loopCount int + alarmDisplayEnabled bool } type ScanConfigData struct { - LoopCount int `json:"loop_count"` + LoopCount int `json:"loop_count"` + AlarmDisplayEnabled *bool `json:"alarm_display_enabled,omitempty"` } -var scanConfigManager = &ScanConfigManager{} +var scanConfigManager = &ScanConfigManager{alarmDisplayEnabled: defaultAlarmDisplayEnabled} func getScanConfigFilePath() string { return filepath.Join(system.GetPathOfProgram(), "data", "scanConfig.json") @@ -33,15 +37,38 @@ func (m *ScanConfigManager) GetLoopCount() int { 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 = loopCount + 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 } - g.GVA_Config.DeviceInfo.LoopCount = loopCount return nil } @@ -54,6 +81,7 @@ func (m *ScanConfigManager) loadFromFile() error { if err != nil { if os.IsNotExist(err) { m.loopCount = normalizeLoopCount(g.Config().DeviceInfo.LoopCount) + m.alarmDisplayEnabled = defaultAlarmDisplayEnabled return m.saveToFile() } return err @@ -64,6 +92,11 @@ func (m *ScanConfigManager) loadFromFile() error { 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 } @@ -76,7 +109,8 @@ func (m *ScanConfigManager) saveToFile() error { } jsonData, err := json.Marshal(ScanConfigData{ - LoopCount: normalizeLoopCount(m.loopCount), + LoopCount: normalizeLoopCount(m.loopCount), + AlarmDisplayEnabled: boolPtr(m.alarmDisplayEnabled), }) if err != nil { return err @@ -86,32 +120,43 @@ func (m *ScanConfigManager) saveToFile() error { func getScanConfig(rpcConn towgo.JsonRpcConnection) { rpcConn.WriteResult(map[string]interface{}{ - "loop_count": scanConfigManager.GetLoopCount(), - "max_loop_count": maxLoopCount, - "min_loop_count": 1, + "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"` + 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 < 1 || req.LoopCount > maxLoopCount { + if req.LoopCount != 0 && (req.LoopCount < 1 || req.LoopCount > maxLoopCount) { rpcConn.WriteError(400, "loop_count must be between 1 and 10") return } - if err := scanConfigManager.SetLoopCount(req.LoopCount); err != nil { + 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(), - "max_loop_count": maxLoopCount, - "min_loop_count": 1, + "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 +} diff --git a/internal/module/m9zTtyApi/scan_test.go b/internal/module/m9zTtyApi/scan_test.go index c32c8ba..1ddef15 100644 --- a/internal/module/m9zTtyApi/scan_test.go +++ b/internal/module/m9zTtyApi/scan_test.go @@ -32,11 +32,14 @@ func TestMonitorDisplayLoopCountAlwaysUsesMaxLoopCount(t *testing.T) { func TestBuildDemoDeviceStatus2KeepsDisplayLoopsIndependentFromScanCount(t *testing.T) { scanConfigManager.mu.Lock() oldLoopCount := scanConfigManager.loopCount + oldAlarmDisplayEnabled := scanConfigManager.alarmDisplayEnabled scanConfigManager.loopCount = 6 + scanConfigManager.alarmDisplayEnabled = true scanConfigManager.mu.Unlock() t.Cleanup(func() { scanConfigManager.mu.Lock() scanConfigManager.loopCount = oldLoopCount + scanConfigManager.alarmDisplayEnabled = oldAlarmDisplayEnabled scanConfigManager.mu.Unlock() }) @@ -53,4 +56,24 @@ func TestBuildDemoDeviceStatus2KeepsDisplayLoopsIndependentFromScanCount(t *test if status.Loops[6].HasFault { t.Fatal("status.Loops[6].HasFault = true, want false outside the scan loop count") } + if !status.AlarmDisplayEnabled { + t.Fatal("status.AlarmDisplayEnabled = false, want true") + } +} + +func TestBuildDemoDeviceStatus2IncludesAlarmDisplayConfig(t *testing.T) { + scanConfigManager.mu.Lock() + oldAlarmDisplayEnabled := scanConfigManager.alarmDisplayEnabled + scanConfigManager.alarmDisplayEnabled = false + scanConfigManager.mu.Unlock() + t.Cleanup(func() { + scanConfigManager.mu.Lock() + scanConfigManager.alarmDisplayEnabled = oldAlarmDisplayEnabled + scanConfigManager.mu.Unlock() + }) + + status := buildDemoDeviceStatus2() + if status.AlarmDisplayEnabled { + t.Fatal("status.AlarmDisplayEnabled = true, want false") + } }