3.4-Air302(NB-IOT)-网络通信-MQTT通信(本机安装MQTT+花生壳映射),MQTT文件封装

2020-12-31 11:24:52 浏览数 (1)

<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服务器,和轮训发送和接收函数

代码语言:javascript复制
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

接收数据

代码语言:javascript复制
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

发送数据

代码语言:javascript复制
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软件的其它配置,将在后面的章节叙述.

0 人点赞