Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

105 řádky
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. fmt.Printf("registered beacon parser: %+v\n", b)
  49. p.ParserList = append(p.ParserList, b)
  50. }
  51. func (b *BeaconParser) Parse(ad []byte) (BeaconEvent, bool) {
  52. flag := false
  53. event := BeaconEvent{Type: b.Name}
  54. if cfg, ok := b.configs["battery"]; ok {
  55. event.Battery = uint32(b.extract(ad, cfg))
  56. flag = true
  57. }
  58. if cfg, ok := b.configs["accX"]; ok {
  59. event.AccX = int16(b.extract(ad, cfg))
  60. flag = true
  61. }
  62. if cfg, ok := b.configs["accY"]; ok {
  63. event.AccY = int16(b.extract(ad, cfg))
  64. flag = true
  65. }
  66. if cfg, ok := b.configs["accZ"]; ok {
  67. event.AccZ = int16(b.extract(ad, cfg))
  68. flag = true
  69. }
  70. return event, flag
  71. }
  72. func (b *BeaconParser) extract(ad []byte, pc ParserConfig) uint16 {
  73. if len(ad) < pc.Offset+pc.Length {
  74. return 0
  75. }
  76. data := ad[pc.Offset : pc.Offset+pc.Length]
  77. if pc.Length == 1 {
  78. return uint16(data[0])
  79. }
  80. return pc.GetOrder().Uint16(data)
  81. }
  82. func (c Config) GetPatternBytes() []byte {
  83. res := make([]byte, len(c.Pattern))
  84. for i, s := range c.Pattern {
  85. fmt.Sscanf(s, "0x%02x", &res[i])
  86. }
  87. return res
  88. }