提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本系列将以0基础新手视角,完整演示Arduino+ESP8266连接OneNET云平台的全流程,涵盖ESP8266固件烧录、物模型的模型设计、MQTT协议配置及代码实现。建议搭配Arduino IDE 2.0+和Arduino开发板使用。
(二)本文为arduino连接ESP8266(ESP-01S)
前文为,ESP8266模块的测试以及MQTT固件的烧录,不可缺少。
一、前期准备
1.1 硬件配置
需准备Arduino开发板 和 ESP8266
1.2 软件环境配置
安装Arduino IDE 2.0.2
安装 EspSoftwareSerial 库(工具→库管理→搜索EspSoftwareSerial→安装)
二、接线
注:arduino的 5V 给ESP8266的3.3V 供电,不然电压可能不够。
代码中的这句话是指 arduino的软串口,RX为9,TX为10;此时我们用ESP8266的TX接9,RX接10
SoftwareSerial espSerial(9, 10); // RX=9, TX=10 注意前面的是指arduino的TRX,连线时候ESP8266的TX应接9,RX接10
arduino uno | ESP8266 |
---|---|
5V | 3.3V 和 EN(即CH_PD) |
10 | RX |
9 | TX |
GND | GND |
再从 引脚5 引出一根导线,连接 小电阻→LED灯→GND
以备之后测试云平台下发
三、核心代码
3.1 总代码
替换
const char* WIFI_SSID = "Xiaomi 15";
const char* WIFI_PWD = "147258369";
// OneNET参数
#define PRODUCT_ID "1SX9Lm39T5"
#define DEVICE_NAME "arduino"
#define TOKEN "version=2018-10-31&res=products%2F1SX
代码:
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
// 网络配置
const char* WIFI_SSID = "Xiaomi 15";
const char* WIFI_PWD = "147258369";
const char* MQTT_SERVER = "mqtts.heclouds.com";
// OneNET 物联参数
const int MQTT_PORT = 1883;
#define PRODUCT_ID "1SX9Lm39T5"
#define DEVICE_NAME "arduino"
#define TOKEN "version=2018-10-31&res=products%2F1SX9Lm39T5%2Fdevices%2Farduino&et=2059472864&method=md5&sign=F5DI%2FHUhIdIeZx1CUsR%2ByQ%3D%3D"
// 硬件配置
SoftwareSerial espSerial(9, 10); // RX=9, TX=10 注意前面的是指arduino的TRX,连线时候ESP8266的TX应接9,RX接10
#define TLED_PIN 5 // LED控制引脚
// 全局变量
const unsigned long readInterval = 3000;// 数据上报周期(ms)
int postMsgId = 0; // 消息序列号
float temp = 20.25; // 温度值
bool TLED_state = true; // LED开关状态
//前置函数声明
bool sendATCommand(const char* cmd, const char* ack, unsigned int timeout);
void initESP8266();
void initSwitch();
void Post_Sensor();
void Post_Switch();
void setup() {
Serial.begin(9600); // 调试串口
espSerial.begin(9600); // ESP8266通信
initESP8266();
initSwitch();
}
void loop() {
handleMQTTMessage();
// 定时上传数据
static unsigned long lastPost = 0;
if (millis() - lastPost >= readInterval) {
Post_Switch();
// Post_Sensor();
lastPost = millis();
}
}
// AT指令发送函数(带超时检测)
bool sendATCommand(const char* cmd, const char* ack, unsigned int timeout) {
espSerial.println(cmd);
unsigned long start = millis();
String response;
while (millis() - start < timeout) {
while (espSerial.available()) {
char c = espSerial.read();
response += c;
}
if (response.indexOf(ack) != -1) {
Serial.print("[SUCCESS] ");
Serial.println(cmd);
return true;
}
}
Serial.print("[ERROR] ");
Serial.print(cmd);
Serial.println(" 未收到预期响应");
return false;
}
void initESP8266(){
// 初始化ESP8266
sendATCommand("AT", "OK", 2000);
// sendATCommand("AT+RST", "ready", 8000);
sendATCommand("AT+CWMODE=1", "OK", 1000);
sendATCommand("AT+CWDHCP=1,1", "OK", 1000);
// 连接WiFi
String cmd = "AT+CWJAP=\"" + String(WIFI_SSID) + "\",\"" + String(WIFI_PWD) + "\"";
sendATCommand(cmd.c_str(), "OK", 5000);\
// 配置MQTT
String mqttCfg = "AT+MQTTUSERCFG=0,1,\"" + String(DEVICE_NAME) + "\",\"" + String(PRODUCT_ID) + "\",\"" + String(TOKEN) + "\",0,0,\"\"";
sendATCommand(mqttCfg.c_str(), "OK", 5000);
// 连接服务器
String connCmd = "AT+MQTTCONN=0,\"" + String(MQTT_SERVER) + "\"," + String(MQTT_PORT) + ",1";
sendATCommand(connCmd.c_str(), "OK", 5000);
// 添加订阅命令(在MQTT连接成功后)
String subscribeCmd = "AT+MQTTSUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME) + "/thing/property/set\",1";
sendATCommand(subscribeCmd.c_str(), "OK", 2000);
}
void initSwitch(){
pinMode(TLED_PIN, OUTPUT);
digitalWrite(TLED_PIN, TLED_state);
}
void Post_Sensor(){
postMsgId++;
// 手动拼接字符串,双引号 \",逗号 \,,符合 ESP8266 的 AT 命令转义要求
String jsonPayload = "\\\"id\\\":\\\"" + String(postMsgId) + "\\\"\\,"
+ "\\\"version\\\":\\\"1.0\\\"\\,"
+ "\\\"params\\\":{"
+ "\\\"temp\\\":{\\\"value\\\":" + String(temp, 2) + "}\\,"
+ "\\\"TLED\\\":{\\\"value\\\":" + (TLED_state ? "true" : "false") + "}"
+ "}";
jsonPayload = "{" + jsonPayload + "}";
// 构造 MQTT 发布命令
String pubCmd = "AT+MQTTPUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME)
+ "/thing/property/post\",\"" + jsonPayload + "\",0,0";
// 发送
sendATCommand(pubCmd.c_str(), "OK", 3000);
}
void Post_Switch(){
postMsgId++;
// 手动拼接字符串,双引号 \",逗号 \,,符合 ESP8266 的 AT 命令转义要求
String jsonPayload = "\\\"id\\\":\\\"" + String(postMsgId) + "\\\"\\,"
+ "\\\"version\\\":\\\"1.0\\\"\\,"
+ "\\\"params\\\":{"
+ "\\\"temp\\\":{\\\"value\\\":" + String(temp, 2) + "}\\,"
+ "\\\"TLED\\\":{\\\"value\\\":" + (TLED_state ? "true" : "false") + "}"
+ "}";
jsonPayload = "{" + jsonPayload + "}";
// 构造 MQTT 发布命令
String pubCmd = "AT+MQTTPUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME)
+ "/thing/property/post\",\"" + jsonPayload + "\",0,0";
// 发送
sendATCommand(pubCmd.c_str(), "OK", 3000);
}
// 接收数据函数 ▼
void handleMQTTMessage() {
while (espSerial.available()) {
String message = espSerial.readStringUntil('\n');
if (message.indexOf("+MQTTSUBRECV:") != -1) { // 检测到新消息
Serial.print("收到原始消息:");
Serial.println(message); // 调试输出
// 提取JSON部分
int jsonStart = message.indexOf('{');
String jsonStr = message.substring(jsonStart);
JsonDocument doc;
DeserializationError error = deserializeJson(doc, jsonStr);
if (!error) {
if (doc["params"]["TLED"].as<bool>()) {
digitalWrite(TLED_PIN, HIGH);
TLED_state = true;
Serial.println("✅ 已开灯");
} else {
digitalWrite(TLED_PIN, LOW);
TLED_state = false;
Serial.println("✅ 已关灯");
}
// 回复 set 指令
int id = doc["id"] | 0; // 取出id进行回复(可选)
String replyJson = String("{\\\"id\\\":\\\"") + id + "\\\",\\\"code\\\":200}";
String cmd = "AT+MQTTPUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME) + "/thing/property/set/reply\",\"" + replyJson + "\",0,0";
sendATCommand(cmd.c_str(), "OK", 1000);
}
else {
Serial.println("[ERROR] JSON解析失败");
}
}
}
}
三、最终效果
串口上,会出现几个error,属于正常情况,如响应超时等
后续出现的success,就代表上传成功
若有问题,则重复上篇文章,使用USB转TTL,进行AT指令测试
总结
本文搭建了 基于Arduino的ESP8266连接OneNET云平台(MQTT协议 物模型)。