You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

158 lines
4.2 KiB

  1. package appcontext
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "github.com/AFASystems/presence/internal/pkg/model"
  6. "github.com/mitchellh/mapstructure"
  7. )
  8. // AppState provides centralized access to application state
  9. type AppState struct {
  10. beacons model.BeaconsList
  11. settings model.Settings
  12. beaconEvents model.BeaconEventList
  13. beaconsLookup model.BeaconsLookup
  14. }
  15. // NewAppState creates a new application context AppState with default values
  16. func NewAppState() *AppState {
  17. return &AppState{
  18. beacons: model.BeaconsList{
  19. Beacons: make(map[string]model.Beacon),
  20. },
  21. settings: model.Settings{
  22. ID: 1,
  23. CurrentAlgorithm: "filter", // possible values filter or AI
  24. LocationConfidence: 4,
  25. LastSeenThreshold: 15,
  26. BeaconMetricSize: 30,
  27. HASendInterval: 5,
  28. HASendChangesOnly: false,
  29. RSSIEnforceThreshold: false,
  30. RSSIMinThreshold: 100,
  31. },
  32. beaconEvents: model.BeaconEventList{
  33. Beacons: make(map[string]model.BeaconEvent),
  34. },
  35. beaconsLookup: model.BeaconsLookup{
  36. Lookup: make(map[string]string),
  37. },
  38. }
  39. }
  40. // GetBeacons returns thread-safe access to beacons list
  41. func (m *AppState) GetBeacons() *model.BeaconsList {
  42. m.beacons.Lock.RLock()
  43. defer m.beacons.Lock.RUnlock()
  44. return &m.beacons
  45. }
  46. // GetSettings returns thread-safe access to settings
  47. func (m *AppState) GetSettings() *model.Settings {
  48. return &m.settings
  49. }
  50. // GetBeaconEvents returns thread-safe access to beacon events
  51. func (m *AppState) GetBeaconEvents() *model.BeaconEventList {
  52. m.beaconEvents.Lock.RLock()
  53. defer m.beaconEvents.Lock.RUnlock()
  54. return &m.beaconEvents
  55. }
  56. // AddBeaconToLookup adds a beacon ID to the lookup map
  57. func (m *AppState) AddBeaconToLookup(id, value string) {
  58. m.beaconsLookup.Lock.Lock()
  59. m.beaconsLookup.Lookup[id] = value
  60. m.beaconsLookup.Lock.Unlock()
  61. }
  62. // RemoveBeaconFromLookup removes a beacon ID from the lookup map
  63. func (m *AppState) RemoveBeaconFromLookup(id string) {
  64. m.beaconsLookup.Lock.Lock()
  65. delete(m.beaconsLookup.Lookup, id)
  66. m.beaconsLookup.Lock.Unlock()
  67. }
  68. func (m *AppState) CleanLookup() {
  69. m.beaconsLookup.Lock.Lock()
  70. clear(m.beaconsLookup.Lookup)
  71. m.beaconsLookup.Lock.Unlock()
  72. }
  73. // BeaconExists checks if a beacon exists in the lookup
  74. func (m *AppState) BeaconExists(id string) (string, bool) {
  75. m.beaconsLookup.Lock.RLock()
  76. defer m.beaconsLookup.Lock.RUnlock()
  77. val, exists := m.beaconsLookup.Lookup[id]
  78. return val, exists
  79. }
  80. // GetBeacon returns a beacon by ID (thread-safe)
  81. func (m *AppState) GetBeacon(id string) (model.Beacon, bool) {
  82. m.beacons.Lock.RLock()
  83. defer m.beacons.Lock.RUnlock()
  84. beacon, exists := m.beacons.Beacons[id]
  85. return beacon, exists
  86. }
  87. // UpdateBeacon updates a beacon in the list (thread-safe)
  88. func (m *AppState) UpdateBeacon(id string, beacon model.Beacon) {
  89. m.beacons.Lock.Lock()
  90. defer m.beacons.Lock.Unlock()
  91. m.beacons.Beacons[id] = beacon
  92. }
  93. // GetBeaconEvent returns a beacon event by ID (thread-safe)
  94. func (m *AppState) GetBeaconEvent(id string) (model.BeaconEvent, bool) {
  95. m.beaconEvents.Lock.RLock()
  96. defer m.beaconEvents.Lock.RUnlock()
  97. event, exists := m.beaconEvents.Beacons[id]
  98. return event, exists
  99. }
  100. // UpdateBeaconEvent updates a beacon event in the list (thread-safe)
  101. func (m *AppState) UpdateBeaconEvent(id string, event model.BeaconEvent) {
  102. m.beaconEvents.Lock.Lock()
  103. defer m.beaconEvents.Lock.Unlock()
  104. m.beaconEvents.Beacons[id] = event
  105. }
  106. // GetAllBeacons returns a copy of all beacons
  107. func (m *AppState) GetAllBeacons() map[string]model.Beacon {
  108. m.beacons.Lock.RLock()
  109. defer m.beacons.Lock.RUnlock()
  110. beacons := make(map[string]model.Beacon)
  111. for id, beacon := range m.beacons.Beacons {
  112. beacons[id] = beacon
  113. }
  114. return beacons
  115. }
  116. // GetBeaconCount returns the number of tracked beacons
  117. func (m *AppState) GetBeaconCount() int {
  118. m.beacons.Lock.RLock()
  119. defer m.beacons.Lock.RUnlock()
  120. return len(m.beacons.Beacons)
  121. }
  122. // GetSettingsValue returns current settings as a value
  123. func (m *AppState) GetSettingsValue() model.Settings {
  124. return m.settings
  125. }
  126. // UpdateSettings updates the system settings (thread-safe)
  127. func (m *AppState) UpdateSettings(settings map[string]any) {
  128. if err := mapstructure.Decode(settings, &m.settings); err != nil {
  129. msg := fmt.Sprintf("Error in persisting settings: %v", err)
  130. slog.Error(msg)
  131. }
  132. }