diff --git a/internal/pkg/common/appcontext/context.go b/internal/pkg/common/appcontext/context.go new file mode 100644 index 0000000..67f09b7 --- /dev/null +++ b/internal/pkg/common/appcontext/context.go @@ -0,0 +1,181 @@ +package appcontext + +import ( + "github.com/AFASystems/presence/internal/pkg/model" +) + +// Manager provides centralized access to application state +type Manager struct { + beacons model.BeaconsList + settings model.Settings + beaconEvents model.BeaconEventList + beaconsLookup map[string]struct{} + latestList model.LatestBeaconsList +} + +// NewManager creates a new application context manager with default values +func NewManager() *Manager { + return &Manager{ + beacons: model.BeaconsList{ + Beacons: make(map[string]model.Beacon), + }, + settings: model.Settings{ + Settings: model.SettingsVal{ + LocationConfidence: 4, + LastSeenThreshold: 15, + BeaconMetricSize: 30, + HASendInterval: 5, + HASendChangesOnly: false, + RSSIEnforceThreshold: false, + RSSIMinThreshold: 100, + }, + }, + beaconEvents: model.BeaconEventList{ + Beacons: make(map[string]model.BeaconEvent), + }, + beaconsLookup: make(map[string]struct{}), + latestList: model.LatestBeaconsList{ + LatestList: make(map[string]model.Beacon), + }, + } +} + +// GetBeacons returns thread-safe access to beacons list +func (m *Manager) GetBeacons() *model.BeaconsList { + return &m.beacons +} + +// GetSettings returns thread-safe access to settings +func (m *Manager) GetSettings() *model.Settings { + return &m.settings +} + +// GetBeaconEvents returns thread-safe access to beacon events +func (m *Manager) GetBeaconEvents() *model.BeaconEventList { + return &m.beaconEvents +} + +// GetBeaconsLookup returns thread-safe access to beacon lookup map +func (m *Manager) GetBeaconsLookup() map[string]struct{} { + return m.beaconsLookup +} + +// GetLatestList returns thread-safe access to latest beacons list +func (m *Manager) GetLatestList() *model.LatestBeaconsList { + return &m.latestList +} + +// AddBeaconToLookup adds a beacon ID to the lookup map +func (m *Manager) AddBeaconToLookup(id string) { + m.beaconsLookup[id] = struct{}{} +} + +// RemoveBeaconFromLookup removes a beacon ID from the lookup map +func (m *Manager) RemoveBeaconFromLookup(id string) { + delete(m.beaconsLookup, id) +} + +// BeaconExists checks if a beacon exists in the lookup +func (m *Manager) BeaconExists(id string) bool { + _, exists := m.beaconsLookup[id] + return exists +} + +// GetBeacon returns a beacon by ID (thread-safe) +func (m *Manager) GetBeacon(id string) (model.Beacon, bool) { + m.beacons.Lock.RLock() + defer m.beacons.Lock.RUnlock() + + beacon, exists := m.beacons.Beacons[id] + return beacon, exists +} + +// UpdateBeacon updates a beacon in the list (thread-safe) +func (m *Manager) UpdateBeacon(id string, beacon model.Beacon) { + m.beacons.Lock.Lock() + defer m.beacons.Lock.Unlock() + + m.beacons.Beacons[id] = beacon +} + +// GetBeaconEvent returns a beacon event by ID (thread-safe) +func (m *Manager) GetBeaconEvent(id string) (model.BeaconEvent, bool) { + m.beaconEvents.Lock.RLock() + defer m.beaconEvents.Lock.RUnlock() + + event, exists := m.beaconEvents.Beacons[id] + return event, exists +} + +// UpdateBeaconEvent updates a beacon event in the list (thread-safe) +func (m *Manager) UpdateBeaconEvent(id string, event model.BeaconEvent) { + m.beaconEvents.Lock.Lock() + defer m.beaconEvents.Lock.Unlock() + + m.beaconEvents.Beacons[id] = event +} + +// GetLatestBeacon returns the latest beacon by ID (thread-safe) +func (m *Manager) GetLatestBeacon(id string) (model.Beacon, bool) { + m.latestList.Lock.RLock() + defer m.latestList.Lock.RUnlock() + + beacon, exists := m.latestList.LatestList[id] + return beacon, exists +} + +// UpdateLatestBeacon updates the latest beacon in the list (thread-safe) +func (m *Manager) UpdateLatestBeacon(id string, beacon model.Beacon) { + m.latestList.Lock.Lock() + defer m.latestList.Lock.Unlock() + + m.latestList.LatestList[id] = beacon +} + +// GetAllBeacons returns a copy of all beacons +func (m *Manager) GetAllBeacons() map[string]model.Beacon { + m.beacons.Lock.RLock() + defer m.beacons.Lock.RUnlock() + + beacons := make(map[string]model.Beacon) + for id, beacon := range m.beacons.Beacons { + beacons[id] = beacon + } + return beacons +} + +// GetAllLatestBeacons returns a copy of all latest beacons +func (m *Manager) GetAllLatestBeacons() map[string]model.Beacon { + m.latestList.Lock.RLock() + defer m.latestList.Lock.RUnlock() + + beacons := make(map[string]model.Beacon) + for id, beacon := range m.latestList.LatestList { + beacons[id] = beacon + } + return beacons +} + +// GetBeaconCount returns the number of tracked beacons +func (m *Manager) GetBeaconCount() int { + m.beacons.Lock.RLock() + defer m.beacons.Lock.RUnlock() + + return len(m.beacons.Beacons) +} + +// GetSettingsValue returns current settings as a value +func (m *Manager) GetSettingsValue() model.SettingsVal { + m.settings.Lock.RLock() + defer m.settings.Lock.RUnlock() + + return m.settings.Settings +} + +// UpdateSettings updates the system settings (thread-safe) +func (m *Manager) UpdateSettings(newSettings model.SettingsVal) { + m.settings.Lock.Lock() + defer m.settings.Lock.Unlock() + + m.settings.Settings = newSettings +} diff --git a/internal/pkg/model/types.go b/internal/pkg/model/types.go index 5ce5569..e151535 100644 --- a/internal/pkg/model/types.go +++ b/internal/pkg/model/types.go @@ -4,7 +4,6 @@ import ( "sync" "github.com/boltdb/bolt" - "github.com/gorilla/websocket" ) // Settings defines configuration parameters for presence detection behavior. @@ -193,19 +192,6 @@ type HTTPResultsList struct { HTTPResults HTTPLocationsList } -type AppContext struct { - HTTPResults HTTPResultsList - Beacons BeaconsList - ButtonsList map[string]Button - Settings Settings - Broadcast chan Message - Locations LocationsList - LatestList LatestBeaconsList - Clients map[*websocket.Conn]bool - BeaconsLookup map[string]struct{} - BeaconEvents BeaconEventList -} - type ApiUpdate struct { Method string Beacon Beacon