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一系列内容)
主题
以我的举例文章来源:https://www.toymoban.com/news/detail-854819.html
//设置mqtt主题topic
const char* transdatatopic = "v1/devices/me/telemetry"; // 网关/直连设备遥测
const char* serverpubtopic = "v1/devices/me/rpc/request/+"; //服务端命令下发到设备端
代码示范
代码示范来自学长学姐 感谢学长学姐文章来源地址https://www.toymoban.com/news/detail-854819.html
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");
}
到了这里,关于esp32通过NBIoT模块连入MQTT服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!