ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Arduino ESP32 ZigbeeSwitch 端点完整指南:用 ESP32 构建 Zigbee HA 智能开关

Arduino ESP32 ZigbeeSwitch 端点完整指南:用 ESP32 构建 Zigbee HA 智能开关 Arduino ESP32 ZigbeeSwitch 端点完整指南用 ESP32 构建 Zigbee HA 智能开关【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32导读本文档基于 arduino-esp32 仓库中 docs/en/zigbee/ep_switch.rst 展开系统讲解ZigbeeSwitch类的用法。该类为 ESP32 提供符合 Zigbee Home AutomationHA标准的开关端点Switch Endpoint用于通过 on/off 命令控制网络中的其他设备典型场景是控制 Zigbee 灯。读完本文你将掌握如何创建开关端点、四种开/关/切换命令的寻址方式、带效果与定时的进阶控制命令以及如何通过绑定机制让灯与开关配对并理解其底层 ZCL 实现原理。ZigbeeSwitch 类概述ZigbeeSwitch类继承自公共端点基类ZigbeeEP定义见 libraries/Zigbee/src/ZigbeeEP.h在 Zigbee 网络中扮演协调器/路由器侧的开关控制器角色。它向网络暴露一个 On/Off Switch 设备ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID可以对已绑定的灯设备发送开、关、切换toggle命令通过 Zigbee组地址一次性控制一组设备通过短地址 端点或IEEE 地址 端点直接寻址特定设备。从源码看类的全部实现位于 libraries/Zigbee/src/ep/ZigbeeSwitch.h 与 libraries/Zigbee/src/ep/ZigbeeSwitch.cpp。构造时它调用esp_zb_on_off_switch_clusters_create()创建 On/Off 集群列表并以 HA ProfileESP_ZB_AF_HA_PROFILE_ID注册端点这一过程封装在ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint)构造函数中见 ZigbeeSwitch.cpp#L21-L32。构造函数与端点规划ZigbeeSwitch(uint8_t endpoint);endpoint端点号取值范围1254。端点号是 Zigbee 设备内部用于区分不同功能单元的编号。示例代码中单开关使用端点 5见 Zigbee_On_Off_Switch.ino多开关示例使用端点 1见 Zigbee_On_Off_MultiSwitch.ino。规划时需保证同一设备上各端点号唯一。创建实例后还需通过Zigbee.addEndpoint(zbSwitch)注册到 Zigbee 核心最后调用Zigbee.begin(role)启动见下文完整实战示例。基本控制命令开、关、切换三个基本命令各提供 4 种重载覆盖广播到绑定设备、组控制、直接寻址三种控制粒度lightToggle —— 切换状态void lightToggle(); void lightToggle(uint16_t group_addr); void lightToggle(uint8_t endpoint, uint16_t short_addr); void lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr);lightOn —— 打开void lightOn(); void lightOn(uint16_t group_addr); void lightOn(uint8_t endpoint, uint16_t short_addr); void lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr);lightOff —— 关闭void lightOff(); void lightOff(uint16_t group_addr); void lightOff(uint8_t endpoint, uint16_t short_addr); void lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr);参数含义三种命令完全一致参数类型含义无参-向所有已绑定设备发送命令绑定模式group_addruint16_t组地址控制组内所有设备endpointshort_addruint8_t,uint16_t目标设备的端点号与 16 位短地址直接寻址endpointieee_addruint8_t,esp_zb_ieee_addr_t目标设备的端点号与 64 位 IEEE/MAC 地址直接寻址底层 ZCL 命令映射从 ZigbeeSwitch.cpp 的实现可以看到每种重载最终都构造一个esp_zb_zcl_on_off_cmd_t请求并通过esp_zb_zcl_on_off_cmd_req()发送核心差异在于address_mode字段无参重载使用ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT绑定模式发往所有已绑定设备命令 ID 分别为ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID/ON_ID/OFF_ID组控制重载使用ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT短地址寻址使用ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENTIEEE 地址寻址使用ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT。值得注意的是所有命令在发送前都会检查_is_bound未绑定时仅打印错误日志而不发送例如 lightToggle() 的 ZigbeeSwitch.cpp#L112-L128。因此必须先完成绑定流程命令才生效。此外每个命令都通过acquireCommandLock()/releaseCommandLock()保证线程安全该锁定义在基类ZigbeeEP中。高级控制命令lightOffWithEffect —— 带效果的关闭void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant);effect_id效果标识符如延时关闭、渐灭等具体值取决于目标灯实现effect_variant效果变体。底层映射为esp_zb_zcl_on_off_off_with_effect_cmd_req()对应 ZCL 标准 Off With Effect 命令见 ZigbeeSwitch.cpp#L352-L369。适合在影院、睡眠等需要柔和关灯的场景使用。lightOnWithTimedOff —— 定时关闭void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off);on_off_control控制字节On/Off Control 字段time_on保持点亮的时间单位1/10 秒即 10 表示 1 秒time_off关闭等待时间单位1/10 秒。底层映射为esp_zb_zcl_on_off_on_with_timed_off_cmd_req()见 ZigbeeSwitch.cpp#L388-L406。适用于走廊灯、楼梯灯等点亮后自动熄灭的场景。注意源码中该字段旁留有 TODO 注释Test how it works, then maybe change API说明on_off_control的具体行为仍可能随版本演进使用时建议实测验证。lightOnWithSceneRecall —— 场景回调用开灯void lightOnWithSceneRecall();无参数。底层映射为esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req()对应 ZCL 的 On With Recall Global Scene 命令见 ZigbeeSwitch.cpp#L371-L386。用于在目标灯支持场景Scene功能时以点亮并恢复全局场景的方式开灯。状态查询与状态变更回调虽然原文档未展开但ZigbeeSwitch头文件还提供了与命令配套的状态读取与回调能力对实战非常重要getLightState —— 读取灯的状态void getLightState(); void getLightState(uint16_t group_addr); void getLightState(uint8_t endpoint, uint16_t short_addr); void getLightState(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr);与基本命令同样的 4 重载寻址方式。底层构造esp_zb_zcl_read_attr_cmd_t读取目标 On/Off 集群的ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID属性见 ZigbeeSwitch.cpp#L408-L475。读取结果会通过回调返回。状态变更回调void onLightStateChange(void (*callback)(bool)); void onLightStateChangeWithSource(void (*callback)(bool, uint8_t, esp_zb_zcl_addr_t));onLightStateChange灯状态变化时回调参数为当前开/关布尔值onLightStateChangeWithSource额外携带来源端点号与来源地址esp_zb_zcl_addr_t便于区分是哪个设备/端点报告了状态。回调触发链路在ZigbeeSwitch::zbAttributeRead()中实现ZigbeeSwitch.cpp#L477-L489当收到 On/Off 集群的ON_OFF属性读取响应且类型为布尔时依次调用两个回调。在 Zigbee_On_Off_Switch.ino 示例中回调用于打印灯状态变化。绑定Binding机制与底层流程开关要控制灯必须先将灯绑定bind到开关。这个流程在源码中分为三步见 ZigbeeSwitch.cpp#L34-L109寻找匹配设备findEndpoint()构造esp_zb_zdo_match_desc_req_param_t向网络广播查找具有 On/Off 集群输入输出各 1 个的 HA 设备记录设备信息findCb()收到响应后保存目标灯的端点、短地址并通过esp_zb_ieee_address_by_short()解析其 IEEE 地址发起绑定请求构造esp_zb_zdo_bind_req_param_t以 64 位扩展地址模式ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED对 On/Off 集群执行esp_zb_zdo_device_bind_req()成功后经bindCb()将设备加入_bound_devices列表并置_is_bound true。绑定相关的辅助 API继承自ZigbeeEP包括bound()是否已绑定getBoundDevices()返回std::listzb_device_params_t *其中zb_device_params_t含ieee_addr、endpoint、short_addr三个字段见 ZigbeeEP.h#L43-L47printBoundDevices(Print print)打印已绑定设备列表allowMultipleBinding(bool)允许绑定多个灯多开关场景必需setManualBinding(bool)开启手动绑定模式绑定由协调器侧如 Home Assistant完成setManufacturerAndModel(name, model)设置设备制造商名与型号便于网关注册识别。完整实战示例基本开关实现仓库提供了可直接编译运行的完整示例 Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino。核心流程如下#include Arduino.h #ifndef ZIGBEE_MODE_ZCZR #error Zigbee coordinator mode is not selected in Tools-Zigbee mode #endif #include Zigbee.h #define SWITCH_ENDPOINT_NUMBER 5 #define GPIO_INPUT_IO_TOGGLE_SWITCH BOOT_PIN ZigbeeSwitch zbSwitch ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); static void onLightStateChange(bool state) { Serial.printf(Light state changed to %d\r\n, state); } void setup() { Serial.begin(115200); zbSwitch.setManufacturerAndModel(Espressif, ZigbeeSwitch); zbSwitch.allowMultipleBinding(true); // 允许绑定多盏灯 zbSwitch.onLightStateChange(onLightStateChange); Zigbee.addEndpoint(zbSwitch); // 注册端点到 Zigbee 核心 Zigbee.setRebootOpenNetwork(180); // 开机后开网 180 秒供配网 pinMode(GPIO_INPUT_IO_TOGGLE_SWITCH, INPUT_PULLUP); // ... 按键中断与队列初始化 ... if (!Zigbee.begin(ZIGBEE_COORDINATOR)) { // 以协调器角色启动 Serial.println(Zigbee failed to start!); ESP.restart(); } while (!zbSwitch.bound()) { // 等待灯绑定到开关 Serial.printf(.); delay(500); } // 可选列出所有已绑定设备 std::listzb_device_params_t * boundLights zbSwitch.getBoundDevices(); for (const auto device : boundLights) { Serial.printf(Device on endpoint %u, short address: 0x%x\r\n, device-endpoint, device-short_addr); } } void loop() { // 按键消抖处理中调用 zbSwitch.lightToggle(); 即可切换灯状态 }示例还包含一个periodicTask每 10 秒调用zbSwitch.printBoundDevices(Serial)打印绑定设备每 1 秒调用zbSwitch.getLightState()轮询灯状态。运行前提编译配置示例开头用#error强制检查宏编译与运行前必须在 Arduino IDE 的Tools → Zigbee mode中选择Zigbee coordinator (ZCZR)模式对应预编译宏ZIGBEE_MODE_ZCZR并选择正确的Partition SchemeZigbee 需要专门的分区表。示例在loop()中通过attachInterruptArg捕获 BOOT 按键的下降沿经 FreeRTOS 队列送入主循环做软件消抖后触发lightToggle()。完整实战示例多开关MultiSwitch实现需要同时控制多盏灯时可参考 Zigbee_On_Off_MultiSwitch/Zigbee_On_Off_MultiSwitch.ino。该示例与单开关版本的关键差异1. 角色可配置支持接入 Home Assistant#define ZIGBEE_ROLE ZIGBEE_ROUTER // ZIGBEE_ROUTER 接入 Home AssistantZIGBEE_COORDINATOR 自建网络代码注释明确说明选择ZIGBEE_ROUTER可让 Home Assistant 侧完成绑定需配合zbSwitch.setManualBinding(true)选择ZIGBEE_COORDINATOR则运行自有网络需zbSwitch.allowMultipleBinding(true)。在loop()中按键会调用zbSwitch.printBoundDevices(Serial)打印绑定设备。2. 通过串口命令配置与操控 3 盏灯示例预置了light_1、light_2、light_3三个zb_device_params_t结构并通过 PreferencesNVS持久化断电不丢失。串口命令包括命令作用config交互式配置某盏灯的端点号与 IEEE 地址格式00:00:00:00:00:00:00:00并存入 NVSremove移除某盏灯的配置on/off/toggle向所有已绑定灯发送开/关/切换无参重载1on/1off/1toggle、2on...、3on...用 IEEE 地址重载精确控制单盏灯例如zbSwitch.lightOn(light_1.endpoint, light_1.ieee_addr)freset调用Zigbee.factoryReset()执行出厂复位open_network调用Zigbee.openNetwork(180)重新开放入网窗口仅协调器角色可用注意config命令对 IEEE 地址做严格校验长度必须为 23 字符即 8 组十六进制 7 个冒号并按 Zigbee 规范将字节逆序存入数组ieee_address_array[7 - index] value。命令发送的线程安全与超时机制在周期任务、串口处理与按键回调同时存在的多任务场景下ZCL 命令的并发安全由基类ZigbeeEP提供的acquireCommandLock()/releaseCommandLock()保证每个命令在调用 ESP-Zigbee-SDK 的发送函数前后成对加锁/解锁例如 ZigbeeSwitch.cpp#L120-L124。此外基类定义了ZB_CMD_TIMEOUT 1000010 秒作为命令超时上限见 ZigbeeEP.h避免阻塞式读写命令无限等待。常见问题与排查建议编译报错Zigbee coordinator mode is not selected未在 Tools → Zigbee mode 选择 ZCZR 模式或未选择正确的分区方案。调用命令无效果且日志出现Light not bound命令发送前强制检查绑定状态需先完成灯与开关的绑定可参照单开关示例在setup()中while (!zbSwitch.bound())等待或用Zigbee.setRebootOpenNetwork(180)延长开网窗口。多灯同时被控制确认是否调用了allowMultipleBinding(true)如需单独控制使用 IEEE 地址重载并校验设备信息是否与getBoundDevices()返回的一致。状态回调不触发确认通过onLightStateChange注册了回调并周期性调用getLightState()主动读取灯的主动上报依赖其自身配置。相关资源类实现libraries/Zigbee/src/ep/ZigbeeSwitch.h、libraries/Zigbee/src/ep/ZigbeeSwitch.cpp公共端点基类libraries/Zigbee/src/ZigbeeEP.h核心初始化与角色管理libraries/Zigbee/src/ZigbeeCore.h、libraries/Zigbee/src/ZigbeeCore.cpp单开关示例libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino多开关示例libraries/Zigbee/examples/Zigbee_On_Off_MultiSwitch/Zigbee_On_Off_MultiSwitch.ino端点配置类型zb_device_params_t定义libraries/Zigbee/src/ZigbeeEP.h【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表