GPRS(Air202) Lua開發: 物聯網MQTT ,DTU


 

 

拷貝官方MQTT源碼

 

 

 

 

 

 

 

 

修改main.lua

打開看門狗,網絡指示燈功能

 

 

 

 

修改mqttTask.lua

本人服務器信息

IP地址: mnif.cn

端口號: TCP:1883  TCPS:8883

用戶名: yang

密    碼: 11223344

 

修改連接信息如下:

 

 

 

 

 

 

修改mqttInMsg.lua 

修改為直接打印接收的數據,去掉hex轉換

 

 

 

 

mqttOutMsg.lua 說明

1.連接上MQTT以后 mqttTask.lua調用了mqttOutMsg 里面的 mqttOutMsg.init()  函數

 

 

 

2.官方給的例子是每隔10S發布主題為 /qos0topic   消息為 qos0data 的消息

每隔20S發布主題為 /中文qos1topic  消息為  中文qos1data  的消息

 

 

 

測試

1.安裝手機卡,安裝天線,下載程序

 

 

 

2.打開我提供的調試助手

 

 

 

 

 

 

連接,訂閱,設置發布的主題如下

發布的主題:111111      訂閱的主題:/qos0topic

 

 

 

 

 

 

 

 

 

 

 

 

 

擴展:DTU

模塊接收的MQTT信息轉發到485/422輸出

485/422接收的數據轉發給MQTT發送

 

設備訂閱的主題:user/設備的imei號碼

設備發布的主題:device/設備的imei號碼

 

1.修改 mqttTask   初始化串口;修改訂閱的主題為:user/設備的imei號;把IMEI號傳遞給發布程序

 

 

 

 

 

 

 

 

 

 

--- 模塊功能:MQTT客戶端處理框架
-- @author openLuat
-- @module mqtt.mqttTask
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28

module(...,package.seeall)

require"misc"
require"mqtt"
require"mqttOutMsg"
require"mqttInMsg"


local ready = false

--- MQTT連接是否處於激活狀態
-- @return 激活狀態返回true,非激活狀態返回false
-- @usage mqttTask.isReady()
function isReady()
    return ready
end


uart.setup(1, 115200, 8, uart.PAR_NONE, uart.STOP_1)


--啟動MQTT客戶端任務
sys.taskInit(
    function()
        local retryConnectCnt = 0
        while true do
            if not socket.isReady() then
                retryConnectCnt = 0
                --等待網絡環境准備就緒,超時時間是5分鍾
                sys.waitUntil("IP_READY_IND",300000)
            end
            
            if socket.isReady() then
                local imei = misc.getImei()
                --創建一個MQTT客戶端
                local mqttClient = mqtt.client(imei,30,"yang","11223344")
                --阻塞執行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("mnif.cn",1883,"tcp") then
                    retryConnectCnt = 0
                    ready = true
                    --訂閱主題
                    if mqttClient:subscribe({["user/"..imei]=0}) then --訂閱主題:
                        mqttOutMsg.init(imei)
                        --循環處理接收和發送的數據
                        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
                        mqttOutMsg.unInit()
                    end
                    ready = false
                else
                    retryConnectCnt = retryConnectCnt+1
                end
                --斷開MQTT連接
                mqttClient:disconnect()
                if retryConnectCnt>=5 then link.shut() retryConnectCnt=0 end
                sys.wait(5000)
            else
                --進入飛行模式,20秒之后,退出飛行模式
                net.switchFly(true)
                sys.wait(20000)
                net.switchFly(false)
            end
        end
    end
)

 

 

2.修改 mqttInMsg 接收的數據串口1輸出

 

 

 

 

--- 模塊功能:MQTT客戶端數據接收處理
-- @author openLuat
-- @module mqtt.mqttInMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28

module(...,package.seeall)


--- MQTT客戶端數據接收處理
-- @param mqttClient,MQTT客戶端對象
-- @return 處理成功返回true,處理出錯返回false
-- @usage mqttInMsg.proc(mqttClient)
function proc(mqttClient)
    local result,data
    while true do
        result,data = mqttClient:receive(2000)
        --接收到數據
        if result then
            log.info("mqttInMsg.proc",data.topic,data.payload)
            --TODO:根據需求自行處理data.payload

            uart.write(1, data.payload) --串口輸出接收的數據

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

 

 

 

3.大幅度裁剪 mqttOutMsg 串口接收的數據,轉發給MQTT發送

 

 

 

--- 模塊功能:MQTT客戶端數據發送處理

module(...,package.seeall)
-- 串口ID,串口讀緩沖區
local sendQueue = {} --接收數據緩存
local uartimeout=25 -- 串口接收超時時間
local recvReady = "UART_RECV_ID" --串口准備好后發布的消息
local myimei="";
-- MQTT
local msgQueue = {}  --數據發送的消息隊列
function init(imei)
    myimei = imei; --獲取IMEI
end
--- 清空對象存儲
function unInit()
    while #msgQueue>0 do
        local outMsg = table.remove(msgQueue,1)
    end
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 proc(mqttClient,imei)
    while #msgQueue>0 do--有消息
        local outMsg = table.remove(msgQueue,1)--提取一條消息
        local result = mqttClient:publish(outMsg.t,outMsg.p,outMsg.q)--發送
        if not result then return end--發送失敗返回空
    end
    return true
end
-- 串口
uart.on(1, "receive", function(uid)
    table.insert(sendQueue, uart.read(uid, 1460))
    sys.timerStart(sys.publish, uartimeout, recvReady)
end)
sys.subscribe(recvReady, function()
    local str = table.concat(sendQueue) --把每一條數據拼接成一條數據
    table.insert(msgQueue,{t="device/"..myimei,p=str,q=0})--串口接收的消息,插入MQTT發送緩存
    sendQueue = {} -- 串口的數據讀完后清空緩沖區
end)

 

擴展1:DTU 測試

1.下載本節程序

2.接上485/422模塊

A+,A- 作為485通信時的接收和發送數據接口,另作為422通信時的發送數據接口

B+,B- 作為422通信時的接收數據接口

用485模塊連接如下:

 

 

 

3.打開MQTT調試助手

提示:設備的IMEI可看自己模塊上的

 

 

 

 

訂閱的主題:  device/設備的imei號

發布的主題:  user/設備的imei號

 

 

 

 

 

4.MQTT助手發布消息

 


免責聲明!

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



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