@@ -25,6 +25,8 @@ void relay_cluster_store_attrs_to_nv(zigbee_relay_cluster *cluster);
2525void relay_cluster_load_attrs_from_nv (zigbee_relay_cluster * cluster );
2626void 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+
2830void sync_indicator_led (zigbee_relay_cluster * cluster );
2931
3032void 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
104108status_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
140160static 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
206227void 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
213239void 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
220249void 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
227299void 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+
395530void 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+ }
0 commit comments