airlbs.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. --[[
  2. @module airlbs
  3. @summary airlbs 定位服务(收费服务,需自行联系销售申请)
  4. @version 1.0
  5. @date 2024.11.01
  6. @author Dozingfiretruck
  7. @usage
  8. -- lbsloc 是异步回调接口,
  9. -- lbsloc2 是是同步接口。
  10. -- lbsloc比lbsloc2多了一个请求地址文本的功能。
  11. -- lbsloc 和 lbsloc2 都是免费LBS定位的实现方式;
  12. -- airlbs 扩展库是收费 LBS 的实现方式。
  13. ]]
  14. sys = require("sys")
  15. sysplus = require("sysplus")
  16. libnet = require "libnet"
  17. local airlbs_host = "airlbs.openluat.com"
  18. local airlbs_port = 12413
  19. local lib_name = "airlbs"
  20. local lib_topic = lib_name .. "topic"
  21. local location_data = 0
  22. local disconnect = -1
  23. local airlbs_timeout = 15000
  24. local airlbs = {}
  25. local function airlbs_task(task_name, buff, timeout, adapter)
  26. local netc = socket.create(nil, lib_name)
  27. socket.config(netc, adapter, true) -- udp
  28. sysplus.cleanMsg(lib_name)
  29. local result = libnet.connect(lib_name, 15000, netc, airlbs_host, airlbs_port)
  30. if result then
  31. log.info(lib_name, "服务器连上了")
  32. libnet.tx(lib_name, 0, netc, buff)
  33. else
  34. log.info(lib_name, "服务器没连上了!!!")
  35. sys.publish(lib_topic, disconnect)
  36. libnet.close(lib_name, 5000, netc)
  37. return
  38. end
  39. buff:del()
  40. while result do
  41. local succ, param = socket.rx(netc, buff)
  42. if not succ then
  43. log.error(lib_name, "服务器断开了", succ, param)
  44. sys.publish(lib_topic, disconnect)
  45. break
  46. end
  47. if buff:used() > 0 then
  48. local location = nil
  49. local data = buff:query(0, 1) -- 获取数据
  50. if data:toHex() == '00' then
  51. location = json.decode(buff:query(1))
  52. else
  53. log.error(lib_name, "not json data")
  54. end
  55. sys.publish(lib_topic, location_data, location)
  56. buff:del()
  57. break
  58. end
  59. result, param, param2 = libnet.wait(lib_name, timeout, netc)
  60. log.info(lib_name, "wait", result, param, param2)
  61. if param == false then
  62. log.error(lib_name, "服务器断开了", succ, param)
  63. sys.publish(lib_topic, disconnect)
  64. break
  65. end
  66. end
  67. libnet.close(lib_name, 5000, netc)
  68. end
  69. -- 处理未识别的网络消息
  70. local function netCB(msg)
  71. log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
  72. end
  73. --[[
  74. 获取定位数据
  75. @api airlbs.request(param)
  76. @param table 参数(联系销售获取id与key) project_id:项目ID project_key:项目密钥 timeout:超时时间,单位毫秒 默认15000 adapter: 网络适配器id,可选,默认是平台自带的网络协议栈
  77. @return bool 成功返回true,失败会返回false
  78. @return table 定位成功生效,成功返回定位数据
  79. @usage
  80. --注意:函数内因使用了sys.waitUntil阻塞接口,所以api需要在协程中使用
  81. --注意:使用前需同步时间
  82. local airlbs = require "airlbs"
  83. sys.taskInit(function()
  84. -- 等待网络就绪
  85. sys.waitUntil("IP_READY")
  86. -- 执行时间同步
  87. socket.sntp()
  88. sys.waitUntil("NTP_UPDATE", 10000)
  89. while 1 do
  90. -- airlbs请求定位
  91. local result ,data = airlbs.request({
  92. project_id = airlbs_project_id,
  93. project_key = airlbs_project_key,
  94. timeout = 10000,
  95. adapter = socket.LWIP_STA
  96. })
  97. if result then
  98. log.info("airlbs", json.encode(data))
  99. end
  100. sys.wait(20000)
  101. end
  102. end)
  103. ]]
  104. function airlbs.request(param)
  105. if not param or param.project_id == nil or param.project_key == nil then
  106. log.error(lib_name, "param error")
  107. return false
  108. end
  109. if not mobile and not param.wifi_info then
  110. log.error(lib_name, "no mobile and no wifi_info")
  111. return false
  112. end
  113. local udp_buff = zbuff.create(1500)
  114. local auth_type = 0x01
  115. local lbs_data_type = 0x00
  116. local project_id = param.project_id
  117. if project_id:len() ~= 6 then
  118. log.error("airlbs", "project_id len not 6")
  119. end
  120. local imei = mobile.imei()
  121. local muid = mobile.muid()
  122. local timestamp = os.time()
  123. local project_key = param.project_key
  124. local nonce = crypto.trng(6)
  125. local hmac_data = crypto.hmac_sha1(project_id .. imei .. muid .. timestamp .. nonce, project_key)
  126. -- log.debug(lib_name,"hmac_sha1", hmac_data)
  127. local lbs_data = {}
  128. if mobile then
  129. mobile.reqCellInfo(60)
  130. sys.waitUntil("CELL_INFO_UPDATE", param.timeout or airlbs_timeout)
  131. lbs_data.cells = {}
  132. -- log.info("cell", json.encode(mobile.getCellInfo()))
  133. for k, v in pairs(mobile.getCellInfo()) do
  134. lbs_data.cells[k] = {}
  135. lbs_data.cells[k][1] = v.mcc
  136. lbs_data.cells[k][2] = v.mnc
  137. lbs_data.cells[k][3] = v.tac
  138. lbs_data.cells[k][4] = v.cid
  139. lbs_data.cells[k][5] = v.rssi or v.rsrp
  140. lbs_data.cells[k][6] = v.snr
  141. lbs_data.cells[k][7] = v.pci
  142. lbs_data.cells[k][8] = v.rsrp
  143. lbs_data.cells[k][9] = v.rsrq
  144. lbs_data.cells[k][10] = v.earfcn
  145. end
  146. end
  147. if param.wifi_info and #param.wifi_info > 0 then
  148. lbs_data.macs = {}
  149. for k, v in pairs(param.wifi_info) do
  150. lbs_data.macs[k] = {}
  151. lbs_data.macs[k][1] = v.bssid:toHex():gsub("(%x%x)", "%1:"):sub(1, -2)
  152. lbs_data.macs[k][2] = v.rssi
  153. end
  154. end
  155. local lbs_jdata = json.encode(lbs_data)
  156. log.info("扫描出的数据",lbs_jdata)
  157. udp_buff:write(string.char(auth_type) .. project_id .. imei .. muid .. timestamp .. nonce .. hmac_data:fromHex() .. string.char(lbs_data_type) .. lbs_jdata)
  158. sysplus.taskInitEx(airlbs_task, lib_name, netCB, lib_name, udp_buff, param.timeout or airlbs_timeout, param.adapter)
  159. while 1 do
  160. local result, tp, data = sys.waitUntil(lib_topic, param.timeout or airlbs_timeout)
  161. log.info("定位请求的结果", result, "超时时间", tp, data)
  162. if not result then
  163. return false, "timeout"
  164. elseif tp == location_data then
  165. if not data then
  166. log.error(lib_name, "无数据, 请检查project_id和project_key")
  167. return false
  168. -- data.result 0-找不到 1-成功 2-qps超限 3-欠费 4-其他错误
  169. elseif data.result == 0 then
  170. log.error(lib_name, "no location(基站定位服务器查询当前地址失败)")
  171. return false
  172. elseif data.result == 1 then
  173. log.info("多基站请求成功,服务器返回的原始数据", data)
  174. return true, {
  175. lng = data.lng,
  176. lat = data.lat
  177. }
  178. elseif data.result == 2 then
  179. log.error(lib_name, "qps limit(当前请求已到达限制,请检查当前请求是否过于频繁))")
  180. return false
  181. elseif data.result == 3 then
  182. log.error(lib_name, "当前设备已欠费,请联系销售充值")
  183. return false
  184. elseif data.result == 4 then
  185. log.error(lib_name, "other error")
  186. return false
  187. else
  188. log.error("其他错误,错误码", data.result, lib_name)
  189. end
  190. else
  191. log.error(lib_name, "net error")
  192. return false
  193. end
  194. end
  195. end
  196. return airlbs