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

189 строки
4.9KB

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