Skip to content

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_ENABLED

ESP_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

目前支持的设备类型

总结

  1. 首先,需要设定ZIgbee Endpoint Device检查,导入ZIgbee的库。
#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"
  1. 然后需要为你的ZIgbee设备分配一个端点编号:
#define TEMP_SENSOR_ENDPOINT_NUMBER 10 // 定义温度传感器的端点编号
  • 设备内部区分:一个 Zigbee 设备可以包含多个功能模块(如温度传感器、湿度传感器等),每个功能模块通过唯一的端点编号进行区分。不同设备可以使用相同的端点编号,因为 Zigbee 网络通过设备的 短地址(Short Address) 或 长地址(IEEE Address) 来区分不同的设备。

  • 通信标识:Zigbee 网络通过端点编号识别设备中的具体功能模块,从而进行正确的数据交换。也就是说,在同一设备中,每个功能模块的端点编号必须是唯一的。例如,如果设备同时包含温度传感器和湿度传感器,它们的端点编号不能相同。

  1. 然后创建传感器对象
ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); // 创建温度传感器对象

其中参数是在第二步里面定义的端点编号的变量名。

  1. 然后写一个功能函数,如果是输入传感器,写一个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 毫秒
}

Powered by VitePress