Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUTTON] Different timeout trigger callback (AEGHB-128) #257

Closed
law-ko opened this issue Apr 5, 2023 · 10 comments
Closed

[BUTTON] Different timeout trigger callback (AEGHB-128) #257

law-ko opened this issue Apr 5, 2023 · 10 comments
Labels

Comments

@law-ko
Copy link

law-ko commented Apr 5, 2023

In the original example under esp-homekit-sdk, we can set different release callback trigger functions with different timeout specified, like below:

iot_button_add_on_release_cb(handle, ON_OFF_BUTTON_TIMEOUT, on_off_handler, NULL);
iot_button_add_on_release_cb(handle, RESTART_BUTTON_TIMEOUT, restart_handler, NULL);
iot_button_add_on_release_cb(handle, RESET_NETWORK_BUTTON_TIMEOUT, reset_network_handler, NULL);
iot_button_add_on_press_cb(handle, RESET_TO_FACTORY_BUTTON_TIMEOUT, reset_to_factory_handler, NULL);

However, with the current version we can only define one long press timeout, with .long_press_ticks

// create gpio button
button_config_t gpio_btn_cfg = {
    .type = BUTTON_TYPE_GPIO,
    .long_press_ticks = CONFIG_BUTTON_LONG_PRESS_TIME_MS,
    .short_press_ticks = CONFIG_BUTTON_SHORT_PRESS_TIME_MS,
    .gpio_button_config = {
        .gpio_num = 0,
        .active_level = 0,
    },
};
button_handle_t gpio_btn = iot_button_create(&gpio_btn_cfg);
if(NULL == gpio_btn) {
    ESP_LOGE(TAG, "Button create failed");
}

Any way we can define multiple timeout callbacks?

Thank you.

@github-actions github-actions bot changed the title [BUTTON] Different timeout trigger callback [BUTTON] Different timeout trigger callback (AEGHB-128) Apr 5, 2023
@leeebo
Copy link
Collaborator

leeebo commented Apr 6, 2023

@law-ko I think it's theoretically possible, and we'll support it in the next release

@lijunru-hub
Copy link
Contributor

The current solution is that you can create multiple button_handles but the underlying layer can use the same hardware IO

@law-ko
Copy link
Author

law-ko commented Apr 10, 2023

The current solution is that you can create multiple button_handles but the underlying layer can use the same hardware IO

Thanks for the insight, I cannot seem to figure out how BUTTON_LONG_PRESS_START and BUTTON_LONG_PRESS_HOLD works.

The current setup is like this:

// create gpio button
	button_config_t gpio_btn_cfg = {
		.type = BUTTON_TYPE_GPIO,
		.long_press_time = RESET_NETWORK_BUTTON_TIMEOUT, // 6 sec
		.short_press_time = ON_OFF_BUTTON_TIMEOUT,
		.gpio_button_config = {
			.gpio_num = RESET_GPIO,
			.active_level = 0,
		},
	};
    button_handle_t handle = iot_button_create(&gpio_btn_cfg);
	iot_button_register_cb(handle, BUTTON_SINGLE_CLICK, on_off_handler, NULL);
	iot_button_register_cb(handle, BUTTON_DOUBLE_CLICK, restart_handler, NULL);
	iot_button_register_cb(handle, BUTTON_LONG_PRESS_HOLD, reset_network_handler, NULL);
	// create reset gpio button
	button_config_t rst_gpio_btn_cfg = {
		.type = BUTTON_TYPE_GPIO,
		.long_press_time = RESET_TO_FACTORY_BUTTON_TIMEOUT, // 10 sec
		.short_press_time = ON_OFF_BUTTON_TIMEOUT,
		.gpio_button_config = {
			.gpio_num = RESET_GPIO,
			.active_level = 0,
		},
	};
	button_handle_t reset_handle = iot_button_create(&rst_gpio_btn_cfg);
	iot_button_register_cb(reset_handle, BUTTON_LONG_PRESS_START, reset_to_factory_handler, NULL);

Seems like I am only able to trigger the reset_to_network_handler not the reset_to_factory_handler.

We want something like this:

iot_button_add_on_release_cb(handle, RESET_NETWORK_BUTTON_TIMEOUT, reset_network_handler, NULL);
iot_button_add_on_press_cb(handle, RESET_TO_FACTORY_BUTTON_TIMEOUT, reset_to_factory_handler, NULL);

where if the user presses more than 6 seconds and release, then it will trigger reset_network_handler. if the user presses more than 10 seconds (doesn't matter if the button is released or not), it will trigger reset_to_factory_handler and not trigger reset_network_handler

@lijunru-hub
Copy link
Contributor

Thanks for your replay, BUTTON_LONG_PRESS_START only triggered once, but BUTTON_LONG_PRESS_HOLD triggered many times during long pressing

@lijunru-hub
Copy link
Contributor

You can register a button_press_up event, call iOT_BUTTTON_GET_TICKS_TIME in the event, judge the lifting time of 6-10s or 10s, and then make corresponding operations to the corresponding operation

@law-ko
Copy link
Author

law-ko commented Apr 15, 2023

You can register a button_press_up event, call iOT_BUTTTON_GET_TICKS_TIME in the event, judge the lifting time of 6-10s or 10s, and then make corresponding operations to the corresponding operation

@lijunru-hub However, this way we are unable to trigger the 10second one without releasing the button, correct?

In the original method, the 10 second will be triggered once the button is hold 10 seconds and not releasing the button.

@lijunru-hub
Copy link
Contributor

Yes, but it is also difficult for the driver to provide a longpress_cb that supports both 5s and 10s long presses. because when the 5s comes, it is not known whether the user will continue to press. So it is better to use release_up in the application layer to assist detection

@leeebo leeebo added the button label Jul 10, 2023
@lijunru-hub
Copy link
Contributor

lijunru-hub commented Aug 29, 2023

Multiple long press events are now supported
https://components.espressif.com/components/espressif/button

@law-ko
Copy link
Author

law-ko commented Dec 18, 2023

@lijunru-hub I have tried it but it seems like the second hold callback cannot be triggered and the first hold callback will get triggered even if the button is not released yet.


static void app_driver_factory_reset_pressed_cb(void *arg, void *data)
{
    ESP_LOGW(TAG, "Reset button pressed for 5 seconds");
    // Factory reset the device when the factory reset button is pressed for 5 seconds
    if (!perform_factory_reset) {
        ESP_LOGI(TAG, "Factory reset triggered. Release the button to start factory reset.");
        perform_factory_reset = true;
    }
}

static void app_driver_factory_reset_released_cb(void *arg, void *data)
{
    if (perform_factory_reset) {
        ESP_LOGW(TAG, "Starting factory reset");
    }
}

static void app_driver_erase_factory_reset_pressed_cb(void *arg, void *data)
{
    ESP_LOGW(TAG, "Reset button pressed for 10 seconds");
    // Erase the device when the factory reset button is pressed for 10 seconds
    if (!perform_factory_reset) {
        ESP_LOGI(TAG, "Erasing device triggered. Release the button to start erasing.");
        perform_factory_reset = true;
    }
}

static void app_driver_erase_factory_reset_released_cb(void *arg, void *data)
{
    if (perform_factory_reset) {
        ESP_LOGW(TAG, "Starting erasing");
    }
}

    /* Button event for 5-second reset */
    button_event_config_t cfg = {
        .event = BUTTON_LONG_PRESS_START,
    };
    cfg.event_data.long_press.press_time = 5000;
    iot_button_register_event_cb(handle, cfg, app_driver_factory_reset_pressed_cb, NULL);
    cfg.event = BUTTON_LONG_PRESS_HOLD;
    iot_button_register_event_cb(handle, cfg, app_driver_factory_reset_released_cb, NULL);
    /* Button event for 10-second reset */
    cfg.event = BUTTON_LONG_PRESS_START;
    cfg.event_data.long_press.press_time = 10000;
    iot_button_register_event_cb(handle, cfg, app_driver_erase_factory_reset_pressed_cb, NULL);
    cfg.event = BUTTON_LONG_PRESS_HOLD;
    iot_button_register_event_cb(handle, cfg, app_driver_erase_factory_reset_released_cb, NULL);
    ```

This `app_driver_erase_factory_reset_pressed_cb` and `app_driver_erase_factory_reset_released_cb` callback can never get called as `app_driver_factory_reset_released_cb` will always happen first.

@law-ko
Copy link
Author

law-ko commented Dec 18, 2023

Using release_up detection to resolve it.

@law-ko law-ko closed this as completed Dec 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants