ESP32 Arduino Zigbee 风速传感器端点开发指南:ZigbeeWindSpeedSensor 类与 Wind Speed Measurement Cluster 全解析
【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32
本指南完整讲解 arduino-esp32 仓库中 Zigbee 库的ZigbeeWindSpeedSensor类:它是符合 Zigbee Home Automation(HA)标准的风速测量端点(Endpoint),用于气象站、风机监控、农业气象、海事与智能家居等场景。阅读完本文,你将掌握该端点的全部 API 用法、底层 ZCL 属性编码规则、端点注册流程,以及一套可直接运行的 End Device 示例和 HomeAssistant ZHA 集成方案。
功能概述与典型应用
ZigbeeWindSpeedSensor类继承自通用的 ZigbeeEP 基类,为 Zigbee 网络提供风速传感器端点,实现 Zigbee HA 标准中针对风速测量设备的规范。类声明位于 ZigbeeWindSpeedSensor.h,实现位于 ZigbeeWindSpeedSensor.cpp。
核心特性:
- 以 m/s 为单位的风速测量
- 可配置的测量量程(最小值/最大值)
- 容差(Tolerance)与上报(Reporting)配置
- 自动上报能力
- 与常见端点功能集成(绑定、OTA 等,由基类
ZigbeeEP提供) - Zigbee HA 标准合规
典型应用场景:
- 气象站
- 风力涡轮机监测
- 农业气象监测
- 海事应用
- 智能家居气象系统
- 工业风况监测
底层实现原理:设备 ID 与集群构成
从源码结构看,风速传感器没有专属的 Zigbee HA 设备 ID,构造函数中使用了通用传感器设备 ID:
ZigbeeWindSpeedSensor::ZigbeeWindSpeedSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; zigbee_wind_speed_sensor_cfg_t windspeed_sensor_cfg = ZIGBEE_DEFAULT_WIND_SPEED_SENSOR_CONFIG(); _cluster_list = zigbee_wind_speed_sensor_clusters_create(&windspeed_sensor_cfg); _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; }端点创建时注册了三个 Server 角色集群(见zigbee_wind_speed_sensor_clusters_create,ZigbeeWindSpeedSensor.cpp):
- Basic 集群(基础信息:zcl 版本、电源类型)
- Identify 集群(设备识别/定位)
- Wind Speed Measurement 集群(风速测量,核心集群,ZCL 集群 ID 为
ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT)
默认集群配置由宏ZIGBEE_DEFAULT_WIND_SPEED_SENSOR_CONFIG()定义(ZigbeeWindSpeedSensor.h),其中measured_value、min_measured_value、max_measured_value均使用 ESP Zigbee Stack 提供的默认值。
关键:0.01 m/s 定点编码。整个类内部所有浮点风速值在写入 ZCL 属性前都通过zb_windspeed_to_u16转为uint16_t:
static uint16_t zb_windspeed_to_u16(float windspeed) { return (uint16_t)(windspeed * 100); }也就是说,传入的1.23m/s 会被编码为123存入 ZCL 属性。调用所有 API 时传入的值单位均为 m/s,而底层属性单位是 0.01 m/s,这一点在后面的 HomeAssistant 集成读数转换中同样重要。
构造函数
ZigbeeWindSpeedSensor(uint8_t endpoint);endpoint—— 端点号,取值范围1–254。
创建一个新的 Zigbee 风速传感器端点。创建后还需通过Zigbee.addEndpoint(&sensor)注册到 Zigbee Core,再调用Zigbee.begin()启动网络。
API 方法详解
以下方法均声明于 ZigbeeWindSpeedSensor.h,实现细节可对照 ZigbeeWindSpeedSensor.cpp。
setWindSpeed —— 设置测量值
bool setWindSpeed(float value);value—— 风速值,单位 m/s(内部按 0.01 m/s 编码)。
更新 Wind Speed Measurement 集群的measured_value属性。实现中调用基类的setClusterAttribute(ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ..., ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID, &zb_windspeed, false)。成功返回true,失败返回false并打印log_e错误日志。该函数适合在测量任务中周期性调用。
setMinMaxValue —— 设置测量量程
bool setMinMaxValue(float min, float max);min—— 最小风速值,单位 m/s(0.01 m/s 编码)max—— 最大风速值,单位 m/s(0.01 m/s 编码)
分别更新min_measured_value与max_measured_value两个属性(ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MIN/MAX_MEASURED_VALUE_ID)。任何一步失败都会返回false。典型用法如示例中的setMinMaxValue(0, 50),表示量程 0~50 m/s。
setDefaultValue —— 设置默认(初始)值
bool setDefaultValue(float defaultValue);defaultValue—— 默认风速值,单位 m/s(0.01 m/s 编码)。
该值将作为设备处于出厂重置状态、传感器尚未给出真实读数时的初始测量值。实现直接更新measured_value属性:
bool ZigbeeWindSpeedSensor::setDefaultValue(float defaultValue) { uint16_t zb_default_value = zb_windspeed_to_u16(defaultValue); ... esp_err_t ret = esp_zb_cluster_update_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID, (void *)&zb_default_value); ... }重要:必须在将端点添加到 Zigbee 类(Zigbee.addEndpoint)之前调用,且仅在设备处于出厂重置模式(即加入/配网之前)时生效。
setTolerance —— 设置测量容差
bool setTolerance(float tolerance);tolerance—— 容差值,单位 m/s(0.01 m/s 编码),最低可取 0.01 m/s。
容差属性不包含在默认集群配置中,因此实现中通过esp_zb_wind_speed_measurement_cluster_add_attr动态追加ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_TOLERANCE_ID属性(ZigbeeWindSpeedSensor.cpp)。容差用于定义设备测量精度范围,也参与上报触发判断。
setReporting —— 配置上报
bool setReporting(uint16_t min_interval, uint16_t max_interval, float delta);min_interval—— 最小上报间隔,单位秒max_interval—— 最大上报间隔,单位秒delta—— 触发上报所需的最小变化量,单位 m/s(0.01 m/s 编码)
实现构造esp_zb_zcl_reporting_info_t上报配置结构:方向为ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,集群为 Wind Speed Measurement,属性为measured_value,delta.u16同样乘以 100 转换为 ZCL 编码,最后调用基类setClusterReporting()注册上报(ZigbeeWindSpeedSensor.cpp)。
必须在Zigbee.begin()之后调用(示例代码注释中明确说明)。上报触发规则(官方示例注释):
min = 1, max = 0:仅在风速变化量达到delta时上报;min = 0, max = 10:每 10 秒上报一次,或风速变化量达到delta时上报;min = 0, max = 10, delta = 0:无论风速是否变化,每 10 秒上报一次。
reportWindSpeed —— 手动上报
bool reportWindSpeed();手动上报当前风速值。实现构造esp_zb_zcl_report_attr_cmd_t命令,方向为ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI,通过基类reportClusterAttribute()发送 report attributes 命令(ZigbeeWindSpeedSensor.cpp)。可用于按钮触发、事件触发等场景,例如示例中短按按键时调用。
完整示例:End Device 风速传感器
仓库在 libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/ 提供了完整可运行的示例(Zigbee_Wind_Speed_Sensor.ino),下面结合源码逐段说明。
编译期检查与全局对象
#include <Arduino.h> #ifndef ZIGBEE_MODE_ED #error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" #endif #include "Zigbee.h" #define BUTTON_PIN 9 //Boot button for C6/H2 #define WIND_SPEED_SENSOR_ENDPOINT_NUMBER 10 ZigbeeWindSpeedSensor zbWindSpeedSensor = ZigbeeWindSpeedSensor(WIND_SPEED_SENSOR_ENDPOINT_NUMBER);- 使用
#ifndef ZIGBEE_MODE_ED做编译期检查,提醒必须在Tools → Zigbee mode中选择ED(End Device)模式(同时在Tools → Partition Scheme中选择正确的 Zigbee 分区方案)。 - 示例面向 ESP32-C6/H2 开发板,Boot 按键接 GPIO 9,端点号取 10。
setup:注册端点并启动 Zigbee
void setup() { Serial.begin(115200); while (!Serial) { delay(10); } pinMode(BUTTON_PIN, INPUT); // 可选:设置 Zigbee 设备名称与型号 zbWindSpeedSensor.setManufacturerAndModel("Espressif", "ZigbeeWindSpeedSensor"); // 设置风速测量量程(单位 m/s) zbWindSpeedSensor.setMinMaxValue(0, 50); // 设置测量容差(单位 m/s,最低 0.01 m/s) zbWindSpeedSensor.setTolerance(1); // 将端点注册到 Zigbee Core Zigbee.addEndpoint(&zbWindSpeedSensor); Serial.println("Starting Zigbee..."); if (!Zigbee.begin()) { Serial.println("Zigbee failed to start!"); Serial.println("Rebooting..."); ESP.restart(); } else { Serial.println("Zigbee started successfully!"); } Serial.println("Connecting to network"); while (!Zigbee.connected()) { Serial.print("."); delay(100); } Serial.println(); // 启动风速读取任务 xTaskCreate(windspeed_sensor_value_update, "wind_speed_sensor_update", 3072, NULL, 10, NULL); // 设置上报(必须在 Zigbee.begin() 之后调用) zbWindSpeedSensor.setReporting(1, 0, 1); }要点:
setManufacturerAndModel由基类提供,用于设置 Basic 集群的制造商与型号字符串。- 调用顺序:
setMinMaxValue/setTolerance等属性设置必须在addEndpoint之前完成;setReporting必须在Zigbee.begin()之后调用。 Zigbee.begin()失败会自动重启设备,连接网络前通过Zigbee.connected()轮询等待。
周期读取任务:模拟风速数据
static void windspeed_sensor_value_update(void *arg) { for (;;) { // 读取风速传感器值(此处用内部温度传感器模拟) float windspeed = temperatureRead(); log_v("Wind speed sensor value: %.2fm/s", windspeed); zbWindSpeedSensor.setWindSpeed(windspeed); delay(1000); } }示例用 ESP32 内部温度传感器读数模拟风速,每秒调用一次setWindSpeed()更新端点属性。实际项目中应替换为真实风速计(如风杯式或超声波风速仪)的采样值。
loop:按键出厂重置与手动上报
void loop() { if (digitalRead(BUTTON_PIN) == LOW) { // 按键按下 delay(100); int startTime = millis(); while (digitalRead(BUTTON_PIN) == LOW) { delay(50); if ((millis() - startTime) > 3000) { // 长按 3 秒:恢复出厂设置并重启 Serial.println("Resetting Zigbee to factory and rebooting in 1s."); delay(1000); Zigbee.factoryReset(); } } zbWindSpeedSensor.reportWindSpeed(); // 短按:手动上报当前风速 } delay(100); }- 长按 3 秒调用
Zigbee.factoryReset()恢复出厂设置并重启,用于设备重新配网; - 短按调用
reportWindSpeed()手动上报一次当前风速,是reportWindSpeed方法的典型事件触发用法。
HomeAssistant ZHA 集成
仓库示例目录下的 README.md 给出了将 ESP32 风速传感器接入 HomeAssistant ZHA 的完整方案。由于 HomeAssistant ZHA 对 wind speed 集群(cluster 1035)原生支持有限,官方推荐两条路线:
路线一:通过 ZHA Toolkit(HACS 插件)读取属性
- 在 HomeAssistant 中通过 HACS 安装 "ZHA Toolkit - Service for advanced Zigbee Usage" 并重启;
- 在 Configuration → Devices & Services → Helpers 中新增一个 Number 辅助变量(如
wind_speed); - 新建自动化,触发器设为每 30 秒的 Time Pattern,动作使用 ZHA Toolkit 的 Read Attribute,示例 YAML 如下:
action: zha_toolkit.attr_read metadata: {} data: ieee: f0:f5:bd:ff:fe:0e:61:30 # 设备 IEEE 地址 endpoint: 10 # 风速设备端点号 cluster: 1035 # wind speed 集群 attribute: 0 # 读取 measured value 属性 state_id: input_number.wind_speed # 保存到辅助变量 state_value_template: value/100 # 将 u16 编码转换为浮点 m/s注意state_value_template: value/100:因为设备侧按 0.01 m/s 定点编码,读取到的原始 u16 值必须除以 100 才能还原为 m/s 浮点值,这与前文zb_windspeed_to_u16的编码规则正好对应。之后wind_speed即成为 HomeAssistant 实体,可用于仪表盘展示或其它自动化。
路线二:自定义 Quirk 设备处理器对进阶用户,可编写自定义 quirk 直接支持 wind speed 集群,获得更无缝的集成体验。该方案需要熟悉 Python 与 Zigbee 协议,但能对设备行为提供更灵活的掌控。
注意事项与最佳实践
- 单位一致性:所有 API 参数以 m/s 为单位,底层属性为 0.01 m/s 定点 u16。设置与读取两端需保持同样的换算逻辑(×100 / ÷100)。
- 调用时序:
setDefaultValue、setMinMaxValue、setTolerance等属性配置须在Zigbee.addEndpoint()之前;setDefaultValue仅在出厂重置模式(加入网络前)生效;setReporting必须在Zigbee.begin()之后调用。
- 编译配置:示例依赖
ZIGBEE_MODE_ED宏,必须在 Arduino IDE 的 Tools → Zigbee mode 选择 End Device(ED),并选择配套的 Zigbee Partition Scheme。 - 返回值为
false的排查:所有方法失败时都会通过log_e输出 ESP-IDF 错误码(如esp_err_to_name、esp_zb_zcl_status_to_name),结合串口日志可快速定位属性更新、集群注册或上报配置失败的原因。 - 上报策略:合理组合
min_interval、max_interval与delta可平衡网络流量与数据实时性——需要即时感知风速突变时使用小的delta,需要周期性数据时设置max_interval。
【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考