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ů.
 
 
 
 

74 řádky
2.1 KiB

  1. package bridge
  2. import (
  3. "context"
  4. "encoding/json"
  5. "log/slog"
  6. "strings"
  7. "time"
  8. "github.com/AFASystems/presence/internal/pkg/common/appcontext"
  9. "github.com/AFASystems/presence/internal/pkg/kafkaclient"
  10. "github.com/AFASystems/presence/internal/pkg/model"
  11. "github.com/segmentio/kafka-go"
  12. )
  13. // BeaconLookup provides MAC->ID lookup (e.g. AppState).
  14. type BeaconLookup interface {
  15. BeaconExists(mac string) (id string, ok bool)
  16. }
  17. // HandleMQTTMessage processes an MQTT message: parses JSON array of RawReading or CSV.
  18. // For JSON, converts each reading to BeaconAdvertisement and writes to the writer if MAC is in lookup.
  19. // Hostname is derived from topic (e.g. "publish_out/gateway1" -> "gateway1"). Safe if topic has no "/".
  20. func HandleMQTTMessage(topic string, payload []byte, lookup BeaconLookup, writer *kafka.Writer) {
  21. parts := strings.SplitN(topic, "/", 2)
  22. hostname := ""
  23. if len(parts) >= 2 {
  24. hostname = parts[1]
  25. }
  26. msgStr := string(payload)
  27. if strings.HasPrefix(msgStr, "[") {
  28. var readings []model.RawReading
  29. if err := json.Unmarshal(payload, &readings); err != nil {
  30. slog.Error("parsing MQTT JSON", "err", err, "topic", topic)
  31. return
  32. }
  33. for _, reading := range readings {
  34. if reading.Type == "Gateway" {
  35. continue
  36. }
  37. id, ok := lookup.BeaconExists(reading.MAC)
  38. if !ok {
  39. continue
  40. }
  41. adv := appcontext.BeaconAdvertisement{
  42. ID: id,
  43. Hostname: hostname,
  44. MAC: reading.MAC,
  45. RSSI: int64(reading.RSSI),
  46. Data: reading.RawData,
  47. }
  48. encoded, err := json.Marshal(adv)
  49. if err != nil {
  50. slog.Error("marshaling beacon advertisement", "err", err)
  51. break
  52. }
  53. if err := kafkaclient.Write(context.Background(), writer, kafka.Message{Value: encoded}); err != nil {
  54. slog.Error("writing to Kafka", "err", err)
  55. time.Sleep(1 * time.Second)
  56. break
  57. }
  58. }
  59. return
  60. }
  61. // CSV format: validate minimum fields (e.g. 6 columns); full parsing can be added later
  62. s := strings.Split(msgStr, ",")
  63. if len(s) < 6 {
  64. slog.Error("invalid CSV MQTT message", "topic", topic, "message", msgStr)
  65. return
  66. }
  67. slog.Debug("CSV MQTT message received", "topic", topic, "fields", len(s))
  68. }