|
|
@@ -15,98 +15,105 @@ local libfota = require("libfota")
|
|
|
|
|
|
-- 总的库对象
|
|
|
local aliyun = {}
|
|
|
+local mqttc = nil
|
|
|
+
|
|
|
local ClientId,PassWord,UserName,SetClientidFnc,SetDeviceTokenFnc,SetDeviceSecretFnc
|
|
|
-local OutQueue =
|
|
|
-{
|
|
|
- SUBSCRIBE = {},
|
|
|
- PUBLISH = {},
|
|
|
-}
|
|
|
-local Item = {}
|
|
|
local EvtCb = {}
|
|
|
-local mqttc = nil
|
|
|
-local Key,Dname
|
|
|
+local opts = {}
|
|
|
|
|
|
---添加
|
|
|
-local function insert(type,topic,qos,payload,cbFnc,cbPara)
|
|
|
- table.insert(OutQueue[type],{t=topic,q=qos,p=payload,cb=cbFnc,para=cbPara})
|
|
|
+-------------------------------------------------------
|
|
|
+---- FOTA 相关
|
|
|
+-------------------------------------------------------
|
|
|
+-- fota的回调函数
|
|
|
+local function libfota_cb(result)
|
|
|
+ log.info("fota", "result", result)
|
|
|
+ -- fota成功
|
|
|
+ if result == 0 then
|
|
|
+ rtos.reboot()
|
|
|
+ end
|
|
|
end
|
|
|
-
|
|
|
---删除
|
|
|
-local function remove(type)
|
|
|
- if #OutQueue[type]>0 then return table.remove(OutQueue[type],1) end
|
|
|
+--收到云端固件升级通知消息时的回调函数
|
|
|
+local function aliyun_upgrade(payload)
|
|
|
+ local jsonData, result = json.decode(payload)
|
|
|
+ if result and jsonData.data and jsonData.data.url then
|
|
|
+ log.info("aliyun", "ota.url", jsonData.data.url)
|
|
|
+ libfota.request(EvtCb["ota"] or libfota_cb, jsonData.data.url)
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
---订阅步骤
|
|
|
-local function procSubscribe(client)
|
|
|
- local i
|
|
|
+-------------------------------------------------------
|
|
|
+--- 用户侧的回调处理
|
|
|
+-------------------------------------------------------
|
|
|
|
|
|
- for i=1,#OutQueue["SUBSCRIBE"] do
|
|
|
- if not client:subscribe(OutQueue["SUBSCRIBE"][i].t , OutQueue["SUBSCRIBE"][i].q) then
|
|
|
- OutQueue["SUBSCRIBE"] = {}
|
|
|
- return false,"procSubscribe"
|
|
|
- end
|
|
|
- end
|
|
|
- OutQueue["SUBSCRIBE"] = {}
|
|
|
- return true
|
|
|
-end
|
|
|
|
|
|
---发布
|
|
|
-local function procSend(client)
|
|
|
- if not procSubscribe(client) then
|
|
|
- return false,"procSubscribe"
|
|
|
- end
|
|
|
|
|
|
- if #OutQueue["PUBLISH"] == 0 then
|
|
|
- sys.waitUntil("ALIYUN_PUB")
|
|
|
- end
|
|
|
+--底层libMQTT回调函数,上层的回调函数,通过 aliyun.on注册
|
|
|
+local function mqtt_cbevent(mqtt_client, event, data, payload,metas)
|
|
|
+ log.debug("aliyun", "event", event, "data", data)
|
|
|
+ if event == "conack" then
|
|
|
+ log.info("aliyun", "conack")
|
|
|
+ -- if opts.ProductKey and opts.DeviceName then
|
|
|
+ aliyun.subscribe("/ota/device/upgrade/"..opts.ProductKey.."/"..opts.DeviceName,1)
|
|
|
+ aliyun.publish("/ota/device/inform/"..opts.ProductKey.."/"..opts.DeviceName,1,"{\"id\":1,\"params\":{\"version\":\"".._G.VERSION.."\"}}")
|
|
|
+ -- end
|
|
|
+ sys.publish("aliyun_conack")
|
|
|
+ if EvtCb["connect"] then
|
|
|
+ EvtCb["connect"](true)
|
|
|
+ end
|
|
|
+ elseif event == "recv" then -- 服务器下发的数据
|
|
|
+ log.debug("aliyun", "downlink", "topic", data, "payload", payload)
|
|
|
+ --OTA消息
|
|
|
+ if data =="/ota/device/upgrade/".. opts.ProductKey.."/".. opts.DeviceName then
|
|
|
+ aliyun_upgrade(payload)
|
|
|
+ end
|
|
|
|
|
|
- while #OutQueue["PUBLISH"] > 0 do
|
|
|
- Item = table.remove(OutQueue["PUBLISH"],1)
|
|
|
- local result = client:publish(Item.t,Item.p,Item.q)
|
|
|
- if type(result) == nil then
|
|
|
- if Item.cb then Item.cb(false,Item.para) end
|
|
|
- else
|
|
|
- local result, data = sys.waitUntil("PUB_SENT")
|
|
|
- if Item.cb then Item.cb(data,Item.para) end
|
|
|
+ if EvtCb["receive"] then
|
|
|
+ EvtCb["receive"](data, payload, metas.qos, metas.retain, metas.dup)
|
|
|
+ end
|
|
|
+ elseif event == "sent" then
|
|
|
+ log.info("aliyun", "sent", data)
|
|
|
+ if data then
|
|
|
+ sys.publish("aliyun_evt", "sent", data)
|
|
|
+ if EvtCb["publish"] then
|
|
|
+ EvtCb["publish"](data)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ elseif event == "disconnect" then
|
|
|
+ log.info("aliyun", "disconnect")
|
|
|
+ if EvtCb["connect"] then
|
|
|
+ EvtCb["connect"](false)
|
|
|
end
|
|
|
end
|
|
|
- return true,"procSend"
|
|
|
end
|
|
|
|
|
|
---二次连接
|
|
|
--- local function clientDataTask(ClientId,user,PassWord,mqtt_host,mqtt_port,mqtt_isssl,DeviceName,ProductKey)
|
|
|
-local function clientDataTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,passtoken,Registration)
|
|
|
- Key = ProductKey
|
|
|
- Dname = DeviceName
|
|
|
- sys.taskInit(function()
|
|
|
- if not Registration then
|
|
|
- local client_id,user_name,password = iotauth.aliyun(ProductKey,DeviceName,SetDeviceSecretFnc)
|
|
|
- mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl) --mqtt客户端创建
|
|
|
- mqttc:auth(client_id,user_name,password) --mqtt三元组配置
|
|
|
- else
|
|
|
- mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl) --mqtt客户端创建
|
|
|
- mqttc:auth(DeviceName,ProductKey,passtoken) --mqtt三元组配置
|
|
|
- end
|
|
|
+local function mqtt_task(mqtt_host, mqtt_port, mqtt_isssl, client_id, user_name, password)
|
|
|
+ mqttc = mqtt.create(nil,mqtt_host, mqtt_port, mqtt_isssl) --mqtt客户端创建
|
|
|
+ log.debug("aliyun", "mqtt三元组", client_id,user_name,password)
|
|
|
+ mqttc:auth(client_id,user_name,password) --mqtt三元组配置
|
|
|
|
|
|
- mqttc:keepalive(300) -- 默认值240s
|
|
|
- mqttc:autoreconn(true, 20000) -- 自动重连机制
|
|
|
- mqttc:on(mqtt_cbevent) --mqtt回调注册
|
|
|
- mqttc:connect()
|
|
|
-
|
|
|
- local conres = sys.waitUntil("aliyun_conack",30000)
|
|
|
- if mqttc:ready() and conres then
|
|
|
- -- if connectCb then connectCb(true,ProductKey,DeviceName) end
|
|
|
- -- if EvtCb["connect"] then EvtCb["connect"](true) end
|
|
|
+ mqttc:keepalive(300) -- 默认值240s
|
|
|
+ mqttc:autoreconn(true, 20000) -- 自动重连机制
|
|
|
+ mqttc:on(mqtt_cbevent) --mqtt回调注册
|
|
|
+ -- mqttc:debug(true)
|
|
|
+ mqttc:connect()
|
|
|
+end
|
|
|
|
|
|
- local result,prompt = procSubscribe(mqttc)
|
|
|
- if result then
|
|
|
- while true do
|
|
|
- procSend(mqttc)
|
|
|
- end
|
|
|
- end
|
|
|
+---------------------------------------------------
|
|
|
+--- 一型一密
|
|
|
+--------------------------------------------------
|
|
|
|
|
|
- -- if connectCb then connectCb(false,ProductKey,DeviceName) end
|
|
|
- -- if EvtCb["connect"] then EvtCb["connect"](false) end
|
|
|
+-- 二次连接, 也就是真正的连接
|
|
|
+local function clientDataTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,passtoken,Registration)
|
|
|
+ sys.taskInit(function()
|
|
|
+ if not Registration then -- 预注册
|
|
|
+ local client_id,user_name,password = iotauth.aliyun(opts.ProductKey, opts.DeviceName,SetDeviceSecretFnc)
|
|
|
+ -- mqttc = mqtt.create(nil,opts.mqtt_host, opts.mqtt_port, opts.mqtt_isssl) --mqtt客户端创建
|
|
|
+ -- mqttc:auth(client_id,user_name,password) --mqtt三元组配置
|
|
|
+ mqtt_task(mqtt_host or opts.mqtt_host, mqtt_port or opts.mqtt_port, mqtt_isssl or opts.mqtt_isssl, client_id, user_name, password)
|
|
|
+ else -- 免预注册
|
|
|
+ -- mqttc = mqtt.create(nil,opts.mqtt_host, opts.mqtt_port, opts.mqtt_isssl) --mqtt客户端创建
|
|
|
+ -- mqttc:auth(opts.DeviceName, opts.ProductKey, passtoken) --mqtt三元组配置
|
|
|
+ mqtt_task(mqtt_host or opts.mqtt_host, mqtt_port or opts.mqtt_port, mqtt_isssl or opts.mqtt_isssl, opts.DeviceName, opts.ProductKey, passtoken)
|
|
|
end
|
|
|
end)
|
|
|
end
|
|
|
@@ -116,216 +123,121 @@ local function directProc(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,R
|
|
|
if not Registration then
|
|
|
local ClientId = DeviceName.."|securemode=3,signmethod=hmacmd5,timestamp=789|"
|
|
|
local UserName = DeviceName.."&"..ProductKey
|
|
|
-
|
|
|
+
|
|
|
local content = "ClientId"..DeviceName.."deviceName"..DeviceName.."productKey"..ProductKey.."timestamp789"
|
|
|
local signKey= SetDeviceSecretFnc
|
|
|
PassWord = crypto.hmac_md5(content,signKey)
|
|
|
-
|
|
|
+
|
|
|
clientDataTask(ClientId,UserName,PassWord,mqtt_host,mqtt_port,mqtt_isssl,DeviceName,ProductKey)
|
|
|
else
|
|
|
local ClientId = SetClientidFnc.."|securemode=-2,authType=connwl|"
|
|
|
local UserName = DeviceName.."&"..ProductKey
|
|
|
local PassWord = SetDeviceTokenFnc
|
|
|
-
|
|
|
+
|
|
|
clientDataTask(ClientId,UserName,mqtt_host,mqtt_port,mqtt_isssl,PassWord,Registration)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
---获取预注册和免预注册一型一密一次连接返回的数据
|
|
|
+--获取一型一密的连接参数
|
|
|
local function clientEncryptionTask(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
|
|
|
- Key = ProductKey
|
|
|
- Dname = DeviceName
|
|
|
sys.taskInit(function()
|
|
|
- local tm = os.time()
|
|
|
- --一型一密
|
|
|
- --预注册
|
|
|
- if not Registration then
|
|
|
- ClientId = DeviceName.."|securemode=2,authType=register,random="..tm..",signmethod=hmacmd5|"
|
|
|
- --免预注册
|
|
|
+ --预注册
|
|
|
+ if not Registration then
|
|
|
+ ClientId = DeviceName.."|securemode=2,authType=register,random=123,signmethod=hmacmd5|"
|
|
|
+ --免预注册
|
|
|
+ else
|
|
|
+ if InstanceId and #InstanceId > 0 then
|
|
|
+ ClientId = DeviceName.."|securemode=-2,authType=regnwl,random=123,signmethod=hmacmd5,instanceId="..InstanceId.."|"
|
|
|
else
|
|
|
- ClientId = DeviceName.."|securemode=-2,authType=regnwl,random="..tm..",signmethod=hmacmd5,instanceId="..InstanceId.."|"
|
|
|
+ ClientId = DeviceName.."|securemode=-2,authType=regnwl,random=123,signmethod=hmacmd5|"
|
|
|
end
|
|
|
- UserName = DeviceName.."&"..ProductKey
|
|
|
- local content = "deviceName"..DeviceName.."productKey"..ProductKey.."random"..tm
|
|
|
- PassWord = crypto.hmac_md5(content,ProductSecret)
|
|
|
-
|
|
|
- local mqttClient = mqtt.create(nil,mqtt_host,mqtt_port, true) --客户端创建
|
|
|
- log.info("mqtt三元组", ClientId,UserName,PassWord)
|
|
|
- mqttClient:auth(ClientId,UserName,PassWord) --三元组配置
|
|
|
- mqttClient:on(function(mqtt_client, event, data, payload) --mqtt回调注册
|
|
|
- -- 用户自定义代码
|
|
|
- if event == "conack" then
|
|
|
- -- 无需订阅topic, 阿里云会主动下发通知
|
|
|
- elseif event == "recv" then
|
|
|
- log.info("mqtt", "downlink", "topic", data, "payload", payload)
|
|
|
- if payload then
|
|
|
- local tJsonDecode,res = json.decode(payload)
|
|
|
- if not Registration then
|
|
|
- --预注册
|
|
|
- if res and tJsonDecode["deviceName"] and tJsonDecode["deviceSecret"] then
|
|
|
-
|
|
|
- SetDeviceSecretFnc = tJsonDecode["deviceSecret"]
|
|
|
- mqttClient:disconnect()
|
|
|
- -- directProc(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,Registration)
|
|
|
- clientDataTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl)
|
|
|
+ end
|
|
|
+ local UserName = DeviceName.."&"..ProductKey
|
|
|
+ local content = "deviceName"..DeviceName.."productKey"..ProductKey.."random123"
|
|
|
+ local PassWord = crypto.hmac_md5(content, ProductSecret)
|
|
|
+
|
|
|
+ local mqttClient = mqtt.create(nil, mqtt_host, mqtt_port, true) --客户端创建
|
|
|
+ if mqttClient == nil then
|
|
|
+ log.error("aliyun", "一型一密要求固件支持TLS加密, 当前固件不支持!!!")
|
|
|
+ return
|
|
|
+ end
|
|
|
+ log.debug("aliyun", "一型一密认证三元组", ClientId, UserName, PassWord)
|
|
|
+ mqttClient:auth(ClientId,UserName,PassWord) --三元组配置
|
|
|
+ mqttClient:autoreconn(true, 30000)
|
|
|
+ local flag = true
|
|
|
+ mqttClient:on(function(mqtt_client, event, data, payload) --mqtt回调注册
|
|
|
+ if event == "recv" then
|
|
|
+ -- 无需订阅topic, 阿里云会主动下发通知
|
|
|
+ log.info("aliyun", "downlink", "topic", data, "payload", payload)
|
|
|
+ if payload then
|
|
|
+ local tJsonDecode,res = json.decode(payload)
|
|
|
+ if not Registration then
|
|
|
+ --预注册
|
|
|
+ if res and tJsonDecode["deviceName"] and tJsonDecode["deviceSecret"] then
|
|
|
+ SetDeviceSecretFnc = tJsonDecode["deviceSecret"]
|
|
|
+ log.debug("aliyun", "一型一密(预注册)", tJsonDecode["deviceName"], SetDeviceSecretFnc)
|
|
|
+ if EvtCb["reg"] then
|
|
|
+ EvtCb["reg"](tJsonDecode)
|
|
|
+ else
|
|
|
+ aliyun.store(tJsonDecode)
|
|
|
end
|
|
|
- else
|
|
|
- --免预注册
|
|
|
- if res and tJsonDecode["deviceName"] and tJsonDecode["deviceToken"] then
|
|
|
- SetDeviceTokenFnc = tJsonDecode["deviceToken"]
|
|
|
- SetClientidFnc = tJsonDecode["clientId"]
|
|
|
- mqttClient:disconnect()
|
|
|
- directProc(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,Registration)
|
|
|
+ mqttClient:autoreconn(false)
|
|
|
+ mqttClient:disconnect()
|
|
|
+ flag = false
|
|
|
+ clientDataTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl)
|
|
|
+ end
|
|
|
+ else
|
|
|
+ --免预注册
|
|
|
+ if res and tJsonDecode["deviceName"] and tJsonDecode["deviceToken"] then
|
|
|
+ SetDeviceTokenFnc = tJsonDecode["deviceToken"]
|
|
|
+ SetClientidFnc = tJsonDecode["clientId"]
|
|
|
+ log.debug("aliyun", "一型一密(免预注册)", SetClientidFnc, SetDeviceTokenFnc)
|
|
|
+ if EvtCb["reg"] then
|
|
|
+ EvtCb["reg"](tJsonDecode)
|
|
|
+ else
|
|
|
+ aliyun.store(tJsonDecode)
|
|
|
end
|
|
|
+ mqttClient:autoreconn(false)
|
|
|
+ mqttClient:disconnect()
|
|
|
+ flag = false
|
|
|
+ directProc(DeviceName, ProductKey, mqtt_host, mqtt_port, mqtt_isssl, Registration)
|
|
|
end
|
|
|
-
|
|
|
end
|
|
|
- elseif event == "sent" then
|
|
|
- log.info("mqtt", "sent", "pkgid", data)
|
|
|
end
|
|
|
- end)
|
|
|
-
|
|
|
- mqttClient:connect()
|
|
|
- end)
|
|
|
-end
|
|
|
-
|
|
|
-
|
|
|
---底层libMQTT回调函数,上层的回调函数,通过 aliyun.on注册
|
|
|
-function mqtt_cbevent(mqtt_client, event, data, payload,metas)
|
|
|
- if event == "conack" then
|
|
|
- sys.publish("aliyun_conack")
|
|
|
- EvtCb["connect"](true)
|
|
|
- elseif event == "recv" then -- 服务器下发的数据
|
|
|
- log.info("mqtt", "downlink", "topic", data, "payload", payload,"qos",metas.qos,"retain",metas.retain,"dup",metas.dup)
|
|
|
-
|
|
|
- log.info("aliyun.procReceive",data,string.toHex(payload))
|
|
|
- --OTA消息
|
|
|
- if data =="/ota/device/upgrade/"..Key.."/"..Dname then
|
|
|
- if upgrade then
|
|
|
- upgrade(payload)
|
|
|
end
|
|
|
+ end)
|
|
|
+ mqttClient:connect()
|
|
|
+ while flag do
|
|
|
+ sys.wait(1000)
|
|
|
end
|
|
|
-
|
|
|
- if EvtCb["receive"] then
|
|
|
- EvtCb["receive"](data, payload,metas.qos,metas.retain,metas.dup)
|
|
|
- end
|
|
|
- elseif event == "sent" then
|
|
|
- if type(data) == "number" then
|
|
|
- sys.publish("PUB_SENT",true)
|
|
|
- end
|
|
|
-
|
|
|
- elseif event == "disconnect" then
|
|
|
- log.info("mqtt", "disconnect")
|
|
|
-
|
|
|
- sys.publish("PUB_SENT",false)
|
|
|
-
|
|
|
- if EvtCb["connect"] then
|
|
|
- EvtCb["connect"](false)
|
|
|
- end
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-
|
|
|
---[[
|
|
|
-配置阿里云物联网套件的产品信息和设备信息
|
|
|
-@api aliyun.setup(tPara)
|
|
|
-@table 阿里云物联网套件的产品信息和设备信息
|
|
|
-@return nil
|
|
|
-@usage
|
|
|
-aliyun.setup(tPara)
|
|
|
--- 参数说明
|
|
|
-一机一密认证方案时,ProductSecret参数传入nil
|
|
|
-一型一密认证方案时,ProductSecret参数传入真实的产品密钥
|
|
|
-Registration 是否是预注册 已预注册为false,未预注册为true
|
|
|
-DeviceName 设备名称
|
|
|
-ProductKey 产品key
|
|
|
-ProductSecret 产品secret,根据此信息判断是一机一密还是一型一密
|
|
|
-DeviceSecret 设备secret
|
|
|
-InstanceId 如果没有注册需要填写实例id,在实例详情页面
|
|
|
-mqtt_port mqtt端口
|
|
|
-mqtt_isssl 是否使用ssl加密连接,true为无证书最简单的加密
|
|
|
-]]
|
|
|
-function aliyun.setup(tPara)
|
|
|
- mqtt_host = tPara.host or tPara.InstanceId..".mqtt.iothub.aliyuncs.com"
|
|
|
- if tPara.ProductSecret == "" or tPara.ProductSecret == nil then
|
|
|
- confiDentialTask(tPara.DeviceName,tPara.ProductKey,tPara.DeviceSecret,mqtt_host,tPara.mqtt_port,tPara.mqtt_isssl)
|
|
|
- else
|
|
|
- clientEncryptionTask(tPara.Registration,tPara.DeviceName,tPara.ProductKey,tPara.ProductSecret,tPara.InstanceId,mqtt_host,tPara.mqtt_port,tPara.mqtt_isssl)
|
|
|
- end
|
|
|
+ end)
|
|
|
end
|
|
|
|
|
|
---一机一密连接 confiDentialTask
|
|
|
-function confiDentialTask(DeviceName,ProductKey,DeviceSecret,mqtt_host,mqtt_port,mqtt_isssl)
|
|
|
- Key = ProductKey
|
|
|
- Dname = DeviceName
|
|
|
+---------------------------------------------
|
|
|
+-- 一机一密
|
|
|
+---------------------------------------------
|
|
|
+local function confiDentialTask()
|
|
|
sys.taskInit(function()
|
|
|
- local client_id,user_name,password = iotauth.aliyun(ProductKey,DeviceName,DeviceSecret)
|
|
|
- mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl) --mqtt客户端创建
|
|
|
- log.info("mqtt三元组", client_id,user_name,password)
|
|
|
- mqttc:auth(client_id,user_name,password) --mqtt三元组配置
|
|
|
-
|
|
|
-
|
|
|
- mqttc:keepalive(300) -- 默认值240s
|
|
|
- mqttc:autoreconn(true, 20000) -- 自动重连机制
|
|
|
- mqttc:connect()
|
|
|
- mqttc:on(mqtt_cbevent) --mqtt回调注册
|
|
|
-
|
|
|
- local conres = sys.waitUntil("aliyun_conack",30000)
|
|
|
- if mqttc:ready() and conres then
|
|
|
- -- if connectCb then connectCb(true,ProductKey,DeviceName) end
|
|
|
- -- if EvtCb["connect"] then EvtCb["connect"](true) end
|
|
|
-
|
|
|
- local result,prompt = procSubscribe(mqttc)
|
|
|
- if result then
|
|
|
- while true do
|
|
|
- procSend(mqttc)
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- -- if connectCb then connectCb(false,ProductKey,DeviceName) end
|
|
|
- -- if EvtCb["connect"] then EvtCb["connect"](false) end
|
|
|
- end
|
|
|
+ local client_id,user_name,password = iotauth.aliyun(opts.ProductKey, opts.DeviceName, opts.DeviceSecret)
|
|
|
+ mqtt_task(opts.mqtt_host, opts.mqtt_port, opts.mqtt_isssl, client_id, user_name, password)
|
|
|
end)
|
|
|
end
|
|
|
|
|
|
|
|
|
---正常连接 预注册一型一密获取DeviceSecret后就是正常的一机一密连接
|
|
|
+--正常连接 预注册一型一密获取DeviceSecret后就是正常的一机一密连接
|
|
|
function aliyun.clientGetDirectDataTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,Registration,DeviceSecret,deviceToken,cid)
|
|
|
- Key = ProductKey
|
|
|
- Dname = DeviceName
|
|
|
sys.taskInit(function()
|
|
|
if not Registration then
|
|
|
local client_id,user_name,password = iotauth.aliyun(ProductKey,DeviceName,DeviceSecret)
|
|
|
- mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl) --mqtt客户端创建
|
|
|
- mqttc:auth(client_id,user_name,password) --mqtt三元组配置
|
|
|
+ -- mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl) --mqtt客户端创建
|
|
|
+ -- mqttc:auth(client_id,user_name,password) --mqtt三元组配置
|
|
|
+ mqtt_task(mqtt_host, mqtt_port,mqtt_isssl, client_id, user_name, password)
|
|
|
else
|
|
|
local clientId = cid.."|securemode=-2,authType=connwl|"
|
|
|
-
|
|
|
local client_id,user_name,password = iotauth.aliyun(ProductKey,DeviceName,deviceToken)
|
|
|
- mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl) --mqtt客户端创建
|
|
|
-
|
|
|
- mqttc:auth(clientId,user_name,deviceToken) --mqtt三元组配置
|
|
|
- end
|
|
|
-
|
|
|
- mqttc:keepalive(30) -- 默认值240s
|
|
|
- mqttc:autoreconn(true, 20000) -- 自动重连机制
|
|
|
- mqttc:connect()
|
|
|
- mqttc:on(mqtt_cbevent) --mqtt回调注册
|
|
|
-
|
|
|
- local conres = sys.waitUntil("aliyun_conack",30000)
|
|
|
- if mqttc:ready() and conres then
|
|
|
- -- if connectCb then connectCb(true,ProductKey,DeviceName) end
|
|
|
- -- if EvtCb["connect"] then EvtCb["connect"](true) end
|
|
|
-
|
|
|
- local result,prompt = procSubscribe(mqttc)
|
|
|
- if result then
|
|
|
- while true do
|
|
|
- procSend(mqttc)
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- -- if connectCb then connectCb(false,ProductKey,DeviceName) end
|
|
|
- -- if EvtCb["connect"] then EvtCb["connect"](false) end
|
|
|
+ -- mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl) --mqtt客户端创建
|
|
|
+ -- mqttc:auth(clientId, user_name, deviceToken) --mqtt三元组配置
|
|
|
+ mqtt_task(mqtt_host, mqtt_port,mqtt_isssl, clientId, user_name, deviceToken)
|
|
|
end
|
|
|
end)
|
|
|
end
|
|
|
@@ -335,13 +247,15 @@ end
|
|
|
订阅主题
|
|
|
@api aliyun.subscribe(topic,qos)
|
|
|
@string 主题内容为UTF8编码
|
|
|
-@number qos为number类型(0/1,默认0)
|
|
|
+@number qos为number类型(0/1,默认1)
|
|
|
@return nil
|
|
|
@usage
|
|
|
-aliyun.subscribe("/b0FMK1Ga5cp/862991234567890/get", 0)
|
|
|
+aliyun.subscribe("/b0FMK1Ga5cp/862991234567890/get", 1)
|
|
|
]]
|
|
|
function aliyun.subscribe(topic,qos)
|
|
|
- insert("SUBSCRIBE",topic,qos)
|
|
|
+ if mqttc and mqttc:ready() then
|
|
|
+ mqttc:subscribe(topic,qos or 1)
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
|
|
|
@@ -359,8 +273,30 @@ aliyun.publish("/b0FMK1Ga5cp/862991234567890/update",0,"test")
|
|
|
aliyun.publish("/b0FMK1Ga5cp/862991234567890/update",1,"test",cbFnc,"cbFncPara")
|
|
|
]]
|
|
|
function aliyun.publish(topic,qos,payload,cbFnc,cbPara)
|
|
|
- insert("PUBLISH",topic,qos,payload,cbFnc,cbPara)
|
|
|
- sys.publish("ALIYUN_PUB")
|
|
|
+ if mqttc and mqttc:ready() then
|
|
|
+ local pkgid = mqttc:publish(topic, payload, qos)
|
|
|
+ if cbFnc then
|
|
|
+ if pkgid then
|
|
|
+ sys.taskInit(function()
|
|
|
+ local timeout = 15000
|
|
|
+ while timeout > 0 do
|
|
|
+ local result, evt, tmp = sys.waitUntil("aliyun_evt", 1000)
|
|
|
+ -- log.debug("aliyun", "等待publish的sent事件", result, evt, tmp)
|
|
|
+ if evt == "sent" and pkgid == tmp then
|
|
|
+ cbFnc(true, cbPara)
|
|
|
+ return
|
|
|
+ end
|
|
|
+ timeout = timeout - 1000
|
|
|
+ end
|
|
|
+ cbFnc(false, cbPara)
|
|
|
+ end)
|
|
|
+ else
|
|
|
+ cbFnc(true, cbPara)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ else
|
|
|
+ cbFnc(false, cbPara)
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
|
|
|
@@ -413,32 +349,114 @@ end
|
|
|
|
|
|
|
|
|
|
|
|
+--[[
|
|
|
+配置阿里云物联网套件的产品信息和设备信息
|
|
|
+@api aliyun.setup(tPara)
|
|
|
+@table 阿里云物联网套件的产品信息和设备信息
|
|
|
+@return nil
|
|
|
+@usage
|
|
|
+aliyun.setup(tPara)
|
|
|
+-- 参数说明
|
|
|
+一机一密认证方案时,ProductSecret参数传入nil
|
|
|
+一型一密认证方案时,ProductSecret参数传入真实的产品密钥
|
|
|
+Registration 是否是预注册 已预注册为false,未预注册为true
|
|
|
+DeviceName 设备名称
|
|
|
+ProductKey 产品key
|
|
|
+ProductSecret 产品secret,根据此信息判断是一机一密还是一型一密
|
|
|
+DeviceSecret 设备secret
|
|
|
+InstanceId 如果没有注册需要填写实例id,在实例详情页面
|
|
|
+mqtt_port mqtt端口
|
|
|
+mqtt_isssl 是否使用ssl加密连接,true为无证书最简单的加密
|
|
|
+]]
|
|
|
+function aliyun.setup(tPara)
|
|
|
+ opts = tPara
|
|
|
+ aliyun.opts = opts
|
|
|
+ if not opts.mqtt_host then
|
|
|
+ if opts.host then
|
|
|
+ opts.mqtt_host = opts.host
|
|
|
+ elseif tPara.InstanceId and #tPara.InstanceId > 0 then
|
|
|
+ opts.mqtt_host = tPara.InstanceId..".mqtt.iothub.aliyuncs.com"
|
|
|
+ else
|
|
|
+ opts.mqtt_host = tPara.ProductKey .. ".iot-as-mqtt."..tPara.RegionId..".aliyuncs.com"
|
|
|
+ end
|
|
|
+ end
|
|
|
+ -- log.debug("aliyun", "mqtt host", opts.mqtt_host)
|
|
|
+ if not tPara.ProductSecret or #tPara.ProductSecret == 0 then
|
|
|
+ log.info("aliyun", "一机一密模式")
|
|
|
+ confiDentialTask()
|
|
|
+ else
|
|
|
+ log.info("aliyun", string.format("一型一密(%s)模式 - %s", tPara.Registration and "预注册" or "免预注册", tPara.reginfo and "已获取注册信息" or "开始获取注册信息"))
|
|
|
+ if tPara.reginfo then
|
|
|
+ aliyun.clientGetDirectDataTask(tPara.DeviceName,tPara.ProductKey, opts.mqtt_host, 1883, tPara.mqtt_isssl,
|
|
|
+ tPara.Registration,
|
|
|
+ tPara.deviceSecret, tPara.deviceToken, tPara.clientId)
|
|
|
+ else
|
|
|
+ clientEncryptionTask(tPara.Registration,tPara.DeviceName,tPara.ProductKey,tPara.ProductSecret,tPara.InstanceId, opts.mqtt_host, 1883,tPara.mqtt_isssl)
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
|
|
|
-
|
|
|
---收到云端固件升级通知消息时的回调函数
|
|
|
-function upgrade(payload)
|
|
|
- local result
|
|
|
- local jsonData,result = json.decode(payload)
|
|
|
- if result and jsonData.data and jsonData.data.url then
|
|
|
- -- sys.taskInit(downloadTask,jsonData.data.url,jsonData.data.size,jsonData.data.md5,jsonData.data.version)
|
|
|
- libfota.request(libfota_cb,jsonData.data.url)
|
|
|
+--[[
|
|
|
+判断阿里云物联网套件是否已经连接
|
|
|
+@api aliyun.ready()
|
|
|
+@return boolean 阿里云物联网套件是否已经连接
|
|
|
+@usage
|
|
|
+-- 本函数于2024.6.17新增
|
|
|
+if aliyun.ready() then
|
|
|
+ log.info("aliyun", "已连接")
|
|
|
+end
|
|
|
+]]
|
|
|
+function aliyun.ready()
|
|
|
+ if mqttc and mqttc:ready() then
|
|
|
+ return true
|
|
|
end
|
|
|
end
|
|
|
|
|
|
--- 功能:获取fota的回调函数
|
|
|
--- 参数:
|
|
|
--- result:number类型
|
|
|
--- 0表示成功
|
|
|
--- 1表示连接失败
|
|
|
--- 2表示url错误
|
|
|
--- 3表示服务器断开
|
|
|
--- 4表示接收报文错误
|
|
|
--- 5表示使用iot平台VERSION需要使用 xxx.yyy.zzz形式
|
|
|
-function libfota_cb(result)
|
|
|
- log.info("fota", "result", result)
|
|
|
- -- fota成功
|
|
|
- if result == 0 then
|
|
|
- rtos.reboot() --如果还有其他事情要做,就不要立刻reboot
|
|
|
+--[[
|
|
|
+获取或存储注册信息
|
|
|
+@api aliyun.store(result)
|
|
|
+@table result 注册结果,如果为nil则表示获取注册信息
|
|
|
+@return table 注册信息,如果为nil则表示获取失败
|
|
|
+@usage
|
|
|
+-- 获取注册信息
|
|
|
+local store = aliyun.store()
|
|
|
+-- 存储注册信息
|
|
|
+aliyun.store(result)
|
|
|
+]]
|
|
|
+function aliyun.store(result)
|
|
|
+ if result then
|
|
|
+ log.debug("aliyun", "注册结果", json.encode(result))
|
|
|
+ if fskv then
|
|
|
+ fskv.set("ProductKey", result["productKey"])
|
|
|
+ fskv.set("DeviceName",result["deviceName"])
|
|
|
+ if result["deviceSecret"] then
|
|
|
+ fskv.set("deviceSecret",result["deviceSecret"])
|
|
|
+ else
|
|
|
+ fskv.set("deviceToken",result["deviceToken"])
|
|
|
+ fskv.set("clientId", result["clientId"])
|
|
|
+ end
|
|
|
+ else
|
|
|
+ log.debug("aliyun", "fskv not found, use io/fs")
|
|
|
+ io.writeFile("/alireg.json", json.encode(result))
|
|
|
+ end
|
|
|
+ else
|
|
|
+ local store = {}
|
|
|
+ if fskv then
|
|
|
+ store.deviceName = fskv.get("DeviceName") or fskv.get("deviceName")
|
|
|
+ store.productKey = fskv.get("ProductKey") or fskv.get("productKey")
|
|
|
+ store.deviceSecret = fskv.get("deviceSecret")
|
|
|
+ store.deviceToken = fskv.get("deviceToken")
|
|
|
+ store.clientid = fskv.get("clientid")
|
|
|
+ else
|
|
|
+ local tmp = io.readFile("/alireg.json")
|
|
|
+ if tmp then
|
|
|
+ store = json.decode(tmp)
|
|
|
+ if not store then
|
|
|
+ store = {}
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ return store
|
|
|
end
|
|
|
end
|
|
|
|