-
Notifications
You must be signed in to change notification settings - Fork 7.6k
/
Copy pathZigbeeColorDimmableLight.cpp
180 lines (158 loc) · 8.22 KB
/
ZigbeeColorDimmableLight.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include "ZigbeeColorDimmableLight.h"
#if CONFIG_ZB_ENABLED
ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) {
_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID;
esp_zb_color_dimmable_light_cfg_t light_cfg = ZIGBEE_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG();
_cluster_list = esp_zb_color_dimmable_light_clusters_create(&light_cfg);
//Add support for hue and saturation
uint8_t hue = 0;
uint8_t saturation = 0;
esp_zb_attribute_list_t *color_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, &hue);
esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, &saturation);
_ep_config = {
.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, .app_device_version = 0
};
//set default values
_current_state = false;
_current_level = 255;
_current_color = {255, 255, 255};
}
uint16_t ZigbeeColorDimmableLight::getCurrentColorX() {
return (*(uint16_t *)esp_zb_zcl_get_attribute(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID
)
->data_p);
}
uint16_t ZigbeeColorDimmableLight::getCurrentColorY() {
return (*(uint16_t *)esp_zb_zcl_get_attribute(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID
)
->data_p);
}
uint8_t ZigbeeColorDimmableLight::getCurrentColorHue() {
return (*(uint8_t *)esp_zb_zcl_get_attribute(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID
)
->data_p);
}
uint8_t ZigbeeColorDimmableLight::getCurrentColorSaturation() {
return (*(uint16_t *)esp_zb_zcl_get_attribute(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID
)
->data_p);
}
//set attribute method -> method overridden in child class
void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {
//check the data and call right method
if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) {
if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) {
if (_current_state != *(bool *)message->attribute.data.value) {
_current_state = *(bool *)message->attribute.data.value;
lightChanged();
}
return;
} else {
log_w("Received message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id);
}
} else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) {
if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) {
if (_current_level != *(uint8_t *)message->attribute.data.value) {
_current_level = *(uint8_t *)message->attribute.data.value;
lightChanged();
}
return;
} else {
log_w("Received message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id);
//TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h
}
} else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) {
if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t light_color_x = (*(uint16_t *)message->attribute.data.value);
uint16_t light_color_y = getCurrentColorY();
//calculate RGB from XY and call setColor()
_current_color = espXYToRgbColor(255, light_color_x, light_color_y); //TODO: Check if level is correct
lightChanged();
return;
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t light_color_x = getCurrentColorX();
uint16_t light_color_y = (*(uint16_t *)message->attribute.data.value);
//calculate RGB from XY and call setColor()
_current_color = espXYToRgbColor(255, light_color_x, light_color_y); //TODO: Check if level is correct
lightChanged();
return;
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) {
uint8_t light_color_hue = (*(uint8_t *)message->attribute.data.value);
_current_color = espHsvToRgbColor(light_color_hue, getCurrentColorSaturation(), 255);
lightChanged();
return;
} else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) {
uint8_t light_color_saturation = (*(uint8_t *)message->attribute.data.value);
_current_color = espHsvToRgbColor(getCurrentColorHue(), light_color_saturation, 255);
lightChanged();
return;
} else {
log_w("Received message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id);
}
} else {
log_w("Received message ignored. Cluster ID: %d not supported for Color dimmable Light", message->info.cluster);
}
}
void ZigbeeColorDimmableLight::lightChanged() {
if (_on_light_change) {
_on_light_change(_current_state, _current_color.r, _current_color.g, _current_color.b, _current_level);
}
}
void ZigbeeColorDimmableLight::setLight(bool state, uint8_t level, uint8_t red, uint8_t green, uint8_t blue) {
//Update all attributes
_current_state = state;
_current_level = level;
_current_color = {red, green, blue};
lightChanged();
espXyColor_t xy_color = espRgbColorToXYColor(_current_color);
espHsvColor_t hsv_color = espRgbColorToHsvColor(_current_color);
log_v("Updating light state: %d, level: %d, color: %d, %d, %d", state, level, red, green, blue);
/* Update light clusters */
esp_zb_lock_acquire(portMAX_DELAY);
//set on/off state
esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false
);
//set level
esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, &_current_level, false
);
//set xy color
esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID, &xy_color.x, false
);
esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID, &xy_color.y, false
);
//set hsv color
uint8_t hue = (uint8_t)hsv_color.h;
esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID, &hue, false
);
esp_zb_zcl_set_attribute_val(
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID, &hsv_color.s, false
);
esp_zb_lock_release();
}
void ZigbeeColorDimmableLight::setLightState(bool state) {
setLight(state, _current_level, _current_color.r, _current_color.g, _current_color.b);
}
void ZigbeeColorDimmableLight::setLightLevel(uint8_t level) {
setLight(_current_state, level, _current_color.r, _current_color.g, _current_color.b);
}
void ZigbeeColorDimmableLight::setLightColor(uint8_t red, uint8_t green, uint8_t blue) {
setLight(_current_state, _current_level, red, green, blue);
}
void ZigbeeColorDimmableLight::setLightColor(espRgbColor_t rgb_color) {
setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b);
}
void ZigbeeColorDimmableLight::setLightColor(espHsvColor_t hsv_color) {
espRgbColor_t rgb_color = espHsvColorToRgbColor(hsv_color);
setLight(_current_state, _current_level, rgb_color.r, rgb_color.g, rgb_color.b);
}
#endif // CONFIG_ZB_ENABLED