Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

78 líneas
1.5KB

  1. package control
  2. import (
  3. "sync"
  4. "time"
  5. offpkg "github.com/jan/fm-rds-tx/internal/offline"
  6. )
  7. type TelemetryMessage struct {
  8. Type string `json:"type"`
  9. TS time.Time `json:"ts"`
  10. Seq uint64 `json:"seq"`
  11. Data *offpkg.MeasurementSnapshot `json:"data,omitempty"`
  12. }
  13. type telemetrySubscriber struct {
  14. ch chan TelemetryMessage
  15. }
  16. type TelemetryHub struct {
  17. mu sync.Mutex
  18. subscribers map[*telemetrySubscriber]struct{}
  19. }
  20. func NewTelemetryHub() *TelemetryHub {
  21. return &TelemetryHub{subscribers: make(map[*telemetrySubscriber]struct{})}
  22. }
  23. func (h *TelemetryHub) Subscribe() (*telemetrySubscriber, func()) {
  24. sub := &telemetrySubscriber{ch: make(chan TelemetryMessage, 1)}
  25. h.mu.Lock()
  26. h.subscribers[sub] = struct{}{}
  27. h.mu.Unlock()
  28. return sub, func() {
  29. h.mu.Lock()
  30. if _, ok := h.subscribers[sub]; ok {
  31. delete(h.subscribers, sub)
  32. close(sub.ch)
  33. }
  34. h.mu.Unlock()
  35. }
  36. }
  37. func (h *TelemetryHub) PublishMeasurement(snapshot *offpkg.MeasurementSnapshot) {
  38. if h == nil || snapshot == nil {
  39. return
  40. }
  41. msg := TelemetryMessage{
  42. Type: "measurement",
  43. TS: snapshot.Timestamp,
  44. Seq: snapshot.Sequence,
  45. Data: snapshot,
  46. }
  47. h.mu.Lock()
  48. subs := make([]*telemetrySubscriber, 0, len(h.subscribers))
  49. for sub := range h.subscribers {
  50. subs = append(subs, sub)
  51. }
  52. h.mu.Unlock()
  53. for _, sub := range subs {
  54. select {
  55. case sub.ch <- msg:
  56. default:
  57. select {
  58. case <-sub.ch:
  59. default:
  60. }
  61. select {
  62. case sub.ch <- msg:
  63. default:
  64. }
  65. }
  66. }
  67. }