Using the PubSubClient library (version 2.8.0), you can quickly implement MQTT data packet encapsulation and use ESP32-C3 as an MQTT Client to connect to the MQTT Server. This article connects to OneNET's MQTT product and selects the old version of the platform's MQTT access.
Figure 10-1 PubSubClient library
The case is completed on the basis of the previous article , and only the added code is shown here.
In order to verify the two-way communication capability of MQTT, the onboard LED of Beetle ESP32-C3 (connected to GPIO10) is enabled. Commands can be sent through the OneNET platform to control the light. Here, "L0" is turned off and "L1" is turned on.
The access address of the old version of OneNET MQTT is: 183.230.40.39, the port is 6002. To access, you need to configure the "Device ID (that is, the Client ID of the MQTT protocol)", "Product ID (that is, the user name of the MQTT protocol)" and "Authentication information (that is, the password of the MQTT protocol)".
In addition, OneNET uploads data by publishing a message with the subject "$dp" to the platform, and the message payload (PayLoad) has a format defined by the platform. This example uses format 3 - a JSON object format, such as: {"temp":29,"humi":26}.
//增加启用LED的相关宏定义
#define LED 10
#define LED_ON digitalWrite(LED, HIGH)
#define LED_OFF digitalWrite(LED, LOW)
//增加OneNET MQTT 信息
const char *mqtt_server = "183.230.40.39"; //onenet 的 IP地址
#define mqtt_devid "deviceid" //设备ID需在OneNET注册
#define mqtt_pubid "productid" //产品ID需在OneNET注册
#define mqtt_password "authorization" //鉴权信息建立产品时自定义
WiFiClient espClient; //tcp client实例用于连接OneNET服务器
PubSubClient client(espClient); //pubsub client实例
char msg_buf[200]; //发送信息的缓存
char dataTemplate[] = "{\"temp\":%d,\"humi\":%d}";//封装格式3的模板
char msgJson[75]; //存放封装好的JSON字串
unsigned short json_len = 0; //JSON字串长度
void sendTempAndHumi(void);
void clientReconnect(void);
//-----get OneNET order callback
void callback(char *topic, byte *payload, unsigned int length) {
Serial.println("message rev:");
Serial.println(topic);
for(size_t i=0; i<length; i++) Serial.print((char)payload[i]);
Serial.println();
if(payload[0] == 'L') {
if(payload[1] == 0x30) //第二个接收字符是0,则接收“L0”,熄灯
LED_OFF;
else if(payload[1] == 0x31) //第二个接收字符是1,则接收“L1”,点灯
LED_ON;
}
}
//-----send data to OneNET
void sendTempAndHumi(void) {
if(client.connected()) {
//为了省事,温湿度只取整数部分,这样可以保证snprintf()转字串成功
int temperature = (int)aht_temp.temperature;
int humidity = (int)aht_humi.relative_humidity;
//将湿度数据套入dataTemplate模板中, 生成的字符串传给msgJson
snprintf(msgJson, 40, dataTemplate, temperature, humidity);
//msgJson的长度
json_len = strlen(msgJson);
//payload首字迹是OneNET格式编号,这里为格式3
msg_buf[0] = char(0x03);
//数据第二位是要发送的数据长度的高八位,数据第三位是要发送数据的长度的低八位
msg_buf[1] = char(json_len >> 8);
msg_buf[2] = char(json_len & 0xff);
//从msg_buf的第四位开始,放入要传的数据msgJson
memcpy(msg_buf + 3, msgJson, strlen(msgJson));
//添加一个0作为最后一位, 这样要发送的msg_buf准备好了
msg_buf[3 + strlen(msgJson)] = 0;
Serial.print("public message:");
Serial.println(msgJson);
//发送数据到主题$dp
client.publish("$dp", (uint8_t *)msg_buf, 3 + strlen(msgJson));
}
}
//重连函数, 如果客户端断线,可以通过此函数重连
void clientReconnect(void) {
while(!client.connected()) {
Serial.println("reconnect MQTT...");
if(client.connect(mqtt_devid, mqtt_pubid, mqtt_password)) {
Serial.println("connected");
} else {
Serial.println("failed");
Serial.println(client.state());
Serial.println("try again in 5 sec");
delay(5000);
}
}
}
//setup()中增加LED初始化和MQTT接入
void setup() {
//省略其它代码
pinMode(LED, OUTPUT);
LED_OFF;
//-----connect to OneNET
//设置客户端连接的服务器,连接Onenet服务器, 使用6002端口
client.setServer(mqtt_server, 6002);
//客户端连接到指定的产品的指定设备.同时输入鉴权信息
client.connect(mqtt_devid, mqtt_pubid, mqtt_password);
//注册回调函数
client.setCallback(callback);
}
//loop()中增加发送
void loop() {
//省略其它代码
//-----update weather info per 5 minutes
if(t.tm_min%5==0 && t.tm_sec==0) {
getAHT10();
if(WiFi.status() == WL_CONNECTED) {
getWeather();
}
sendTempAndHumi(); //此处增加发送温湿度调用
}
//省略其它代码
}
After the platform sends the command, the serial port can see the analysis, and the LED will also change. Command analysis relies on receiving callback callback(). The PubSubClient library automatically analyzes the received data packet and obtains the topic and payload. The topic of the command sent by OneNET is "$crep" plus a uuid, and the command is the payload. Because the parsed command is a byte array, in order to save trouble, no String class conversion is performed. The custom commands are "L0" and "L1", which are also relatively simple, and a byte-by-byte comparison is sufficient.
Figure 10-2 Serial port output of parsing command