BxDataPack.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package bx
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. )
  6. type BxDataPack struct {
  7. WRAP_A5_NUM int
  8. WRAP_5A_NUM int
  9. dstAddr uint16
  10. srcAddr uint16
  11. r0 byte
  12. r1 byte
  13. r2 byte
  14. option byte
  15. crcMode byte
  16. dispMode byte
  17. deviceType byte
  18. version byte
  19. dataLen uint16
  20. data []byte
  21. crc uint16
  22. }
  23. func NewBxDataPackData(data []byte) BxDataPack {
  24. return BxDataPack{
  25. data: data,
  26. dataLen: uint16(len(data)),
  27. WRAP_A5_NUM: 8,
  28. WRAP_5A_NUM: 1,
  29. dstAddr: 0xfffe,
  30. srcAddr: 0x8000,
  31. deviceType: 0xfe,
  32. version: 0x02,
  33. }
  34. }
  35. func NewBxDataPackCmd(cmd BxCmd) BxDataPack {
  36. b := cmd.Build()
  37. return BxDataPack{
  38. data: b,
  39. dataLen: uint16(len(b)),
  40. WRAP_A5_NUM: 8,
  41. WRAP_5A_NUM: 1,
  42. dstAddr: 0x0002,
  43. srcAddr: 0x8000,
  44. deviceType: 0xfe,
  45. version: 0x02,
  46. }
  47. }
  48. // SetDispType 注:特殊动态区不支持动态模式
  49. // 0x00:普通模式,动态区与节目可同时显示,但各区域不可重叠。
  50. // 0x01:动态模式,优先显示动态区,无动态区则显示节目,动态区与节目区可重叠。
  51. func (dp *BxDataPack) SetDispType(typ byte) {
  52. dp.dispMode = typ
  53. }
  54. func (dp *BxDataPack) wrap(src []byte) []byte {
  55. len := len(src)
  56. for _, v := range src { //每次转义会使长度+1
  57. if v == 0xa5 || v == 0x5a || v == 0xa6 || v == 0x5b {
  58. len++
  59. }
  60. }
  61. len += dp.WRAP_5A_NUM
  62. len += dp.WRAP_A5_NUM
  63. dst := make([]byte, len)
  64. offset := 0
  65. for i := 0; i < dp.WRAP_A5_NUM; i++ {
  66. dst[offset] = 0xa5
  67. offset++
  68. }
  69. //转义
  70. for _, v := range src {
  71. if v == 0xa5 {
  72. dst[offset] = 0xa6
  73. offset++
  74. dst[offset] = 0xa2
  75. offset++
  76. } else if v == 0xa6 {
  77. dst[offset] = 0xa6
  78. offset++
  79. dst[offset] = 0xa1
  80. offset++
  81. } else if v == 0x5a {
  82. dst[offset] = 0x5b
  83. offset++
  84. dst[offset] = 0xa2
  85. offset++
  86. } else if v == 0x5b {
  87. dst[offset] = 0x5b
  88. offset++
  89. dst[offset] = 0x01
  90. offset++
  91. } else {
  92. dst[offset] = v
  93. offset++
  94. }
  95. }
  96. for i := 0; i < dp.WRAP_5A_NUM; i++ {
  97. dst[offset] = 0x5a
  98. offset++
  99. }
  100. return dst
  101. }
  102. func (dp *BxDataPack) Pack() []byte {
  103. w := bytes.NewBuffer(make([]byte, 0, 1024))
  104. //目标地址
  105. binary.Write(w, binary.LittleEndian, dp.dstAddr)
  106. //源地址
  107. binary.Write(w, binary.LittleEndian, dp.srcAddr)
  108. binary.Write(w, binary.LittleEndian, dp.r0)
  109. binary.Write(w, binary.LittleEndian, dp.r1)
  110. binary.Write(w, binary.LittleEndian, dp.r2)
  111. binary.Write(w, binary.LittleEndian, dp.option)
  112. binary.Write(w, binary.LittleEndian, dp.crcMode)
  113. binary.Write(w, binary.LittleEndian, dp.dispMode)
  114. binary.Write(w, binary.LittleEndian, dp.deviceType)
  115. binary.Write(w, binary.LittleEndian, dp.version)
  116. binary.Write(w, binary.LittleEndian, dp.dataLen)
  117. binary.Write(w, binary.LittleEndian, dp.data)
  118. dp.crc = 0x0
  119. binary.Write(w, binary.LittleEndian, dp.crc)
  120. data := w.Bytes()
  121. len := w.Len()
  122. dp.crc = CRC16(data, 0, len-2)
  123. data[len-2] = byte(dp.crc & 0xff)
  124. data[len-1] = byte(dp.crc >> 8)
  125. return dp.wrap(data)
  126. }
  127. func dpParse(src []byte, length int) *BxDataPack {
  128. dst := unwrap(src, length)
  129. if dst == nil {
  130. return nil
  131. }
  132. crcCalculated := CRC16(dst, 0, len(dst)-2)
  133. crcGot := bytesToUint16(dst, len(dst)-2, binary.LittleEndian)
  134. if crcCalculated != crcGot {
  135. return nil
  136. }
  137. dp := BxDataPack{}
  138. offset := 0
  139. //目标地址
  140. dp.dstAddr = bytesToUint16(dst, offset, binary.LittleEndian)
  141. offset += 2
  142. //源地址
  143. dp.srcAddr = bytesToUint16(dst, offset, binary.LittleEndian)
  144. offset += 2
  145. //保留字 r0,r1,r2
  146. dp.r0 = dst[offset]
  147. offset++
  148. dp.r1 = dst[offset]
  149. offset++
  150. dp.r2 = dst[offset]
  151. offset++
  152. dp.option = dst[offset]
  153. offset++
  154. dp.crcMode = dst[offset]
  155. offset++
  156. dp.dispMode = dst[offset]
  157. offset++
  158. dp.deviceType = dst[offset]
  159. offset++
  160. dp.version = dst[offset]
  161. offset++
  162. dp.dataLen = bytesToUint16(dst, offset, binary.LittleEndian)
  163. offset += 2
  164. //数据
  165. dp.data = dst[offset : offset+int(dp.dataLen)]
  166. offset += int(dp.dataLen)
  167. dp.crc = bytesToUint16(dst, offset, binary.LittleEndian)
  168. return &dp
  169. }
  170. func unwrap(src []byte, length int) []byte {
  171. len := length
  172. for _, v := range src {
  173. if v == 0xa5 || v == 0x5a || v == 0xa6 {
  174. len--
  175. }
  176. }
  177. //如果计算的帧长度为0, 说明数据不正确
  178. if len == 0 {
  179. return nil
  180. }
  181. dst := make([]byte, len)
  182. offset := 0
  183. for i := 0; i < length; {
  184. if src[i] == 0xa5 || src[i] == 0x5a {
  185. i++
  186. } else if src[i] == 0xa6 {
  187. if src[i+1] == 0x01 {
  188. dst[offset] = 0xa6
  189. offset++
  190. i = i + 2
  191. } else if src[i+1] == 0x02 {
  192. dst[offset] = 0xa5
  193. offset++
  194. i = i + 2
  195. } else {
  196. return nil
  197. }
  198. } else if src[i] == 0x5b {
  199. if src[i+1] == 0x01 {
  200. dst[offset] = 0x5b
  201. offset++
  202. i = i + 2
  203. } else if src[i+1] == 0x02 {
  204. dst[offset] = 0x5a
  205. offset++
  206. i = i + 2
  207. } else {
  208. return nil
  209. }
  210. } else {
  211. dst[offset] = src[i]
  212. offset++
  213. i++
  214. }
  215. }
  216. return dst
  217. }