From 541d1be6ac18919a61f26b8c7ec99fc634e70ea8 Mon Sep 17 00:00:00 2001 From: dvdrw Date: Fri, 15 May 2026 16:05:12 +0200 Subject: [PATCH] feat: handle factory_reset and reconfigure_settings commands --- .../config_store/include/config_store.h | 6 ++++ components/config_store/src/config_store.c | 26 ++++++++++++++++ .../mqtt_publisher/include/mqtt_publisher.h | 26 ++++++++++++---- .../mqtt_publisher/src/mqtt_publisher.c | 25 ++++++++++++++-- main/main.c | 30 ++++++++++++++++++- 5 files changed, 104 insertions(+), 9 deletions(-) diff --git a/components/config_store/include/config_store.h b/components/config_store/include/config_store.h index bda833c..f198660 100644 --- a/components/config_store/include/config_store.h +++ b/components/config_store/include/config_store.h @@ -20,3 +20,9 @@ esp_err_t config_store_get_mqtt_override(char host_out[MQTT_HOST_MAX_LEN], uint1 /* Returns ESP_ERR_NVS_NOT_FOUND if no override is stored. */ esp_err_t config_store_get_mqtt_override_uri(char *uri_out, size_t uri_max_len); + +/* Clears the stored MQTT broker override. */ +esp_err_t config_store_clear_mqtt_override(void); + +/* Erases all stored configuration. */ +esp_err_t config_store_erase(void); \ No newline at end of file diff --git a/components/config_store/src/config_store.c b/components/config_store/src/config_store.c index 6f127ab..f3344d9 100644 --- a/components/config_store/src/config_store.c +++ b/components/config_store/src/config_store.c @@ -96,3 +96,29 @@ esp_err_t config_store_get_mqtt_override_uri(char *uri_out, size_t uri_max_len) snprintf(uri_out, uri_max_len, "mqtt://%s:%u", broker_host, broker_port); return ESP_OK; } + +esp_err_t config_store_clear_mqtt_override(void) +{ + nvs_handle_t h; + esp_err_t err = nvs_open(NS, NVS_READWRITE, &h); + if (err != ESP_OK) return err; + nvs_erase_key(h, KEY_HOST); + nvs_erase_key(h, KEY_PORT); + err = nvs_commit(h); + nvs_close(h); + return err; +} + +/* Erases all stored configuration. */ +esp_err_t config_store_erase(void) +{ + nvs_handle_t h; + esp_err_t err = nvs_open(NS, NVS_READWRITE, &h); + if (err != ESP_OK) return err; + nvs_erase_key(h, KEY_PROV); + nvs_erase_key(h, KEY_HOST); + nvs_erase_key(h, KEY_PORT); + err = nvs_commit(h); + nvs_close(h); + return err; +} \ No newline at end of file diff --git a/components/mqtt_publisher/include/mqtt_publisher.h b/components/mqtt_publisher/include/mqtt_publisher.h index 6f3839d..9b43dae 100644 --- a/components/mqtt_publisher/include/mqtt_publisher.h +++ b/components/mqtt_publisher/include/mqtt_publisher.h @@ -3,13 +3,29 @@ #include "esp_err.h" #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" +#include /* Event bits set by the MQTT publisher into the shared event group */ -#define MQTT_CONNECTED_BIT BIT0 -#define MQTT_CALIBRATE_START BIT1 -#define MQTT_CALIBRATE_STOP BIT2 -#define MQTT_SELECTED_BIT BIT3 -#define MQTT_DESELECTED_BIT BIT4 +#define MQTT_CONNECTED_BIT BIT0 +#define MQTT_CALIBRATE_START BIT1 +#define MQTT_CALIBRATE_STOP BIT2 +#define MQTT_SELECTED_BIT BIT3 +#define MQTT_DESELECTED_BIT BIT4 +#define MQTT_FACTORY_RESET_BIT BIT5 +#define MQTT_RECONFIGURE_SETTINGS_BIT BIT6 + +/* Populated by handle_cmd() before MQTT_RECONFIGURE_SETTINGS_BIT is set. + * All fields are optional — empty string means "not provided, leave unchanged". */ +typedef struct { + char ssid[32]; + char password[64]; + char mqtt_host[128]; + uint16_t mqtt_port; +} mqtt_reconfigure_data_t; + +/** Returns a pointer to the last parsed reconfigure payload. Valid only after + * MQTT_RECONFIGURE_SETTINGS_BIT fires; must be read before the next MQTT event. */ +const mqtt_reconfigure_data_t *mqtt_publisher_get_reconfigure_data(void); /** * Initialise and connect the MQTT client. diff --git a/components/mqtt_publisher/src/mqtt_publisher.c b/components/mqtt_publisher/src/mqtt_publisher.c index 4b28910..b4cf18e 100644 --- a/components/mqtt_publisher/src/mqtt_publisher.c +++ b/components/mqtt_publisher/src/mqtt_publisher.c @@ -8,9 +8,15 @@ #define TAG "mqtt_publisher" #define TOPIC_PREFIX "localiser/sensor" -static esp_mqtt_client_handle_t s_client = NULL; -static char s_sensor_id[32]; -static EventGroupHandle_t s_evt = NULL; +static esp_mqtt_client_handle_t s_client = NULL; +static char s_sensor_id[32]; +static EventGroupHandle_t s_evt = NULL; +static mqtt_reconfigure_data_t s_reconfigure_data; + +const mqtt_reconfigure_data_t *mqtt_publisher_get_reconfigure_data(void) +{ + return &s_reconfigure_data; +} /* Pre-built topic strings */ static char s_topic_rssi[96]; @@ -43,6 +49,19 @@ static void handle_cmd(const char *data, int data_len) else if (strcmp(a, "calibrate_stop") == 0) xEventGroupSetBits(s_evt, MQTT_CALIBRATE_STOP); else if (strcmp(a, "selected") == 0) xEventGroupSetBits(s_evt, MQTT_SELECTED_BIT); else if (strcmp(a, "deselected") == 0) xEventGroupSetBits(s_evt, MQTT_DESELECTED_BIT); + else if (strcmp(a, "factory_reset") == 0) xEventGroupSetBits(s_evt, MQTT_FACTORY_RESET_BIT); + else if (strcmp(a, "reconfigure_settings") == 0) { + memset(&s_reconfigure_data, 0, sizeof(s_reconfigure_data)); + cJSON *ssid_j = cJSON_GetObjectItemCaseSensitive(root, "ssid"); + cJSON *pass_j = cJSON_GetObjectItemCaseSensitive(root, "password"); + cJSON *host_j = cJSON_GetObjectItemCaseSensitive(root, "mqtt_host"); + cJSON *port_j = cJSON_GetObjectItemCaseSensitive(root, "mqtt_port"); + if (cJSON_IsString(ssid_j)) strncpy(s_reconfigure_data.ssid, ssid_j->valuestring, sizeof(s_reconfigure_data.ssid) - 1); + if (cJSON_IsString(pass_j)) strncpy(s_reconfigure_data.password, pass_j->valuestring, sizeof(s_reconfigure_data.password) - 1); + if (cJSON_IsString(host_j)) strncpy(s_reconfigure_data.mqtt_host, host_j->valuestring, sizeof(s_reconfigure_data.mqtt_host) - 1); + if (cJSON_IsNumber(port_j)) s_reconfigure_data.mqtt_port = (uint16_t)port_j->valuedouble; + xEventGroupSetBits(s_evt, MQTT_RECONFIGURE_SETTINGS_BIT); + } else ESP_LOGW(TAG, "Unknown cmd action: %s", a); } cJSON_Delete(root); diff --git a/main/main.c b/main/main.c index c8582e1..307b4f7 100644 --- a/main/main.c +++ b/main/main.c @@ -177,7 +177,8 @@ void app_main(void) // main event loop const EventBits_t cmd_bits = MQTT_CALIBRATE_START | MQTT_CALIBRATE_STOP | - MQTT_SELECTED_BIT | MQTT_DESELECTED_BIT; + MQTT_SELECTED_BIT | MQTT_DESELECTED_BIT | + MQTT_FACTORY_RESET_BIT | MQTT_RECONFIGURE_SETTINGS_BIT; bool calibrating = false; bool selected = false; @@ -206,5 +207,32 @@ void app_main(void) selected = false; if (!calibrating) led_indicator_set(LED_SCANNING); } + if (bits & MQTT_FACTORY_RESET_BIT) { + // factory reset requested - erase NVS and reboot + ESP_LOGI(TAG, "Factory reset requested"); + config_store_erase(); + esp_restart(); + } + if (bits & MQTT_RECONFIGURE_SETTINGS_BIT) { + ESP_LOGI(TAG, "Reconfigure settings requested"); + const mqtt_reconfigure_data_t *cfg = mqtt_publisher_get_reconfigure_data(); + + if (cfg->ssid[0] != '\0') { + wifi_config_t wifi_cfg = {0}; + strncpy((char *)wifi_cfg.sta.ssid, cfg->ssid, sizeof(wifi_cfg.sta.ssid) - 1); + strncpy((char *)wifi_cfg.sta.password, cfg->password, sizeof(wifi_cfg.sta.password) - 1); + esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + ESP_LOGI(TAG, "Updated WiFi SSID: %s", cfg->ssid); + } + + if (cfg->mqtt_host[0] != '\0') { + uint16_t port = cfg->mqtt_port ? cfg->mqtt_port : DEFAULT_MQTT_PORT; + config_store_set_mqtt_override(cfg->mqtt_host, port); + ESP_LOGI(TAG, "Updated MQTT broker: %s:%u", cfg->mqtt_host, port); + } + + ESP_LOGI(TAG, "Rebooting to apply new settings"); + esp_restart(); + } } }