/** * @file config.c * @brief Config module implementation */ #include "config.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "esp_system.h" #include "nvs_flash.h" #include "nvs.h" #include "soc/gpio_num.h" #include "mbedtls/sha256.h" #include static const char *TAG = "CONFIG"; #define NVS_NAMESPACE "led_ctrl" #define HARDCODED_CONFIG #ifdef HARDCODED_CONFIG #define HARDCODED_CONFIG_LED_STRIP_A_PIN 12U #define HARDCODED_CONFIG_LED_STRIP_B_PIN 14U #define HARDCODED_CONFIG_LED_STRIP_A_COUNT 7U #define HARDCODED_CONFIG_LED_STRIP_B_COUNT 7U #define HARDCODED_CONFIG_PWM_PIN 13U #define HARDCODED_CONFIG_LOCALBTN_PIN GPIO_NUM_0 #endif // Global state static config_t current_config = { .led_pin_strip_a = -1, .led_pin_strip_b = -1, .led_count_strip_a = -1, .led_count_strip_b = -1, .pwm_pin = -1, .localBtn_pin = -1}; static void calculate_config_hash(const config_t *cfg, uint8_t *out_hash); // NVS Functions static esp_err_t load_config_from_nvs(void) { nvs_handle_t nvs_handle; size_t size = sizeof(config_t); config_t tmp; for (uint8_t i = 0; i < 2U; i++) { esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle); if (err != ESP_OK) { ESP_LOGW(TAG, "NVS not found, using defaults"); config_reset_config(); continue; } err = nvs_get_blob(nvs_handle, "config", &tmp, &size); nvs_close(nvs_handle); uint8_t calc_hash[CONFIG_HASH_LEN]; calculate_config_hash(&tmp, calc_hash); if (memcmp(calc_hash, tmp.hash, CONFIG_HASH_LEN) != 0) { ESP_LOGW(TAG, "Invalid config in NVS, using defaults"); config_reset_config(); continue; } // We found a valid config break; } ESP_LOGI(TAG, "Loaded config from NVS"); ESP_LOGI(TAG, " Strip A: GPIO%d", current_config.led_pin_strip_a); ESP_LOGI(TAG, " Strip B: GPIO%d", current_config.led_pin_strip_b); ESP_LOGI(TAG, " Strip A LED count: %d", current_config.led_count_strip_a); ESP_LOGI(TAG, " Strip B LED count: %d", current_config.led_count_strip_b); ESP_LOGI(TAG, " PWM Pin: GPIO%d", current_config.pwm_pin); ESP_LOGI(TAG, " Local btn Pin: GPIO%d", current_config.localBtn_pin); return ESP_OK; } static esp_err_t save_config_to_nvs(void) { calculate_config_hash(¤t_config, current_config.hash); nvs_handle_t nvs_handle; esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); if (err != ESP_OK) { return err; } err = nvs_set_blob(nvs_handle, "config", ¤t_config, sizeof(config_t)); if (err == ESP_OK) { err = nvs_commit(nvs_handle); } nvs_close(nvs_handle); if (err == ESP_OK) { ESP_LOGI(TAG, "Config saved to NVS"); } else { ESP_LOGE(TAG, "Failed to save config: %s", esp_err_to_name(err)); } return err; } esp_err_t config_reset_config(void) { current_config.led_pin_strip_a = -1; current_config.led_pin_strip_b = -1; current_config.led_count_strip_a = -1; current_config.led_count_strip_b = -1; current_config.pwm_pin = -1; current_config.localBtn_pin = -1; return save_config_to_nvs(); } void config_get_config(config_t *const cnf) { cnf->led_pin_strip_a = current_config.led_pin_strip_a; cnf->led_pin_strip_b = current_config.led_pin_strip_b; cnf->led_count_strip_a = current_config.led_count_strip_a; cnf->led_count_strip_b = current_config.led_count_strip_b; cnf->pwm_pin = current_config.pwm_pin; cnf->localBtn_pin = current_config.localBtn_pin; } esp_err_t config_init(void) { esp_err_t ret; ESP_LOGI(TAG, "Initializing Config..."); // Initialize NVS ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); ESP_ERROR_CHECK(config_reset_config()); } ESP_ERROR_CHECK(ret); #ifdef HARDCODED_CONFIG current_config.led_pin_strip_a = HARDCODED_CONFIG_LED_STRIP_A_PIN; current_config.led_pin_strip_b = HARDCODED_CONFIG_LED_STRIP_B_PIN; current_config.led_count_strip_a = HARDCODED_CONFIG_LED_STRIP_A_COUNT; current_config.led_count_strip_b = HARDCODED_CONFIG_LED_STRIP_B_COUNT; current_config.pwm_pin = HARDCODED_CONFIG_PWM_PIN; current_config.localBtn_pin = HARDCODED_CONFIG_LOCALBTN_PIN; save_config_to_nvs(); #endif // Load configuration load_config_from_nvs(); ESP_LOGI(TAG, "Config initialized successfully"); return ESP_OK; } static void calculate_config_hash(const config_t *cfg, uint8_t *out_hash) { mbedtls_sha256_context ctx; mbedtls_sha256_init(&ctx); mbedtls_sha256_starts(&ctx, 0); // 0 = SHA-256, 1 = SHA-224 mbedtls_sha256_update( &ctx, (const unsigned char *)cfg, offsetof(config_t, hash)); mbedtls_sha256_finish(&ctx, out_hash); mbedtls_sha256_free(&ctx); }