208 lines
4.7 KiB
Go
208 lines
4.7 KiB
Go
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
|
|
}
|