Wideband autonomous SDR analysis engine forked from sdr-visual-suite
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

205 řádky
5.5KB

  1. package runtime
  2. import (
  3. "errors"
  4. "sync"
  5. "sdr-visual-suite/internal/config"
  6. )
  7. type ConfigUpdate struct {
  8. CenterHz *float64 `json:"center_hz"`
  9. SampleRate *int `json:"sample_rate"`
  10. FFTSize *int `json:"fft_size"`
  11. GainDb *float64 `json:"gain_db"`
  12. TunerBwKHz *int `json:"tuner_bw_khz"`
  13. UseGPUFFT *bool `json:"use_gpu_fft"`
  14. Detector *DetectorUpdate `json:"detector"`
  15. Recorder *RecorderUpdate `json:"recorder"`
  16. }
  17. type DetectorUpdate struct {
  18. ThresholdDb *float64 `json:"threshold_db"`
  19. MinDuration *int `json:"min_duration_ms"`
  20. HoldMs *int `json:"hold_ms"`
  21. EmaAlpha *float64 `json:"ema_alpha"`
  22. HysteresisDb *float64 `json:"hysteresis_db"`
  23. MinStableFrames *int `json:"min_stable_frames"`
  24. GapToleranceMs *int `json:"gap_tolerance_ms"`
  25. }
  26. type SettingsUpdate struct {
  27. AGC *bool `json:"agc"`
  28. DCBlock *bool `json:"dc_block"`
  29. IQBalance *bool `json:"iq_balance"`
  30. }
  31. type RecorderUpdate struct {
  32. Enabled *bool `json:"enabled"`
  33. MinSNRDb *float64 `json:"min_snr_db"`
  34. MinDuration *string `json:"min_duration"`
  35. MaxDuration *string `json:"max_duration"`
  36. PrerollMs *int `json:"preroll_ms"`
  37. RecordIQ *bool `json:"record_iq"`
  38. RecordAudio *bool `json:"record_audio"`
  39. AutoDemod *bool `json:"auto_demod"`
  40. AutoDecode *bool `json:"auto_decode"`
  41. MaxDiskMB *int `json:"max_disk_mb"`
  42. OutputDir *string `json:"output_dir"`
  43. ClassFilter *[]string `json:"class_filter"`
  44. RingSeconds *int `json:"ring_seconds"`
  45. }
  46. type Manager struct {
  47. mu sync.RWMutex
  48. cfg config.Config
  49. }
  50. func New(cfg config.Config) *Manager {
  51. return &Manager{cfg: cfg}
  52. }
  53. func (m *Manager) Snapshot() config.Config {
  54. m.mu.RLock()
  55. defer m.mu.RUnlock()
  56. return m.cfg
  57. }
  58. func (m *Manager) Replace(cfg config.Config) {
  59. m.mu.Lock()
  60. defer m.mu.Unlock()
  61. m.cfg = cfg
  62. }
  63. func (m *Manager) ApplyConfig(update ConfigUpdate) (config.Config, error) {
  64. m.mu.Lock()
  65. defer m.mu.Unlock()
  66. next := m.cfg
  67. if update.CenterHz != nil {
  68. if *update.CenterHz < 1e3 || *update.CenterHz > 2e9 {
  69. return m.cfg, errors.New("center_hz out of range")
  70. }
  71. next.CenterHz = *update.CenterHz
  72. }
  73. if update.SampleRate != nil {
  74. if *update.SampleRate <= 0 {
  75. return m.cfg, errors.New("sample_rate must be > 0")
  76. }
  77. next.SampleRate = *update.SampleRate
  78. }
  79. if update.FFTSize != nil {
  80. if *update.FFTSize <= 0 {
  81. return m.cfg, errors.New("fft_size must be > 0")
  82. }
  83. if *update.FFTSize&(*update.FFTSize-1) != 0 {
  84. return m.cfg, errors.New("fft_size must be a power of 2")
  85. }
  86. next.FFTSize = *update.FFTSize
  87. }
  88. if update.GainDb != nil {
  89. next.GainDb = *update.GainDb
  90. }
  91. if update.TunerBwKHz != nil {
  92. if *update.TunerBwKHz <= 0 {
  93. return m.cfg, errors.New("tuner_bw_khz must be > 0")
  94. }
  95. next.TunerBwKHz = *update.TunerBwKHz
  96. }
  97. if update.UseGPUFFT != nil {
  98. next.UseGPUFFT = *update.UseGPUFFT
  99. }
  100. if update.Detector != nil {
  101. if update.Detector.ThresholdDb != nil {
  102. next.Detector.ThresholdDb = *update.Detector.ThresholdDb
  103. }
  104. if update.Detector.MinDuration != nil {
  105. if *update.Detector.MinDuration <= 0 {
  106. return m.cfg, errors.New("min_duration_ms must be > 0")
  107. }
  108. next.Detector.MinDurationMs = *update.Detector.MinDuration
  109. }
  110. if update.Detector.HoldMs != nil {
  111. if *update.Detector.HoldMs <= 0 {
  112. return m.cfg, errors.New("hold_ms must be > 0")
  113. }
  114. next.Detector.HoldMs = *update.Detector.HoldMs
  115. }
  116. if update.Detector.EmaAlpha != nil {
  117. next.Detector.EmaAlpha = *update.Detector.EmaAlpha
  118. }
  119. if update.Detector.HysteresisDb != nil {
  120. next.Detector.HysteresisDb = *update.Detector.HysteresisDb
  121. }
  122. if update.Detector.MinStableFrames != nil {
  123. next.Detector.MinStableFrames = *update.Detector.MinStableFrames
  124. }
  125. if update.Detector.GapToleranceMs != nil {
  126. next.Detector.GapToleranceMs = *update.Detector.GapToleranceMs
  127. }
  128. }
  129. if update.Recorder != nil {
  130. if update.Recorder.Enabled != nil {
  131. next.Recorder.Enabled = *update.Recorder.Enabled
  132. }
  133. if update.Recorder.MinSNRDb != nil {
  134. next.Recorder.MinSNRDb = *update.Recorder.MinSNRDb
  135. }
  136. if update.Recorder.MinDuration != nil {
  137. next.Recorder.MinDuration = *update.Recorder.MinDuration
  138. }
  139. if update.Recorder.MaxDuration != nil {
  140. next.Recorder.MaxDuration = *update.Recorder.MaxDuration
  141. }
  142. if update.Recorder.PrerollMs != nil {
  143. next.Recorder.PrerollMs = *update.Recorder.PrerollMs
  144. }
  145. if update.Recorder.RecordIQ != nil {
  146. next.Recorder.RecordIQ = *update.Recorder.RecordIQ
  147. }
  148. if update.Recorder.RecordAudio != nil {
  149. next.Recorder.RecordAudio = *update.Recorder.RecordAudio
  150. }
  151. if update.Recorder.AutoDemod != nil {
  152. next.Recorder.AutoDemod = *update.Recorder.AutoDemod
  153. }
  154. if update.Recorder.AutoDecode != nil {
  155. next.Recorder.AutoDecode = *update.Recorder.AutoDecode
  156. }
  157. if update.Recorder.MaxDiskMB != nil {
  158. next.Recorder.MaxDiskMB = *update.Recorder.MaxDiskMB
  159. }
  160. if update.Recorder.OutputDir != nil {
  161. next.Recorder.OutputDir = *update.Recorder.OutputDir
  162. }
  163. if update.Recorder.ClassFilter != nil {
  164. next.Recorder.ClassFilter = *update.Recorder.ClassFilter
  165. }
  166. if update.Recorder.RingSeconds != nil {
  167. next.Recorder.RingSeconds = *update.Recorder.RingSeconds
  168. }
  169. }
  170. m.cfg = next
  171. return m.cfg, nil
  172. }
  173. func (m *Manager) ApplySettings(update SettingsUpdate) (config.Config, error) {
  174. m.mu.Lock()
  175. defer m.mu.Unlock()
  176. next := m.cfg
  177. if update.AGC != nil {
  178. next.AGC = *update.AGC
  179. }
  180. if update.DCBlock != nil {
  181. next.DCBlock = *update.DCBlock
  182. }
  183. if update.IQBalance != nil {
  184. next.IQBalance = *update.IQBalance
  185. }
  186. m.cfg = next
  187. return m.cfg, nil
  188. }