| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- --- 模块功能:腾讯云平台
- -- @module txiot
- -- @author Dozingfiretruck
- -- @license MIT
- -- @copyright OpenLuat.com
- -- @release 2020.12.31
- module(...,package.seeall)
- require "ntp"
- require "misc"
- require "mqtt"
- require "utils"
- require "patch"
- require "socket"
- require "http"
- require "common"
- -- 产品ID和产品动态注册秘钥
- local ProductId = "5FCW79CXYD"
- local ProductSecret = "XOBuiSs4EUCjmP5NcFWrwdOe"
- local tx_mqttClient
- --[[
- 函数名:getDeviceName
- 功能 :获取设备名称
- 参数 :无
- 返回值:设备名称
- ]]
- local function getDeviceName()
- --默认使用设备的IMEI作为设备名称,用户可以根据项目需求自行修改
- return misc.getImei()
- end
- function txiot_publish()
- --sys.publish("APP_SOCKET_SEND_DATA")
- --mqtt发布主题
- tx_mqttClient:publish("$thing/up/property/"..ProductId.."/"..getDeviceName(), "publish from luat mqtt client", 0)
- end
- -- 无网络重启时间,飞行模式启动时间
- local rstTim, flyTim = 600000, 300000
- local enrol_end = false
- local mqtt_ready = false
- --- MQTT连接是否处于激活状态
- -- @return 激活状态返回true,非激活状态返回false
- -- @usage mqttTask.isReady()
- function isReady()
- return mqtt_ready
- end
- --- MQTT客户端数据接收处理
- -- @param mqttClient,MQTT客户端对象
- -- @return 处理成功返回true,处理出错返回false
- -- @usage mqttInMsg.proc(mqttClient)
- local function proc(mqttClient)
- local result,data
- while true do
- result,data = mqttClient:receive(120000,"APP_SOCKET_SEND_DATA")
- --接收到数据
- if result then
- log.info("mqttInMsg.proc",data.topic,string.toHex(data.payload))
- --TODO:根据需求自行处理data.payload
- else
- break
- end
- end
- return result or data=="timeout" or data=="APP_SOCKET_SEND_DATA"
- end
- local function cbFnc(result,prompt,head,body)
- log.info("testHttp.cbFnc",result,prompt,head,body)
- local dat, result, errinfo = json.decode(body)
- if result then
- if dat.code==0 then
- io.writeFile("/txiot.dat", body)
- log.info("腾讯云注册设备成功:", body)
- else
- log.info("腾讯云设备注册失败:", body)
- end
- enrol_end = true
- end
- end
- local function device_enrol()
- local deviceName = getDeviceName()
- local nonce = math.random(1,100)
- local timestamp = os.time()
- local data = "deviceName="..deviceName.."&nonce="..nonce.."&productId="..ProductId.."×tamp="..timestamp
- local hmac_sha1_data = crypto.hmac_sha1(data,#data,ProductSecret,#ProductSecret):lower()
- local signature = crypto.base64_encode(hmac_sha1_data,#hmac_sha1_data)
- local tx_body = {
- deviceName=deviceName,
- nonce=nonce,
- productId=ProductId,
- timestamp=timestamp,
- signature=signature,
- }
- local tx_body_json = json.encode(tx_body)
- http.request("POST","https://ap-guangzhou.gateway.tencentdevices.com/register/dev",nil,{["Content-Type"]="application/json; charset=UTF-8"},tx_body_json,30000,cbFnc)
- end
- local function tencent_iot()
- if not io.exists("/txiot.dat") then device_enrol() while not enrol_end do sys.wait(100) end end
- if not io.exists("/txiot.dat") then device_enrol() log.warn("设备注册失败或设备已注册") return end
- local dat = json.decode(io.readFile("/txiot.dat"))
- local clientid = ProductId .. getDeviceName() --生成 MQTT 的 clientid 部分, 格式为 ${productid}${devicename}
- local connid = math.random(10000,99999)
- local expiry = tostring(os.time() + 3600)
- local username = string.format("%s;12010126;%s;%s", clientid, connid, expiry) --生成 MQTT 的 username 部分, 格式为 ${clientid};${sdkappid};${connid};${expiry}
- local payload = json.decode(crypto.aes_decrypt("CBC","ZERO",crypto.base64_decode(dat.payload, #dat.payload),string.sub(ProductSecret,1,16),"0000000000000000"))
- local password
- if payload.encryptionType==2 then
- local raw_key = crypto.base64_decode(payload.psk, #payload.psk) --生成 MQTT 的 设备密钥 部分
- password = crypto.hmac_sha256(username, raw_key):lower() .. ";hmacsha256" --根据物联网通信平台规则生成 password 字段
- elseif payload.encryptionType==1 then
- io.writeFile("/client.crt", payload.clientCert)
- io.writeFile("/client.key", payload.clientKey)
- end
- while true do
- if not socket.isReady() and not sys.waitUntil("IP_READY_IND", rstTim) then sys.restart("网络初始化失败!") end
- --创建一个MQTT客户端
- tx_mqttClient = mqtt.client(clientid,300,username,password)
- --阻塞执行MQTT CONNECT动作,直至成功
- if payload.encryptionType==2 then
- while not tx_mqttClient:connect(ProductId..".iotcloud.tencentdevices.com",1883,"tcp",nil,2000) do sys.wait(2000) end
- elseif payload.encryptionType==1 then
- while not tx_mqttClient:connect(ProductId..".iotcloud.tencentdevices.com",8883,"tcp_ssl",{clientCert="/client.crt",clientKey="/client.key"},2000) do sys.wait(2000) end
- end
- log.info("mqtt连接成功")
- tx_mqttClient:publish("$thing/up/property/"..ProductId.."/"..getDeviceName(), "publish from luat mqtt client", 0)
- --mqtt订阅主题
- local txiot_subscribetopic = {
- ["$thing/down/property/"..ProductId.."/"..getDeviceName()]=0
- }
- --订阅主题
- if tx_mqttClient:subscribe(txiot_subscribetopic, nil) then
- log.info("mqtt订阅成功")
- --循环处理接收和发送的数据
- while true do
- mqtt_ready = true
- if not proc(tx_mqttClient) then log.error("mqttTask.mqttInMsg.proc error") break end
- end
- else
- log.info("mqtt订阅失败")
- end
- mqtt_ready = false
- --断开MQTT连接
- tx_mqttClient:disconnect()
- end
- end
- local function iot()
- ntp.timeSync()
- if not socket.isReady() and not sys.waitUntil("IP_READY_IND", rstTim) then sys.restart("网络初始化失败!") end
- while not ntp.isEnd() do sys.wait(1000) end
- tencent_iot()
- end
- net.switchFly(false)
- -- NTP同步失败强制重启
- local tid = sys.timerStart(function()
- net.switchFly(true)
- sys.timerStart(net.switchFly, 5000, false)
- end, flyTim)
- sys.subscribe("IP_READY_IND", function()
- sys.timerStop(tid)
- log.info("---------------------- 网络注册已成功 ----------------------")
- end)
- sys.taskInit(iot)
|