ep开发
.cpp
#include "ZigbeeSensor.h"
#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED
/**
* @brief ZigbeeSensor类的构造函数。
*
* 该构造函数用于初始化Zigbee传感器设备的端点信息,包括设备ID、集群列表和端点配置。
*
* @param endpoint 传感器设备的端点号。
*/
ZigbeeSensor::ZigbeeSensor(uint8_t endpoint) : ZigbeeEP(endpoint) {
// 设置设备ID为 {ESP_ZB_HA_SENSOR_DEVICE_ID} ,开发者请修改为相应传感器设备的设备ID,ID在ZigbeeCore有列举
_device_id = {ESP_ZB_HA_SENSOR_DEVICE_ID};
// 创建一个默认的传感器配置对象
esp_zb_sensor_cfg_t sensor_cfg = {ESP_ZB_DEFAULT_SENSOR_CONFIG()}; // 开发者若有必要,请修改默认传感器配置
// 根据传感器配置创建集群列表
_cluster_list = {esp_zb_sensor_clusters_create(&sensor_cfg)};
// 初始化端点配置,设置端点号、应用程序配置文件ID、应用程序设备ID和设备版本
_ep_config = {
.endpoint = endpoint,
.app_profile_id = {ESP_ZB_AF_HA_PROFILE_ID}, // 开发者请根据实际应用修改配置文件ID
.app_device_id = {ESP_ZB_HA_SENSOR_DEVICE_ID}, // 开发者请根据实际应用修改设备ID
.app_device_version = 1 // 开发者可根据设备版本进行调整
};
// 记录调试日志,表明传感器端点已创建
log_v("Sensor endpoint created %d", endpoint);
}
/**
* @brief 处理Zigbee属性上报消息的方法。
*
* 当传感器设备收到来自网络的属性上报消息时,该方法解析消息,并更新传感器数值。
*
* @param message 指向Zigbee属性上报消息结构体的指针。
*/
void ZigbeeSensor::zbAttributeReport(const esp_zb_zcl_attr_report_msg_t *message) {
// 检查消息所属的集群是否为传感器数据所在的集群(假定为 {ESP_ZB_ZCL_CLUSTER_ID_SENSOR})
if (message->info.cluster == {ESP_ZB_ZCL_CLUSTER_ID_SENSOR}) {
// 假定传感器数据为浮点型,检查数据类型(开发者根据具体实现进行调整)
if (message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_FLOAT) {
// 更新当前传感器数值
_current_value = *(float *)message->attribute.data.value;
// 调用传感器数据变更回调
sensorDataChanged();
} else {
// 记录警告日志,表明收到的数据类型不正确
log_w("Received message ignored. Incorrect data type for sensor data");
}
} else {
// 记录警告日志,表明收到的集群ID不支持
log_w("Received message ignored. Cluster ID: %d not supported for Sensor", message->info.cluster);
}
}
/**
* @brief 当传感器数据变化时调用的方法。
*
* 如果设置了传感器数据变化的回调函数,则会通知调用者。
*/
void ZigbeeSensor::sensorDataChanged() {
if (_on_sensor_data_change) {
_on_sensor_data_change(_current_value);
} else {
log_w("No callback function set for sensor data change");
}
}
/**
* @brief 更新传感器数值的方法。
*
* 此方法用于主动更新传感器数值,并将新数值同步到Zigbee网络中。
*
* @param value 新传感器数值(例如温度、湿度等)。
*/
void ZigbeeSensor::updateSensorValue(float value) {
_current_value = value;
sensorDataChanged();
log_v("Updating sensor value: %f", value);
/* 将传感器新数值同步到Zigbee网络 */
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(
_endpoint,
{ESP_ZB_ZCL_CLUSTER_ID_SENSOR}, // 开发者请根据实际传感器数据所在集群修改此字段
ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
{ESP_ZB_ZCL_ATTR_SENSOR_VALUE_ID}, // 开发者请根据实际传感器属性ID修改此字段
&_current_value,
false
);
esp_zb_lock_release();
}
#endif // SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLEDESP_ZB_DEFAULT_SENSOR_CONFIG()和esp_zb_sensor_clusters_create()这俩函数该怎么写?
目前不建议自己来写,自己写也没法在esp-zigbee-sdk里面用。最好用现成的:https://github.com/espressif/esp-zigbee-sdk/blob/main/components/esp-zigbee-lib/include/ha/esp_zigbee_ha_standard.h
目前支持的设备类型

总结
- 首先,需要设定ZIgbee Endpoint Device检查,导入ZIgbee的库。
#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif
#include "Zigbee.h"- 然后需要为你的ZIgbee设备分配一个端点编号:
#define TEMP_SENSOR_ENDPOINT_NUMBER 10 // 定义温度传感器的端点编号设备内部区分:一个 Zigbee 设备可以包含多个功能模块(如温度传感器、湿度传感器等),每个功能模块通过唯一的端点编号进行区分。不同设备可以使用相同的端点编号,因为 Zigbee 网络通过设备的 短地址(Short Address) 或 长地址(IEEE Address) 来区分不同的设备。
通信标识:Zigbee 网络通过端点编号识别设备中的具体功能模块,从而进行正确的数据交换。也就是说,在同一设备中,每个功能模块的端点编号必须是唯一的。例如,如果设备同时包含温度传感器和湿度传感器,它们的端点编号不能相同。
- 然后创建传感器对象
ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); // 创建温度传感器对象其中参数是在第二步里面定义的端点编号的变量名。
- 然后写一个功能函数,如果是输入传感器,写一个xxx_value_update的函数,用于传感器数据获取。如果是执行器,那么写一个setXXX的函数,用来控制执行器。
static void temp_sensor_value_update(void *arg) {
for (;;) {
// 读取温度传感器值
float tsens_value = temperatureRead();
Serial.printf("更新的温度传感器值为 %.2f°C\r\n", tsens_value);
// 更新温度传感器端点的温度值
zbTempSensor.setTemperature(tsens_value);
delay(1000); // 延迟1秒
}
}
void setLED(bool value) {
digitalWrite(led, value);
}setup()部分
传感器参考:
// 可选:设置 Zigbee 设备名称和型号
zbTempSensor.setManufacturerAndModel("Espressif", "ZigbeeTempSensor");
// 将端点添加到 Zigbee 核心
Zigbee.addEndpoint(&zbTempSensor);
Serial.println("启动 Zigbee...");
// 当所有端点注册完成后,以终端设备模式启动 Zigbee
if (!Zigbee.begin()) {
Serial.println("Zigbee 启动失败!");
Serial.println("重启中...");
ESP.restart(); // 重启设备
} else {
Serial.println("Zigbee 启动成功!");
}
Serial.println("连接到网络");
while (!Zigbee.connected()) {
Serial.print(".");
delay(100);
}
Serial.println();
// 启动温度传感器读取任务
xTaskCreate(temp_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL);
// 设置温度测量的报告间隔(以秒为单位),必须在 Zigbee.begin() 之后调用
// min_interval 和 max_interval 以秒为单位,delta 为温度变化量(0.1°C)
// 如果 min = 1 且 max = 0,则仅在温度变化超过 delta 时发送报告
// 如果 min = 0 且 max = 10,则每 10 秒或温度变化超过 delta 时发送报告
// 如果 min = 0,max = 10 且 delta = 0,则每 10 秒发送报告,无论温度是否变化
zbTempSensor.setReporting(1, 0, 1);执行器参考:
//Optional: set Zigbee device name and model
zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb");
// Set callback function for light change
zbLight.onLightChange(setLED);
//Add endpoint to Zigbee Core
Serial.println("Adding ZigbeeLight endpoint to Zigbee Core");
Zigbee.addEndpoint(&zbLight);
// When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE
if (!Zigbee.begin()) {
Serial.println("Zigbee failed to start!");
Serial.println("Rebooting...");
ESP.restart();
}
Serial.println("Connecting to network");
while (!Zigbee.connected()) {
Serial.print(".");
delay(100);
}
Serial.println();对于setManufacturerAndModel()函数,传入的第一个参数是制造商的名称,第二个参数是Zigbee Device Model,这个Model就是产品名称即可。
loop()部分
loop部分一般设置一个重置和复位的按键功能:
void loop() {
// 检查按钮是否按下以执行恢复出厂设置
if (digitalRead(button) == LOW) { // 按钮按下
// 按键去抖处理
delay(100);
int startTime = millis();
while (digitalRead(button) == LOW) {
delay(50);
if ((millis() - startTime) > 3000) {
// 如果按钮按下超过 3 秒,恢复 Zigbee 出厂设置并重启
Serial.println("重置 Zigbee 到出厂设置并将在 1 秒后重启。");
delay(1000);
Zigbee.factoryReset(); // 恢复出厂设置
}
}
zbTempSensor.reportTemperature(); // 报告当前温度
}
delay(100); // 延迟 100 毫秒
}