因为疫情,封控在家。
找出很久之前买的Arduino和ESP8266练习了下,在此记录。
环境:
Arduino UNO R3
ESP-01,很老的固件(AT版本0.23),使用透传模拟MQTT数据
MQTT服务器安装在手机上,Termux+Mosquitto
电脑上装了Node-RED,然后发送测试消息。
代码:
#include <SoftwareSerial.h>
SoftwareSerial ss(3, 2); //RX,TX 分别接ESP8266的TX和RX
unsigned char con[17] = {0x10, 0x0f, 0x00, 0x04, 0x4d, 0x51, 0x54, 0x54, 0x04, 0x00, 0x00, 0x78, 0x00, 0x03, 0x61, 0x61, 0x61}; //连接,设备名:aaa,保活时间120秒
unsigned char sub[11] = {0x82, 0x09, 0x00, 0x02, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x00}; //订阅test主题
//unsigned char msg[13] = {0x31, 0x0B, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x6E, 0x69, 0x68, 0x61, 0x6F}; //发送消息
unsigned char xin[2] = {0xc0, 0x00}; //心跳包
//unsigned char dis[2] = {0xe0, 0x00}; //断开
unsigned long time0 = 0; //上次发送心跳包时间
unsigned long time1 = 0; //开始接收数据时间
int b = 0; //每次收到的数据
int flag = 0; //是否开始接收数据
int count = 0; //数据计数器
int len = 0; //数据长度
byte buff[20]; //暂存收到的数据
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.begin(9600);
ss.begin(9600);
ss.listen();
delay(5000); //等下ESP8266
ss.println("AT+CIPMUX=0");
delay(1000);
ss.println("AT+CIPSERVER=0");
delay(1000);
ss.println("AT+CIPMODE=1");
delay(1000);
ss.println("AT+CIPSTART=\"TCP\",\"192.168.0.112\",1883"); //和MQTT服务器建立TCP连接
delay(1000);
ss.println("AT+CIPSEND"); //开始透传
delay(100);
ss.write(con, 17); //和服务器建立MQTT协议连接
delay(100);
ss.write(sub, 11); //订阅主题
time0 = millis();
}
void loop() {
if ((millis() - time0) > 120000UL) { //每隔120秒发送一次心跳包
ss.write(xin, 2);
Serial.println("Keep");
time0 = millis();
}
if ((millis() - time1) > 1000) { //单次接收数据不超过1秒
flag = 0;
len = 0;
count = 0;
}
if (ss.available() > 0) {
b = ss.read();
Serial.write(b);
if (flag == 1) {
if (len == 0) {
len = b;
if (len > 20) {
flag = 0;
len = 0;
}
//Serial.print("Len:");
//Serial.println(len, DEC);
} else {
buff[count] = b;
count++;
if (count == len) { //接收完
//Serial.println("end");
int topic_len = buff[0] * 16 + buff[1];
//Serial.print("Topic Length:");
//Serial.println(topic_len, DEC);
String topic = "";
for (int i = 0; i < topic_len; i++) {
topic += (char)buff[i + 2];
}
Serial.print("Topic:");
Serial.println(topic);
String playload = "";
for (int i = 2 + topic_len; i < len; i++) {
playload += (char)buff[i];
}
Serial.print("Playload:");
Serial.println(playload);
if (topic == "test" && playload == "12345") { //turn on condition
Serial.println("ON");
digitalWrite(LED_BUILTIN, HIGH);
}
if (topic == "test" && playload == "12346") { //turn off condition
Serial.println("OFF");
digitalWrite(LED_BUILTIN, LOW);
}
flag = 0;
len = 0;
count = 0;
}
}
}
if (flag == 0) {
if (b == 0x30) {
flag = 1;
time1 = millis();
//Serial.println("start");
}
}
}
}
调试结果:
为了监控状况,使用了软串口连接ESP8266,但Arduino软串口有点不稳定。改成硬件串口没问题。