|
- package model
-
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "sync"
- )
-
- type ParserConfig struct {
- Length int `json:"length"`
- Offset int `json:"offset"`
- Order string `json:"order"`
- }
-
- type BeaconParser struct {
- CanParse func([]byte) bool
- configs map[string]ParserConfig
- }
-
- type ParserRegistry struct {
- ParserList map[string]BeaconParser
- rw sync.RWMutex
- }
-
- type Config struct {
- Name string `json:"name" gorm:"primaryKey"`
- Min int `json:"min"`
- Max int `json:"max"`
- Pattern []string `json:"pattern" gorm:"serializer:json"`
- Configs map[string]ParserConfig `json:"configs" gorm:"serializer:json"`
- }
-
- type KafkaParser struct {
- ID string
- Name string
- Config Config
- }
-
- func (pc ParserConfig) GetOrder() any {
- if pc.Order == "fixedpoint" {
- return "fixedpoint"
- }
- if pc.Order == "bigendian" {
- return binary.BigEndian
- }
-
- return binary.LittleEndian
- }
-
- func (p *ParserRegistry) Register(name string, c Config) {
- p.rw.Lock()
- defer p.rw.Unlock()
-
- b := BeaconParser{
- CanParse: func(ad []byte) bool {
- if len(ad) < 2 {
- return false
- }
- return len(ad) >= c.Min && len(ad) <= c.Max && bytes.HasPrefix(ad[1:], c.GetPatternBytes())
- },
- configs: c.Configs,
- }
-
- p.ParserList[name] = b
- }
-
- func (p *ParserRegistry) Unregister(name string) {
- p.rw.Lock()
- delete(p.ParserList, name)
- p.rw.Unlock()
- }
-
- // TODO: change this to be dynamic, maybe event is interface with no predefined properties
- // or types
-
- func (b *BeaconParser) Parse(name string, ad []byte) (BeaconEvent, bool) {
- flag := false
- event := BeaconEvent{Type: name}
- fmt.Printf("parsing: %s\n", name)
- if cfg, ok := b.configs["battery"]; ok {
- event.Battery = uint32(b.extract(ad, cfg).(uint16))
- flag = true
- }
- if cfg, ok := b.configs["accX"]; ok {
- val := b.extract(ad, cfg).(float64)
- event.AccX = int16(val)
- flag = true
- }
- if cfg, ok := b.configs["accY"]; ok {
- val := b.extract(ad, cfg).(float64)
- event.AccY = int16(val)
- flag = true
- }
- if cfg, ok := b.configs["accZ"]; ok {
- val := b.extract(ad, cfg).(float64)
- event.AccZ = int16(val)
- flag = true
- }
- fmt.Printf("success: %s, event: %+v\n", flag, event)
- return event, flag
- }
-
- func (b *BeaconParser) extract(ad []byte, pc ParserConfig) any {
- if len(ad) < pc.Offset+pc.Length {
- return 0
- }
- data := ad[pc.Offset : pc.Offset+pc.Length]
-
- if pc.Length == 1 {
- return uint16(data[0])
- }
-
- order := pc.GetOrder()
- if order == "fixedpoint" {
- val := int16(data[0])<<8 | int16(data[1])
- return float64(val) / 256.0
- }
-
- o := order.(binary.ByteOrder)
- return o.Uint16(data)
- }
-
- func (c Config) GetPatternBytes() []byte {
- res := make([]byte, len(c.Pattern))
- for i, s := range c.Pattern {
- fmt.Sscanf(s, "0x%02x", &res[i])
- }
- return res
- }
|