Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

221 строка
5.6 KiB

  1. package appcontext
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "os"
  6. "time"
  7. "github.com/AFASystems/presence/internal/pkg/kafkaclient"
  8. "github.com/mitchellh/mapstructure"
  9. )
  10. // AppState provides centralized access to application state
  11. type AppState struct {
  12. beacons BeaconsList
  13. settings Settings
  14. beaconEvents BeaconEventList
  15. beaconsLookup BeaconsLookup
  16. health Health
  17. startTime time.Time
  18. }
  19. func getEnv(key, def string) string {
  20. if v := os.Getenv(key); v != "" {
  21. return v
  22. }
  23. return def
  24. }
  25. // NewAppState creates a new application context AppState with default values
  26. func NewAppState() *AppState {
  27. return &AppState{
  28. startTime: time.Now(),
  29. beacons: BeaconsList{
  30. Beacons: make(map[string]Beacon),
  31. },
  32. settings: Settings{
  33. ID: 1,
  34. CurrentAlgorithm: getEnv("ALGORITHM", "filter"),
  35. LocationConfidence: 4,
  36. LastSeenThreshold: 15,
  37. BeaconMetricSize: 30,
  38. HASendInterval: 5,
  39. HASendChangesOnly: false,
  40. RSSIEnforceThreshold: false,
  41. RSSIMinThreshold: 100,
  42. },
  43. beaconEvents: BeaconEventList{
  44. Beacons: make(map[string]BeaconEvent),
  45. },
  46. beaconsLookup: BeaconsLookup{
  47. Lookup: make(map[string]string),
  48. },
  49. health: Health{
  50. ID: "1",
  51. Location: LocationHealth{
  52. BaseHealth: BaseHealth{
  53. Uptime: 0,
  54. ActiveReaders: []string{},
  55. ActiveWriters: []string{},
  56. ActiveBeacons: []string{},
  57. },
  58. },
  59. Decoder: DecoderHealth{
  60. BaseHealth: BaseHealth{
  61. Uptime: 0,
  62. ActiveReaders: []string{},
  63. ActiveWriters: []string{},
  64. ActiveBeacons: []string{},
  65. },
  66. },
  67. Bridge: BridgeHealth{
  68. BaseHealth: BaseHealth{
  69. Uptime: 0,
  70. ActiveReaders: []string{},
  71. ActiveWriters: []string{},
  72. ActiveBeacons: []string{},
  73. },
  74. },
  75. },
  76. }
  77. }
  78. func (m *AppState) GetLocationHealth(k *kafkaclient.KafkaManager) ([]byte, error) {
  79. m.health.Location.GetUptime(m.startTime)
  80. m.health.Location.GetActiveReaders(k)
  81. m.health.Location.GetActiveWriters(k)
  82. m.health.Location.GetActiveBeacons(m)
  83. return m.health.Location.Marshal()
  84. }
  85. func (m *AppState) GetDecoderHealth(k *kafkaclient.KafkaManager) ([]byte, error) {
  86. m.health.Decoder.GetUptime(m.startTime)
  87. m.health.Decoder.GetActiveReaders(k)
  88. m.health.Decoder.GetActiveWriters(k)
  89. m.health.Decoder.GetActiveBeacons(m)
  90. return m.health.Decoder.Marshal()
  91. }
  92. func (m *AppState) GetBridgeHealth(k *kafkaclient.KafkaManager) ([]byte, error) {
  93. m.health.Bridge.GetUptime(m.startTime)
  94. m.health.Bridge.GetActiveReaders(k)
  95. m.health.Bridge.GetActiveWriters(k)
  96. m.health.Bridge.GetActiveBeacons(m)
  97. return m.health.Bridge.Marshal()
  98. }
  99. // GetBeacons returns thread-safe access to beacons list
  100. func (m *AppState) GetBeacons() *BeaconsList {
  101. m.beacons.Lock.RLock()
  102. defer m.beacons.Lock.RUnlock()
  103. return &m.beacons
  104. }
  105. // GetSettings returns thread-safe access to settings
  106. func (m *AppState) GetSettings() *Settings {
  107. return &m.settings
  108. }
  109. // GetBeaconEvents returns thread-safe access to beacon events
  110. func (m *AppState) GetBeaconEvents() *BeaconEventList {
  111. m.beaconEvents.Lock.RLock()
  112. defer m.beaconEvents.Lock.RUnlock()
  113. return &m.beaconEvents
  114. }
  115. // AddBeaconToLookup adds a beacon ID to the lookup map
  116. func (m *AppState) AddBeaconToLookup(id, value string) {
  117. m.beaconsLookup.Lock.Lock()
  118. m.beaconsLookup.Lookup[id] = value
  119. m.beaconsLookup.Lock.Unlock()
  120. }
  121. // RemoveBeaconFromLookup removes a beacon ID from the lookup map
  122. func (m *AppState) RemoveBeaconFromLookup(id string) {
  123. m.beaconsLookup.Lock.Lock()
  124. delete(m.beaconsLookup.Lookup, id)
  125. m.beaconsLookup.Lock.Unlock()
  126. }
  127. func (m *AppState) CleanLookup() {
  128. m.beaconsLookup.Lock.Lock()
  129. clear(m.beaconsLookup.Lookup)
  130. m.beaconsLookup.Lock.Unlock()
  131. }
  132. // BeaconExists checks if a beacon exists in the lookup
  133. func (m *AppState) BeaconExists(id string) (string, bool) {
  134. m.beaconsLookup.Lock.RLock()
  135. defer m.beaconsLookup.Lock.RUnlock()
  136. val, exists := m.beaconsLookup.Lookup[id]
  137. return val, exists
  138. }
  139. // GetBeacon returns a beacon by ID (thread-safe)
  140. func (m *AppState) GetBeacon(id string) (Beacon, bool) {
  141. m.beacons.Lock.RLock()
  142. defer m.beacons.Lock.RUnlock()
  143. beacon, exists := m.beacons.Beacons[id]
  144. return beacon, exists
  145. }
  146. // UpdateBeacon updates a beacon in the list (thread-safe)
  147. func (m *AppState) UpdateBeacon(id string, beacon Beacon) {
  148. m.beacons.Lock.Lock()
  149. defer m.beacons.Lock.Unlock()
  150. m.beacons.Beacons[id] = beacon
  151. }
  152. // GetBeaconEvent returns a beacon event by ID (thread-safe)
  153. func (m *AppState) GetBeaconEvent(id string) (BeaconEvent, bool) {
  154. m.beaconEvents.Lock.RLock()
  155. defer m.beaconEvents.Lock.RUnlock()
  156. event, exists := m.beaconEvents.Beacons[id]
  157. return event, exists
  158. }
  159. // UpdateBeaconEvent updates a beacon event in the list (thread-safe)
  160. func (m *AppState) UpdateBeaconEvent(id string, event BeaconEvent) {
  161. m.beaconEvents.Lock.Lock()
  162. defer m.beaconEvents.Lock.Unlock()
  163. m.beaconEvents.Beacons[id] = event
  164. }
  165. // GetAllBeacons returns a copy of all beacons
  166. func (m *AppState) GetAllBeacons() map[string]Beacon {
  167. m.beacons.Lock.RLock()
  168. defer m.beacons.Lock.RUnlock()
  169. beacons := make(map[string]Beacon)
  170. for id, beacon := range m.beacons.Beacons {
  171. beacons[id] = beacon
  172. }
  173. return beacons
  174. }
  175. // GetBeaconCount returns the number of tracked beacons
  176. func (m *AppState) GetBeaconCount() int {
  177. m.beacons.Lock.RLock()
  178. defer m.beacons.Lock.RUnlock()
  179. return len(m.beacons.Beacons)
  180. }
  181. // GetSettingsValue returns current settings as a value
  182. func (m *AppState) GetSettingsValue() Settings {
  183. return m.settings
  184. }
  185. // UpdateSettings updates the system settings (thread-safe)
  186. func (m *AppState) UpdateSettings(settings map[string]any) {
  187. if err := mapstructure.Decode(settings, &m.settings); err != nil {
  188. msg := fmt.Sprintf("Error in persisting settings: %v", err)
  189. slog.Error(msg)
  190. }
  191. }