|
|
@@ -3,13 +3,12 @@ package main |
|
|
import ( |
|
|
import ( |
|
|
"bytes" |
|
|
"bytes" |
|
|
"context" |
|
|
"context" |
|
|
"encoding/binary" |
|
|
|
|
|
"encoding/hex" |
|
|
"encoding/hex" |
|
|
"encoding/json" |
|
|
|
|
|
"fmt" |
|
|
"fmt" |
|
|
"strings" |
|
|
"strings" |
|
|
|
|
|
|
|
|
"github.com/AFASystems/presence/internal/pkg/common/appcontext" |
|
|
"github.com/AFASystems/presence/internal/pkg/common/appcontext" |
|
|
|
|
|
"github.com/AFASystems/presence/internal/pkg/common/utils" |
|
|
"github.com/AFASystems/presence/internal/pkg/config" |
|
|
"github.com/AFASystems/presence/internal/pkg/config" |
|
|
"github.com/AFASystems/presence/internal/pkg/kafkaclient" |
|
|
"github.com/AFASystems/presence/internal/pkg/kafkaclient" |
|
|
"github.com/AFASystems/presence/internal/pkg/model" |
|
|
"github.com/AFASystems/presence/internal/pkg/model" |
|
|
@@ -73,7 +72,7 @@ func decodeBeacon(adv model.BeaconAdvertisement, appState *appcontext.AppState, |
|
|
beacon := strings.TrimSpace(adv.Data) |
|
|
beacon := strings.TrimSpace(adv.Data) |
|
|
id := adv.MAC |
|
|
id := adv.MAC |
|
|
if beacon == "" { |
|
|
if beacon == "" { |
|
|
return nil // How to return error?, do I even need to return error |
|
|
|
|
|
|
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
b, err := hex.DecodeString(beacon) |
|
|
b, err := hex.DecodeString(beacon) |
|
|
@@ -81,126 +80,29 @@ func decodeBeacon(adv model.BeaconAdvertisement, appState *appcontext.AppState, |
|
|
return err |
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// check for flag byte, if first AD structure is flag bytes, remove it |
|
|
|
|
|
if len(b) > 1 && b[1] == 0x01 { |
|
|
|
|
|
l := int(b[0]) // length of AD structure |
|
|
|
|
|
if 1+l <= len(b) { |
|
|
|
|
|
b = b[1+l:] |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
adStructureIndeces := ParseADFast(b) |
|
|
|
|
|
event := model.BeaconEvent{} |
|
|
|
|
|
for _, r := range adStructureIndeces { |
|
|
|
|
|
ad := b[r[0]:r[1]] |
|
|
|
|
|
if checkIngics(ad) { |
|
|
|
|
|
event = parseIngicsState(ad) |
|
|
|
|
|
event.ID = id |
|
|
|
|
|
event.Name = id |
|
|
|
|
|
break |
|
|
|
|
|
} else if checkEddystoneTLM(ad) { |
|
|
|
|
|
event = parseEddystoneState(ad) |
|
|
|
|
|
event.ID = id |
|
|
|
|
|
event.Name = id |
|
|
|
|
|
break |
|
|
|
|
|
} else if checkMinewB7(ad) { |
|
|
|
|
|
fmt.Println("Minew B7 vendor format") |
|
|
|
|
|
break |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if event.ID != "" { |
|
|
|
|
|
prevEvent, ok := appState.GetBeaconEvent(id) |
|
|
|
|
|
appState.UpdateBeaconEvent(id, event) |
|
|
|
|
|
if ok && bytes.Equal(prevEvent.Hash(), event.Hash()) { |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
eMsg, err := json.Marshal(event) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return err |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = writer.WriteMessages(context.Background(), kafka.Message{ |
|
|
|
|
|
Value: eMsg, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return err |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fmt.Println("Message sent") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func checkIngics(ad []byte) bool { |
|
|
|
|
|
if len(ad) >= 6 && |
|
|
|
|
|
ad[1] == 0xFF && |
|
|
|
|
|
ad[2] == 0x59 && |
|
|
|
|
|
ad[3] == 0x00 && |
|
|
|
|
|
ad[4] == 0x80 && |
|
|
|
|
|
ad[5] == 0xBC { |
|
|
|
|
|
return true |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
b = utils.RemoveFlagBytes(b) |
|
|
|
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
indeces := utils.ParseADFast(b) |
|
|
|
|
|
event := utils.LoopADStructures(b, indeces, id) |
|
|
|
|
|
|
|
|
func parseIngicsState(ad []byte) model.BeaconEvent { |
|
|
|
|
|
return model.BeaconEvent{ |
|
|
|
|
|
Battery: uint32(binary.LittleEndian.Uint16(ad[6:8])), |
|
|
|
|
|
Event: int(ad[8]), |
|
|
|
|
|
Type: "Ingics", |
|
|
|
|
|
|
|
|
if event.ID == "" { |
|
|
|
|
|
return nil |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func checkEddystoneTLM(ad []byte) bool { |
|
|
|
|
|
if len(ad) >= 4 && |
|
|
|
|
|
ad[1] == 0x16 && |
|
|
|
|
|
ad[2] == 0xAA && |
|
|
|
|
|
ad[3] == 0xFE && |
|
|
|
|
|
ad[4] == 0x20 { |
|
|
|
|
|
return true |
|
|
|
|
|
|
|
|
prevEvent, ok := appState.GetBeaconEvent(id) |
|
|
|
|
|
appState.UpdateBeaconEvent(id, event) |
|
|
|
|
|
if ok && bytes.Equal(prevEvent.Hash(), event.Hash()) { |
|
|
|
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func parseEddystoneState(ad []byte) model.BeaconEvent { |
|
|
|
|
|
return model.BeaconEvent{ |
|
|
|
|
|
Battery: uint32(binary.BigEndian.Uint16(ad[6:8])), |
|
|
|
|
|
Type: "Eddystone", |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// I dont think this is always true, but for testing is ok |
|
|
|
|
|
func checkMinewB7(ad []byte) bool { |
|
|
|
|
|
if len(ad) >= 4 && |
|
|
|
|
|
ad[1] == 0x16 && |
|
|
|
|
|
ad[2] == 0xE1 && |
|
|
|
|
|
ad[3] == 0xFF { |
|
|
|
|
|
return true |
|
|
|
|
|
|
|
|
eMsg, err := event.ToJSON() |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func ParseADFast(b []byte) [][2]int { |
|
|
|
|
|
var res [][2]int |
|
|
|
|
|
i := 0 |
|
|
|
|
|
|
|
|
|
|
|
for i < len(b) { |
|
|
|
|
|
l := int(b[i]) |
|
|
|
|
|
if l == 0 || i+1+l > len(b) { |
|
|
|
|
|
break |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
res = append(res, [2]int{i, i + 1 + l}) |
|
|
|
|
|
|
|
|
|
|
|
i += 1 + l |
|
|
|
|
|
|
|
|
if err := writer.WriteMessages(context.Background(), kafka.Message{Value: eMsg}); err != nil { |
|
|
|
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return res |
|
|
|
|
|
|
|
|
return nil |
|
|
} |
|
|
} |