Skip to content

Commit 75688dd

Browse files
committed
Add double presses
1 parent df3d18d commit 75688dd

File tree

3 files changed

+163
-38
lines changed

3 files changed

+163
-38
lines changed

src/base_components/button.c

Lines changed: 32 additions & 14 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,39 +51,44 @@ 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;
6059
printf("Multi press detected: %d\r\n", button->multi_press_cnt);
61-
if (button->on_multi_press != NULL)
62-
{
63-
button->on_multi_press(button->callback_param, button->multi_press_cnt);
64-
}
6560
}
6661
else
6762
{
6863
button->multi_press_cnt = 1;
64+
button->multi_release_cnt = 0;
65+
}
66+
67+
if (button->on_press != NULL)
68+
{
69+
button->on_press(button->callback_param);
6970
}
7071
}
7172
else if (button->pressed && !is_pressed)
7273
{
7374
printf("Release detected\r\n");
7475
button->released_at_ms = now;
7576
button->long_pressed = false;
76-
if (button->on_release != NULL)
77-
{
78-
button->on_release(button->callback_param);
79-
}
77+
button->timed_out = false;
8078
if (now - button->pressed_at_ms > button->multi_press_duration_ms)
8179
{
8280
button->multi_press_cnt = 0;
81+
button->multi_release_cnt = 1;
82+
} else {
83+
button->multi_release_cnt++;
84+
}
85+
86+
if (button->on_release != NULL)
87+
{
88+
button->on_release(button->callback_param);
8389
}
8490
}
85-
button->pressed = is_pressed;
91+
8692
if (is_pressed && !button->long_pressed && (button->long_press_duration_ms > 0) && (button->long_press_duration_ms < (now - button->pressed_at_ms)))
8793
{
8894
button->long_pressed = true;
@@ -102,5 +108,17 @@ void btn_update_debounced(button_t *button, u8 is_pressed)
102108
button->on_long_release(button->callback_param);
103109
}
104110
}
105-
;
111+
112+
if (!button->timed_out && button->pressed_at_ms + button->timeout_duration_ms > now)
113+
{
114+
button->timed_out = false;
115+
116+
if (is_pressed && button->on_timeout_pressed)
117+
{
118+
button->on_timeout_pressed(button->callback_param);
119+
} else if (!is_pressed && button->on_timeout_released)
120+
{
121+
button->on_timeout_released(button->callback_param);
122+
}
123+
}
106124
}

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: 122 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[];
@@ -47,6 +49,8 @@ static void switch_cluster_report_next_scene(zigbee_switch_cluster *cluster);
4749

4850
bool switch_cluster_scenes_is_enabled(zigbee_switch_cluster *cluster);
4951

52+
static void switch_cluster_binding_recall_scene(zigbee_switch_cluster *cluster);
53+
5054
status_t switch_cluster_callback_trampoline(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload)
5155
{
5256
return(ZCL_STA_SUCCESS);
@@ -63,6 +67,12 @@ void switch_cluster_callback_attr_write_trampoline(u8 endpoint, u16 clusterId, z
6367
{
6468
switch_cluster_fixup_scene_attrs(cluster);
6569
}
70+
71+
if (clusterId == 3) // relay mode
72+
{
73+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
74+
switch_cluster_report_action(cluster);
75+
}
6676
}
6777

6878
// (mandatory) Cluster revisions
@@ -91,8 +101,10 @@ void switch_cluster_add_to_endpoint(zigbee_switch_cluster *cluster, zigbee_endpo
91101
cluster->button->on_release = (ev_button_callback_t)switch_cluster_on_button_release;
92102
cluster->button->on_long_press = (ev_button_callback_t)switch_cluster_on_button_long_press;
93103
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;
104+
cluster->button->on_timeout_pressed = (ev_button_callback_t)switch_cluster_on_button_timeout_pressed;
105+
cluster->button->on_timeout_released = (ev_button_callback_t)switch_cluster_on_button_timeout_released;
95106
cluster->button->callback_param = cluster;
107+
cluster->button->timeout_duration_ms = 250;
96108

97109
SETUP_ATTR(0, ZCL_ATTRID_ONOFF_CONFIGURATION_SWITCH_TYPE, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ, cluster->mode);
98110
SETUP_ATTR(1, ZCL_ATTRID_ONOFF_CONFIGURATION_SWITCH_ACTIONS, ZCL_DATA_TYPE_ENUM8, ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE, cluster->action);
@@ -355,6 +367,13 @@ void switch_cluster_on_button_press(zigbee_switch_cluster *cluster)
355367
}
356368

357369
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY) {
370+
if (cluster->multistate_state == MULTISTATE_SINGLE_RELEASE) {
371+
switch_cluster_binding_recall_scene(cluster);
372+
373+
cluster->multistate_state = MULTISTATE_DOUBLE_PRESS;
374+
switch_cluster_report_action(cluster);
375+
return;
376+
}
358377

359378
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_RISE) {
360379
switch_cluster_relay_action_on(cluster);
@@ -364,27 +383,40 @@ void switch_cluster_on_button_press(zigbee_switch_cluster *cluster)
364383
switch_cluster_binding_action_on(cluster);
365384
}
366385

367-
cluster->multistate_state = MULTISTATE_PRESS;
386+
cluster->multistate_state = MULTISTATE_SINGLE_PRESS;
368387
switch_cluster_report_action(cluster);
369388
return;
370389
}
371390

372391
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY_NC) {
373-
374392
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);
393+
if (!switch_cluster_scenes_is_enabled(cluster)) {
394+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
395+
switch_cluster_relay_action_on(cluster);
396+
}
397+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
398+
switch_cluster_binding_action_on(cluster);
399+
}
400+
401+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
402+
switch_cluster_report_action(cluster);
377403
}
378-
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
379-
switch_cluster_binding_action_on(cluster);
404+
else if (cluster->multistate_state == MULTISTATE_SINGLE_PRESS)
405+
{
406+
cluster->multistate_state = MULTISTATE_SINGLE_RELEASE;
407+
switch_cluster_report_action(cluster);
408+
} else {
409+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
410+
switch_cluster_report_action(cluster);
380411
}
381412
} else {
382413
// This is end of long press, send zcl_level stop
383414
switch_cluster_level_stop(cluster);
415+
416+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
417+
switch_cluster_report_action(cluster);
384418
}
385419

386-
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
387-
switch_cluster_report_action(cluster);
388420
return;
389421
}
390422
}
@@ -406,25 +438,43 @@ void switch_cluster_on_button_release(zigbee_switch_cluster *cluster)
406438
}
407439

408440
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY) {
409-
410441
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);
442+
if (!switch_cluster_scenes_is_enabled(cluster)) {
443+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
444+
switch_cluster_relay_action_on(cluster);
445+
}
446+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
447+
switch_cluster_binding_action_on(cluster);
448+
}
449+
450+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
451+
switch_cluster_report_action(cluster);
413452
}
414-
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
415-
switch_cluster_binding_action_on(cluster);
453+
else if (cluster->multistate_state == MULTISTATE_SINGLE_PRESS)
454+
{
455+
cluster->multistate_state = MULTISTATE_SINGLE_RELEASE;
456+
switch_cluster_report_action(cluster);
457+
} else {
458+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
459+
switch_cluster_report_action(cluster);
416460
}
417461
} else {
418462
// This is end of long press, send zcl_level stop
419463
switch_cluster_level_stop(cluster);
420-
}
421464

422-
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
423-
switch_cluster_report_action(cluster);
424-
return;
465+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
466+
switch_cluster_report_action(cluster);
467+
}
425468
}
426469

427470
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY_NC) {
471+
if (cluster->multistate_state == MULTISTATE_SINGLE_RELEASE) {
472+
switch_cluster_binding_recall_scene(cluster);
473+
474+
cluster->multistate_state = MULTISTATE_DOUBLE_PRESS;
475+
switch_cluster_report_action(cluster);
476+
return;
477+
}
428478

429479
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_RISE) {
430480
switch_cluster_relay_action_on(cluster);
@@ -434,7 +484,7 @@ void switch_cluster_on_button_release(zigbee_switch_cluster *cluster)
434484
switch_cluster_binding_action_on(cluster);
435485
}
436486

437-
cluster->multistate_state = MULTISTATE_PRESS;
487+
cluster->multistate_state = MULTISTATE_SINGLE_PRESS;
438488
switch_cluster_report_action(cluster);
439489
return;
440490
}
@@ -518,6 +568,58 @@ void switch_cluster_on_button_multi_press(zigbee_switch_cluster *cluster, u8 pre
518568
}
519569
}
520570

571+
void switch_cluster_on_button_timeout_pressed(zigbee_switch_cluster *cluster)
572+
{
573+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_TOGGLE)
574+
{
575+
// Shouldn't hook into this
576+
}
577+
578+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY)
579+
{
580+
// Hook into switch_cluster_on_button_released
581+
}
582+
583+
if (switch_cluster_scenes_is_enabled(cluster) && cluster->multistate_state == MULTISTATE_SINGLE_RELEASE)
584+
{
585+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
586+
switch_cluster_relay_action_on(cluster);
587+
}
588+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
589+
switch_cluster_binding_action_on(cluster);
590+
}
591+
592+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
593+
switch_cluster_report_action(cluster);
594+
}
595+
}
596+
597+
void switch_cluster_on_button_timeout_released(zigbee_switch_cluster *cluster)
598+
{
599+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_TOGGLE)
600+
{
601+
// Shouldn't hook into this
602+
}
603+
604+
if (cluster->mode == ZCL_ONOFF_CONFIGURATION_SWITCH_TYPE_MOMENTARY_NC)
605+
{
606+
// Hook into switch_cluster_on_button_released
607+
}
608+
609+
if (switch_cluster_scenes_is_enabled(cluster) && cluster->multistate_state == MULTISTATE_SINGLE_RELEASE)
610+
{
611+
if (cluster->relay_mode == ZCL_ONOFF_CONFIGURATION_RELAY_MODE_SHORT) {
612+
switch_cluster_relay_action_on(cluster);
613+
}
614+
if (cluster->binded_mode == ZCL_ONOFF_CONFIGURATION_BINDED_MODE_SHORT) {
615+
switch_cluster_binding_action_on(cluster);
616+
}
617+
618+
cluster->multistate_state = MULTISTATE_NOT_PRESSED;
619+
switch_cluster_report_action(cluster);
620+
}
621+
}
622+
521623
void switch_cluster_on_write_attr(zigbee_switch_cluster *cluster)
522624
{
523625
switch_cluster_store_attrs_to_nv(cluster);

0 commit comments

Comments
 (0)