Skip to content

Commit 0ec12bf

Browse files
committed
Implement On with timed Off
1 parent cfc99b1 commit 0ec12bf

File tree

2 files changed

+162
-13
lines changed

2 files changed

+162
-13
lines changed

src/zigbee/relay_cluster.c

Lines changed: 155 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ void relay_cluster_store_attrs_to_nv(zigbee_relay_cluster *cluster);
2525
void relay_cluster_load_attrs_from_nv(zigbee_relay_cluster *cluster);
2626
void relay_cluster_handle_startup_mode(zigbee_relay_cluster *cluster);
2727

28+
void relay_cluster_on_with_timed_off(zigbee_relay_cluster *cluster, zcl_onoffCtrl_t on_off_control, u16 on_time, u16 off_wait_time);
29+
2830
void sync_indicator_led(zigbee_relay_cluster *cluster);
2931

3032
void relay_cluster_update_effect(zigbee_relay_cluster *cluster);
@@ -65,18 +67,20 @@ void relay_cluster_add_to_endpoint(zigbee_relay_cluster *cluster, zigbee_endpoin
6567
sync_indicator_led(cluster);
6668

6769
SETUP_ATTR(0, ZCL_ATTRID_ONOFF, ZCL_DATA_TYPE_BOOLEAN, ACCESS_CONTROL_READ | ACCESS_CONTROL_REPORTABLE, cluster->relay->on);
68-
SETUP_ATTR(1, ZCL_ATTRID_START_UP_ONOFF, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->startup_mode);
70+
SETUP_ATTR(1, ZCL_ATTRID_ON_TIME, ZCL_DATA_TYPE_UINT16, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->on_wait_time);
71+
SETUP_ATTR(2, ZCL_ATTRID_OFF_WAIT_TIME, ZCL_DATA_TYPE_UINT16, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->off_wait_time);
72+
SETUP_ATTR(3, ZCL_ATTRID_START_UP_ONOFF, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->startup_mode);
6973
if (cluster->indicator_led != NULL)
7074
{
71-
SETUP_ATTR(2, ZCL_ATTRID_ONOFF_INDICATOR_MODE, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->indicator_led_mode);
72-
SETUP_ATTR(3, ZCL_ATTRID_ONOFF_INDICATOR_STATE, ZCL_DATA_TYPE_BOOLEAN, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->indicator_led->on);
75+
SETUP_ATTR(4, ZCL_ATTRID_ONOFF_INDICATOR_MODE, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->indicator_led_mode);
76+
SETUP_ATTR(5, ZCL_ATTRID_ONOFF_INDICATOR_STATE, ZCL_DATA_TYPE_BOOLEAN, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->indicator_led->on);
7377
}
7478

7579
zigbee_endpoint_add_cluster(endpoint, 1, ZCL_CLUSTER_GEN_ON_OFF);
7680
zcl_specClusterInfo_t *info = zigbee_endpoint_reserve_info(endpoint);
7781
info->clusterId = ZCL_CLUSTER_GEN_ON_OFF;
7882
info->manuCode = MANUFACTURER_CODE_NONE;
79-
info->attrNum = cluster->indicator_led != NULL ? 4 : 2;
83+
info->attrNum = cluster->indicator_led != NULL ? 6 : 4;
8084
info->attrTbl = cluster->attr_infos;
8185
info->clusterRegisterFunc = zcl_onOff_register;
8286
info->clusterAppCb = relay_cluster_callback_trampoline;
@@ -103,6 +107,8 @@ status_t relay_cluster_callback_trampoline(zclIncomingAddrInfo_t *pAddrInfo, u8
103107

104108
status_t relay_cluster_callback(zigbee_relay_cluster *cluster, zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload)
105109
{
110+
zcl_onoff_cmdPayload_t *payload = cmdPayload;
111+
106112
if (cmdId == ZCL_CMD_ONOFF_ON)
107113
{
108114
relay_cluster_on(cluster);
@@ -123,9 +129,23 @@ status_t relay_cluster_callback(zigbee_relay_cluster *cluster, zclIncomingAddrIn
123129
{
124130
relay_cluster_on(cluster);
125131
}
132+
else if (cmdId == ZCL_CMD_ON_WITH_TIMED_OFF)
133+
{
134+
u16 on_time = payload->onWithTimeOff.onTime;
135+
u16 off_time = payload->onWithTimeOff.offWaitTime;
136+
zcl_onoffCtrl_t ctrl = payload->onWithTimeOff.onOffCtrl;
137+
138+
if (on_time == 0xffff || off_time == 0xffff) // values from 0x0000 to 0xfffe are allowed
139+
{
140+
return ZCL_STA_INVALID_VALUE;
141+
}
142+
143+
relay_cluster_on_with_timed_off(cluster, ctrl, on_time, off_time);
144+
}
126145
else
127146
{
128147
printf("Unknown command: %d\r\n", cmdId);
148+
return ZCL_STA_UNSUP_CLUSTER_COMMAND;
129149
}
130150

131151
return(ZCL_STA_SUCCESS);
@@ -139,7 +159,8 @@ status_t identify_cluster_callback_trampoline(zclIncomingAddrInfo_t *pAddrInfo,
139159

140160
static void identify_set(zigbee_relay_cluster *cluster, u16 time)
141161
{
142-
if (time == 0) {
162+
if (time == 0)
163+
{
143164
if (cluster->identify_time)
144165
{
145166
relay_cluster_stop_effect(cluster);
@@ -187,7 +208,7 @@ void sync_indicator_led(zigbee_relay_cluster *cluster)
187208
}
188209
if (cluster->indicator_led != NULL)
189210
{
190-
u8 turn_on_led = cluster->relay->on;
211+
u8 turn_on_led = relay_cluster_is_on(cluster);
191212
if (cluster->indicator_led_mode == ZCL_ONOFF_INDICATOR_MODE_OPPOSITE)
192213
{
193214
turn_on_led = !turn_on_led;
@@ -205,23 +226,74 @@ void sync_indicator_led(zigbee_relay_cluster *cluster)
205226

206227
void relay_cluster_on(zigbee_relay_cluster *cluster)
207228
{
229+
if (cluster->on_wait_time == 0)
230+
{
231+
cluster->off_wait_time = 0;
232+
}
233+
208234
relay_on(cluster->relay);
209235
sync_indicator_led(cluster);
210236
relay_cluster_report(cluster);
211237
}
212238

213239
void relay_cluster_off(zigbee_relay_cluster *cluster)
214240
{
241+
cluster->on_wait_time = 0;
242+
cluster->on_off_count_from = millis();
243+
215244
relay_off(cluster->relay);
216245
sync_indicator_led(cluster);
217246
relay_cluster_report(cluster);
218247
}
219248

220249
void relay_cluster_toggle(zigbee_relay_cluster *cluster)
221250
{
222-
relay_toggle(cluster->relay);
223-
sync_indicator_led(cluster);
224-
relay_cluster_report(cluster);
251+
bool cluster_on = cluster->relay->on;
252+
253+
if (cluster_on)
254+
{
255+
relay_cluster_off(cluster);
256+
}
257+
else
258+
{
259+
relay_cluster_on(cluster);
260+
}
261+
}
262+
263+
void relay_cluster_on_with_timed_off(zigbee_relay_cluster *cluster, zcl_onoffCtrl_t on_off_control, u16 on_time, u16 off_wait_time)
264+
{
265+
bool cluster_on = cluster->relay->on;
266+
267+
if (on_off_control.bits.acceptOnlyWhenOn && !cluster_on)
268+
{
269+
return;
270+
}
271+
272+
if (off_wait_time > 0 && !cluster_on)
273+
{
274+
if (off_wait_time < cluster->off_wait_time)
275+
{
276+
cluster->off_wait_time = off_wait_time;
277+
cluster->on_off_count_from = millis();
278+
}
279+
280+
return;
281+
}
282+
283+
if (on_time >= cluster->on_wait_time)
284+
{
285+
cluster->on_wait_time = on_time;
286+
cluster->on_off_count_from = millis();
287+
}
288+
289+
cluster->off_wait_time = off_wait_time;
290+
291+
if (!cluster_on)
292+
{
293+
relay_on(cluster->relay);
294+
sync_indicator_led(cluster);
295+
relay_cluster_report(cluster);
296+
}
225297
}
226298

227299
void relay_cluster_report(zigbee_relay_cluster *cluster)
@@ -260,7 +332,8 @@ void relay_cluster_on_write_attr(zigbee_relay_cluster *cluster, zclWriteCmd_t *p
260332
{
261333
for (int index = 0; index < pWriteReqCmd->numAttr; index++)
262334
{
263-
if (pWriteReqCmd->attrList[index].attrID == ZCL_ATTRID_ONOFF_INDICATOR_STATE)
335+
zclWriteRec_t attr = pWriteReqCmd->attrList[index];
336+
if (attr.attrID == ZCL_ATTRID_ONOFF_INDICATOR_STATE)
264337
{
265338
if (cluster->indicator_led->on)
266339
{
@@ -271,6 +344,31 @@ void relay_cluster_on_write_attr(zigbee_relay_cluster *cluster, zclWriteCmd_t *p
271344
led_off(cluster->indicator_led);
272345
}
273346
}
347+
348+
bool cluster_on = relay_cluster_is_on(cluster);
349+
350+
if (attr.attrID == ZCL_ATTRID_ON_TIME && attr.dataType == ZCL_DATA_TYPE_UINT16)
351+
{
352+
if (!cluster_on)
353+
{
354+
return;
355+
}
356+
357+
u16 time = BUILD_U16(attr.attrData[0], attr.attrData[1]);
358+
cluster->on_wait_time = time;
359+
cluster->on_off_count_from = millis();
360+
}
361+
362+
if (attr.attrID == ZCL_ATTRID_OFF_WAIT_TIME && attr.dataType == ZCL_DATA_TYPE_UINT16)
363+
{
364+
u16 time = BUILD_U16(attr.attrData[0], attr.attrData[1]);
365+
366+
cluster->off_wait_time = time;
367+
if (!cluster_on)
368+
{
369+
cluster->on_off_count_from = millis();
370+
}
371+
}
274372
}
275373
if (cluster->indicator_led_mode != ZCL_ONOFF_INDICATOR_MODE_MANUAL)
276374
{
@@ -392,8 +490,48 @@ void relay_cluster_stop_effect(zigbee_relay_cluster *cluster)
392490
cluster->switch_counter = 0;
393491
}
394492

493+
static bool on_off_decrement(zigbee_relay_cluster *cluster, u32 current_time)
494+
{
495+
bool relay_on = relay_cluster_is_on(cluster);
496+
497+
if (relay_on)
498+
{
499+
return !(cluster->on_wait_time == 0 || cluster->on_wait_time == 0xffff) && ((cluster->on_off_count_from + 100) <= current_time);
500+
}
501+
else
502+
{
503+
return cluster->off_wait_time != 0 && ((cluster->on_off_count_from + 100) <= current_time);
504+
}
505+
}
506+
507+
void relay_cluster_update_timed_off(zigbee_relay_cluster *cluster)
508+
{
509+
u32 time = millis();
510+
while (on_off_decrement(cluster, time))
511+
{
512+
if (relay_cluster_is_on(cluster))
513+
{
514+
cluster->on_wait_time -= 1;
515+
cluster->on_off_count_from += 100;
516+
if (cluster->on_wait_time == 0)
517+
{
518+
cluster->off_wait_time = 0;
519+
relay_cluster_off(cluster);
520+
}
521+
}
522+
else
523+
{
524+
cluster->off_wait_time -= 1;
525+
cluster->on_off_count_from += 100;
526+
}
527+
}
528+
}
529+
395530
void relay_cluster_update_effect(zigbee_relay_cluster *cluster)
396531
{
532+
// TODO
533+
relay_cluster_update_timed_off(cluster);
534+
397535
if (!(cluster->identify_time) && !(cluster->toggles_left))
398536
{
399537
return;
@@ -409,7 +547,7 @@ void relay_cluster_update_effect(zigbee_relay_cluster *cluster)
409547

410548
if (cluster->next_state == NEXT_STATE_OFF)
411549
{
412-
relay_off(cluster->relay);
550+
relay_cluster_off(cluster);
413551
cluster->next_state = NEXT_STATE_ON;
414552

415553
if (!cluster->identify_time)
@@ -425,7 +563,7 @@ void relay_cluster_update_effect(zigbee_relay_cluster *cluster)
425563
}
426564
else
427565
{
428-
relay_on(cluster->relay);
566+
relay_cluster_on(cluster);
429567
cluster->next_state = NEXT_STATE_OFF;
430568

431569
if (cluster->identify_time)
@@ -448,3 +586,8 @@ void relay_cluster_update_effect(zigbee_relay_cluster *cluster)
448586
}
449587
cluster->switch_counter -= time_carry;
450588
}
589+
590+
bool relay_cluster_is_on(zigbee_relay_cluster *cluster)
591+
{
592+
return cluster->relay->on;
593+
}

src/zigbee/relay_cluster.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ typedef struct
2121
u8 endpoint;
2222
u8 startup_mode;
2323
u8 indicator_led_mode;
24-
zclAttrInfo_t attr_infos[4];
24+
u16 off_wait_time;
25+
u16 on_wait_time;
26+
zclAttrInfo_t attr_infos[6];
2527
relay_t * relay;
2628
led_t * indicator_led;
2729

30+
u32 on_off_count_from;
31+
2832
u16 identify_time;
2933
zclAttrInfo_t identify_attr_infos[1];
3034

@@ -50,4 +54,6 @@ void relay_cluster_callback_attr_write_trampoline(u8 clusterId, zclWriteCmd_t *p
5054

5155
void gen_identify_callback_attr_write_trampoline(u8 clusterId, zclWriteCmd_t *pWriteReqCmd);
5256

57+
bool relay_cluster_is_on(zigbee_relay_cluster *cluster);
58+
5359
#endif

0 commit comments

Comments
 (0)