先註冊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雲的控制檯控制燈的開關,須要設備把接受到的值在返回給服務器,改變開關圖標,這樣服務器才能肯定下發數據是否成功,如圖。可在程序中,當模塊接收到數據後緊接着發佈數據就能夠了。