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

103 строки
2.1 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. Name string
  15. CanParse func([]byte) bool
  16. configs map[string]ParserConfig
  17. }
  18. type ParserRegistry struct {
  19. ParserList []BeaconParser
  20. rw sync.RWMutex
  21. }
  22. type Config struct {
  23. Name string `json:"name"`
  24. Min int `json:"min"`
  25. Max int `json:"max"`
  26. Pattern []string `json:"pattern"`
  27. Configs map[string]ParserConfig `json:"configs"`
  28. }
  29. func (pc ParserConfig) GetOrder() binary.ByteOrder {
  30. if pc.Order == "bigendian" {
  31. return binary.BigEndian
  32. }
  33. return binary.LittleEndian
  34. }
  35. func (p *ParserRegistry) Register(name string, c Config) {
  36. p.rw.Lock()
  37. defer p.rw.Unlock()
  38. b := BeaconParser{
  39. Name: name,
  40. CanParse: func(ad []byte) bool {
  41. if len(ad) < 2 {
  42. return false
  43. }
  44. return len(ad) >= c.Min && len(ad) <= c.Max && bytes.HasPrefix(ad[1:], c.GetPatternBytes())
  45. },
  46. configs: c.Configs,
  47. }
  48. p.ParserList = append(p.ParserList, b)
  49. }
  50. func (b *BeaconParser) Parse(ad []byte) (BeaconEvent, bool) {
  51. flag := false
  52. event := BeaconEvent{Type: b.Name}
  53. if cfg, ok := b.configs["battery"]; ok {
  54. event.Battery = uint32(b.extract(ad, cfg))
  55. flag = true
  56. }
  57. if cfg, ok := b.configs["accX"]; ok {
  58. event.AccX = int16(b.extract(ad, cfg))
  59. flag = true
  60. }
  61. if cfg, ok := b.configs["accY"]; ok {
  62. event.AccY = int16(b.extract(ad, cfg))
  63. flag = true
  64. }
  65. if cfg, ok := b.configs["accZ"]; ok {
  66. event.AccZ = int16(b.extract(ad, cfg))
  67. flag = true
  68. }
  69. return event, flag
  70. }
  71. func (b *BeaconParser) extract(ad []byte, pc ParserConfig) uint16 {
  72. if len(ad) < pc.Offset+pc.Length {
  73. return 0
  74. }
  75. data := ad[pc.Offset : pc.Offset+pc.Length]
  76. if pc.Length == 1 {
  77. return uint16(data[0])
  78. }
  79. return pc.GetOrder().Uint16(data)
  80. }
  81. func (c Config) GetPatternBytes() []byte {
  82. res := make([]byte, len(c.Pattern))
  83. for i, s := range c.Pattern {
  84. fmt.Sscanf(s, "0x%02x", &res[i])
  85. }
  86. return res
  87. }