Skip to content

Commit 5dc5f7f

Browse files
authored
feat(zigbee): Add windspeed sensor endpoint
1 parent 2d0a597 commit 5dc5f7f

File tree

4 files changed

+165
-132
lines changed

4 files changed

+165
-132
lines changed

libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor/Zigbee_Wind_Speed_Sensor.ino

+93-80
Original file line numberDiff line numberDiff line change
@@ -26,83 +26,96 @@
2626
* Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/)
2727
*/
2828

29-
#ifndef ZIGBEE_MODE_ED
30-
#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode"
31-
#endif
32-
33-
#include "ZigbeeCore.h"
34-
#include "ep/ZigbeeWindSpeedSensor.h"
35-
36-
#define BUTTON_PIN 9 //Boot button for C6/H2
37-
#define WIND_SPEED_SENSOR_ENDPOINT_NUMBER 10
38-
39-
ZigbeeWindSpeedSensor zbWindSpeedSensor = ZigbeeWindSpeedSensor(WIND_SPEED_SENSOR_ENDPOINT_NUMBER);
40-
41-
/************************ WindSpeed sensor *****************************/
42-
static void windspeed_sensor_value_update(void *arg) {
43-
for (;;) {
44-
// Read wind speed sensor value
45-
// float wssens_value = windspeedRead();
46-
float wssens_value = 5.2;
47-
log_v("Wind speed sensor value: %.2fm/s", wssens_value);
48-
// Update windspeed value in Windspeed sensor EP
49-
zbWindSpeedSensor.setWindSpeed(wssens_value);
50-
delay(1000);
51-
}
52-
}
53-
54-
/********************* Arduino functions **************************/
55-
void setup() {
56-
57-
Serial.begin(115200);
58-
while (!Serial) {
59-
delay(10);
60-
}
61-
62-
// Init button switch
63-
pinMode(BUTTON_PIN, INPUT);
64-
65-
// Optional: set Zigbee device name and model
66-
zbWindSpeedSensor.setManufacturerAndModel("Espressif", "ZigbeeWindSpeedSensor");
67-
68-
// Set minimum and maximum windspeed measurement value (10-50°C is default range for chip windspeed measurement)
69-
zbWindSpeedSensor.setMinMaxValue(10, 50);
70-
71-
// Set tolerance for windspeed measurement in °C (lowest possible value is 0.01°C)
72-
zbWindSpeedSensor.setTolerance(1);
73-
74-
// Add endpoint to Zigbee Core
75-
Zigbee.addEndpoint(&zbWindSpeedSensor);
76-
77-
// When all EPs are registered, start Zigbee in End Device mode
78-
Zigbee.begin();
79-
80-
// Start Wind speed sensor reading task
81-
xTaskCreate(windspeed_sensor_value_update, "wind_speed_sensor_update", 2048, NULL, 10, NULL);
82-
83-
// Set reporting interval for windspeed measurement in seconds, must be called after Zigbee.begin()
84-
// min_interval and max_interval in seconds, delta (WindSpeed change in °C)
85-
// if min = 1 and max = 0, reporting is sent only when windspeed changes by delta
86-
// if min = 0 and max = 10, reporting is sent every 10 seconds or windspeed changes by delta
87-
// if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of windspeed change
88-
zbWindSpeedSensor.setReporting(1, 0, 1);
89-
}
90-
91-
void loop() {
92-
// Checking button for factory reset
93-
if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed
94-
// Key debounce handling
95-
delay(100);
96-
int startTime = millis();
97-
while (digitalRead(BUTTON_PIN) == LOW) {
98-
delay(50);
99-
if ((millis() - startTime) > 3000) {
100-
// If key pressed for more than 3secs, factory reset Zigbee and reboot
101-
Serial.printf("Resetting Zigbee to factory settings, reboot.\n");
102-
Zigbee.factoryReset();
103-
}
104-
}
105-
zbWindSpeedSensor.reportWindSpeed();
106-
}
107-
delay(100);
108-
}
29+
#ifndef ZIGBEE_MODE_ED
30+
#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode"
31+
#endif
32+
33+
#include "ZigbeeCore.h"
34+
#include "ep/ZigbeeWindSpeedSensor.h"
35+
36+
#define BUTTON_PIN 9 //Boot button for C6/H2
37+
#define WIND_SPEED_SENSOR_ENDPOINT_NUMBER 10
38+
39+
ZigbeeWindSpeedSensor zbWindSpeedSensor = ZigbeeWindSpeedSensor(WIND_SPEED_SENSOR_ENDPOINT_NUMBER);
40+
41+
/************************ WindSpeed sensor *****************************/
42+
static void windspeed_sensor_value_update(void *arg) {
43+
for (;;) {
44+
// Read wind speed sensor value (simulated now by temperature sensor)
45+
float windspeed = temperatureRead();
46+
log_v("Wind speed sensor value: %.2fm/s", windspeed);
47+
// Update windspeed value in Windspeed sensor EP
48+
zbWindSpeedSensor.setWindSpeed(windspeed);
49+
delay(1000);
50+
}
51+
}
52+
53+
/********************* Arduino functions **************************/
54+
void setup() {
55+
Serial.begin(115200);
56+
while (!Serial) {
57+
delay(10);
58+
}
59+
60+
// Init button switch
61+
pinMode(BUTTON_PIN, INPUT);
62+
63+
// Optional: set Zigbee device name and model
64+
zbWindSpeedSensor.setManufacturerAndModel("Espressif", "ZigbeeWindSpeedSensor");
65+
66+
// Set minimum and maximum windspeed measurement value in m/s
67+
zbWindSpeedSensor.setMinMaxValue(0, 50);
68+
69+
// Set tolerance for windspeed measurement in m/s (lowest possible value is 0.01 m/s)
70+
zbWindSpeedSensor.setTolerance(1);
71+
72+
// Add endpoint to Zigbee Core
73+
Zigbee.addEndpoint(&zbWindSpeedSensor);
74+
75+
Serial.println("Starting Zigbee...");
76+
// When all EPs are registered, start Zigbee in End Device mode
77+
if (!Zigbee.begin()) {
78+
Serial.println("Zigbee failed to start!");
79+
Serial.println("Rebooting...");
80+
ESP.restart();
81+
} else {
82+
Serial.println("Zigbee started successfully!");
83+
}
84+
Serial.println("Connecting to network");
85+
while (!Zigbee.connected()) {
86+
Serial.print(".");
87+
delay(100);
88+
}
89+
Serial.println();
90+
91+
// Start Wind speed sensor reading task
92+
xTaskCreate(windspeed_sensor_value_update, "wind_speed_sensor_update", 2048, NULL, 10, NULL);
93+
94+
// Set reporting interval for windspeed measurement in seconds, must be called after Zigbee.begin()
95+
// min_interval and max_interval in seconds, delta (WindSpeed change in m/s)
96+
// if min = 1 and max = 0, reporting is sent only when windspeed changes by delta
97+
// if min = 0 and max = 10, reporting is sent every 10 seconds or windspeed changes by delta
98+
// if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of windspeed change
99+
zbWindSpeedSensor.setReporting(1, 0, 1);
100+
}
101+
102+
void loop() {
103+
// Checking button for factory reset
104+
if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed
105+
// Key debounce handling
106+
delay(100);
107+
int startTime = millis();
108+
while (digitalRead(BUTTON_PIN) == LOW) {
109+
delay(50);
110+
if ((millis() - startTime) > 3000) {
111+
// If key pressed for more than 3secs, factory reset Zigbee and reboot
112+
Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
113+
delay(1000);
114+
Zigbee.factoryReset();
115+
}
116+
}
117+
zbWindSpeedSensor.reportWindSpeed();
118+
}
119+
delay(100);
120+
}
121+
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed",
33
"requires": [
4-
"CONFIG_SOC_IEEE802154_SUPPORTED=y"
4+
"CONFIG_SOC_IEEE802154_SUPPORTED=y",
5+
"CONFIG_ZB_ENABLED=y"
56
]
67
}
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
11
#include "ZigbeeWindSpeedSensor.h"
2-
#if SOC_IEEE802154_SUPPORTED
2+
#if CONFIG_ZB_ENABLED
3+
4+
esp_zb_cluster_list_t *zigbee_wind_speed_sensor_clusters_create(zigbee_wind_speed_sensor_cfg_t *wind_speed_sensor) {
5+
esp_zb_basic_cluster_cfg_t *basic_cfg = wind_speed_sensor ? &(wind_speed_sensor->basic_cfg) : NULL;
6+
esp_zb_identify_cluster_cfg_t *identify_cfg = wind_speed_sensor ? &(wind_speed_sensor->identify_cfg) : NULL;
7+
esp_zb_wind_speed_measurement_cluster_cfg_t *wind_speed_cfg = wind_speed_sensor ? &(wind_speed_sensor->wind_speed_meas_cfg) : NULL;
8+
esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create();
9+
esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
10+
esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
11+
esp_zb_cluster_list_add_wind_speed_measurement_cluster(cluster_list, esp_zb_wind_speed_measurement_cluster_create(wind_speed_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
12+
return cluster_list;
13+
}
314

415
// There is no device_id for wind speed sensor, we use a generic one
516
ZigbeeWindSpeedSensor::ZigbeeWindSpeedSensor(uint8_t endpoint) : ZigbeeEP(endpoint) {
617
_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID;
718

8-
esp_zb_windspeed_sensor_cfg_t windspeed_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG();
9-
_cluster_list = esp_zb_windspeed_sensor_clusters_create(&windspeed_sensor_cfg);
19+
zigbee_wind_speed_sensor_cfg_t windspeed_sensor_cfg = ZIGBEE_DEFAULT_WIND_SPEED_SENSOR_CONFIG();
20+
_cluster_list = zigbee_wind_speed_sensor_clusters_create(&windspeed_sensor_cfg);
1021

1122
_ep_config = {
1223
.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
1324
};
1425
}
1526

16-
static int16_t zb_windspeed_to_s16(float windspeed) {
17-
return (int16_t)(windspeed * 100);
27+
static uint16_t zb_windspeed_to_u16(float windspeed) {
28+
return (uint16_t)(windspeed * 100);
1829
}
1930

20-
/** @brief Wind_Speed_Measurement cluster server attribute identifiers
21-
typedef enum {
22-
ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID = 0x0000, < MeasuredValue Attribute
23-
ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MIN_MEASURED_VALUE_ID = 0x0001, < MinMeasuredValue Attribute
24-
ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MAX_MEASURED_VALUE_ID = 0x0002, < MaxMeasuredValue Attribute
25-
ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_TOLERANCE_ID = 0x0003, < Tolerance Attribute
26-
} esp_zb_zcl_wind_speed_measurement_srv_attr_t;
27-
*/
2831
void ZigbeeWindSpeedSensor::setMinMaxValue(float min, float max) {
29-
int16_t zb_min = zb_windspeed_to_s16(min);
30-
int16_t zb_max = zb_windspeed_to_s16(max);
32+
uint16_t zb_min = zb_windspeed_to_u16(min);
33+
uint16_t zb_max = zb_windspeed_to_u16(max);
3134
esp_zb_attribute_list_t *windspeed_measure_cluster =
3235
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
3336
//
@@ -37,44 +40,34 @@ void ZigbeeWindSpeedSensor::setMinMaxValue(float min, float max) {
3740

3841
void ZigbeeWindSpeedSensor::setTolerance(float tolerance) {
3942
// Convert tolerance to ZCL uint16_t
40-
uint16_t zb_tolerance = (uint16_t)(tolerance * 100);
43+
uint16_t zb_tolerance = zb_windspeed_to_u16(tolerance);
4144
esp_zb_attribute_list_t *windspeed_measure_cluster =
4245
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
43-
esp_zb_windspeed_meas_cluster_add_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
46+
esp_zb_wind_speed_measurement_cluster_add_attr(windspeed_measure_cluster, ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance);
4447
}
4548

4649
void ZigbeeWindSpeedSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
47-
esp_zb_zcl_reporting_info_t reporting_info = {
48-
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
49-
.ep = _endpoint,
50-
.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT,
51-
.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
52-
.attr_id = ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID,
53-
.u =
54-
{
55-
.send_info =
56-
{
57-
.min_interval = min_interval,
58-
.max_interval = max_interval,
59-
.delta =
60-
{
61-
.u16 = (uint16_t)(delta * 100), // Convert delta to ZCL uint16_t
62-
},
63-
.def_min_interval = min_interval,
64-
.def_max_interval = max_interval,
65-
},
66-
},
67-
.dst =
68-
{
69-
.profile_id = ESP_ZB_AF_HA_PROFILE_ID,
70-
},
71-
.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC,
72-
};
50+
esp_zb_zcl_reporting_info_t reporting_info;
51+
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
52+
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
53+
reporting_info.ep = _endpoint;
54+
reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT;
55+
reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
56+
reporting_info.attr_id = ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID;
57+
reporting_info.u.send_info.min_interval = min_interval;
58+
reporting_info.u.send_info.max_interval = max_interval;
59+
reporting_info.u.send_info.def_min_interval = min_interval;
60+
reporting_info.u.send_info.def_max_interval = max_interval;
61+
reporting_info.u.send_info.delta.u16 = (uint16_t)(delta * 100); // Convert delta to ZCL uint16_t
62+
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
63+
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
64+
esp_zb_lock_acquire(portMAX_DELAY);
7365
esp_zb_zcl_update_reporting_info(&reporting_info);
66+
esp_zb_lock_release();
7467
}
7568

7669
void ZigbeeWindSpeedSensor::setWindSpeed(float windspeed) {
77-
int16_t zb_windspeed = zb_windspeed_to_s16(windspeed);
70+
uint16_t zb_windspeed = zb_windspeed_to_u16(windspeed);
7871
log_v("Updating windspeed sensor value...");
7972
/* Update windspeed sensor measured value */
8073
log_d("Setting windspeed to %d", zb_windspeed);
@@ -90,14 +83,15 @@ void ZigbeeWindSpeedSensor::reportWindSpeed() {
9083
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
9184
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
9285
report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_ID;
93-
report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
86+
report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI;
9487
report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_WIND_SPEED_MEASUREMENT;
9588
report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
89+
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
9690

9791
esp_zb_lock_acquire(portMAX_DELAY);
9892
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
9993
esp_zb_lock_release();
100-
log_v("Temperature report sent");
94+
log_v("Wind speed measurement report sent");
10195
}
10296

103-
#endif //SOC_IEEE802154_SUPPORTED
97+
#endif //CONFIG_ZB_ENABLED

libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.h

+29-4
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,42 @@
33
#pragma once
44

55
#include "soc/soc_caps.h"
6-
#if SOC_IEEE802154_SUPPORTED
6+
#if CONFIG_ZB_ENABLED
77

88
#include "ZigbeeEP.h"
99
#include "ha/esp_zigbee_ha_standard.h"
1010

11+
#define ZIGBEE_DEFAULT_WIND_SPEED_SENSOR_CONFIG() \
12+
{ \
13+
.basic_cfg = \
14+
{ \
15+
.zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \
16+
.power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \
17+
}, \
18+
.identify_cfg = \
19+
{ \
20+
.identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \
21+
}, \
22+
.wind_speed_meas_cfg = \
23+
{ \
24+
.measured_value = ESP_ZB_ZCL_WIND_SPEED_MEASUREMENT_MEASURED_VALUE_DEFAULT, \
25+
.min_measured_value = ESP_ZB_ZCL_WIND_SPEED_MEASUREMENT_MIN_MEASURED_VALUE_DEFAULT, \
26+
.max_measured_value = ESP_ZB_ZCL_WIND_SPEED_MEASUREMENT_MAX_MEASURED_VALUE_DEFAULT, \
27+
}, \
28+
}
29+
30+
typedef struct zigbee_wind_speed_sensor_cfg_s {
31+
esp_zb_basic_cluster_cfg_t basic_cfg; /*!< Basic cluster configuration, @ref esp_zb_basic_cluster_cfg_s */
32+
esp_zb_identify_cluster_cfg_t identify_cfg; /*!< Identify cluster configuration, @ref esp_zb_identify_cluster_cfg_s */
33+
esp_zb_wind_speed_measurement_cluster_cfg_t wind_speed_meas_cfg; /*!< Wind speed measurement cluster configuration, @ref esp_zb_wind_speed_measurement_cluster_cfg_s */
34+
} zigbee_wind_speed_sensor_cfg_t;
35+
1136
class ZigbeeWindSpeedSensor : public ZigbeeEP {
1237
public:
1338
ZigbeeWindSpeedSensor(uint8_t endpoint);
14-
~ZigbeeWindSpeedSensor();
39+
~ZigbeeWindSpeedSensor() {}
1540

16-
// Set the WindSpeed value in 0,01°C
41+
// Set the WindSpeed value in 0,01 m/s
1742
void setWindSpeed(float value);
1843

1944
// Set the min and max value for the WindSpeed sensor
@@ -27,4 +52,4 @@ class ZigbeeWindSpeedSensor : public ZigbeeEP {
2752
void reportWindSpeed();
2853
};
2954

30-
#endif //SOC_IEEE802154_SUPPORTED
55+
#endif //CONFIG_ZB_ENABLED

0 commit comments

Comments
 (0)