|
- package bridge
-
- import (
- "context"
- "encoding/json"
- "log/slog"
- "strings"
- "time"
-
- "github.com/AFASystems/presence/internal/pkg/model"
- "github.com/segmentio/kafka-go"
- )
-
- // RawBeaconWriter writes beacon advertisements to the rawbeacons topic.
- type RawBeaconWriter interface {
- WriteMessages(ctx context.Context, msgs ...kafka.Message) error
- }
-
- // BeaconLookup provides MAC->ID lookup (e.g. AppState).
- type BeaconLookup interface {
- BeaconExists(mac string) (id string, ok bool)
- }
-
- // HandleMQTTMessage processes an MQTT message: parses JSON array of RawReading or CSV.
- // For JSON, converts each reading to BeaconAdvertisement and writes to the writer if MAC is in lookup.
- // Hostname is derived from topic (e.g. "publish_out/gateway1" -> "gateway1"). Safe if topic has no "/".
- func HandleMQTTMessage(topic string, payload []byte, lookup BeaconLookup, writer RawBeaconWriter) {
- parts := strings.SplitN(topic, "/", 2)
- hostname := ""
- if len(parts) >= 2 {
- hostname = parts[1]
- }
-
- msgStr := string(payload)
- if strings.HasPrefix(msgStr, "[") {
- var readings []model.RawReading
- if err := json.Unmarshal(payload, &readings); err != nil {
- slog.Error("parsing MQTT JSON", "err", err, "topic", topic)
- return
- }
- for _, reading := range readings {
- if reading.Type == "Gateway" {
- continue
- }
- id, ok := lookup.BeaconExists(reading.MAC)
- if !ok {
- continue
- }
- adv := model.BeaconAdvertisement{
- ID: id,
- Hostname: hostname,
- MAC: reading.MAC,
- RSSI: int64(reading.RSSI),
- Data: reading.RawData,
- }
- encoded, err := json.Marshal(adv)
- if err != nil {
- slog.Error("marshaling beacon advertisement", "err", err)
- break
- }
- if err := writer.WriteMessages(context.Background(), kafka.Message{Value: encoded}); err != nil {
- slog.Error("writing to Kafka", "err", err)
- time.Sleep(1 * time.Second)
- break
- }
- }
- return
- }
- // CSV format: validate minimum fields (e.g. 6 columns); full parsing can be added later
- s := strings.Split(msgStr, ",")
- if len(s) < 6 {
- slog.Error("invalid CSV MQTT message", "topic", topic, "message", msgStr)
- return
- }
- slog.Debug("CSV MQTT message received", "topic", topic, "fields", len(s))
- }
|