feat(control-plane): add configurable Wi-Fi reset button

This commit is contained in:
chenjintao
2026-08-18 16:00:10 +08:00
parent 96f5e535d3
commit 22a409973e
10 changed files with 153 additions and 4 deletions
+1
View File
@@ -14,6 +14,7 @@ idf_component_register(
"src/runtime/control_plane_fortune_service.c"
"src/runtime/control_plane_system_events.c"
"src/runtime/control_plane_key_input.c"
"src/runtime/control_plane_reset_service.c"
"src/runtime/control_plane_remote_log_service.c"
"src/runtime/control_plane_runtime_workers.c"
"src/runtime/control_plane_ota.c"
@@ -24,6 +24,7 @@ typedef enum {
CONTROL_PLANE_KEY_ID_PTT = 0,
CONTROL_PLANE_KEY_ID_SW1,
CONTROL_PLANE_KEY_ID_SW2,
CONTROL_PLANE_KEY_ID_RESET,
} control_plane_key_id_t;
typedef enum {
@@ -54,4 +55,3 @@ typedef struct {
control_plane_key_event_t key;
} data;
} control_plane_system_event_t;
@@ -158,6 +158,7 @@ const char *control_plane_key_event_type_name(control_plane_key_event_type_t typ
esp_err_t control_plane_start_key_input_task(void);
void control_plane_stop_key_input_task(void);
void control_plane_reset_wifi_provisioning_and_restart(void);
esp_err_t control_plane_schedule_websocket_wait_task(void);
void control_plane_set_ptt_active(bool active);
esp_err_t control_plane_enter_mini_program_reprovisioning(const char *reason);
@@ -94,6 +94,18 @@
#define CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN 0
#endif
#ifndef CONFIG_TQ_RESET_BUTTON_ENABLE
#define CONFIG_TQ_RESET_BUTTON_ENABLE 0
#endif
#ifndef CONFIG_TQ_RESET_BUTTON_PULLUP
#define CONFIG_TQ_RESET_BUTTON_PULLUP 0
#endif
#ifndef CONFIG_TQ_RESET_BUTTON_PULLDOWN
#define CONFIG_TQ_RESET_BUTTON_PULLDOWN 0
#endif
static const char *TAG = "cp_key_input";
typedef struct {
@@ -181,6 +193,22 @@ static const control_plane_key_config_t s_key_configs[] = {
.enable_long_press = true,
.enable_double_click = true,
},
#if CONFIG_TQ_RESET_BUTTON_ENABLE
{
.key_id = CONTROL_PLANE_KEY_ID_RESET,
.gpio_num = CONFIG_TQ_RESET_BUTTON_GPIO,
.active_level = CONFIG_TQ_RESET_BUTTON_ACTIVE_LEVEL,
.pullup_enabled = CONFIG_TQ_RESET_BUTTON_PULLUP,
.pulldown_enabled = CONFIG_TQ_RESET_BUTTON_PULLDOWN,
.debounce_ms = CONFIG_TQ_KEY_DEBOUNCE_INTERVAL_MS,
.long_press_ms = CONFIG_TQ_RESET_BUTTON_LONG_PRESS_MS,
.double_click_ms = 0,
.emit_press_release = false,
.enable_short_press = false,
.enable_long_press = true,
.enable_double_click = false,
},
#endif
};
static QueueHandle_t s_gpio_irq_queue;
@@ -262,6 +290,31 @@ static esp_err_t control_plane_configure_key_gpio(const control_plane_key_config
return gpio_intr_enable(config->gpio_num);
}
static esp_err_t control_plane_validate_key_configs(void)
{
for (size_t i = 0; i < sizeof(s_key_configs) / sizeof(s_key_configs[0]); ++i) {
const control_plane_key_config_t *config = &s_key_configs[i];
if (config->pullup_enabled && config->pulldown_enabled) {
ESP_LOGE(TAG,
"key=%s gpio=%d cannot enable pull-up and pull-down together",
control_plane_key_id_name(config->key_id),
(int)config->gpio_num);
return ESP_ERR_INVALID_ARG;
}
for (size_t j = 0; j < i; ++j) {
if (s_key_configs[j].gpio_num == config->gpio_num) {
ESP_LOGE(TAG,
"key GPIO conflict: key=%s and key=%s both use gpio=%d",
control_plane_key_id_name(s_key_configs[j].key_id),
control_plane_key_id_name(config->key_id),
(int)config->gpio_num);
return ESP_ERR_INVALID_ARG;
}
}
}
return ESP_OK;
}
static void control_plane_emit_key_event(const control_plane_key_config_t *config,
control_plane_key_event_type_t type,
int level,
@@ -469,6 +522,12 @@ static void control_plane_key_input_task(void *arg)
esp_err_t setup_err = ESP_OK;
memset(s_key_states, 0, sizeof(s_key_states));
setup_err = control_plane_validate_key_configs();
if (setup_err != ESP_OK) {
s_key_input_task = NULL;
vTaskDelete(NULL);
return;
}
for (size_t i = 0; i < sizeof(s_key_configs) / sizeof(s_key_configs[0]); ++i) {
const control_plane_key_config_t *config = &s_key_configs[i];
s_key_states[i].initialized = true;
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "control_plane_internal.h"
#include "esp_log.h"
static const char *TAG = "cp_reset";
void control_plane_reset_wifi_provisioning_and_restart(void)
{
ESP_LOGW(TAG, "Wi-Fi reset requested; clearing saved credentials");
esp_err_t err = domain_runtime_wifi_portal_clear_saved_credentials();
if (err != ESP_OK) {
ESP_LOGE(TAG,
"Wi-Fi credential reset failed; device will not restart: %s",
esp_err_to_name(err));
return;
}
ESP_LOGW(TAG, "Saved Wi-Fi credentials cleared; restarting device");
domain_runtime_restart();
}
@@ -84,6 +84,8 @@ const char *control_plane_key_id_name(control_plane_key_id_t key_id)
return "SW1";
case CONTROL_PLANE_KEY_ID_SW2:
return "SW2";
case CONTROL_PLANE_KEY_ID_RESET:
return "RESET";
default:
return "UNKNOWN";
}
@@ -128,6 +130,13 @@ static void control_plane_dispatch_key_event(const control_plane_key_event_t *ev
event->press_duration_ms,
event->click_count);
if (event->key_id == CONTROL_PLANE_KEY_ID_RESET) {
if (event->type == CONTROL_PLANE_KEY_EVENT_LONG_PRESS_START) {
control_plane_reset_wifi_provisioning_and_restart();
}
return;
}
if (event->key_id == CONTROL_PLANE_KEY_ID_SW2) {
if (event->type == CONTROL_PLANE_KEY_EVENT_SHORT_PRESS) {
esp_err_t request_err = control_plane_request_cloud_chouqian();