Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 254fd8d

Browse files
feat(zigbee): Add sernsor type and configuration
1 parent b333bf2 commit 254fd8d

File tree

3 files changed

+250
-7
lines changed

3 files changed

+250
-7
lines changed

‎libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/Zigbee_Occupancy_Sensor.ino

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include "Zigbee.h"
3535

3636
/* Zigbee occupancy sensor configuration */
37-
#define OCCUPANCY_SENSOR_ENDPOINT_NUMBER 10
37+
#define OCCUPANCY_SENSOR_ENDPOINT_NUMBER 1
3838
uint8_t button = BOOT_PIN;
3939
uint8_t sensor_pin = 4;
4040

@@ -47,9 +47,21 @@ void setup() {
4747
pinMode(button, INPUT_PULLUP);
4848
pinMode(sensor_pin, INPUT);
4949

50-
// Optional: set Zigbee device name and model
50+
// Set Zigbee device name and model
5151
zbOccupancySensor.setManufacturerAndModel("Espressif", "ZigbeeOccupancyPIRSensor");
5252

53+
// Optional: Set sensor type (PIR, Ultrasonic, PIR and Ultrasonic or Physical Contact)
54+
zbOccupancySensor.setSensorType(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR, ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PIR);
55+
56+
// Optional: Set occupied to unoccupied delay (if your sensor supports it) to PIR sensor as its set by setSensorType
57+
zbOccupancySensor.setOccupiedToUnoccupiedDelay(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR, 1); // 1 second delay
58+
59+
// Optional: Set unoccupied to occupied delay (if your sensor supports it) to PIR sensor as its set by setSensorType
60+
zbOccupancySensor.setUnoccupiedToOccupiedDelay(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR, 1); // 1 second delay
61+
62+
// Optional: Set unoccupied to occupied threshold (if your sensor supports it) to PIR sensor as its set by setSensorType
63+
zbOccupancySensor.setUnoccupiedToOccupiedThreshold(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR, 1); // 1 movement event threshold
64+
5365
// Add endpoint to Zigbee Core
5466
Zigbee.addEndpoint(&zbOccupancySensor);
5567

‎libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp

Lines changed: 198 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,164 @@ ZigbeeOccupancySensor::ZigbeeOccupancySensor(uint8_t endpoint) : ZigbeeEP(endpoi
2222
_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};
2323
}
2424

25-
bool ZigbeeOccupancySensor::setSensorType(uint8_t sensor_type) {
26-
uint8_t sensor_type_bitmap = 1 << sensor_type;
25+
bool ZigbeeOccupancySensor::setSensorType(ZigbeeOccupancySensorType sensor_type, ZigbeeOccupancySensorTypeBitmap sensor_type_bitmap) {
26+
uint8_t sensor_type_bitmap_value = sensor_type_bitmap;
27+
if(sensor_type_bitmap == ZIGBEE_OCCUPANCY_SENSOR_BITMAP_DEFAULT) {
28+
sensor_type_bitmap_value = (1 << sensor_type); // Default to single sensor type if bitmap is default
29+
}
2730
esp_zb_attribute_list_t *occupancy_sens_cluster =
2831
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
2932
esp_err_t ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID, (void *)&sensor_type);
3033
if (ret != ESP_OK) {
3134
log_e("Failed to set sensor type: 0x%x: %s", ret, esp_err_to_name(ret));
3235
return false;
3336
}
34-
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, (void *)&sensor_type_bitmap);
37+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, (void *)&sensor_type_bitmap_value);
3538
if (ret != ESP_OK) {
3639
log_e("Failed to set sensor type bitmap: 0x%x: %s", ret, esp_err_to_name(ret));
3740
return false;
3841
}
42+
43+
// Handle PIR attributes if PIR bit is set (bit 0)
44+
if (sensor_type_bitmap & ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PIR) {
45+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_ID, ESP_ZB_ZCL_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_DEFAULT_VALUE);
46+
if (ret != ESP_OK) {
47+
log_e("Failed to set PIR occupied to unoccupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
48+
return false;
49+
}
50+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_ID, ESP_ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_DEFAULT_VALUE);
51+
if (ret != ESP_OK) {
52+
log_e("Failed to set PIR unoccupied to occupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
53+
return false;
54+
}
55+
uint8_t pir_threshold = ESP_ZB_ZCL_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_DEFAULT_VALUE;
56+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_ID, &pir_threshold);
57+
if (ret != ESP_OK) {
58+
log_e("Failed to set PIR unoccupied to occupied threshold: 0x%x: %s", ret, esp_err_to_name(ret));
59+
return false;
60+
}
61+
}
62+
63+
// Handle Ultrasonic attributes if Ultrasonic bit is set (bit 1)
64+
if (sensor_type_bitmap & ZIGBEE_OCCUPANCY_SENSOR_BITMAP_ULTRASONIC) {
65+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_ID, ESP_ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_DEFAULT_VALUE);
66+
if (ret != ESP_OK) {
67+
log_e("Failed to set ultrasonic occupied to unoccupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
68+
return false;
69+
}
70+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_ID, ESP_ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_DEFAULT_VALUE);
71+
if (ret != ESP_OK) {
72+
log_e("Failed to set ultrasonic unoccupied to occupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
73+
return false;
74+
}
75+
uint8_t ultrasonic_threshold = ESP_ZB_ZCL_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_DEFAULT_VALUE;
76+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID, &ultrasonic_threshold);
77+
if (ret != ESP_OK) {
78+
log_e("Failed to set ultrasonic unoccupied to occupied threshold: 0x%x: %s", ret, esp_err_to_name(ret));
79+
return false;
80+
}
81+
}
82+
83+
// Handle Physical Contact attributes if Physical Contact bit is set (bit 2)
84+
if (sensor_type_bitmap & ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PHYSICAL_CONTACT_AND_PIR) {
85+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ID, ESP_ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_DEFAULT_VALUE);
86+
if (ret != ESP_OK) {
87+
log_e("Failed to set physical contact occupied to unoccupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
88+
return false;
89+
}
90+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ID, ESP_ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_DEFAULT_VALUE);
91+
if (ret != ESP_OK) {
92+
log_e("Failed to set physical contact unoccupied to occupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
93+
return false;
94+
}
95+
uint8_t physical_contact_threshold = ESP_ZB_ZCL_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_MIN_VALUE;
96+
ret = esp_zb_occupancy_sensing_cluster_add_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID, &physical_contact_threshold);
97+
if (ret != ESP_OK) {
98+
log_e("Failed to set physical contact unoccupied to occupied threshold: 0x%x: %s", ret, esp_err_to_name(ret));
99+
return false;
100+
}
101+
}
102+
return true;
103+
}
104+
105+
bool ZigbeeOccupancySensor::setOccupiedToUnoccupiedDelay(ZigbeeOccupancySensorType sensor_type, uint16_t delay) {
106+
esp_zb_attribute_list_t *occupancy_sens_cluster =
107+
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
108+
109+
esp_err_t ret;
110+
switch (sensor_type) {
111+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR:
112+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_ID, (void *)&delay);
113+
break;
114+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_ULTRASONIC:
115+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_ID, (void *)&delay);
116+
break;
117+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT:
118+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ID, (void *)&delay);
119+
break;
120+
default:
121+
log_e("Invalid sensor type for delay setting: 0x%x", sensor_type);
122+
return false;
123+
}
124+
125+
if (ret != ESP_OK) {
126+
log_e("Failed to set occupied to unoccupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
127+
return false;
128+
}
129+
return true;
130+
}
131+
132+
bool ZigbeeOccupancySensor::setUnoccupiedToOccupiedDelay(ZigbeeOccupancySensorType sensor_type, uint16_t delay) {
133+
esp_zb_attribute_list_t *occupancy_sens_cluster =
134+
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
135+
136+
esp_err_t ret;
137+
switch (sensor_type) {
138+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR:
139+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_ID, (void *)&delay);
140+
break;
141+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_ULTRASONIC:
142+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_ID, (void *)&delay);
143+
break;
144+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT:
145+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ID, (void *)&delay);
146+
break;
147+
default:
148+
log_e("Invalid sensor type for delay setting: 0x%x", sensor_type);
149+
return false;
150+
}
151+
152+
if (ret != ESP_OK) {
153+
log_e("Failed to set unoccupied to occupied delay: 0x%x: %s", ret, esp_err_to_name(ret));
154+
return false;
155+
}
156+
return true;
157+
}
158+
159+
bool ZigbeeOccupancySensor::setUnoccupiedToOccupiedThreshold(ZigbeeOccupancySensorType sensor_type, uint8_t threshold) {
160+
esp_zb_attribute_list_t *occupancy_sens_cluster =
161+
esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
162+
163+
esp_err_t ret;
164+
switch (sensor_type) {
165+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR:
166+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_ID, (void *)&threshold);
167+
break;
168+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_ULTRASONIC:
169+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID, (void *)&threshold);
170+
break;
171+
case ZIGBEE_OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT:
172+
ret = esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID, (void *)&threshold);
173+
break;
174+
default:
175+
log_e("Invalid sensor type for threshold setting: 0x%x", sensor_type);
176+
return false;
177+
}
178+
179+
if (ret != ESP_OK) {
180+
log_e("Failed to set unoccupied to occupied threshold: 0x%x: %s", ret, esp_err_to_name(ret));
181+
return false;
182+
}
39183
return true;
40184
}
41185

@@ -77,4 +221,55 @@ bool ZigbeeOccupancySensor::report() {
77221
return true;
78222
}
79223

224+
//set attribute method -> method overridden in child class
225+
void ZigbeeOccupancySensor::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {
226+
if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING) {
227+
//PIR
228+
if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_OCC_TO_UNOCC_DELAY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
229+
uint16_t pir_occ_to_unocc_delay = *(uint16_t *)message->attribute.data.value;
230+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR);
231+
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_DELAY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
232+
uint16_t pir_unocc_to_occ_delay = *(uint16_t *)message->attribute.data.value;
233+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR);
234+
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PIR_UNOCC_TO_OCC_THRESHOLD_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) {
235+
uint8_t pir_unocc_to_occ_threshold = *(uint8_t *)message->attribute.data.value;
236+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR);
237+
}
238+
//Ultrasonic
239+
else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_OCCUPIED_TO_UNOCCUPIED_DELAY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
240+
uint16_t ultrasonic_occ_to_unocc_delay = *(uint16_t *)message->attribute.data.value;
241+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_ULTRASONIC);
242+
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_DELAY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
243+
uint16_t ultrasonic_unocc_to_occ_delay = *(uint16_t *)message->attribute.data.value;
244+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_ULTRASONIC);
245+
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_ULTRASONIC_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) {
246+
uint8_t ultrasonic_unocc_to_occ_threshold = *(uint8_t *)message->attribute.data.value;
247+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_ULTRASONIC);
248+
}
249+
//Physical Contact
250+
else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_OCCUPIED_TO_UNOCCUPIED_DELAY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
251+
uint16_t physical_contact_occ_to_unocc_delay = *(uint16_t *)message->attribute.data.value;
252+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT);
253+
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_DELAY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
254+
uint16_t physical_contact_unocc_to_occ_delay = *(uint16_t *)message->attribute.data.value;
255+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT);
256+
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_PHYSICAL_CONTACT_UNOCCUPIED_TO_OCCUPIED_THRESHOLD_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) {
257+
uint8_t physical_contact_unocc_to_occ_threshold = *(uint8_t *)message->attribute.data.value;
258+
occupancyConfigChanged(ZIGBEE_OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT);
259+
} else {
260+
log_w("Received message ignored. Attribute ID: %d not supported for Occupancy Sensor endpoint", message->attribute.id);
261+
}
262+
} else {
263+
log_w("Received message ignored. Cluster ID: %d not supported for Occupancy Sensor endpoint", message->info.cluster);
264+
}
265+
}
266+
267+
void ZigbeeOccupancySensor::occupancyConfigChanged(ZigbeeOccupancySensorType sensor_type) {
268+
if (_on_occupancy_config_change) {
269+
_on_occupancy_config_change(sensor_type); //sensor type, delay, delay, threshold
270+
} else {
271+
log_w("No callback function set for occupancy config change");
272+
}
273+
}
274+
80275
#endif // CONFIG_ZB_ENABLED

‎libraries/Zigbee/src/ep/ZigbeeOccupancySensor.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,24 @@
3030
}
3131
// clang-format on
3232

33+
enum ZigbeeOccupancySensorType{
34+
ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR = 0,
35+
ZIGBEE_OCCUPANCY_SENSOR_TYPE_ULTRASONIC = 1,
36+
ZIGBEE_OCCUPANCY_SENSOR_TYPE_PIR_AND_ULTRASONIC = 2,
37+
ZIGBEE_OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT = 3
38+
};
39+
40+
enum ZigbeeOccupancySensorTypeBitmap{
41+
ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PIR = 0x01,
42+
ZIGBEE_OCCUPANCY_SENSOR_BITMAP_ULTRASONIC = 0x02,
43+
ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PIR_AND_ULTRASONIC = 0x03,
44+
// ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PHYSICAL_CONTACT = 0x04, // No info in cluster specification R8
45+
ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PHYSICAL_CONTACT_AND_PIR = 0x05,
46+
ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PHYSICAL_CONTACT_AND_ULTRASONIC = 0x06,
47+
ZIGBEE_OCCUPANCY_SENSOR_BITMAP_PHYSICAL_CONTACT_AND_PIR_AND_ULTRASONIC = 0x07,
48+
ZIGBEE_OCCUPANCY_SENSOR_BITMAP_DEFAULT = 0xff
49+
};
50+
3351
typedef struct zigbee_occupancy_sensor_cfg_s {
3452
esp_zb_basic_cluster_cfg_t basic_cfg;
3553
esp_zb_identify_cluster_cfg_t identify_cfg;
@@ -44,11 +62,29 @@ class ZigbeeOccupancySensor : public ZigbeeEP {
4462
// Set the occupancy value. True for occupied, false for unoccupied
4563
bool setOccupancy(bool occupied);
4664

47-
// Set the sensor type, see esp_zb_zcl_occupancy_sensing_occupancy_sensor_type_t
48-
bool setSensorType(uint8_t sensor_type);
65+
// Set the sensor type, see ZigbeeOccupancySensorType
66+
bool setSensorType(ZigbeeOccupancySensorType sensor_type, ZigbeeOccupancySensorTypeBitmap sensor_type_bitmap = ZIGBEE_OCCUPANCY_SENSOR_BITMAP_DEFAULT);
67+
68+
// Set the occupied to unoccupied delay
69+
// Specifies the time delay, in seconds, before the sensor changes to its unoccupied state after the last detection of movement in the sensed area.
70+
bool setOccupiedToUnoccupiedDelay(ZigbeeOccupancySensorType sensor_type, uint16_t delay);
71+
72+
// Set the unoccupied to occupied delay
73+
// Specifies the time delay, in seconds, before the sensor changes to its occupied state after the detection of movement in the sensed area.
74+
bool setUnoccupiedToOccupiedDelay(ZigbeeOccupancySensorType sensor_type, uint16_t delay);
75+
76+
// Set the unoccupied to occupied threshold
77+
// Specifies the number of movement detection events that must occur in the period unoccupied to occupied delay, before the sensor changes to its occupied state.
78+
bool setUnoccupiedToOccupiedThreshold(ZigbeeOccupancySensorType sensor_type, uint8_t threshold);
4979

5080
// Report the occupancy value
5181
bool report();
82+
83+
private:
84+
void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override;
85+
86+
void (*_on_occupancy_config_change)(bool);
87+
void occupancyConfigChanged(ZigbeeOccupancySensorType sensor_type);
5288
};
5389

5490
#endif // CONFIG_ZB_ENABLED

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /