air_gt808.lua 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. local moduleName = "air_jt808"
  2. local air_jt808 = {}
  3. local logSwitch = false
  4. local function logF(...)
  5. if logSwitch then
  6. log.info(moduleName, ...)
  7. end
  8. end
  9. -- 发送数据转义
  10. -- inData string
  11. -- 输出string
  12. local function msgEncode(inData)
  13. local oldString = string.char(0x7d)
  14. local newString = string.char(0x7d) .. string.char(0x01)
  15. inData = string.gsub(inData, oldString, newString)
  16. oldString = string.char(0x7e)
  17. newString = string.char(0x7d) .. string.char(0x02)
  18. inData = string.gsub(inData, oldString, newString)
  19. return oldString .. inData .. oldString
  20. end
  21. -- 接收数据转义,输入数据不能包含0x7e
  22. -- inData string型
  23. -- 输出string
  24. local function msgDecode(inData)
  25. local oldString = string.char(0x7d) .. string.char(0x02)
  26. local newString = string.char(0x7e)
  27. inData = string.gsub(inData, oldString, newString)
  28. oldString = string.char(0x7d) .. string.char(0x01)
  29. newString = string.char(0x7d)
  30. return string.gsub(inData, oldString, newString)
  31. end
  32. -- 接收包头解析
  33. -- inData string型
  34. -- 输出
  35. -- msgID 平台发送包的ID uint16_t
  36. -- msgSn 平台发送包的SN uint16_t
  37. -- simID 设备ID string
  38. -- msgBuf 数据体 string
  39. local function analyzeHead(inData)
  40. local msgID, msgSn, simID, msgLen, Len, i, msgBuf
  41. if type(inData) ~= "string" then
  42. return nil
  43. end
  44. Len = #inData
  45. msgID = api.BigBinToNum(string.sub(inData, 1, 2), 2)
  46. msgLen = api.BigBinToNum(string.sub(inData, 3, 4), 2)
  47. if msgLen ~= (Len - 12) then
  48. log.error(moduleName, "协议头长度不正确", msgLen, Len - 12)
  49. -- if msgLen ~= (Len - 13) then
  50. -- log.error(moduleName,"协议头长度不正确", msgLen, Len - 13)
  51. return nil
  52. end
  53. simID = string.sub(inData, 5, 10)
  54. msgSn = api.BigBinToNum(string.sub(inData, 11, 12), 2)
  55. msgBuf = string.sub(inData, 13, #inData)
  56. -- simID = string.sub(inData, 5, 11)
  57. -- msgSn = api.BigBinToNum(string.sub(inData, 12, 13), 2)
  58. -- msgBuf = string.sub(inData, 14, #inData)
  59. return msgID, msgSn, simID, msgBuf
  60. end
  61. -- 接收数据解析
  62. -- inData string型
  63. -- 输出
  64. -- packet 有效的接收包
  65. -- lastData 剩余数据
  66. local function analyzePacket(inData)
  67. local packet, lastData
  68. local matchByte = string.char(0x7e)
  69. local Pos = string.find(inData, matchByte)
  70. if Pos == nil then
  71. -- 找不到开始标识符
  72. return nil, nil
  73. end
  74. inData = string.sub(inData, Pos + 1, #inData)
  75. Pos = string.find(inData, matchByte)
  76. if Pos == nil then
  77. -- 找不到结束标识符
  78. return nil, inData
  79. end
  80. packet = string.sub(inData, 1, Pos - 1)
  81. lastData = string.sub(inData, Pos, #inData)
  82. return packet, lastData
  83. end
  84. -- 客户端接收解析
  85. function air_jt808.rxAnalyze(lastRxData)
  86. local lastRxMsgSn = 0
  87. local queue = {}
  88. local result, msgID, msgSn, msgBody, rxSimID, inData, packet, check
  89. logF("rxdata", #lastRxData, api.BinToHex(lastRxData, " "))
  90. packet = ""
  91. while true do
  92. if string.len(lastRxData) > 512 then
  93. logF("lastmsg len too long!!!")
  94. lastRxData = ""
  95. return lastRxData, queue
  96. end
  97. packet, lastRxData = analyzePacket(lastRxData)
  98. if packet then
  99. logF("packet", packet:toHex())
  100. end
  101. if lastRxData == nil then
  102. logF("lastmsg no start flag!!!")
  103. lastRxData = ""
  104. return lastRxData, queue
  105. end
  106. if packet and packet ~= "" then
  107. packet = msgDecode(packet)
  108. check = api.XorCheck(packet, #packet - 1)
  109. if string.byte(packet, #packet) == check then
  110. packet = string.sub(packet, 1, #packet - 1)
  111. msgID, msgSn, rxSimID, msgBody = analyzeHead(packet)
  112. if msgID ~= nil then
  113. table.insert(queue, {
  114. msgID = msgID,
  115. msgSn = msgSn,
  116. rxSimID = rxSimID,
  117. body = msgBody
  118. })
  119. end
  120. else
  121. logF("packet check error", string.byte(packet, #packet), check)
  122. end
  123. elseif not packet then
  124. return lastRxData, queue
  125. end
  126. end
  127. end
  128. -- 打包包头和校验码并转义,组织完数据体后,调用本函数打包后发送
  129. -- msgID uint16_t
  130. -- msgSn uint16_t
  131. -- simID string 6byte
  132. -- msgBody string
  133. -- 输出 string型,输出数据直接用于发送
  134. function air_jt808.air_jt808Head(msgID, msgSn, simID, msgBody)
  135. local inBuf, check, msgLen
  136. -- if #simID ~= 6 then
  137. -- log.info(moduleName, "simID len error", #simID)
  138. -- end
  139. if msgBody then
  140. msgLen = #msgBody
  141. inBuf = api.NumToBigBin(msgID, 2) .. api.NumToBigBin(msgLen, 2) .. simID .. api.NumToBigBin(msgSn, 2) .. msgBody
  142. else
  143. msgLen = 0
  144. inBuf = api.NumToBigBin(msgID, 2) .. api.NumToBigBin(msgLen, 2) .. simID .. api.NumToBigBin(msgSn, 2)
  145. end
  146. inBuf = inBuf .. string.char(api.XorCheck(inBuf))
  147. return msgEncode(inBuf)
  148. end
  149. -- 注册包数据体
  150. -- sProvinceID uint16_t
  151. -- sCityID uint16_t
  152. -- pFactoryID string 5byte
  153. -- pDeviceType string 20byte
  154. -- pDeviceID string 7byte
  155. -- uColor uint8_t
  156. -- pCarID string
  157. -- 输出 string型
  158. function air_jt808.makeRegMsg(sProvinceID, sCityID, pFactoryID, pDeviceType, pDeviceID, uColor, pCarID)
  159. local temp = string.rep("0", 40)
  160. temp = api.StrToBin(temp)
  161. if type(pFactoryID) ~= "string" or type(pDeviceType) ~= "string" or type(pDeviceID) ~= "string" or type(pCarID) ~= "string" then
  162. return nil
  163. end
  164. if #pFactoryID < 5 then
  165. pFactoryID = pFactoryID .. temp
  166. end
  167. if #pDeviceType < 20 then
  168. pDeviceType = pDeviceType .. temp
  169. end
  170. if #pDeviceID < 7 then
  171. pDeviceID = pDeviceID .. temp
  172. end
  173. return api.NumToBigBin(sProvinceID, 2) .. api.NumToBigBin(sCityID, 2) .. string.sub(pFactoryID, 1, 5) .. string.sub(pDeviceType, 1, 20) .. string.sub(pDeviceID, 1, 7) .. api.NumToBigBin(uColor, 1) .. pCarID
  174. end
  175. -- 设备应答包数据体
  176. -- lastRxMsgSn uint16_t
  177. -- lastRxMsgID uint16_t
  178. -- procResult uint8_t
  179. -- 输出 string型
  180. function air_jt808.makeResponseBody(lastRxMsgSn, lastRxMsgID, procResult)
  181. return api.NumToBigBin(lastRxMsgSn, 2) .. api.NumToBigBin(lastRxMsgID, 2) .. api.NumToBigBin(procResult, 1)
  182. end
  183. -- 透传包回复数据体
  184. -- text string
  185. -- 输出 string型
  186. function air_jt808.makeTransResponseBody(text)
  187. return api.NumToBigBin(0xFB, 1) .. text
  188. end
  189. -- 基本定位信息包数据体
  190. -- alarm uint32_t
  191. -- status uint32_t
  192. -- lat uint32_t
  193. -- lgt uint32_t
  194. -- high uint16_t
  195. -- speed uint16_t
  196. -- dir uint16_t
  197. -- dateTime string 6byte
  198. -- 输出 string型
  199. function air_jt808.makeLocatBaseInfoMsg(alarm, status, lat, lgt, high, speed, dir, dateTime)
  200. return api.NumToBigBin(alarm, 4) .. api.NumToBigBin(status, 4) .. api.NumToBigBin(lat, 4) .. api.NumToBigBin(lgt, 4) .. api.NumToBigBin(high, 2) .. api.NumToBigBin(speed, 2) .. api.NumToBigBin(dir, 2) .. dateTime
  201. end
  202. -- 参数包数据体
  203. -- lastRxMsgSn uint16_t
  204. -- paramNum uint8_t
  205. -- paramCode table uint16_t
  206. -- paramValue table string
  207. -- 输出 string型
  208. function air_jt808.makeParamBody(lastRxMsgSn, paramNum, paramCode, paramValue)
  209. local i, Buf
  210. Buf = api.NumToBigBin(lastRxMsgSn, 2) .. string.char(paramNum)
  211. for i = 1, paramNum do
  212. Buf = Buf .. api.NumToBigBin(paramCode[i], 2) .. string.char(string.len(paramValue[i])) .. paramValue[i]
  213. end
  214. return Buf
  215. end
  216. -- 平台应答包数据体解析
  217. -- inData string型
  218. -- 输出
  219. -- lastTxMsgSn 设备发送包的SN uint16_t
  220. -- lastTxMsgID 设备发送包的ID uint16_t
  221. -- procResult 处理结果 uint8_t
  222. function air_jt808.analyzeMonitorResopnse(inData)
  223. local lastTxMsgID, lastTxMsgSn, procResult
  224. if #inData < 5 then
  225. log.error(moduleName, "普通应答内容长度不对", #inData)
  226. return nil
  227. end
  228. lastTxMsgSn = api.BigBinToNum(string.sub(inData, 1, 2), 2)
  229. lastTxMsgID = api.BigBinToNum(string.sub(inData, 3, 4), 2)
  230. procResult = string.byte(inData, 5)
  231. return lastTxMsgSn, lastTxMsgID, procResult
  232. end
  233. -- 平台注册包数据体解析
  234. -- inData string型
  235. -- 输出
  236. -- lastTxMsgSn 设备发送包的SN uint16_t
  237. -- procResult 处理结果 uint8_t
  238. -- authCode 鉴权码 string
  239. function air_jt808.analyzeRegResopnse(inData)
  240. local lastTxMsgSn, procResult, authCode, Len
  241. Len = #inData
  242. if Len < 3 then
  243. log.error(moduleName, "注册应答长度不对", #inData)
  244. return nil, nil, nil
  245. end
  246. lastTxMsgSn = api.BigBinToNum(string.sub(inData, 1, 2), 2)
  247. procResult = string.byte(inData, 3)
  248. if procResult > 0 then
  249. return lastTxMsgSn, procResult, nil
  250. end
  251. authCode = string.sub(inData, 4, #inData)
  252. return lastTxMsgSn, procResult, authCode
  253. end
  254. -- 平台设备控制包数据体解析
  255. -- inData string型
  256. -- 输出
  257. -- procResult 处理结果 uint8_t
  258. function air_jt808.analyzeDeviceCtrl(inData)
  259. return string.byte(inData, 1)
  260. end
  261. -- 设备注册包数据体打包
  262. -- msgSn number型,
  263. -- simID string型
  264. -- 输出
  265. -- string 打包好的注册数据包
  266. function air_jt808.regPackage(msgSn, simID)
  267. local pTxBuf = air_jt808.makeRegMsg(0, 0, "", "", "", 0, string.char(0x00))
  268. return air_jt808.air_jt808Head(0x0100, msgSn, simID, pTxBuf)
  269. end
  270. -- 设备鉴权包数据体打包
  271. -- msgSn number型
  272. -- simID string型
  273. -- authCode string型
  274. -- 输出
  275. -- string 打包好的鉴权数据包
  276. function air_jt808.authPackage(msgSn, simID, authCode)
  277. return air_jt808.air_jt808Head(0x0102, msgSn, simID, authCode)
  278. end
  279. -- 设备心跳包数据体打包
  280. -- msgSn number型,
  281. -- simID string型
  282. -- 输出
  283. -- string 打包好的心跳数据包
  284. function air_jt808.heartPackage(msgSn, simID)
  285. return air_jt808.air_jt808Head(0x0002, msgSn, simID, nil)
  286. end
  287. -- 设备定位包数据体打包
  288. -- msgSn number型
  289. -- simID string型
  290. -- msgBody string型
  291. -- 输出
  292. -- string 打包好的位置数据包
  293. function air_jt808.positionPackage(msgSn, simID, msgBody)
  294. return air_jt808.air_jt808Head(0x0200, msgSn, simID, msgBody)
  295. end
  296. return air_jt808