zoukankan      html  css  js  c++  java
  • 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软件的其它配置,将在后面的章节叙述.

  • 相关阅读:
    WYT的刷子
    小烈送菜
    猴腮雷
    基于Docker的Mysql主从复制搭建
    C#集合类型大揭秘
    ASP.NET三剑客 HttpApplication HttpModule HttpHandler 解析
    使用缓存的正确姿势
    【模块化那些事】 拆散的模块化
    分享一个开源的网盘下载工具BaiduPCS-Go
    【抽象那些事】不必要的抽象
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/14204583.html
Copyright © 2011-2022 走看看