package device import ( "maps" "sync" ) // DeviceState holds the simulated device state with thread-safe access type DeviceState struct { mu sync.RWMutex progMode bool caliMode bool alarmActive bool alarmType string // "TRIGGERED" or "TAMPER" // Parameters from docs.toon // W1=1200 (Min Threshold), W2=4000 (Max Threshold), W3=2 (Pulse Count), // W4=40 (Time Window), W20=128 (Gain) params map[int]int sensorValue int // Default 2067 (ideal rest value) jitterRange int // Default 10 (means ±10) connectedClients int // Track number of connected BLE clients } // NewDeviceState creates a new DeviceState with default values func NewDeviceState() *DeviceState { return &DeviceState{ progMode: false, caliMode: false, alarmActive: false, alarmType: "", params: map[int]int{ 1: 1000, // W1 - Min Threshold (middle of 0-2000) 2: 2047, // W2 - Max Threshold (middle of 0-4095) 3: 25, // W3 - Pulse Count (middle of 1-50) 4: 505, // W4 - Time Window (middle of 10-1000) 11: 0, // W11 - Min Pulse Duration (min) 12: 1000, // W12 - Max Pulse Duration (max) 20: 127, // W20 - Gain (middle of 0-255) }, sensorValue: 2067, jitterRange: 10, connectedClients: 0, } } // GetProgMode returns whether programming mode is active func (s *DeviceState) GetProgMode() bool { s.mu.RLock() defer s.mu.RUnlock() return s.progMode } // SetProgMode sets the programming mode func (s *DeviceState) SetProgMode(enabled bool) { s.mu.Lock() defer s.mu.Unlock() s.progMode = enabled } // GetCaliMode returns whether calibration mode is active func (s *DeviceState) GetCaliMode() bool { s.mu.RLock() defer s.mu.RUnlock() return s.caliMode } // ToggleCaliMode toggles the calibration mode func (s *DeviceState) ToggleCaliMode() bool { s.mu.Lock() defer s.mu.Unlock() s.caliMode = !s.caliMode return s.caliMode } // GetAlarmActive returns whether the alarm is active func (s *DeviceState) GetAlarmActive() bool { s.mu.RLock() defer s.mu.RUnlock() return s.alarmActive } // ResetAlarm resets the alarm state func (s *DeviceState) ResetAlarm() { s.mu.Lock() defer s.mu.Unlock() s.alarmActive = false } // GetParam returns a parameter value by ID func (s *DeviceState) GetParam(id int) (int, bool) { s.mu.RLock() defer s.mu.RUnlock() val, ok := s.params[id] return val, ok } // SetParam sets a parameter value by ID func (s *DeviceState) SetParam(id, value int) { s.mu.Lock() defer s.mu.Unlock() s.params[id] = value } // GetSensorValue returns the current sensor value func (s *DeviceState) GetSensorValue() int { s.mu.RLock() defer s.mu.RUnlock() return s.sensorValue } // ResetToDefaults resets all parameters to factory defaults func (s *DeviceState) ResetToDefaults() { s.mu.Lock() defer s.mu.Unlock() s.progMode = false s.caliMode = false s.alarmActive = false s.alarmType = "" s.params = map[int]int{ 1: 1000, 2: 2047, 3: 25, 4: 505, 11: 0, 12: 1000, 20: 127, } s.sensorValue = 2067 s.jitterRange = 10 } // SetSensorValue sets the current sensor value func (s *DeviceState) SetSensorValue(value int) { s.mu.Lock() defer s.mu.Unlock() s.sensorValue = value } // GetJitterRange returns the current jitter range func (s *DeviceState) GetJitterRange() int { s.mu.RLock() defer s.mu.RUnlock() return s.jitterRange } // SetJitterRange sets the jitter range func (s *DeviceState) SetJitterRange(jitter int) { s.mu.Lock() defer s.mu.Unlock() s.jitterRange = jitter } // TriggerAlarm triggers an alarm with the given type ("TRIGGERED" or "TAMPER") func (s *DeviceState) TriggerAlarm(alarmType string) { s.mu.Lock() defer s.mu.Unlock() s.alarmActive = true s.alarmType = alarmType } // GetAlarmType returns the current alarm type func (s *DeviceState) GetAlarmType() string { s.mu.RLock() defer s.mu.RUnlock() return s.alarmType } // GetAlarmState returns both the alarm active state and type atomically func (s *DeviceState) GetAlarmState() (bool, string) { s.mu.RLock() defer s.mu.RUnlock() return s.alarmActive, s.alarmType } // GetAllParams returns a copy of all parameters func (s *DeviceState) GetAllParams() map[int]int { s.mu.RLock() defer s.mu.RUnlock() return maps.Clone(s.params) } // IncrConnectedClients increments the connected clients count func (s *DeviceState) IncrConnectedClients() { s.mu.Lock() defer s.mu.Unlock() s.connectedClients++ } // DecrConnectedClients decrements the connected clients count func (s *DeviceState) DecrConnectedClients() { s.mu.Lock() defer s.mu.Unlock() if s.connectedClients > 0 { s.connectedClients-- } } // GetConnectedClients returns the number of connected clients func (s *DeviceState) GetConnectedClients() int { s.mu.RLock() defer s.mu.RUnlock() return s.connectedClients }