合宙NB-IOT模塊Air302鏈接Tlink雲平臺,APP和微信控制燈開關

 

先註冊Tlink雲平臺帳號(網址),註冊成功後找到開發者中心,查看Tlink雲平臺的MQTT協議說明。添加一個設備,把模塊的電壓,信號強度和燈狀態上傳雲平臺,Tlink提供的APP和微信控制燈開關,鏈接協議選MQTT。html

Air302模塊與Tlink雲平臺通訊使用Json格式通訊。web

在Tlink雲的開發者中心查看MQTT通訊格式要求,寫程序會用到,以下:編程

鏈接域名和端口號:每一種協議的鏈接服務器地址和端口號都不同,請登陸平臺>設備管理>進入設置鏈接界面查看。json

客戶端ID:發佈和訂閱是在同一個設備進行時,客戶端ID只須要一個,能夠直接使用設備序列號當作客戶端ID,若是存在多個設備進行訂閱,須要在平臺獲取新的客戶端ID。服務器

用戶名密碼:用戶名(User Name):同平臺的登陸賬號同樣。 密碼(Password):同平臺的登陸密碼同樣(注:修改登陸密碼會致使設備沒法鏈接,企業版可單獨設置用戶名密碼)。微信

發佈主題:發佈主題:設備序列號,指設備發佈上行數據到平臺的主題。網絡

訂閱主題:訂閱主題:設備序列號/+,指設備接收下行數據時訂閱的主題。這裏利用了通配符的概念,訂閱該主題能夠接收該設備全部傳感器的下行數據(傳感器下行數據所使用的主題爲序列號/傳感器ID)。socket

JSON格式的消息內容............tcp

main.lua以下:函數

PROJECT = "tlink_demo"
VERSION = "1.0.0"

-- 引入必要的庫文件(lua編寫), 內部庫不須要require
local sys = require "sys"
local mqtt = require "mqtt"

log.info("version", _VERSION, VERSION)

-- GPIO 和 PWM 相關 -------------------------------
-- 網絡燈 GPIO19/PWM5
NETLED = gpio.setup(19, 0, gpio.PULLUP)     -- 初始化GPIO19, 並設置爲低電平
gpio.set(19, 0)       -- 設置爲高電平
----發送數據table---------------
local vPowerSwitch = 0

--數據發送的消息隊列,緩衝做用
local msgQueue = {}

function insertMsg( )
    rssi_value = nbiot.rssi()
    --rgb_led = gpio.get(19)
    adc.open(1) -- VBAT電壓
    vbt = adc.read(1)
    local re = {
        sensorDatas = {
            {
                sensorsId = 200456308,
                flag = 'dianya',
                value = vbt
            },
            {
                sensorsId = '200456309',
                flag = 'xinhao',
                value = rssi_value
            },
            {
                sensorsId = 200456387,
                flag = 'deng',
                switcher = vPowerSwitch
            }
        }
    }
    payload =  json.encode(re)
    table.insert(msgQueue,{topic='O5UUTBP9146XN0L5',payload=payload,qos=1})
end
--循環120s執行插入數據
sys.timerLoopStart(insertMsg, 120000)

--燈閃爍線程-------------------------------
--[[sys.taskInit(function()
    while 1 do
        -- 一閃一閃亮晶晶
        NETLED(0)
        sys.wait(1000)
        NETLED(1)
        sys.wait(1500)
        --log.info("gpio", "18", G18())
    end
end)
]]
--接受發送函數----------------------------
--- MQTT客戶端數據接收處理
-- @param mqttClient,MQTT客戶端對象
-- @return 處理成功返回true,處理出錯返回false
-- @usage mqttInMsg.proc(mqttClient)
function mqttInMsg_proc(mqttClient)
    local result,data
    while true do
        result,data = mqttClient:receive(5000)
        --接收到數據
        if result then
            --TODO:根據需求自行處理data.payload
            log.info("mqttInMsg_proc",string.toHex(data.payload))
            log.info("mqttc", "mqttc:receive!!!!", result or nil ,data or nil)
            local tjsondata,res,errinfo = json.decode(data.payload)
            if res then 
                    vPowerSwitch = tjsondata['sensorDatas'][1]['switcher']
                    gpio.set(19, vPowerSwitch) 
                    --接受數據成功後返回燈的狀態,由於要更新web頁面燈開關的狀態
                    insertMsg() 
                    mqttOutMsg_proc(mqttClient)
                    log.info("vPowerSwitch!!!!!", vPowerSwitch)
            else    log.info("json decode faile",errinfo)
            end 
            --uart.write(1,"\r\n topic = "..data.topic .. "  paload = " ..data.payload) --經過串口1發送出去
            --若是mqttOutMsg中有等待發送的數據,則當即退出本循環
            if waitForSend() then return true end
        else
            break
        end
    end
    return result or data=="timeout"
end
--- MQTT客戶端是否有數據等待發送
-- @return 有數據等待發送返回true,不然返回false
-- @usage mqttOutMsg.waitForSend()
function waitForSend()
    return #msgQueue > 0
end
--- MQTT客戶端數據發送處理
-- @param mqttClient,MQTT客戶端對象
-- @return 處理成功返回true,處理出錯返回false
-- @usage mqttOutMsg.proc(mqttClient)
function mqttOutMsg_proc(mqttClient)
    while #msgQueue>0 do
        local outMsg = table.remove(msgQueue,1)
        local result = mqttClient:publish(outMsg.topic,outMsg.payload,outMsg.qos)
        log.info("mqttOutMsg_proc", outMsg.topic,outMsg.payload,outMsg.qos)
        --if outMsg.user and outMsg.user.cb then outMsg.user.cb(result,outMsg.user.para) end
        if not result then return end
    end
    log.info("mqttOutMsg_proc", 'msgQueue length zero')
    return true
end


--鏈接mqtt線程----------------------------
        local host, port, selfid = 'mq.tlink.io', 1883, 'O5UUTBP9146XN0L5'
        local mqttClientId = selfid
        local mqttUsername = '17852270083'
        local mqttPassword = 'chunqing0083!'


sys.taskInit(
    function()
        local retryConnectCnt = 0
        while true do
            if not socket.isReady() then
                retryConnectCnt = 0
                --等待網絡環境準備就緒,超時時間是30s
                log.info("net", "wait for network ready")
                sys.waitUntil("NET_READY",30000)
            end
            --是否獲取到分配的IP(是否連上網)
            if socket.isReady() then
                log.info("net", "network ready")
                --建立一個MQTT客戶端
                local mqttClient = mqtt.client(mqttClientId, 60, mqttUsername, mqttPassword)
                --阻塞執行MQTT CONNECT動做,直至成功
                --若是使用ssl鏈接,打開mqttClient:connect("lbsmqtt.airm2m.com",1884,"tcp_ssl",{caCert="ca.crt"}),根據本身的需求配置
                --mqttClient:connect("lbsmqtt.airm2m.com",1884,"tcp_ssl",{caCert="ca.crt"})
                if mqttClient:connect(host, port,"tcp") then
                    --鏈接成功
                    log.info("mqttClient","Connet ok!") 
                    retryConnectCnt = 0 --失敗次數清零
                    --ready = true
                    --訂閱主題
                    if mqttClient:subscribe({["O5UUTBP9146XN0L5".."/+"]=0}) then --xxx表明的是序列號
                        log.info("mqttClient","subscribe ok!") 
                        --訂閱成功,發佈第一次消息,先把消息寫入table在調用發佈函數
                        insertMsg() 
                        mqttOutMsg_proc(mqttClient)
                        --mqttOutMsg.insertMsg("xxx","Iccid = " .. sim.getIccid(),0)--這個沒啥用
                        --循環處理接收和發送的數據
                        while true do
                            if not mqttInMsg_proc(mqttClient) then 
                                log.error("mqttTask.mqttInMsg.proc error") 
                                break 
                            end
                            if not mqttOutMsg_proc(mqttClient) then 
                                log.error("mqttTask.mqttOutMsg proc error") 
                                break 
                            end
                        end
                    end
                    --ready = false
                else
                    log.info("mqttTask.mqttClient","Connet fail!") 
                    retryConnectCnt = retryConnectCnt+1 --失敗次數加一
                end
                --斷開MQTT鏈接
                mqttClient:disconnect()
                if retryConnectCnt>=5 then  retryConnectCnt=0 end
                sys.wait(5000)
            else
                --進入飛行模式,5秒以後,退出飛行模式
                nbiot.setCFUN(0)
                sys.wait(5000)
                log.info("net", "I am in fly mode")
                nbiot.setCFUN(1)
            end
        end
    end
)




-- 用戶代碼已結束---------------------------------------------
-- 結尾老是這一句
sys.run()
-- sys.run()以後後面不要加任何語句!!!!!

一個小細節,就是在Tlink雲的控制檯控制燈的開關,須要設備把接受到的值在返回給服務器,改變開關圖標,這樣服務器才能肯定下發數據是否成功,如圖。可在程序中,當模塊接收到數據後緊接着發佈數據就能夠了。

 


參考:【2G模組Air202開發】Lua腳本編程實現MQTT協議鏈接Tlink平臺

             NB-IOT(Air302) Lua開發

相關文章
相關標籤/搜索