Files
BLE_emulator/internal/device/state.go
2026-02-23 01:35:53 +01:00

226 lines
5.2 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
ncParam bool // NC parameter: true = NO (1), false = NC (0), default is NO
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: 1200, // W1 - Min Threshold (default as per docs)
2: 2047, // W2 - Max Threshold (middle of 0-4095)
3: 25, // W3 - Pulse Count (middle of 1-50)
4: 30500, // W4 - Time Window (middle of 1000-60000)
11: 152, // W11 - Min Pulse Duration (middle of 5-300)
12: 152, // W12 - Max Pulse Duration (middle of 5-300)
20: 127, // W20 - Gain (middle of 0-255)
},
ncParam: true, // Default NO mode (1)
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: 127,
2: 2047,
3: 25,
4: 30500,
11: 152,
12: 152,
20: 127,
}
s.ncParam = true // Default NO mode (1)
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
}
// GetNCParam returns the NC parameter value (true = NO, false = NC)
func (s *DeviceState) GetNCParam() bool {
s.mu.RLock()
defer s.mu.RUnlock()
return s.ncParam
}
// SetNCParam sets the NC parameter value (true = NO, false = NC)
func (s *DeviceState) SetNCParam(value bool) {
s.mu.Lock()
defer s.mu.Unlock()
s.ncParam = value
}
// 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
}