Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

116 строки
2.4 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() binary.ByteOrder {
  34. if pc.Order == "bigendian" {
  35. return binary.BigEndian
  36. }
  37. return binary.LittleEndian
  38. }
  39. func (p *ParserRegistry) Register(name string, c Config) {
  40. p.rw.Lock()
  41. defer p.rw.Unlock()
  42. b := BeaconParser{
  43. CanParse: func(ad []byte) bool {
  44. if len(ad) < 2 {
  45. return false
  46. }
  47. return len(ad) >= c.Min && len(ad) <= c.Max && bytes.HasPrefix(ad[1:], c.GetPatternBytes())
  48. },
  49. configs: c.Configs,
  50. }
  51. p.ParserList[name] = b
  52. }
  53. func (p *ParserRegistry) Unregister(name string) {
  54. p.rw.Lock()
  55. delete(p.ParserList, name)
  56. p.rw.Unlock()
  57. }
  58. // TODO: change this to be dynamic, maybe event is interface with no predefined properties
  59. // or types
  60. func (b *BeaconParser) Parse(name string, ad []byte) (BeaconEvent, bool) {
  61. flag := false
  62. event := BeaconEvent{Type: name}
  63. if cfg, ok := b.configs["battery"]; ok {
  64. event.Battery = uint32(b.extract(ad, cfg))
  65. flag = true
  66. }
  67. if cfg, ok := b.configs["accX"]; ok {
  68. event.AccX = int16(b.extract(ad, cfg))
  69. flag = true
  70. }
  71. if cfg, ok := b.configs["accY"]; ok {
  72. event.AccY = int16(b.extract(ad, cfg))
  73. flag = true
  74. }
  75. if cfg, ok := b.configs["accZ"]; ok {
  76. event.AccZ = int16(b.extract(ad, cfg))
  77. flag = true
  78. }
  79. return event, flag
  80. }
  81. func (b *BeaconParser) extract(ad []byte, pc ParserConfig) uint16 {
  82. if len(ad) < pc.Offset+pc.Length {
  83. return 0
  84. }
  85. data := ad[pc.Offset : pc.Offset+pc.Length]
  86. if pc.Length == 1 {
  87. return uint16(data[0])
  88. }
  89. return pc.GetOrder().Uint16(data)
  90. }
  91. func (c Config) GetPatternBytes() []byte {
  92. res := make([]byte, len(c.Pattern))
  93. for i, s := range c.Pattern {
  94. fmt.Sscanf(s, "0x%02x", &res[i])
  95. }
  96. return res
  97. }