diff --git a/main/io/nvs_handler.cpp b/main/io/nvs_handler.cpp index cc83d66..7aed74d 100644 --- a/main/io/nvs_handler.cpp +++ b/main/io/nvs_handler.cpp @@ -20,6 +20,7 @@ NVSStorageHandler::~NVSStorageHandler() { void NVSStorageHandler::init(const EventGroupHandle_t& system_event_group) { esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGW(TAG, "NVS Flash init failed with %s, erasing and retrying...", esp_err_to_name(err)); nvs_flash_erase(); err = nvs_flash_init(); } @@ -43,11 +44,26 @@ void NVSStorageHandler::put(const std::string& key, const std::string& value) { } esp_err_t err = nvs_set_str(this->nvsHandle, key.c_str(), value.c_str()); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error (%s) setting key-value pair in NVS!", esp_err_to_name(err)); - } else { + if (err == ESP_ERR_NVS_NOT_ENOUGH_SPACE) { + ESP_LOGE(TAG, "NVS storage full! Cannot store key '%s'. Consider clearing old data.", key.c_str()); + ESP_LOGI(TAG, "Attempting to erase and retry..."); + // Try to commit pending changes first nvs_commit(this->nvsHandle); - // ESP_LOGI(TAG, "Key-value pair (%s, %s) stored in NVS.", key.c_str(), value.c_str()); + // Retry once + err = nvs_set_str(this->nvsHandle, key.c_str(), value.c_str()); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Retry failed: %s", esp_err_to_name(err)); + return; + } + } else if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) setting key-value pair in NVS!", esp_err_to_name(err)); + return; + } + + // Commit successful write + err = nvs_commit(this->nvsHandle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) committing to NVS!", esp_err_to_name(err)); } } diff --git a/main/network/wifi_handler.cpp b/main/network/wifi_handler.cpp index 6d9f9e6..a5a08ab 100644 --- a/main/network/wifi_handler.cpp +++ b/main/network/wifi_handler.cpp @@ -160,6 +160,7 @@ esp_err_t WifiHandler::connect(const std::string& ssid, const std::string& passw this->current_ssid.clear(); } this->current_ssid = ssid; + this->current_password = password; // wifi_config_t wifi_config = {}; @@ -182,8 +183,8 @@ esp_err_t WifiHandler::connect(const std::string& ssid, const std::string& passw return err; } - // store credentials after successful connection attempt - this->store_wifi_credentials(this->current_ssid, password); + // Note: Credentials will be stored in the event handler after successful connection + // to avoid storing credentials for failed connection attempts return ESP_OK; } @@ -305,6 +306,10 @@ void WifiHandler::wifi_event_handler(void* arg, esp_event_base_t event_base, int self->s_wifi_event_group, WIFI_CONNECTED_BIT ); + // Store credentials only after successful connection + if (!self->current_ssid.empty() && !self->current_password.empty()) { + self->store_wifi_credentials(self->current_ssid, self->current_password); + } break; } default: @@ -328,7 +333,11 @@ void WifiHandler::store_wifi_credentials(const std::string& ssid, const std::str ESP_LOGE(TAG, "Failed to take credential mutex"); return; } - // store the password according to the JSON structure + + // Store current SSID + kvs->put(WIFI_SSID_KEY, ssid); + + // Store the password according to the JSON structure std::string password_key_store = kvs->get(WIFI_PASSWORD_STORE_KEY); cJSON* json = nullptr; if (password_key_store.empty()) { @@ -348,17 +357,37 @@ void WifiHandler::store_wifi_credentials(const std::string& ssid, const std::str credentials = cJSON_CreateObject(); cJSON_AddItemToObject(json, "credentials", credentials); } + + // Limit stored credentials to prevent NVS overflow (keep max 10 SSIDs) + int credential_count = cJSON_GetArraySize(credentials); + if (credential_count >= 10) { + ESP_LOGW(TAG, "Too many stored credentials (%d), clearing old ones", credential_count); + // Keep only the current SSID's credentials, clear others + cJSON_DeleteItemFromObject(credentials, ssid.c_str()); // Remove if exists + cJSON* new_credentials = cJSON_CreateObject(); + cJSON_ReplaceItemInObject(json, "credentials", new_credentials); + credentials = new_credentials; + } + + // Remove existing entry for this SSID to update it + cJSON_DeleteItemFromObject(credentials, ssid.c_str()); + // create SSID object cJSON* ssid_item = cJSON_CreateObject(); // add password field cJSON_AddStringToObject(ssid_item, "password", password.c_str()); // add SSID object to credentials cJSON_AddItemToObject(credentials, ssid.c_str(), ssid_item); + // store updated JSON string char* updated_json_str = cJSON_PrintUnformatted(json); if (updated_json_str) { + esp_err_t err = ESP_OK; kvs->put(WIFI_PASSWORD_STORE_KEY, std::string(updated_json_str)); + // Note: Error handling is done in nvs_handler.cpp put() method cJSON_free(updated_json_str); + } else { + ESP_LOGE(TAG, "Failed to serialize WiFi credentials JSON"); } cJSON_Delete(json); } diff --git a/main/network/wifi_handler.h b/main/network/wifi_handler.h index 31a0f17..53e3213 100644 --- a/main/network/wifi_handler.h +++ b/main/network/wifi_handler.h @@ -51,6 +51,8 @@ private: SemaphoreHandle_t credential_mutex = nullptr; // current connected / preferred SSID std::string current_ssid; + // current password (temporarily stored for successful connection event) + std::string current_password; // prevent auto-reconnect on expected disconnection, e.g. when user calls disconnect() // should be reset to false after connect() bool expect_disconnected = false;