基于Arduino的ESP8266连接OneNET云平台(MQTT协议 物模型)(三)连接云平台-优化版

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本系列将以0基础新手视角,完整演示Arduino+ESP8266连接OneNET云平台的全流程,涵盖ESP8266固件烧录、物模型的模型设计、MQTT协议配置及代码实现。建议搭配Arduino IDE 2.0+和Arduino开发板使用。

(三)本文为arduino连接ESP8266(ESP-01S)的 优化版

优化了,上传的格式,(二)中的转义符过于复杂,改用 Raw

可不看(二),直接看(三)

一、前期准备

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 unoESP8266
5V3.3V 和 EN(即CH_PD)
10RX
9TX
GNDGND

再从 引脚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
相较于上个版本,我修改了上传格式,更为简洁,若还是不明白添加或者减少 上传数量 的格式,可用ai辅助。
并且注意代码中的标识符和定义和云平台的已经对不上了,要根据实际去修改。包括回调函数里面的标识符

代码:

#include <SoftwareSerial.h>
#include <ArduinoJson.h>
/*

若发现上传一直error,从第一次上传开始就error,则需要,
将上传的函数注释掉两个,也就是只上传一个函数,这时会成功。
然后再取消另外两个函数的注释,就都可以上传成功,

*/

// 网络配置
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_test = 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++;

  // 使用原始字符串构造JSON(无需转义符)
  String jsonPayload = "{";
  jsonPayload += "\"id\":\"" + String(postMsgId) + "\",";
  jsonPayload += "\"version\":\"1.0\",";
  jsonPayload += "\"params\":{";
  jsonPayload += "\"t1\":{\"value\":" + String(t1) + "},"; 
  jsonPayload += "\"t2\":{\"value\":" + String(t2) + "}";
  jsonPayload += "}}";

  // 构造MQTT二进制发布指令(规避转义问题)
  String pubCmd = "AT+MQTTPUBRAW=0,\"$sys/" + String(PRODUCT_ID) + "/" 
                + String(DEVICE_NAME) + "/thing/property/post\","
                + String(jsonPayload.length()) + ",0,0";
  
  // 发送指令和JSON数据(分两步)
  sendATCommand(pubCmd.c_str(), ">", 1000);  // 等待">"提示符
  delay(50);
  sendATCommand(jsonPayload.c_str(), "OK", 3000);
}


void Post_Switch() {
  postMsgId++;

  // 直接构建合法JSON字符串(无需手动转义双引号)
  String jsonPayload = "{";
  jsonPayload += "\"id\":\"" + String(postMsgId) + "\",";
  jsonPayload += "\"version\":\"1.0\",";
  jsonPayload += "\"params\":{";
  jsonPayload += "\"T\":{\"value\":" + String(TLED_state ? "true" : "false") + "},";
  jsonPayload += "\"H\":{\"value\":" + String(Heating_state ? "true" : "false") + "},";
  jsonPayload += "\"A\":{\"value\":" + String(AddHeating_state ? "true" : "false") + "}";
  jsonPayload += "}}";  // 闭合外层JSON结构

  // 构造MQTT二进制发布指令(规避转义问题)
  String pubCmd = "AT+MQTTPUBRAW=0,\"$sys/" + String(PRODUCT_ID) + "/" 
                + String(DEVICE_NAME) + "/thing/property/post\","
                + String(jsonPayload.length()) + ",0,0";
  
  // 分两步发送:先发送指令头,再发送原始JSON数据
  sendATCommand(pubCmd.c_str(), ">", 1000);  // 等待">"提示符
  delay(50);                                  // 确保模块准备好接收数据
  sendATCommand(jsonPayload.c_str(), "OK", 3000); // 发送JSON内容
}

// 接收数据函数 ▼
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协议 物模型)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

承前智

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值