ESP32智能家居传感器组网实战:用ESP-NOW搭建多对一数据采集系统,直连Home Assistant
ESP32智能家居传感器组网实战用ESP-NOW搭建多对一数据采集系统直连Home Assistant在智能家居DIY领域如何高效、稳定地采集分布在不同位置的传感器数据一直是个挑战。传统Wi-Fi组网虽然常见但存在功耗高、配置复杂等问题。本文将带你用ESP32和ESP-NOW协议构建一个多对一数据采集系统将多个传感器节点的数据汇总到中心网关并最终上报至Home Assistant实现低功耗、高可靠的智能家居传感网络。1. ESP-NOW技术解析与方案设计ESP-NOW是乐鑫推出的一种高效的无线通信协议它工作在2.4GHz频段不需要复杂的网络配置就能实现设备间的直接通信。与传统的Wi-Fi连接相比ESP-NOW具有以下显著优势低功耗通信过程不需要维持长连接适合电池供电场景低延迟点对点传输数据直达目标设备简单配置无需路由器或复杂的网络设置多拓扑支持支持一对一、一对多和多对一通信模式在我们的智能家居传感器组网方案中将采用多对一的通信模式多个作为发送端的ESP32传感器节点将采集到的环境数据如温湿度、门窗状态等通过ESP-NOW发送到中心网关ESP32网关再通过MQTT协议将数据上传到Home Assistant服务器。提示ESP-NOW的有效载荷限制为250字节对于传感器数据采集场景完全够用但不宜用于传输大块数据。2. 硬件准备与网络拓扑搭建2.1 所需硬件组件构建完整的系统需要以下硬件组件类型数量说明ESP32开发板N1N个传感器节点 1个中心网关温湿度传感器若干如DHT22、BME280等门窗磁传感器若干用于检测门窗开关状态电源方案-节点可采用电池供电网关建议USB供电2.2 网络拓扑设计我们的系统采用三层架构传感层分布在各个位置的ESP32节点负责采集环境数据汇聚层中心网关ESP32接收所有节点数据应用层Home Assistant服务器通过MQTT接收网关数据[传感器节点1] --ESP-NOW-- [传感器节点2] --ESP-NOW-- [网关ESP32] --MQTT-- [Home Assistant] [传感器节点3] --ESP-NOW--2.3 节点供电方案根据部署位置不同可采用不同供电方式常电位置如靠近插座的门窗传感器可使用USB电源适配器无电位置采用18650锂电池TP4056充电模块配合深度睡眠实现长续航太阳能供电户外传感器可搭配小型太阳能板3. 传感器节点固件开发传感器节点需要完成数据采集和ESP-NOW发送两个主要功能。下面以温湿度传感器节点为例介绍具体实现。3.1 硬件连接将DHT22传感器连接到ESP32DHT22 VCC - ESP32 3.3V DHT22 GND - ESP32 GND DHT22 DATA - ESP32 GPIO43.2 基础代码框架#include WiFi.h #include esp_now.h #include DHT.h #define DHTPIN 4 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); // 网关MAC地址 uint8_t gatewayAddress[] {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX}; // 数据结构定义 typedef struct sensor_data { float temperature; float humidity; uint16_t node_id; } sensor_data; sensor_data myData;3.3 ESP-NOW初始化和发送void setup() { Serial.begin(115200); dht.begin(); WiFi.mode(WIFI_STA); if (esp_now_init() ! ESP_OK) { Serial.println(ESP-NOW初始化失败); return; } esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, gatewayAddress, 6); peerInfo.channel 0; peerInfo.encrypt false; if (esp_now_add_peer(peerInfo) ! ESP_OK) { Serial.println(添加网关失败); return; } } void loop() { myData.temperature dht.readTemperature(); myData.humidity dht.readHumidity(); myData.node_id 1; // 每个节点有唯一ID esp_err_t result esp_now_send(gatewayAddress, (uint8_t *) myData, sizeof(myData)); if (result ESP_OK) { Serial.println(数据发送成功); } else { Serial.println(数据发送失败); } // 深度睡眠实现低功耗 esp_deep_sleep(60e6); // 睡眠60秒 }注意实际部署时需要为每个节点设置唯一的node_id方便网关识别数据来源。4. 网关固件开发与MQTT集成网关ESP32需要完成三项核心功能接收ESP-NOW数据、聚合处理数据、通过MQTT上报到Home Assistant。4.1 接收ESP-NOW数据#include WiFi.h #include esp_now.h #include ArduinoJson.h #include PubSubClient.h // 数据结构定义 typedef struct sensor_data { float temperature; float humidity; uint16_t node_id; } sensor_data; sensor_data receivedData; // MQTT客户端 WiFiClient espClient; PubSubClient client(espClient); void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { memcpy(receivedData, incomingData, sizeof(receivedData)); // 处理接收到的数据 processSensorData(receivedData); }4.2 数据处理与MQTT发布void processSensorData(sensor_data data) { // 创建JSON文档 DynamicJsonDocument doc(256); doc[node_id] data.node_id; doc[temperature] data.temperature; doc[humidity] data.humidity; char jsonBuffer[256]; serializeJson(doc, jsonBuffer); // 发布到MQTT String topic home/sensor/ String(data.node_id); client.publish(topic.c_str(), jsonBuffer); } void setup() { // 初始化串口、WiFi等 Serial.begin(115200); WiFi.begin(your_ssid, your_password); // 初始化ESP-NOW WiFi.mode(WIFI_STA); if (esp_now_init() ! ESP_OK) { Serial.println(ESP-NOW初始化失败); return; } esp_now_register_recv_cb(OnDataRecv); // 配置MQTT client.setServer(mqtt_server_ip, 1883); } void loop() { if (!client.connected()) { reconnectMQTT(); } client.loop(); }4.3 MQTT连接管理void reconnectMQTT() { while (!client.connected()) { if (client.connect(ESP32Gateway)) { Serial.println(MQTT连接成功); } else { Serial.print(MQTT连接失败rc); Serial.print(client.state()); Serial.println( 5秒后重试); delay(5000); } } }5. Home Assistant配置与自动化5.1 MQTT集成配置在Home Assistant的configuration.yaml中添加mqtt: broker: 192.168.x.x username: your_username password: your_password sensor: - platform: mqtt name: Living Room Temperature state_topic: home/sensor/1 value_template: {{ value_json.temperature }} unit_of_measurement: °C - platform: mqtt name: Living Room Humidity state_topic: home/sensor/1 value_template: {{ value_json.humidity }} unit_of_measurement: %5.2 自动化示例当温度超过阈值时发送通知automation: - alias: High Temperature Alert trigger: platform: numeric_state entity_id: sensor.living_room_temperature above: 28 action: - service: notify.mobile_app_phone data: message: 客厅温度过高当前温度{{ states(sensor.living_room_temperature)}}°C6. 实际部署优化与问题排查6.1 信号覆盖优化天线方向调整ESP32板载天线方向避免被金属物体遮挡中继节点在信号弱的区域可部署中继ESP32节点信道选择使用WiFi分析仪选择干扰最小的信道6.2 数据一致性保障加入时间戳在数据结构中添加RTC时间戳避免数据处理混乱数据校验添加CRC校验字段确保数据完整性重传机制实现简单的重传逻辑应对偶尔的传输失败6.3 常见问题排查问题1数据接收不全检查数据结构定义在发送端和接收端是否一致确认MAC地址配置正确检查电源稳定性电压不足可能导致发送异常问题2MQTT连接不稳定检查WiFi信号强度增加MQTT心跳间隔考虑使用更稳定的MQTT broker实现问题3电池消耗过快优化深度睡眠时间检查是否有外设未进入低功耗模式考虑使用更高容量的电池在实际部署中我发现将传感器节点的发送间隔设置为60秒是一个较好的平衡点既能保证数据及时性又能实现较长的电池续航。对于关键区域的门窗传感器可以缩短到30秒间隔而温湿度等变化较慢的传感器可以延长到5分钟。