3.4-Air302(NB-IOT)-網絡通信-MQTT通信(本機安裝MQTT+花生殼映射),MQTT文件封裝


<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/Learn-NB-IOT-Air302-ForLua" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>

說明

 

這節測試一下模組連接MQTT服務器,然后和MQTT調試助手互發消息!

這一節把MQTT服務器(軟件)安裝到本地電腦.

因為模組只能廣域網連接通信所以咱再通過花生殼映射下.

 

安裝MQTT軟件

1.把下面的軟件放到一個沒有中文的目錄下,並解壓

 

 

 

2.我解壓到了H盤(隨意哈)

 

 

 

3.運行cmd 進入emqttd/bin目錄

 

 

 

 

 

 

 

 

4.啟動服務器(控制台模式),一次啟動不起來,再執行一次!

emqttd console

 

 

 

5.提示,如果出現下面的錯誤,需要拷貝補丁,然后重新執行命令

 

 

 

 

 

 

 

把補丁拷貝到 Windows/System32里面

 

 

 

 

 

6.出現下面的窗口說明服務器已經以控制台模式運行起來了

 

 

 

18083端口是網頁端控制台

11883端口是普通TCP連接(僅限於安裝MQTT軟件的本機上的客戶端連接)

1883端口是普通TCP連接

8883端口是TCP + SSL

8083端口是WebSocket

8084端口是WebSocket + SSL

8080端口是配置MQTT參數

 

測試MQTT軟件是否可以連接

1.打開MQTT調試軟件

注:這是我使用C#寫的一個MQTT調試助手,含源碼

 

 

 

 

 

 

 

2.查看自己電腦的IP地址

 

 

 

 

3.測試連接服務器

 

 

配置花生殼

1.搜索花生殼

 

 

2.下載並安裝,注冊,登錄

 

3.選擇映射配置

 

4.輸入先前注冊的賬號和密碼

 

 

 

5.添加映射

 

 

 

6.按照下面說明填寫

 

 

 

7.解釋

網絡設備訪問 IP地址: 358n960z57.wicp.vip   端口號:36548

就能夠訪問到本機192.168.1.93  上的1883端口的服務器應用程序.

 

 

 

8.使用調試助手測試

 

 

 

使用模組連接

1.安裝上手機卡和天線

 

 

 

2.把例程里面的mqtt.lua源碼拷貝到user  main.lua

 

 

 

 

3.修改IP地址,端口號,訂閱和發布的主題

注:IP地址和端口號就是通過花生殼映射出去的信息

訂閱和發布的主題之所以改為簡單點,是因為方便咱測試,然后接收到什么數據就返回.

 

 

 

 

4.編譯並下載到開發板,看到訂閱成功就說明連接上了

 

 

 

 

5.用調試助手訂閱開發板發布的主題

 

 

 

 

6.調試助手發送信息給開發板

 

 

 

 

 

 

 

 

 

MQTT文件封裝

1.以后做項目,不能把所有的都寫到一個文件里面,需要把連接,接收,發送分開.

下面的文件是參考官方202的mqtt的demo修改的.

 

 

 

 

mqttTask.lua
負責連接MQTT服務器,和輪訓發送和接收函數
local mqttTask = {}

_G.sys = require("sys")
local mqtt = require "mqtt"
local mqttOutMsg = require "mqttOutMsg"
local mqttInMsg = require "mqttInMsg"
local ready = false

--- MQTT連接狀態
function mqttTask.isReady()
    return ready
end

sys.taskInit(function()
    -- 服務器配置信息
    local host, port, clientId = "358n960z57.wicp.vip", 36548, nbiot.imei()
    mqttOutMsg.set_imei(clientId);
    -- 等待聯網成功
    while true do
        while not socket.isReady() do 
            log.info("net", "wait for network ready")
            sys.waitUntil("NET_READY", 1000)
        end
        
        local mqttc = mqtt.client(clientId, nil, nil, false)
        while not mqttc:connect(host, port) do sys.wait(2000) end
        ready = true
        
        local subscribe_topic = "111111" --設備訂閱的主題 111111
        if mqttc:subscribe(subscribe_topic) then
            while true do
                if not mqttInMsg.proc(mqttc) then log.error("mqttTask.mqttInMsg.proc error") break end
                if not mqttOutMsg.proc(mqttc) then log.error("mqttTask.mqttOutMsg proc error") break end
            end
        end
        ready = false
        mqttOutMsg.unInit();
        mqttc:disconnect()
        log.info("mqttTask", "mqtt loop")
        sys.wait(5000) -- 等待一小會, 免得瘋狂重連
    end

end)

return mqttTask;

 

mqttInMsg.lua
接收數據
local mqttInMsg = {}

_G.sys = require("sys")

local mqttOutMsg = require "mqttOutMsg"

--- MQTT客戶端數據接收處理
-- @param mqttc
-- @return 處理成功返回true,處理出錯返回false
-- @usage mqttInMsg.proc(mqttc)
function mqttInMsg.proc(mqttc)
    local result,data
    while true do
        result, data = mqttc:receive(2000)
        if result then
            log.info("mqttc", "get message from server", data.payload or "nil", data.topic)
        else
            break;
        end

        --如果mqttOutMsg中有等待發送的數據,則立即退出本循環
        if mqttOutMsg.waitForSend() then return true end
    end
    
    return result or data=="timeout"
end

return mqttInMsg;

 

 

mqttOutMsg.lua
發送數據
local mqttOutMsg = {}

_G.sys = require("sys")

local sendQueue = {} --接收數據緩存
local this_imei=nil;
-- MQTT
local msgQueue = {}  --數據發送的消息隊列

--設置imei
function mqttOutMsg.set_imei(imei)
    this_imei = imei; --設置IMEI
end

--獲取imei
function mqttOutMsg.get_imei()
    return this_imei; --獲取IMEI
end

--插入消息
--topic:發布的主題
--payload:發布的消息
--qos:消息等級 0或1或2
--retain:消息是否讓服務器保留 0(不保留)  1(保留)
--restart:發送完成是否復位模塊 0(不復位) 1(復位)
function mqttOutMsg.insertMsg(topic,payload,qos,retain,restart)
    table.insert(msgQueue,{topic=topic,payload=payload,qos=qos,retain=retain,restart=restart})
end

--- 清空對象存儲
function mqttOutMsg.unInit()
    while #msgQueue>0 do
        local outMsg = table.remove(msgQueue,1)
    end
end
--- MQTT客戶端是否有數據等待發送
-- @return 有數據等待發送返回true,否則返回false
-- @usage mqttOutMsg.waitForSend()
function mqttOutMsg.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,outMsg.retain)--發送
        if not result then 
            return --發送失敗返回空
        else
            if  outMsg.restart == 1  then
                rtos.reboot();
            end
        end
    end
    return true
end


return mqttOutMsg;

 

使用

1.把這三個文件拷貝到工程

 

 

 

 

2.根據自己的服務器修改MQTT參數

 

 

 

3.加載此程序文件

 

 

連接用戶配置的MQTT服務器

 

 

4.接收消息

 

 

5.發送消息
在需要發送消息的文件里面請求  mqttOutMsg 文件,然后調用里面的
mqttOutMsg.insertMsg(topic,payload,qos,retain,restart)  插入數據即可.
如果在其它文件里面想知道mqtt連接狀態, 請求  mqttTask 文件,然后調用  mqttTask.isReady()
 

 

 

 

 

結語

這節只是為后面的學習做鋪墊.

關於MQTT軟件的其它配置,將在后面的章節敘述.

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM