簡介
Air780EP 是合宙的低功耗4G模組之一,支持LuatOS的腳本二次開發,即使是不太懂技術的老板,也能輕松使用 Air780EP開發產品。
本文應各位大佬邀請,詳細講解了Air780EP 的MQTT的應用教程!
MQTT協議具有長連接、低帶寬、高可靠性的優勢,非常適合物聯網設備的通信需求。
除了MQTT,Air780EP還提供了TCP、UDP、HTTP、WebSocket、FTP、NTP等多種網絡協議的支持,使得設備可以靈活地接入不同的網絡環境和平臺。
實用場景:需要服務器下發消息給設備,需要及時收到。例如,遠程開關,充電樁等
合宙支持LuatOS功能的模組型號,除本文介紹的Air780EP外, 還有Air780EPA、Air780E、Air780EX、Air201、Air780EPT、Air780EPS等型號, 本文介紹的MQTT應用流程,同樣也適用于這些型號。
材料準備
需要用到的材料和工具:
780EP開發板一套,包括天線SIM卡,USB線
PC電腦,以及登錄官方IOT后臺 https://iot.openluat.com/
固件和DEMO下載地址 LuatOS軟件包
名詞解析:
user_name用戶名,password密碼,client_id用戶標識,MQTT可以通過前兩個參數保證連接的安全,通過client_id確保設備唯一性。
QOS表示消息質量,分為0,1,2三個等級,分別表示只發一次,至少收到一次和只收到一次,通過QOS可以根據數據的重要性靈活選擇發送方式以節省帶寬和保證數據可靠。
關于publish時QOS值的說明
QOS為0時,壓入底層TCP發送堆棧,視為成功
QOS為1時,收到服務器回應PUBACK,視為成功
QOS為2時,收到服務器響應PUBREC,立即上行PUBCOMP壓入TCP發送隊列,視為成功
mqtt_host主機,mqtt_port端口,MQTT需要連接的服務器參數。mqtt_host可以說是ip或者域名。
topic主題,根據主題區別消息類型和來源,主要用來分類數據。同時mqtt是發布訂閱模型,topic是發布和訂閱者通信的重要通道。
payload消息內容,發布和訂閱的具體數據。
retain保留消息,保留消息是一條將保留標志(retained flag)置為true的普通MQTT消息。
broker會針對主題依照QoS級別保留最后一條保留消息,當訂閱者訂閱主題時會立即收到保留消息。broker僅為每個主題保留一條保留消息。
API說明:
API接口 | 描述 |
---|---|
mqtt.create() | 創建一個mqtt client實例 |
mqttc:connect() | 連接mqtt服務器 |
mqttc:subscribe() | 訂閱主題 |
mqttc:unsubscribe() | 取消訂閱主題 |
mqttc:publish() | 發布消息 |
mqttc:disconnect() | 斷開與服務器的連接 |
實現流程
1. 創建一個Task協程
接口
? sys.taskInit(func, arg1, arg2, argN)
參數
傳入值類型 | 解釋 |
---|---|
function | 待執行的函數,可以是匿名函數, 也可以是local或全局函數 |
any | 需要傳遞的參數1,可選 |
any | 需要傳遞的參數2,可選 |
any | 需要傳遞的參數N,可選 |
返回值
返回值類型 | 解釋 |
---|---|
task | 協程對象 |
2. 等待網絡就緒
3. 創建一個mqtt實例
接口
? mqtt.create(adapter,host,port,ssl,isipv6)
參數
傳入值類型 | 解釋 |
---|---|
int | 適配器序號, 只能是socket.ETH0, socket.STA, socket.AP,如果不填,會選擇平臺自帶的方式,然后是最后一個注冊的適配器 |
string | 服務器地址,可以是域名, 也可以是ip |
int | 端口號 |
bool/table | 是否為ssl加密連接,默認不加密,true為無證書最簡單的加密,table為有證書的加密 server_cert 服務器ca證書數據 client_cert 客戶端證書數據 client_key 客戶端私鑰加密數據 client_password 客戶端私鑰口令數據 verify 是否強制校驗 0不校驗/1可選校驗/2強制校驗 默認2 |
bool/table | bool 是否為ipv6,默認不是 table mqtt擴展參數, ipv6 是否為ipv6, rxSize 接收緩沖區大小 |
返回值
返回值類型 | 解釋 |
---|---|
userdata | 若成功會返回mqtt客戶端實例,否則返回nil |
4. 連接服務器
接口: mqttc:connect()
參數:
返回值
返回值類型 | 解釋 |
---|---|
boolean | 發起成功返回true, 否則返回false |
注意:本函數僅代表發起成功, 后續仍需根據ready函數判斷mqtt是否連接正常
5. 訂閱主題
接口
? mqttc:subscribe(topic, qos)
參數
傳入值類型 | 解釋 |
---|---|
string/table | 主題 |
int | topic為string時生效 0/1/2 默認0 |
返回值
返回值類型 | 解釋 |
---|---|
int | 消息id,當qos為1/2時有效, 若底層返回失敗,會返回nil |
6. 發布消息
接口:mqttc:publish(topic, data, qos, retain)
參數
傳入值類型 | 解釋 |
---|---|
string | 主題,必填 |
string | 消息,必填,但長度可以是0 |
int | 消息級別 0/1 默認0 |
int | 是否存檔, 0/1,默認0 |
返回值
返回值類型 | 解釋 |
---|---|
int | 消息id, 當qos為1或2時會有效值. 若底層返回是否, 會返回nil |
7. 接收消息
8. 斷開服務器的連接
接口:? mqttc:disconnect()
參數:無
返回值
返回值類型 | 解釋 |
---|---|
boolean | 發起成功返回true, 否則返回false |
示例
本文以demo_luaLuatOSdemomqtt這個demo為例作為演示,以MQTTX工具來測試MQTT運行狀況
1.在MQTTX軟件上建立連接
2.在MQTTX軟件上添加訂閱
注意:訂閱主題格式要求默認為 /luatos/pub/ 加模塊的IMEI號,例如 /luatos/pub/868488076506128
3.設置MQTTX軟件上發布消息的主題
? 注意:格式要求默認為 /luatos/sub/ 加模塊的IMEI號,例如 /luatos/sub/868488076506128
4.燒錄腳本,上電開機后模塊會自動向服務器發送消息,這是代碼默認設置的,若不需要可以刪掉
5.模塊向服務器發送消息,通過Luatools軟件可以看到
MQTT單鏈接示例
在代碼開頭部分,可根據自己的服務器修改指定的參數
注意:user_name、password在有些服務器上是可以不傳入的,或者是對傳入的值沒有要求限制。要根據實際服務器要求來填寫
--根據自己的服務器修改以下參數 local mqtt_host = "lbsmqtt.airm2m.com" local mqtt_port = 1884 local mqtt_isssl = false local client_id = "abc" local user_name = "user" local password = "password" local pub_topic = "/luatos/pub/" .. (mcu.unique_id():toHex()) -- 該變量在下方代碼有重新賦值,根據實際應用場景,可自行修改腳本邏輯 local sub_topic = "/luatos/sub/" .. (mcu.unique_id():toHex()) -- 該變量在下方代碼有重新賦值,根據實際應用場景,可自行修改腳本邏輯
此task實現的是mqtt的連接、訂閱消息、發布消息的流程。
要先等待網絡就緒之后才可進行mqtt后續操作
待網絡就緒之后,根據代碼編寫情況此時client_id、pub_topic和sub_topic會發生變化,會覆蓋掉代碼開頭部分時的配置,這點需要注意。device_id為模塊的IMEI號
sys.taskInit(function() -- 等待聯網 local ret, device_id = sys.waitUntil("net_ready") -- 下面的是mqtt的參數均可自行修改 -- client_id = device_id pub_topic = "/luatos/pub/" .. device_id sub_topic = "/luatos/sub/" .. device_id -- 打印一下上報(pub)和下發(sub)的topic名稱 -- 上報: 設備 ---> 服務器 -- 下發: 設備 --- 服務器 -- 可使用mqtt.x等客戶端進行調試 log.info("mqtt", "pub", pub_topic) log.info("mqtt", "sub", sub_topic) -- 打印一下支持的加密套件, 通常來說, 固件已包含常見的99%的加密套件 -- if crypto.cipher_suites then -- log.info("cipher", "suites", json.encode(crypto.cipher_suites())) -- end if mqtt == nil then while 1 do sys.wait(1000) log.info("bsp", "本bsp未適配mqtt庫, 請查證") end end ------------------------------------- -------- MQTT 演示代碼 -------------- ------------------------------------- mqttc = mqtt.create(nil, mqtt_host, mqtt_port, mqtt_isssl, ca_file) mqttc:auth(client_id,user_name,password) -- client_id必填,其余選填 -- mqttc:keepalive(240) -- 默認值240s mqttc:autoreconn(true, 3000) -- 自動重連機制 mqttc:on(function(mqtt_client, event, data, payload) -- 用戶自定義代碼 log.info("mqtt", "event", event, mqtt_client, data, payload) if event == "conack" then -- 聯上了 sys.publish("mqtt_conack") mqtt_client:subscribe(sub_topic)--單主題訂閱 -- mqtt_client:subscribe({[topic1]=1,[topic2]=1,[topic3]=1})--多主題訂閱 elseif event == "recv" then log.info("mqtt", "downlink", "topic", data, "payload", payload) sys.publish("mqtt_payload", data, payload) elseif event == "sent" then -- log.info("mqtt", "sent", "pkgid", data) -- elseif event == "disconnect" then -- 非自動重連時,按需重啟mqttc -- mqtt_client:connect() end end) -- mqttc自動處理重連, 除非自行關閉 mqttc:connect() sys.waitUntil("mqtt_conack") while true do -- 演示等待其他task發送過來的上報信息 local ret, topic, data, qos = sys.waitUntil("mqtt_pub", 300000) if ret then -- 提供關閉本while循環的途徑, 不需要可以注釋掉 if topic == "close" then break end mqttc:publish(topic, data, qos) end -- 如果沒有其他task上報, 可以寫個空等待 --sys.wait(60000000) end mqttc:close() mqttc = nil end)
此task的功能為模塊每3秒向服務器發送一次數據
-- 這里演示在另一個task里上報數據, 會定時上報數據,不需要就注釋掉 sys.taskInit(function() sys.wait(3000) local data = "123," local qos = 1 -- QOS0不帶puback, QOS1是帶puback的 while true do sys.wait(3000) if mqttc and mqttc:ready() then local pkgid = mqttc:publish(pub_topic, data .. os.date(), qos) -- local pkgid = mqttc:publish(topic2, data, qos) -- local pkgid = mqttc:publish(topic3, data, qos) end end end)
此代碼可實現mqtt-uart透傳,利用串口工具給服務器發消息或者接收來著服務器的消息
注意要使用串口1,且波特率為9600
-- 以下是演示與uart結合, 簡單的mqtt-uart透傳實現,不需要就注釋掉 local uart_id = 1 uart.setup(uart_id, 9600) uart.on(uart_id, "receive", function(id, len) local data = "" while 1 do local tmp = uart.read(uart_id) if not tmp or #tmp == 0 then break end data = data .. tmp end log.info("uart", "uart收到數據長度", #data) sys.publish("mqtt_pub", pub_topic, data) end) sys.subscribe("mqtt_payload", function(topic, payload) log.info("uart", "uart發送數據長度", #payload) uart.write(1, payload) end)
MQTT多鏈接示例
多鏈接的核心,就是要創建兩個mqtt客戶端的對象,通過不同的變量控制,代碼部分如下:
--------------------第一個mqtt客戶端-------------------- mqttc1 = mqtt.create(nil, mqtt_host, mqtt_port, mqtt_isssl, ca_file) -- 創建的第一個mqtt對象 mqttc1:auth(client1_id,user_name,password) -- client_id必填,其余選填 -- mqttc1:keepalive(240) -- 默認值240s mqttc1:autoreconn(true, 3000) -- 自動重連機制 mqttc1:on(function(mqtt_client, event, data, payload) -- 用戶自定義代碼 log.info("mqtt", "event", event, mqtt_client, data, payload) if event == "conack" then -- 聯上了 sys.publish("mqtt_conack") mqtt_client:subscribe(sub_topic_client)--單主題訂閱 -- mqtt_client:subscribe({[topic1]=1,[topic2]=1,[topic3]=1})--多主題訂閱 elseif event == "recv" then -- 客戶端1 接收數據 log.info("mqtt", "downlink", "topic", data, "payload", payload) sys.publish("mqtt_payload", data, payload) elseif event == "sent" then -- log.info("mqtt", "sent", "pkgid", data) -- elseif event == "disconnect" then -- 非自動重連時,按需重啟mqttc -- mqtt_client:connect() end~ end) --------------------第二個mqtt客戶端-------------------- mqttc2 = mqtt.create(nil, mqtt_host, mqtt_port, mqtt_isssl, ca_file) -- 創建的第二個mqtt對象 mqttc2:auth(client2_id,user_name,password) -- client_id必填,其余選填 -- mqttc2:keepalive(240) -- 默認值240s mqttc2:autoreconn(true, 3000) -- 自動重連機制 mqttc2:on(function(mqtt_client, event, data, payload) -- 用戶自定義代碼 log.info("mqtt", "event", event, mqtt_client, data, payload) if event == "conack" then -- 聯上了 sys.publish("mqtt_conack") mqtt_client:subscribe(sub_topic_client) -- 主題訂閱 -> 訂閱主題可以額外自定義 -- mqtt_client:subscribe({[topic1]=1,[topic2]=1,[topic3]=1})--多主題訂閱 elseif event == "recv" then -- 客戶端2 接收數據 log.info("mqtt", "downlink", "topic", data, "payload", payload) sys.publish("mqtt_payload", data, payload) elseif event == "sent" then -- log.info("mqtt", "sent", "pkgid", data) -- elseif event == "disconnect" then -- 非自動重連時,按需重啟mqttc -- mqtt_client:connect() end end) -- 客戶端1 發送數據 mqttc1:publish(topic, data, qos) -- 發布topic主題可以自定義,可以不相同 -- 客戶端2 發送數據 mqttc2:publish(topic, data, qos) -- 發布topic主題可以自定義,可以不相同
常見問題:
Q: 模組支持MQTT最新的版本是多少?
A: MQTT_V3.1.1版本
Q: 模組最多支持幾路鏈接?
A: mqtt/tcp/udp的鏈接公用8路通道
好啦,通過以上步驟,你就能夠實現設備到MQTT服務器的連接與數據交互了。
評論區討論下你遇到的問題吧~
審核編輯 黃宇
-
服務器
+關注
關注
12文章
8588瀏覽量
84084 -
MQTT
+關注
關注
5文章
620瀏覽量
22229
發布評論請先 登錄
相關推薦
評論