4. 云端指令下发至边缘
任务目标
本案例实现云端向边缘设备下发控制指令的完整闭环:在云平台(MQTT Broker)上发布一条JSON格式的控制指令,边缘设备(ESP8266/ESP32)订阅对应主题并接收指令,解析后驱动GPIO执行开关动作,同时回传执行状态确认。
环境与依赖
- 硬件:ESP8266 或 ESP32 开发板(内置LED或外接LED至GPIO2)
- Arduino IDE(安装ESP8266/ESP32开发板支持包)
- 所需库:
PubSubClient(MQTT客户端)、ArduinoJson(JSON解析) - MQTT Broker:可使用公共测试服务器
broker.emqx.io(端口1883)
实现方案
采用MQTT发布/订阅模型。云端作为发布者向主题 device/control 发送指令;边缘设备订阅该主题,收到消息后解析JSON中的 action 字段,执行对应GPIO操作,并向主题 device/status 发布执行结果。设备离线时云端无法感知,因此增加MQTT遗嘱消息(LWT)用于状态监控。
完整代码
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
// WiFi配置
const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
// MQTT配置
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
const char* client_id = "edge_device_001";
const char* topic_control = "device/control";
const char* topic_status = "device/status";
WiFiClient espClient;
PubSubClient client(espClient);
const int ledPin = 2; // 板载LED
void setup_wifi() {
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void publish_status(const char* action, bool success) {
StaticJsonDocument<128> doc;
doc["device_id"] = client_id;
doc["action"] = action;
doc["success"] = success;
doc["timestamp"] = millis();
char buffer[128];
serializeJson(doc, buffer);
client.publish(topic_status, buffer);
}
void callback(char* topic, byte* payload, unsigned int length) {
// 解析JSON指令
StaticJsonDocument<128> doc;
deserializeJson(doc, payload, length);
const char* action = doc["action"] | "";
if (strcmp(action, "ON") == 0) {
digitalWrite(ledPin, LOW); // ESP8266低电平点亮
publish_status("ON", true);
} else if (strcmp(action, "OFF") == 0) {
digitalWrite(ledPin, HIGH);
publish_status("OFF", true);
} else {
publish_status(action, false); // 未知指令
}
}
void reconnect() {
while (!client.connected()) {
if (client.connect(client_id)) {
client.subscribe(topic_control);
}
}
}
void setup() {
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH); // 初始关闭
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
reconnect();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
运行与验证
- 将代码中的
ssid和password替换为实际WiFi信息,编译烧录至开发板。 - 打开串口监视器(波特率115200),确认设备成功连接WiFi和MQTT Broker。
- 使用MQTT客户端工具(如MQTT X、mosquitto_pub)向主题
device/control发布指令:
mosquitto_pub -h broker.emqx.io -t device/control -m '{"action":"ON"}'
- 观察开发板板载LED应点亮;再发布
{"action":"OFF"},LED应熄灭。 - 订阅主题
device/status,应收到设备回传的状态确认消息,格式类似:
{"device_id":"edge_device_001","action":"ON","success":true,"timestamp":12345}
通过条件:LED状态随云端指令正确切换,且状态主题能收到对应的成功回执。若发布未知指令(如 {"action":"TOGGLE"}),状态主题应返回 "success":false,LED状态不变。
常见问题
- 无法连接MQTT:确认WiFi已连接,且目标Broker允许匿名访问;公共Broker偶尔不稳定,可更换为
test.mosquitto.org。 - 收不到指令:检查订阅主题是否与发布主题完全一致(区分大小写);确认设备在线(串口输出无报错)。
- JSON解析失败:确保发布的消息是合法JSON格式,且字段名与代码中一致(
action)。