main.lua 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. -- LuaTools需要PROJECT和VERSION这两个信息
  2. PROJECT = "txiot_demo"
  3. VERSION = "1.0.0"
  4. -- sys库是标配
  5. _G.sys = require("sys")
  6. --[[特别注意, 使用mqtt库需要下列语句]]
  7. _G.sysplus = require("sysplus")
  8. -- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
  9. if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
  10. pm.power(pm.PWK_MODE, false)
  11. end
  12. -- 产品ID和产品动态注册秘钥
  13. local ProductId = "SU83PBK5YF"
  14. local ProductSecret = "DliTrlLmab4zo2FiZFNOyLsQ"
  15. local mqttc
  16. local mqtt_isssl = false
  17. --[[
  18. 函数名:getDeviceName
  19. 功能 :获取设备名称
  20. 参数 :无
  21. 返回值:设备名称
  22. ]]
  23. local function getDeviceName()
  24. --默认使用设备的IMEI作为设备名称,用户可以根据项目需求自行修改
  25. return mobile.imei()
  26. end
  27. function device_enrol()
  28. local deviceName = getDeviceName()
  29. local nonce = math.random(1, 100)
  30. local timestamp = os.time()
  31. local data = "deviceName=" .. deviceName .. "&nonce=" .. nonce .. "&productId=" ..
  32. ProductId .. "&timestamp=" .. timestamp
  33. local hmac_sha1_data = crypto.hmac_sha1(data, ProductSecret):lower()
  34. local signature = crypto.base64_encode(hmac_sha1_data)
  35. local tx_body = {
  36. productId = ProductId,
  37. deviceName = deviceName,
  38. nonce = nonce,
  39. timestamp = timestamp,
  40. signature = signature,
  41. }
  42. local tx_body_json = json.encode(tx_body)
  43. local code, headers, body = http.request("POST", "https://ap-guangzhou.gateway.tencentdevices.com/register/dev",
  44. {
  45. ["Content-Type"] = "application/json; charset=UTF-8",
  46. ["X-TC-Version"] = "2019-04-23",
  47. ["X-TC-Region"] = "ap-guangzhou"
  48. }, tx_body_json, { timeout = 30000 }).wait()
  49. log.info("http.post", code, headers, body)
  50. if code == 200 then
  51. local m, result, err = json.decode(body)
  52. log.info(" m,result,err", m, result, err)
  53. if result == 0 then
  54. log.info("json解析失败", err)
  55. device_enrol()
  56. end
  57. if m.message == "success" then
  58. log.info("腾讯云注册设备成功:", body)
  59. log.info("http.body.message", m.message)
  60. local result = io.writeFile("/txiot.dat", body)
  61. log.info("密钥写入结果", result)
  62. else
  63. log.info("腾讯云注册设备失败:失败原因", m.message)
  64. end
  65. else
  66. log.info("http请求失败:", body)
  67. end
  68. end
  69. sys.subscribe("MQTT_SIGN_AUTH", function(clientid, username, password)
  70. sys.taskInit(function()
  71. log.info("clientid,username,password", result, clientid, username, password, payload)
  72. local mqtt_host = ProductId .. ".iotcloud.tencentdevices.com"
  73. mqttc = mqtt.create(nil, mqtt_host, 1883, mqtt_isssl)
  74. mqttc:auth(clientid, username, password, false) -- client_id必填,其余选填
  75. mqttc:keepalive(300) -- 默认300s
  76. mqttc:autoreconn(true, 3000) -- 自动重连机制
  77. mqttc:on(function(mqtt_client, event, data, payload)
  78. -- 用户自定义代码
  79. log.info("mqtt", "event", event, mqtt_client, data, payload)
  80. if event == "conack" then
  81. log.info("mqtt", "sent", "pkgid", data)
  82. --连上了
  83. sys.publish("mqtt_conack")
  84. local txiot_subscribetopic = {
  85. ["$thing/down/property/" .. ProductId .. "/" .. getDeviceName()] = 0
  86. }
  87. mqtt_client:subscribe(txiot_subscribetopic)
  88. elseif event == "recv" then
  89. log.info("mqtt", "downlink", "topic", data, "payload", payload)
  90. --TODO:根据需求自行处理data.payload
  91. --sys.publish("mqtt_payload", data, payload)
  92. mqttc:publish("$thing/up/property/" .. ProductId .. "/" .. getDeviceName(),
  93. "publish from luat mqtt client",
  94. 0)
  95. elseif event == "sent" then
  96. log.info("mqtt", "sent", "pkgid", data)
  97. elseif event == "disconnect" then
  98. log.info("连接失败")
  99. -- --非自动重连时,按需重启mqttc
  100. -- mqtt_client:connect()
  101. end
  102. end)
  103. mqttc:connect()
  104. sys.waitUntil("mqtt_conack")
  105. while true do
  106. -- 如果没有其他task上报, 可以写个空等待
  107. sys.wait(60000000)
  108. end
  109. end)
  110. end)
  111. sys.subscribe("MQTT_CERT_AUTH", function() ---证书认证连接
  112. sys.taskInit(function()
  113. local clientid = ProductId .. getDeviceName()
  114. local connid = math.random(10000, 99999)
  115. log.info("connid类型", type(connid))
  116. local expiry = "32472115200"
  117. local username = string.format("%s;12010126;%s;%s", clientid, connid, expiry) --生成 MQTT 的 username 部分, 格式为 ${clientid};${sdkappid};${connid};${expiry}
  118. local password = 123 --证书认证不会验证password
  119. log.info("clientid1,username1,password1", clientid, username, password)
  120. local mqtt_host = ProductId .. ".iotcloud.tencentdevices.com"
  121. mqttc = mqtt.create(nil, mqtt_host, 8883,
  122. { server_cert = io.readFile("/luadb/ca.crt"),
  123. client_cert = io.readFile("/client.crt"),
  124. client_key = io.readFile("/client.key") })
  125. mqttc:auth(clientid, username, password) -- client_id必填,其余选填
  126. mqttc:keepalive(300) -- 默认值300s
  127. mqttc:autoreconn(true, 20000) -- 自动重连机制
  128. mqttc:on(function(mqtt_client, event, data, payload)
  129. -- 用户自定义代码
  130. log.info("mqtt", "event", event, mqtt_client, data, payload)
  131. if event == "conack" then
  132. log.info("mqtt", "sent", "pkgid", data)
  133. --连上了
  134. sys.publish("mqtt_conack")
  135. local txiot_subscribetopic = {
  136. ["$thing/down/property/" .. ProductId .. "/" .. getDeviceName()] = 0
  137. }
  138. mqtt_client:subscribe(txiot_subscribetopic)
  139. elseif event == "recv" then
  140. log.info("mqtt", "downlink", "topic", data, "payload", payload)
  141. --TODO:根据需求自行处理data.payload
  142. --sys.publish("mqtt_payload", data, payload)
  143. mqttc:publish("$thing/up/property/" .. ProductId .. "/" .. getDeviceName(),
  144. "publish from luat mqtt client",
  145. 0)
  146. elseif event == "sent" then
  147. log.info("mqtt", "sent", "pkgid", data)
  148. elseif event == "disconnect" then
  149. log.info("连接失败")
  150. -- --非自动重连时,按需重启mqttc
  151. -- mqtt_client:connect()
  152. end
  153. end)
  154. local result = mqttc:connect()
  155. log.info("connect.result", result)
  156. sys.waitUntil("mqtt_conack")
  157. while true do
  158. -- 如果没有其他task上报, 可以写个空等待
  159. sys.wait(60000000)
  160. end
  161. end)
  162. end)
  163. sys.taskInit(function()
  164. if mobile.status() ~= 1 and not sys.waitUntil("IP_READY", 600000) then
  165. log.info("网络初始化失败!")
  166. end
  167. log.info("io.exists", io.exists("/txiot.dat"))
  168. if not io.exists("/txiot.dat") then
  169. device_enrol()
  170. end
  171. local dat, result, err = json.decode(io.readFile("/txiot.dat"))
  172. log.info("dat,result,err", dat, result, err)
  173. if result == 0 then
  174. log.info("json解码失败", err)
  175. device_enrol() --解析失败重新下载文件
  176. local dat, result, err = json.decode(io.readFile("/txiot.dat"))
  177. end
  178. local payload = json.decode(crypto.cipher_decrypt("AES-128-CBC", "ZERO", crypto.base64_decode(dat.payload),
  179. string.sub(ProductSecret, 1, 16), "0000000000000000"))
  180. log.info("payload[encryptionType]", payload.encryptionType)
  181. log.info("payload[psk]", payload.psk)
  182. if payload.encryptionType == 2 then
  183. local clientid, username, password = iotauth.qcloud(ProductId, getDeviceName(), payload.psk)
  184. sys.publish("MQTT_SIGN_AUTH", clientid, username, password) --签名认证
  185. elseif payload.encryptionType == 1 then
  186. log.info("payload date ", payload.encryptionType, payload.psk, payload.clientCert, payload.clientKey)
  187. io.writeFile("/client.crt", payload.clientCert)
  188. io.writeFile("/client.key", payload.clientKey)
  189. sys.publish("MQTT_CERT_AUTH") --证书认证
  190. end
  191. end)
  192. -- 用户代码已结束---------------------------------------------
  193. -- 结尾总是这一句
  194. sys.run()
  195. -- sys.run()之后后面不要加任何语句!!!!!