Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

70 рядки
2.0 KiB

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