No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

131 líneas
2.7 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. fmt.Printf("parsing: %s\n", name)
  67. if cfg, ok := b.configs["battery"]; ok {
  68. event.Battery = uint32(b.extract(ad, cfg).(uint16))
  69. flag = true
  70. }
  71. if cfg, ok := b.configs["accX"]; ok {
  72. val := b.extract(ad, cfg).(float64)
  73. event.AccX = int16(val)
  74. flag = true
  75. }
  76. if cfg, ok := b.configs["accY"]; ok {
  77. val := b.extract(ad, cfg).(float64)
  78. event.AccY = int16(val)
  79. flag = true
  80. }
  81. if cfg, ok := b.configs["accZ"]; ok {
  82. val := b.extract(ad, cfg).(float64)
  83. event.AccZ = int16(val)
  84. flag = true
  85. }
  86. fmt.Printf("success: %s, event: %+v\n", flag, event)
  87. return event, flag
  88. }
  89. func (b *BeaconParser) extract(ad []byte, pc ParserConfig) any {
  90. if len(ad) < pc.Offset+pc.Length {
  91. return 0
  92. }
  93. data := ad[pc.Offset : pc.Offset+pc.Length]
  94. if pc.Length == 1 {
  95. return uint16(data[0])
  96. }
  97. order := pc.GetOrder()
  98. if order == "fixedpoint" {
  99. val := int16(data[0])<<8 | int16(data[1])
  100. return float64(val) / 256.0
  101. }
  102. o := order.(binary.ByteOrder)
  103. return o.Uint16(data)
  104. }
  105. func (c Config) GetPatternBytes() []byte {
  106. res := make([]byte, len(c.Pattern))
  107. for i, s := range c.Pattern {
  108. fmt.Sscanf(s, "0x%02x", &res[i])
  109. }
  110. return res
  111. }