title: esp32通過NBIoT模塊連入MQTT服務(wù)器
keywords: nbiot,esp32,c++,python,mqtt
tags: [esp32,c++,python,mqtt,nbiot]
categories: [嵌入式,前后端]
esp32通過NBIoT模塊連入MQTT服務(wù)器
先簡單介紹一下
MQTT
(Message Queuing Telemetry Transport),是一種輕量級、開放的發(fā)布-訂閱式通信協(xié)議。它適用于物聯(lián)網(wǎng)、移動應(yīng)用和其他帶有低帶寬或不穩(wěn)定網(wǎng)絡(luò)的場景。MQTT遵循“生產(chǎn)者/消費(fèi)者”模型,其中生產(chǎn)者是發(fā)送消息的客戶端(稱為發(fā)布者),而消費(fèi)者是接收消息的客戶端(稱為訂閱者)。MQTT基于TCP/IP協(xié)議棧,它具有簡單、可擴(kuò)展、低開銷等特點(diǎn),且支持多種安全驗(yàn)證機(jī)制。
通過這個方式以便于我們管理大量單片機(jī)
NB-IoT介紹
NB-IoT 和 AT 指令
NB-IoT(Narrowband Internet of Things)是一種基于蜂窩網(wǎng)絡(luò)的低功耗廣域網(wǎng)(LPWAN)技術(shù),旨在連接各種設(shè)備到互聯(lián)網(wǎng),特別適合于需要低數(shù)據(jù)傳輸率、長電池壽命和遠(yuǎn)程連接的應(yīng)用。AT指令是用于控制和配置調(diào)制解調(diào)器的指令集。在NB-IoT設(shè)備中,AT指令用于與模塊進(jìn)行通信,執(zhí)行操作如連接網(wǎng)絡(luò)、發(fā)送和接收數(shù)據(jù)等。
搭建一個基于Django的NB-IoT云平臺樣例涉及到幾個步驟:創(chuàng)建Django項(xiàng)目、定義模型來存儲從NB-IoT設(shè)備接收到的數(shù)據(jù)、創(chuàng)建視圖和URL來處理數(shù)據(jù)的接收,以及編寫相應(yīng)的NB-IoT設(shè)備端代碼來發(fā)送數(shù)據(jù)。
從零開始搭建MQTT服務(wù)器(python Django)
Linux下安裝好Mosquitto與python管理插件
步驟1:安裝paho-mqtt
首先,你需要安裝paho-mqtt庫??梢酝ㄟ^pip安裝:
pip install paho-mqtt
步驟2:創(chuàng)建MQTT客戶端訂閱者
import paho.mqtt.client as mqtt
MQTT_SERVER = "localhost"
MQTT_PATH = "test_channel"
當(dāng)連接到服務(wù)器時的回調(diào)函數(shù)
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc)) #或可收到字典處理
client.subscribe(MQTT_PATH)
當(dāng)從服務(wù)器接收到消息時的回調(diào)函數(shù)
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:創(chuàng)建MQTT客戶端發(fā)布者測試
import paho.mqtt.publish as publish
MQTT_SERVER = "localhost"
MQTT_PATH = "test_channel"
publish.single(MQTT_PATH, "{"LED_SW":1}", hostname=MQTT_SERVER)
MQTT服務(wù)器配置(使用Mosquitto)
如果你沒有MQTT服務(wù)器,你可以安裝并使用Mosquitto。Mosquitto是一個流行的開源MQTT代理。
安裝Mosquitto
在Ubuntu上:
sudo apt-get update
sudo apt-get install mosquitto
sudo apt-get install mosquitto-clients
配置路由
在MQTT的上下文中,“配置路由”通常指的是設(shè)置主題(topics)和相關(guān)的消息傳遞邏輯。這通常在客戶端進(jìn)行設(shè)置,而不是在MQTT服務(wù)器本身上配置。MQTT主題是由斜杠(/)分隔的字符串,客戶端可以訂閱這些主題,以接收發(fā)布到這些主題的消息。例如,如果你有一個關(guān)于溫度的主題,可以命名為home/living_room/temperature,客戶端可以訂閱這個主題來獲取客廳的溫度更新。
通過上面的步驟,你可以創(chuàng)建Python腳本來發(fā)布和訂閱MQTT消息,從而實(shí)現(xiàn)基于MQTT的通信。這可以用于各種應(yīng)用,例如物聯(lián)網(wǎng)(IoT)項(xiàng)目、遠(yuǎn)程傳感器數(shù)據(jù)收集、消息發(fā)布/訂閱系統(tǒng)等。
對于MQTT協(xié)議,默認(rèn)情況下,它使用TCP協(xié)議作為底層的傳輸層協(xié)議。因此,當(dāng)你在學(xué)習(xí)配置MQTT服務(wù)時,確實(shí)需要在你的服務(wù)器的安全組(或稱作防火墻規(guī)則)中開放MQTT所使用的TCP端口。對于MQTT,有兩個主要的端口需要考慮:
默認(rèn)端口:1883是MQTT協(xié)議的標(biāo)準(zhǔn)非加密通信端口。
加密通信端口:8883是用于通過TLS/SSL進(jìn)行加密通信的端口
esp32串口適配NBIoT收發(fā)
確定好模塊沒問題
// NB-IOT激活上網(wǎng)AT指令集
String ATcommands[] =
{
{"AT+NRB"}, // 模塊重啟
{"AT"},
// {"AT+CPIN?"}, //SIM卡檢測
{"AT+CGSN=1"}, // 查詢模組編號
{"AT+CIMI"}, // 查詢國際移動設(shè)備身份碼
{"AT+NCCID"}, // 獲取NB卡的唯一編碼
{"AT+CGATT=1"}, // 模塊連接到基站/模組入網(wǎng)
{"AT+CSQ"}, // 獲取信號強(qiáng)度
{"AT+CEREG=1"}, // 模組網(wǎng)絡(luò)注冊
{"AT+CEREG?"}, // 查詢模組網(wǎng)絡(luò)連接狀態(tài)
{"AT+CGATT?"} // 查詢模塊是否連接到基站
};
通過以上指令確定好模塊沒問題
連接到服務(wù)器
AT+QMTOPEN=0,"你的IP",你的端口
AT+QMTCONN=0,"clientid","mqttusername","mqttpwd"
完成以上兩步你就發(fā)現(xiàn)你的服務(wù)器已經(jīng)激活了
接下來就是適配的過程(路由,json一系列內(nèi)容)
主題
以我的舉例文章來源:http://www.zghlxwxcb.cn/news/detail-854819.html
//設(shè)置mqtt主題topic
const char* transdatatopic = "v1/devices/me/telemetry"; // 網(wǎng)關(guān)/直連設(shè)備遙測
const char* serverpubtopic = "v1/devices/me/rpc/request/+"; //服務(wù)端命令下發(fā)到設(shè)備端
代碼示范
代碼示范來自學(xué)長學(xué)姐 感謝學(xué)長學(xué)姐文章來源地址http://www.zghlxwxcb.cn/news/detail-854819.html
const char* mqttServer_ip = "xxxxxxxx"; //ip地址
const char* mqttServer_Port = "xxxxxx"; // MQTT 端口號
//設(shè)置mqtt設(shè)備名和訪問密碼
const char* deviceid = "0"; //設(shè)備唯一標(biāo)識號
const char* clientid = "titochan's esp32"; //本設(shè)備的名稱
const char* mqttusername = "xxxx"; //使用mqtt協(xié)議連接云平臺時所用的用戶名
const char* mqttpwd = "xxxx"; //使用mqtt協(xié)議連接云平臺時所用的密碼
//云平臺的mqtt產(chǎn)品名稱、設(shè)備名稱、設(shè)備屬性
const char* productname = "titoTest";
const char* devicename = "titoTest";
//設(shè)置mqtt主題topic
const char* transdatatopic = "v1/devices/me/telemetry"; // 網(wǎng)關(guān)/直連設(shè)備遙測
const char* serverpubtopic = "v1/devices/me/rpc/request/+"; //服務(wù)端命令下發(fā)到設(shè)備端
void setup() {
//初始化Serial和SerialL610
Serial.begin(9600);
SerialNB.begin(9600, SERIAL_8N1, PIN_NB_RX,PIN_NB_TX);
NB_Attach(1); //發(fā)送AT指令使L610聯(lián)網(wǎng)
#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形式上報(bào)數(shù)據(jù)
// 讀取數(shù)據(jù)
bool ledsw=readLedSw();
// 將數(shù)據(jù)整理成json格式
String jsonpayload = "{\"LED_SW";
jsonpayload = jsonpayload + "\":";
jsonpayload = jsonpayload + ledsw;
jsonpayload = jsonpayload + "}";
NB_MQTTPub(msgID, transdatatopic, 0, 0, jsonpayload);
#endif
}
/*函數(shù)名稱: MqttConnect
*說明: 通過NB-IoT與云平臺建立MQTT連接
*參數(shù): devide_id: 設(shè)備唯一標(biāo)識號 user_name: 云平臺對應(yīng)設(shè)備的用戶名 password:云平臺對應(yīng)設(shè)備的密鑰 ClientIDStr: 云平臺對應(yīng)設(shè)備的client_id
mqttServer_ip:待連接的云平臺ip地址 mqttServer_Port:待連接的云平臺mqtt協(xié)議端口號
CleansessionFlag:遺囑標(biāo)志位(0:保留所有訂閱主題,1:清楚所有訂閱主題) Qos: 服務(wù)質(zhì)量等級(0-2,部分平臺不支持QoS 等級 2) Keepalive_Time:心跳?;顣r間
*返回值:無
*/
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 )
{
// //設(shè)置本設(shè)備的數(shù)據(jù)格式、心跳保活時間、斷開后是否保留信息設(shè)置
String cmd;
// cmd = cmd + "AT+QMTCFG=\"dataformat\",1,0,0"; //數(shù)據(jù)格式設(shè)置,send_format和recv_format:可選值0(文本格式)、1(十六進(jìn)制格式)
// 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");
//最后進(jìn)行鑒權(quán)連接綁定云平臺設(shè)備
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");
}
/*函數(shù)名稱: SendCmdToNB_IoT
*說明: esp32向NB-IoT模組發(fā)送指令
*參數(shù): data: 要發(fā)送的指令 res:期望NB-IoT模組返回的消息
*返回值:無
*/
void SendCmdToNB_IoT(String data,const char* res)
{
Serial.println(data);
SerialNB.println(data); //向SerialNB串口發(fā)送數(shù)據(jù)
if (data.indexOf("+QMTPUB")){
char end = (char)0x1A;
SerialNB.print(end); //"CTRL+Z"發(fā)送數(shù)據(jù)
}
delay(200);
int i = 0;
rpy = "";
while(SerialNB.available())
{
rpy=SerialNB.readString(); //讀取SerialNB串口緩存數(shù)組內(nèi)的數(shù)據(jù)保存到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相同的內(nèi)容,若找到,則返回字符串所在的位置
{
Serial.println(rpy); //打印獲取到的回復(fù)信息
break;
}
else
{
Serial.println("error");
SerialNB.println(data);
if (data.indexOf("+QMTPUB")){
char end = (char)0x1A;
SerialNB.print(end); //"CTRL+Z"發(fā)送數(shù)據(jù)
}
}
delay(100);
i++;
if(i>5)
break;
}
}
/*函數(shù)名稱: NB_MQTTSub
*說明: 訂閱某個主題的消息內(nèi)容
*參數(shù): msgID: 消息標(biāo)識符,范圍:1-65535 topic: 待訂閱的主題 Qos: 服務(wù)質(zhì)量等級(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");
}
到了這里,關(guān)于esp32通過NBIoT模塊連入MQTT服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!