mqttTask.lua 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. require "mqtt"
  2. module(..., package.seeall)
  3. -- 这里请填写华为云后台对接信息所展示的设备信息MQTT接入方式信息
  4. local host, port ="iot-mqtts.cn-north-4.myhuaweicloud.com", 1883
  5. --这里设置设备的device id和密钥,之前新建设备时得到的两个字符串
  6. --实际使用中,这两个值可以存在SN中,在生产时一个个烧录进去
  7. local device = "6063e66caaafca02d89db9bf_asd1234"
  8. local secret = "able6123"
  9. --同步NTP时间,因为鉴权需要用到UTC时间
  10. require"ntp"
  11. local function ntbcb(r)
  12. if r then
  13. sys.publish("NTP_OK")--时间同步完成后,发送命令,开始mqtt连接
  14. else
  15. ntp.timeSync(nil,ntbcb)
  16. end
  17. end
  18. ntp.timeSync(nil,ntbcb)--开始同步时间任务
  19. --此处参照华为云文档,生成连接时使用的密钥
  20. local function keyGenerate(key)
  21. local clk = os.date("*t",os.time()-3600*8)--获取UTC时间的table
  22. local timeStr = string.format("%02d%02d%02d%02d",clk.year,clk.month,clk.day,clk.hour)--时间戳
  23. local result = crypto.hmac_sha256(key,timeStr):lower()
  24. log.info("keyGenerate",timeStr,key,result)
  25. if crypto.hmac_sha256 then
  26. return result
  27. else
  28. log.error("crypto.hmac_sha256","please update your lod version, higher than 0034!")
  29. rtos.poweroff()
  30. end
  31. end
  32. --socket.setSendMode(1)
  33. -- 测试MQTT的任务代码
  34. sys.taskInit(function()
  35. sys.waitUntil("NTP_OK")--等待时间同步成功
  36. while true do
  37. while not socket.isReady() do sys.wait(1000) end
  38. local clk = os.date("*t",os.time()-3600*8)--获取UTC时间的table
  39. local mqttc = mqtt.client(
  40. device.."_0_0_"..string.format("%02d%02d%02d%02d",clk.year,clk.month,clk.day,clk.hour),--时间戳鉴权模式
  41. 300,
  42. device,
  43. keyGenerate(secret))
  44. while not mqttc:connect(host, port, "tcp_ssl",{caCert="hw.crt"}) do sys.wait(2000) end
  45. --topic订阅规则详细请见华为云文档:https://support.huaweicloud.com/api-IoT/iot_06_3008.html#ZH-CN_TOPIC_0172230104
  46. if mqttc:subscribe("/huawei/v1/devices/"..device.."/command/json") then
  47. while true do
  48. local r, data, param = mqttc:receive(120000, "pub_msg")
  49. if r then
  50. log.info("这是收到了服务器下发的消息:", data.payload or "nil")
  51. sys.publish("rev_msg",data.payload)--把收到的数据推送出去
  52. elseif data == "pub_msg" then
  53. log.info("这是收到了订阅的消息和参数显示:", param)
  54. --topic订阅规则详细请见华为云文档
  55. mqttc:publish("/huawei/v1/devices/"..device.."/data/json", param)
  56. elseif data == "timeout" then
  57. --等待超时,进行下一轮等待
  58. else
  59. break
  60. end
  61. end
  62. end
  63. mqttc:disconnect()
  64. end
  65. end)
  66. --接收到mqtt之后,对数据进行处理
  67. sys.subscribe("rev_msg",function(data)
  68. local t,r,e = json.decode(data)--解包收到的json数据,具体参考手册:https://support.huaweicloud.com/api-IoT/iot_06_3011.html
  69. if r and type(t)=="table" then
  70. log.info("receive.msgType",t.msgType)--表示平台下发的请求,固定值“cloudReq”
  71. log.info("receive.serviceId",t.serviceId)--设备服务的ID
  72. log.info("receive.cmd",t.cmd)--服务的命令名,参见profile的服务命令定义
  73. log.info("receive.mid",t.mid)--2字节无符号的命令id,平台内部分配(范围1-65535),设备命令响应平台时,需要返回该值
  74. if t.cmd == "testcmd" then--匹配上了之前写的cmd名称
  75. log.info("receive.paras.testControl",t.paras.testControl)
  76. local clk = os.date("*t",os.time()-3600*8)--获取UTC时间的table
  77. --组包回复用的json,具体参考手册:https://support.huaweicloud.com/api-IoT/iot_06_3012.html
  78. local reply = {
  79. msgType = "deviceRsp",--固定值“deviceRsp”,表示设备的应答消息
  80. mid = t.mid,--2字节无符号的命令ID,根据平台下发命令时的mid返回给平台。建议在消息中携带此参数
  81. errcode = 0,--请求处理的结果码。“0”表示成功。“1”表示失败
  82. body = {--命令的应答,具体字段由profile定义
  83. testReply = "done",--这是之前后台设置的那个
  84. }
  85. }
  86. sys.publish("pub_msg",json.encode(reply))--上报返回的报文
  87. --组包上报用的json,具体参考手册:https://support.huaweicloud.com/api-IoT/iot_06_3010.html
  88. local upload = {
  89. msgType = "deviceReq",--表示设备上报数据,固定值“deviceReq”
  90. data = {--一组服务的数据(具体结构参考下表ServiceData定义表),当需要上传批量数据时,可在该字段中添加数据
  91. {
  92. serviceId = "testServer",--设备服务的ID
  93. serviceData = {--一个服务的数据,具体字段在profile里定义
  94. testProperty = t.paras.testControl,--把刚刚下发的东西,上报上去
  95. },
  96. eventTime = string.format("%02d%02d%02d%02d%02d%02dZ",--设备采集数据UTC时间(格式:yyyyMMddTHHmmssZ)
  97. clk.year,clk.month,clk.day,clk.hour,clk.min,clk.sec)--时间戳
  98. },
  99. }
  100. }
  101. sys.publish("pub_msg",json.encode(upload))--上报返回的报文
  102. end
  103. else
  104. log.info("json.decode error",e)
  105. end
  106. end)