main.lua 9.0 KB

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