Skip to content

Commit 95dd7f4

Browse files
committed
Add double presses
1 parent df3d18d commit 95dd7f4

File tree

3 files changed

+172
-33
lines changed

3 files changed

+172
-33
lines changed

src/base_components/button.c

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ void btn_init(button_t *button)
1616
button->pressed = true;
1717
button->long_pressed = true;
1818
button->long_released = true;
19+
button->timed_out = true;
1920
}
2021
}
2122

@@ -50,10 +51,8 @@ void btn_update_debounced(button_t *button, u8 is_pressed)
5051
printf("Press detected\r\n");
5152
button->pressed_at_ms = now;
5253
button->long_released = false;
53-
if (button->on_press != NULL)
54-
{
55-
button->on_press(button->callback_param);
56-
}
54+
button->timed_out = false;
55+
5756
if (now - button->released_at_ms < button->multi_press_duration_ms)
5857
{
5958
button->multi_press_cnt += 1;
@@ -66,23 +65,36 @@ void btn_update_debounced(button_t *button, u8 is_pressed)
6665
else
6766
{
6867
button->multi_press_cnt = 1;
68+
button->multi_release_cnt = 0;
69+
}
70+
71+
if (button->on_press != NULL)
72+
{
73+
button->on_press(button->callback_param);
6974
}
7075
}
7176
else if (button->pressed && !is_pressed)
7277
{
7378
printf("Release detected\r\n");
7479
button->released_at_ms = now;
7580
button->long_pressed = false;
76-
if (button->on_release != NULL)
77-
{
78-
button->on_release(button->callback_param);
79-
}
81+
button->timed_out = false;
8082
if (now - button->pressed_at_ms > button->multi_press_duration_ms)
8183
{
8284
button->multi_press_cnt = 0;
85+
button->multi_release_cnt = 1;
86+
} else {
87+
button->multi_release_cnt++;
88+
}
89+
90+
if (button->on_release != NULL)
91+
{
92+
button->on_release(button->callback_param);
8393
}
8494
}
95+
8596
button->pressed = is_pressed;
97+
8698
if (is_pressed && !button->long_pressed && (button->long_press_duration_ms > 0) && (button->long_press_duration_ms < (now - button->pressed_at_ms)))
8799
{
88100
button->long_pressed = true;
@@ -102,5 +114,18 @@ void btn_update_debounced(button_t *button, u8 is_pressed)
102114
button->on_long_release(button->callback_param);
103115
}
104116
}
105-
;
117+
118+
if (!button->timed_out)
119+
{
120+
if (is_pressed && button->pressed_at_ms + button->timeout_duration_ms < now && button->on_timeout_pressed)
121+
{
122+
button->timed_out = true;
123+
button->on_timeout_pressed(button->callback_param);
124+
}
125+
else if (!is_pressed && button->released_at_ms + button->timeout_duration_ms < now && button->on_timeout_released)
126+
{
127+
button->timed_out = true;
128+
button->on_timeout_released(button->callback_param);
129+
}
130+
}
106131
}

src/base_components/button.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,22 @@ typedef struct
1515
u8 pressed;
1616
u8 long_pressed;
1717
u8 long_released;
18+
u8 timed_out;
1819
u32 pressed_at_ms;
1920
u32 released_at_ms;
2021
u32 long_press_duration_ms;
2122
u32 multi_press_duration_ms;
23+
u32 timeout_duration_ms;
2224
u8 multi_press_cnt;
25+
u8 multi_release_cnt;
2326
u8 debounce_last_state;
2427
u32 debounce_last_change;
25-
ev_button_callback_t on_press;
26-
ev_button_callback_t on_long_press;
27-
ev_button_callback_t on_release;
28-
ev_button_callback_t on_long_release;
28+
ev_button_callback_t on_press;
29+
ev_button_callback_t on_long_press;
30+
ev_button_callback_t on_release;
31+
ev_button_callback_t on_long_release;
32+
ev_button_callback_t on_timeout_pressed;
33+
ev_button_callback_t on_timeout_released;
2934
ev_button_multi_press_callback_t on_multi_press;
3035
void * callback_param;
3136
}button_t;

src/zigbee/switch_cluster.c

Lines changed: 129 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ const u16 multistate_num_of_states = 3;
1919

2020

2121
#define MULTISTATE_NOT_PRESSED 0
22-
#define MULTISTATE_PRESS 1
22+
#define MULTISTATE_SINGLE_PRESS 1
2323
#define MULTISTATE_LONG_PRESS 2
2424
#define MULTISTATE_POSITION_ON 3
2525
#define MULTISTATE_POSITION_OFF 4
26+
#define MULTISTATE_DOUBLE_PRESS 5
27+
#define MULTISTATE_SINGLE_RELEASE 6
2628

2729

2830
extern zigbee_relay_cluster relay_clusters[];
@@ -33,6 +35,8 @@ void switch_cluster_on_button_release(zigbee_switch_cluster *cluster);
3335
void switch_cluster_on_button_long_press(zigbee_switch_cluster *cluster);
3436
void switch_cluster_on_button_long_release(zigbee_switch_cluster *cluster);
3537
void switch_cluster_on_button_multi_press(zigbee_switch_cluster *cluster, u8 press_count);
38+
void switch_cluster_on_button_timeout_pressed(zigbee_switch_cluster *cluster);
39+
void switch_cluster_on_button_timeout_released(zigbee_switch_cluster *cluster);
3640

3741
zigbee_switch_cluster *switch_cluster_by_endpoint[10];
3842

@@ -47,6 +51,8 @@ static void switch_cluster_report_next_scene(zigbee_switch_cluster *cluster);
4751

4852
bool switch_cluster_scenes_is_enabled(zigbee_switch_cluster *cluster);
4953

54+
static void switch_cluster_binding_recall_scene(zigbee_switch_cluster *cluster);
55+
5056
status_t switch_cluster_callback_trampoline(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload)
5157
{
5258
return(ZCL_STA_SUCCESS);
@@ -63,6 +69,12 @@ void switch_cluster_callback_attr_write_trampoline(u8 endpoint, u16 clusterId, z
6369
{
6470
switch_cluster_fixup_scene_attrs(cluster);
6571
}
72+
73+
if (clusterId == 3) // relay mode
74+
{
75+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
76+
switch_cluster_report_action(cluster);
77+
}
6678
}
6779

6880
// (mandatory) Cluster revisions
@@ -91,8 +103,10 @@ void switch_cluster_add_to_endpoint(zigbee_switch_cluster *cluster, zigbee_endpo
91103
cluster->button->on_release = (ev_button_callback_t)switch_cluster_on_button_release;
92104
cluster->button->on_long_press = (ev_button_callback_t)switch_cluster_on_button_long_press;
93105
cluster->button->on_long_release = (ev_button_callback_t)switch_cluster_on_button_long_release;
94-
cluster->button->on_multi_press = (ev_button_multi_press_callback_t)switch_cluster_on_button_multi_press;
106+
cluster->button->on_timeout_pressed = (ev_button_callback_t)switch_cluster_on_button_timeout_pressed;
107+
cluster->button->on_timeout_released = (ev_button_callback_t)switch_cluster_on_button_timeout_released;
95108
cluster->button->callback_param = cluster;
109+
cluster->button->timeout_duration_ms = 250;
96110

97111
SETUP_ATTR(0, ZCL_ATTRID_ONOFF_CONFIGURATION_SWITCH_TYPE, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ, cluster->mode);
98112
SETUP_ATTR(1, ZCL_ATTRID_ONOFF_CONFIGURATION_SWITCH_ACTIONS, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->action);
@@ -355,6 +369,13 @@ void switch_cluster_on_button_press(zigbee_switch_cluster *cluster)
355369
}
356370

357371
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY) {
372+
if (cluster->multistate_state == MULTISTATE_SINGLE_RELEASE) {
373+
switch_cluster_binding_recall_scene(cluster);
374+
375+
cluster->multistate_state = MULTISTATE_DOUBLE_PRESS;
376+
switch_cluster_report_action(cluster);
377+
return;
378+
}
358379

359380
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_RISE) {
360381
switch_cluster_relay_action_on(cluster);
@@ -364,27 +385,40 @@ void switch_cluster_on_button_press(zigbee_switch_cluster *cluster)
364385
switch_cluster_binding_action_on(cluster);
365386
}
366387

367-
cluster->multistate_state = MULTISTATE_PRESS;
388+
cluster->multistate_state = MULTISTATE_SINGLE_PRESS;
368389
switch_cluster_report_action(cluster);
369390
return;
370391
}
371392

372393
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY_NC) {
373-
374394
if (cluster->multistate_state != MULTISTATE_LONG_PRESS) {
375-
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
376-
switch_cluster_relay_action_on(cluster);
395+
if (!switch_cluster_scenes_is_enabled(cluster)) {
396+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
397+
switch_cluster_relay_action_on(cluster);
398+
}
399+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
400+
switch_cluster_binding_action_on(cluster);
401+
}
402+
403+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
404+
switch_cluster_report_action(cluster);
377405
}
378-
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
379-
switch_cluster_binding_action_on(cluster);
406+
else if (cluster->multistate_state == MULTISTATE_SINGLE_PRESS)
407+
{
408+
cluster->multistate_state = MULTISTATE_SINGLE_RELEASE;
409+
switch_cluster_report_action(cluster);
410+
} else {
411+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
412+
switch_cluster_report_action(cluster);
380413
}
381414
} else {
382415
// This is end of long press, send zcl_level stop
383416
switch_cluster_level_stop(cluster);
417+
418+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
419+
switch_cluster_report_action(cluster);
384420
}
385421

386-
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
387-
switch_cluster_report_action(cluster);
388422
return;
389423
}
390424
}
@@ -406,25 +440,43 @@ void switch_cluster_on_button_release(zigbee_switch_cluster *cluster)
406440
}
407441

408442
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY) {
409-
410443
if (cluster->multistate_state != MULTISTATE_LONG_PRESS) {
411-
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
412-
switch_cluster_relay_action_on(cluster);
444+
if (!switch_cluster_scenes_is_enabled(cluster)) {
445+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
446+
switch_cluster_relay_action_on(cluster);
447+
}
448+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
449+
switch_cluster_binding_action_on(cluster);
450+
}
451+
452+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
453+
switch_cluster_report_action(cluster);
413454
}
414-
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
415-
switch_cluster_binding_action_on(cluster);
455+
else if (cluster->multistate_state == MULTISTATE_SINGLE_PRESS)
456+
{
457+
cluster->multistate_state = MULTISTATE_SINGLE_RELEASE;
458+
switch_cluster_report_action(cluster);
459+
} else {
460+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
461+
switch_cluster_report_action(cluster);
416462
}
417463
} else {
418464
// This is end of long press, send zcl_level stop
419465
switch_cluster_level_stop(cluster);
420-
}
421466

422-
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
423-
switch_cluster_report_action(cluster);
424-
return;
467+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
468+
switch_cluster_report_action(cluster);
469+
}
425470
}
426471

427472
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY_NC) {
473+
if (cluster->multistate_state == MULTISTATE_SINGLE_RELEASE) {
474+
switch_cluster_binding_recall_scene(cluster);
475+
476+
cluster->multistate_state = MULTISTATE_DOUBLE_PRESS;
477+
switch_cluster_report_action(cluster);
478+
return;
479+
}
428480

429481
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_RISE) {
430482
switch_cluster_relay_action_on(cluster);
@@ -434,7 +486,7 @@ void switch_cluster_on_button_release(zigbee_switch_cluster *cluster)
434486
switch_cluster_binding_action_on(cluster);
435487
}
436488

437-
cluster->multistate_state = MULTISTATE_PRESS;
489+
cluster->multistate_state = MULTISTATE_SINGLE_PRESS;
438490
switch_cluster_report_action(cluster);
439491
return;
440492
}
@@ -518,6 +570,58 @@ void switch_cluster_on_button_multi_press(zigbee_switch_cluster *cluster, u8 pre
518570
}
519571
}
520572

573+
void switch_cluster_on_button_timeout_pressed(zigbee_switch_cluster *cluster)
574+
{
575+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_TOGGLE)
576+
{
577+
// Shouldn't hook into this
578+
}
579+
580+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY)
581+
{
582+
// Hook into switch_cluster_on_button_released
583+
}
584+
585+
if (switch_cluster_scenes_is_enabled(cluster) && cluster->multistate_state == MULTISTATE_SINGLE_RELEASE)
586+
{
587+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
588+
switch_cluster_relay_action_on(cluster);
589+
}
590+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
591+
switch_cluster_binding_action_on(cluster);
592+
}
593+
594+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
595+
switch_cluster_report_action(cluster);
596+
}
597+
}
598+
599+
void switch_cluster_on_button_timeout_released(zigbee_switch_cluster *cluster)
600+
{
601+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_TOGGLE)
602+
{
603+
// Shouldn't hook into this
604+
}
605+
606+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY_NC)
607+
{
608+
// Hook into switch_cluster_on_button_released
609+
}
610+
611+
if (switch_cluster_scenes_is_enabled(cluster) && cluster->multistate_state == MULTISTATE_SINGLE_RELEASE)
612+
{
613+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
614+
switch_cluster_relay_action_on(cluster);
615+
}
616+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
617+
switch_cluster_binding_action_on(cluster);
618+
}
619+
620+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
621+
switch_cluster_report_action(cluster);
622+
}
623+
}
624+
521625
void switch_cluster_on_write_attr(zigbee_switch_cluster *cluster)
522626
{
523627
switch_cluster_store_attrs_to_nv(cluster);
@@ -697,3 +801,8 @@ static void switch_cluster_binding_recall_scene(zigbee_switch_cluster *cluster)
697801
out:
698802
switch_cluster_report_next_scene(cluster);
699803
}
804+
805+
bool switch_cluster_scenes_is_enabled(zigbee_switch_cluster *cluster)
806+
{
807+
return cluster->out_scene_count;
808+
}

0 commit comments

Comments
 (0)