Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

135 rindas
2.8 KiB

  1. package model
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "sync"
  7. )
  8. type ParserConfig struct {
  9. Length int `json:"length"`
  10. Offset int `json:"offset"`
  11. Order string `json:"order"`
  12. }
  13. type BeaconParser struct {
  14. CanParse func([]byte) bool
  15. configs map[string]ParserConfig
  16. }
  17. type ParserRegistry struct {
  18. ParserList map[string]BeaconParser
  19. rw sync.RWMutex
  20. }
  21. type Config struct {
  22. Name string `json:"name" gorm:"primaryKey"`
  23. Min int `json:"min"`
  24. Max int `json:"max"`
  25. Pattern []string `json:"pattern" gorm:"serializer:json"`
  26. Configs map[string]ParserConfig `json:"configs" gorm:"serializer:json"`
  27. }
  28. type KafkaParser struct {
  29. ID string
  30. Name string
  31. Config Config
  32. }
  33. func (pc ParserConfig) GetOrder() any {
  34. if pc.Order == "fixedpoint" {
  35. return "fixedpoint"
  36. }
  37. if pc.Order == "bigendian" {
  38. return binary.BigEndian
  39. }
  40. return binary.LittleEndian
  41. }
  42. func (p *ParserRegistry) Register(name string, c Config) {
  43. p.rw.Lock()
  44. defer p.rw.Unlock()
  45. b := BeaconParser{
  46. CanParse: func(ad []byte) bool {
  47. if len(ad) < 2 {
  48. return false
  49. }
  50. return len(ad) >= c.Min && len(ad) <= c.Max && bytes.HasPrefix(ad[1:], c.GetPatternBytes())
  51. },
  52. configs: c.Configs,
  53. }
  54. p.ParserList[name] = b
  55. }
  56. func (p *ParserRegistry) Unregister(name string) {
  57. p.rw.Lock()
  58. delete(p.ParserList, name)
  59. p.rw.Unlock()
  60. }
  61. // TODO: change this to be dynamic, maybe event is interface with no predefined properties
  62. // or types
  63. func (b *BeaconParser) Parse(name string, ad []byte) (BeaconEvent, bool) {
  64. flag := false
  65. event := BeaconEvent{Type: name}
  66. if cfg, ok := b.configs["battery"]; ok {
  67. event.Battery = uint32(b.extract(ad, cfg).(uint16))
  68. flag = true
  69. }
  70. if cfg, ok := b.configs["accX"]; ok {
  71. val := b.extract(ad, cfg).(float64)
  72. event.AccX = int16(val)
  73. flag = true
  74. }
  75. if cfg, ok := b.configs["accY"]; ok {
  76. val := b.extract(ad, cfg).(float64)
  77. event.AccY = int16(val)
  78. flag = true
  79. }
  80. if cfg, ok := b.configs["accZ"]; ok {
  81. val := b.extract(ad, cfg).(float64)
  82. event.AccZ = int16(val)
  83. flag = true
  84. }
  85. if cfg, ok := b.configs["temperature"]; ok {
  86. val := b.extract(ad, cfg).(float64)
  87. event.Temperature = uint16(val)
  88. flag = true
  89. }
  90. return event, flag
  91. }
  92. func (b *BeaconParser) extract(ad []byte, pc ParserConfig) any {
  93. if len(ad) < pc.Offset+pc.Length {
  94. return 0
  95. }
  96. data := ad[pc.Offset : pc.Offset+pc.Length]
  97. if pc.Length == 1 {
  98. return uint16(data[0])
  99. }
  100. order := pc.GetOrder()
  101. if order == "fixedpoint" {
  102. val := int16(data[0])<<8 | int16(data[1])
  103. return float64(val) / 256.0
  104. }
  105. o := order.(binary.ByteOrder)
  106. return o.Uint16(data)
  107. }
  108. func (c Config) GetPatternBytes() []byte {
  109. res := make([]byte, len(c.Pattern))
  110. for i, s := range c.Pattern {
  111. fmt.Sscanf(s, "0x%02x", &res[i])
  112. }
  113. return res
  114. }