|
- package decoder
-
- import (
- "bytes"
- "context"
- "encoding/hex"
- "fmt"
- "log/slog"
- "strings"
-
- "github.com/AFASystems/presence/internal/pkg/common/appcontext"
- "github.com/AFASystems/presence/internal/pkg/common/utils"
- "github.com/AFASystems/presence/internal/pkg/model"
- "github.com/segmentio/kafka-go"
- )
-
- // AlertWriter writes decoded beacon events (e.g. to alertbeacons topic).
- type AlertWriter interface {
- WriteMessages(ctx context.Context, msgs ...kafka.Message) error
- }
-
- // ProcessIncoming decodes a beacon advertisement and writes the event to the writer if it changed.
- func ProcessIncoming(adv model.BeaconAdvertisement, appState *appcontext.AppState, writer AlertWriter, registry *model.ParserRegistry) {
- if err := DecodeBeacon(adv, appState, writer, registry); err != nil {
- slog.Error("decoding beacon", "err", err, "id", adv.ID)
- }
- }
-
- // DecodeBeacon hex-decodes the payload, runs the parser registry, dedupes by event hash, and writes to writer.
- func DecodeBeacon(adv model.BeaconAdvertisement, appState *appcontext.AppState, writer AlertWriter, registry *model.ParserRegistry) error {
- beacon := strings.TrimSpace(adv.Data)
- id := adv.ID
- if beacon == "" {
- return nil
- }
-
- b, err := hex.DecodeString(beacon)
- if err != nil {
- return err
- }
-
- b = utils.RemoveFlagBytes(b)
- indices := utils.ParseADFast(b)
- event := utils.LoopADStructures(b, indices, id, registry)
-
- if event.ID == "" {
- return nil
- }
-
- prevEvent, ok := appState.GetBeaconEvent(id)
- appState.UpdateBeaconEvent(id, event)
-
- if event.Type == "iBeacon" {
- event.BtnPressed = true
- }
-
- if ok && bytes.Equal(prevEvent.Hash(), event.Hash()) {
- return nil
- }
-
- eMsg, err := event.ToJSON()
- if err != nil {
- return err
- }
-
- if err := writer.WriteMessages(context.Background(), kafka.Message{Value: eMsg}); err != nil {
- return fmt.Errorf("write alert: %w", err)
- }
-
- return nil
- }
|