esp32通过NBIoT模块连入MQTT服务器


title: esp32通过NBIoT模块连入MQTT服务器
keywords: nbiot,esp32,c++,python,mqtt
tags: [esp32,c++,python,mqtt,nbiot]
categories: [嵌入式,前后端]


esp32通过NBIoT模块连入MQTT服务器

先简单介绍一下

MQTT

(Message Queuing Telemetry Transport),是一种轻量级、开放的发布-订阅式通信协议。它适用于物联网、移动应用和其他带有低带宽或不稳定网络的场景。MQTT遵循“生产者/消费者”模型,其中生产者是发送消息的客户端(称为发布者),而消费者是接收消息的客户端(称为订阅者)。MQTT基于TCP/IP协议栈,它具有简单、可扩展、低开销等特点,且支持多种安全验证机制。

通过这个方式以便于我们管理大量单片机

NB-IoT介绍

NB-IoT 和 AT 指令
NB-IoT(Narrowband Internet of Things)是一种基于蜂窝网络的低功耗广域网(LPWAN)技术,旨在连接各种设备到互联网,特别适合于需要低数据传输率、长电池寿命和远程连接的应用。AT指令是用于控制和配置调制解调器的指令集。在NB-IoT设备中,AT指令用于与模块进行通信,执行操作如连接网络、发送和接收数据等。

搭建一个基于Django的NB-IoT云平台样例涉及到几个步骤:创建Django项目、定义模型来存储从NB-IoT设备接收到的数据、创建视图和URL来处理数据的接收,以及编写相应的NB-IoT设备端代码来发送数据。

从零开始搭建MQTT服务器(python Django)

Linux下安装好Mosquitto与python管理插件

步骤1:安装paho-mqtt

首先,你需要安装paho-mqtt库。可以通过pip安装:

pip install paho-mqtt

步骤2:创建MQTT客户端订阅者

import paho.mqtt.client as mqtt

MQTT_SERVER = "localhost"

MQTT_PATH = "test_channel"

当连接到服务器时的回调函数

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc)) #或可收到字典处理
    client.subscribe(MQTT_PATH)

当从服务器接收到消息时的回调函数

def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect(MQTT_SERVER, 1883, 60)

保持连接,直到收到消息

client.loop_forever()

步骤3:创建MQTT客户端发布者测试

import paho.mqtt.publish as publish

MQTT_SERVER = "localhost"
MQTT_PATH = "test_channel"

publish.single(MQTT_PATH, "{"LED_SW":1}", hostname=MQTT_SERVER)

MQTT服务器配置(使用Mosquitto)
如果你没有MQTT服务器,你可以安装并使用Mosquitto。Mosquitto是一个流行的开源MQTT代理。

安装Mosquitto

在Ubuntu上:

sudo apt-get update
sudo apt-get install mosquitto
sudo apt-get install mosquitto-clients

配置路由

在MQTT的上下文中,“配置路由”通常指的是设置主题(topics)和相关的消息传递逻辑。这通常在客户端进行设置,而不是在MQTT服务器本身上配置。MQTT主题是由斜杠(/)分隔的字符串,客户端可以订阅这些主题,以接收发布到这些主题的消息。例如,如果你有一个关于温度的主题,可以命名为home/living_room/temperature,客户端可以订阅这个主题来获取客厅的温度更新。

通过上面的步骤,你可以创建Python脚本来发布和订阅MQTT消息,从而实现基于MQTT的通信。这可以用于各种应用,例如物联网(IoT)项目、远程传感器数据收集、消息发布/订阅系统等。

对于MQTT协议,默认情况下,它使用TCP协议作为底层的传输层协议。因此,当你在学习配置MQTT服务时,确实需要在你的服务器的安全组(或称作防火墙规则)中开放MQTT所使用的TCP端口。对于MQTT,有两个主要的端口需要考虑:

默认端口:1883是MQTT协议的标准非加密通信端口。
加密通信端口:8883是用于通过TLS/SSL进行加密通信的端口

esp32串口适配NBIoT收发

确定好模块没问题

// NB-IOT激活上网AT指令集
String ATcommands[] =
    {
        {"AT+NRB"}, // 模块重启
        {"AT"},
        // {"AT+CPIN?"},     //SIM卡检测
        {"AT+CGSN=1"},  // 查询模组编号
        {"AT+CIMI"},    // 查询国际移动设备身份码
        {"AT+NCCID"},   // 获取NB卡的唯一编码
        {"AT+CGATT=1"}, // 模块连接到基站/模组入网
        {"AT+CSQ"},     // 获取信号强度
        {"AT+CEREG=1"}, // 模组网络注册
        {"AT+CEREG?"},  // 查询模组网络连接状态
        {"AT+CGATT?"}   // 查询模块是否连接到基站
};

通过以上指令确定好模块没问题

连接到服务器

AT+QMTOPEN=0,"你的IP",你的端口
AT+QMTCONN=0,"clientid","mqttusername","mqttpwd"

完成以上两步你就发现你的服务器已经激活了

接下来就是适配的过程(路由,json一系列内容)

主题

以我的举例

//设置mqtt主题topic
    const char* transdatatopic = "v1/devices/me/telemetry";  //	网关/直连设备遥测
    const char* serverpubtopic = "v1/devices/me/rpc/request/+"; //服务端命令下发到设备端

代码示范

代码示范来自学长学姐 感谢学长学姐

	const char* mqttServer_ip = "xxxxxxxx";     //ip地址
    const char* mqttServer_Port = "xxxxxx";              //  MQTT 端口号

    //设置mqtt设备名和访问密码
    const char* deviceid = "0";                   //设备唯一标识号
    const char* clientid = "titochan's esp32";    //本设备的名称
    const char* mqttusername = "xxxx";            //使用mqtt协议连接云平台时所用的用户名
    const char* mqttpwd = "xxxx";                 //使用mqtt协议连接云平台时所用的密码

    //云平台的mqtt产品名称、设备名称、设备属性
    const char* productname = "titoTest";
    const char* devicename = "titoTest";

    //设置mqtt主题topic
    const char* transdatatopic = "v1/devices/me/telemetry";  //	网关/直连设备遥测
    const char* serverpubtopic = "v1/devices/me/rpc/request/+"; //服务端命令下发到设备端

void setup() {
  //初始化Serial和SerialL610
  Serial.begin(9600);
  SerialNB.begin(9600, SERIAL_8N1, PIN_NB_RX,PIN_NB_TX);

  NB_Attach(1);  //发送AT指令使L610联网
  #ifdef MQTT
    MqttConnect(mqttusername,mqttpwd,clientid,mqttServer_ip,mqttServer_Port,"0","60");  //建立Mqtt连接

    NB_MQTTSub(1,serverpubtopic,0);  //订阅主题
  #endif
}
void loop() {
  #ifdef MQTT // 如果建立MQTT连接,则使用MQTT形式的jsonpayload形式上报数据
  // 读取数据
  bool ledsw=readLedSw();
  // 将数据整理成json格式
  String jsonpayload = "{\"LED_SW";
  jsonpayload = jsonpayload + "\":";
  jsonpayload = jsonpayload + ledsw;
  jsonpayload = jsonpayload + "}";
  NB_MQTTPub(msgID, transdatatopic, 0, 0, jsonpayload);
#endif
}
/*函数名称: MqttConnect
*说明: 通过NB-IoT与云平台建立MQTT连接
*参数: devide_id: 设备唯一标识号  user_name: 云平台对应设备的用户名	 password:云平台对应设备的密钥 ClientIDStr: 云平台对应设备的client_id 
mqttServer_ip:待连接的云平台ip地址  mqttServer_Port:待连接的云平台mqtt协议端口号
CleansessionFlag:遗嘱标志位(0:保留所有订阅主题,1:清楚所有订阅主题) Qos: 服务质量等级(0-2,部分平台不支持QoS 等级 2) Keepalive_Time:心跳保活时间
*返回值:无
*/
void MqttConnect(const char* user_name,const char* password,const char* ClientIDStr, const char* mqttServer_ip,const char* mqttServer_Port,const char* CleansessionFlag ,const char* Keepalive_Time )
{
  // //设置本设备的数据格式、心跳保活时间、断开后是否保留信息设置
  String cmd;
  // cmd = cmd + "AT+QMTCFG=\"dataformat\",1,0,0";  //数据格式设置,send_format和recv_format:可选值0(文本格式)、1(十六进制格式)
  // SendCmdToNB_IoT(cmd,"OK");
  // cmd = "";
  // cmd = cmd + "AT+QMTCFG=\"keepalive\",1,";
  // cmd = cmd + Keepalive_Time;
  // SendCmdToNB_IoT(cmd,"OK");
  // cmd = "";
  // cmd = cmd + "AT+QMTCFG=\"session\",1,";
  // cmd = cmd + CleansessionFlag;
  // SendCmdToNB_IoT(cmd,"OK");

  //再建立mqtt连接
  cmd = "";
  cmd = cmd + "AT+QMTOPEN=0,\"";
  cmd = cmd + mqttServer_ip;
  cmd = cmd + "\",";
  cmd = cmd + mqttServer_Port;
  // SendCmdToNB_IoT(cmd,"+QMTOPEN: 0,0");
  SendCmdToNB_IoT(cmd,"+QMTOPEN: 0,0");

  //最后进行鉴权连接绑定云平台设备
  cmd = "";
  cmd = cmd + "AT+QMTCONN=0,\"";
  cmd = cmd + ClientIDStr;
  cmd = cmd + "\",\"";
  cmd = cmd + user_name;
  cmd = cmd + "\",\"";
  cmd = cmd + password;
  cmd = cmd + "\"";
  SendCmdToNB_IoT(cmd,"+QMTCONN: 0,0,0");

}
/*函数名称: SendCmdToNB_IoT
*说明: esp32向NB-IoT模组发送指令
*参数: data: 要发送的指令  res:期望NB-IoT模组返回的消息
*返回值:无
*/
void SendCmdToNB_IoT(String data,const char* res)
{
  Serial.println(data);
  SerialNB.println(data);  //向SerialNB串口发送数据
  if (data.indexOf("+QMTPUB")){
    char end = (char)0x1A;
    SerialNB.print(end);  //"CTRL+Z"发送数据
  }
  delay(200);
  int i = 0;
  rpy = "";
  while(SerialNB.available())
  {
    rpy=SerialNB.readString();  //读取SerialNB串口缓存数组内的数据保存到rpy中
    //xx指令接收处理程序
    int LED_SWIndex = rpy.indexOf("LED_SW");
    if (LED_SWIndex != -1) {
      String LED_SWValueString = rpy.substring(LED_SWIndex + 7,rpy.indexOf("}"));
      if(LED_SWValueString.toInt()){   //接收到xx启动指令
        digitalWrite(LED_SW, HIGH); //给模拟xx输出高电平,启动
      }else{
        digitalWrite(LED_SW, LOW); //给模拟xx输出高电平,启动
      }
    }

    if(rpy.indexOf(res)>=0)  //在rpy中查找是否存在与res相同的内容,若找到,则返回字符串所在的位置
    {
      Serial.println(rpy);    //打印获取到的回复信息
      break;
    }
    else
    {
      Serial.println("error");
      SerialNB.println(data);
      if (data.indexOf("+QMTPUB")){
        char end = (char)0x1A;
        SerialNB.print(end);  //"CTRL+Z"发送数据
      }
    }
    delay(100);
    i++;
    if(i>5)
      break;
  }
}
/*函数名称: NB_MQTTSub
*说明: 订阅某个主题的消息内容
*参数: msgID: 消息标识符,范围:1-65535  topic: 待订阅的主题	 Qos: 服务质量等级(0-2,部分平台不支持QoS 等级 2)
*返回值:无
*/
void NB_MQTTSub(const int msgID, const char* topic,const int QoS)
{
  String cmd;
  cmd="";
  cmd = cmd + "AT+QMTSUB=0,";
  cmd = cmd + (char)(msgID+'0');
  cmd = cmd + ",\"";
  cmd = cmd + topic;
  cmd = cmd + "\",";
  cmd = cmd + (char)(QoS+'0');
  SendCmdToNB_IoT(cmd,"+QMTSUB: 0,1,0,0");

}
  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发愤图强想做全栈的小陈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值