/** * Config Manager - NVS-basierte Konfigurationsverwaltung */ #include #include "config_manager.h" #include "esp_log.h" #include "nvs_flash.h" #include "nvs.h" static const char* TAG = "CONFIG"; // NVS Namespace #define NVS_NAMESPACE "bsc_config" // NVS Keys #define KEY_WIFI_SSID "wifi_ssid" #define KEY_WIFI_PASS "wifi_pass" #define KEY_WIFI_IP_MODE "wifi_ip_mode" #define KEY_WIFI_STATIC_IP "wifi_static_ip" #define KEY_WIFI_GATEWAY "wifi_gw" #define KEY_WIFI_NETMASK "wifi_nm" #define KEY_WIFI_DNS "wifi_dns" #define KEY_SIP_SERVER "sip_server" #define KEY_SIP_PORT "sip_port" #define KEY_SIP_USER "sip_user" #define KEY_SIP_PASS "sip_pass" #define KEY_SIP_DISPLAY "sip_display" #define KEY_BT_NAME "bt_name" #define KEY_BT_DISCOVERABLE "bt_disc" #define KEY_BT_DEV_COUNT "bt_dev_cnt" #define KEY_BT_DEV_PREFIX "bt_dev_" // bt_dev_0, bt_dev_1, ... // Aktuelle Konfiguration static device_config_t s_config; static bool s_initialized = false; // NVS Handle static nvs_handle_t s_nvs_handle; // Hilfsfunktionen static esp_err_t load_string(const char* key, char* buf, size_t max_len) { size_t len = max_len; esp_err_t err = nvs_get_str(s_nvs_handle, key, buf, &len); if (err == ESP_ERR_NVS_NOT_FOUND) { buf[0] = '\0'; return ESP_OK; } return err; } static esp_err_t save_string(const char* key, const char* value) { return nvs_set_str(s_nvs_handle, key, value); } static esp_err_t load_wifi_config(void) { esp_err_t err; err = load_string(KEY_WIFI_SSID, s_config.wifi.ssid, CONFIG_MAX_SSID_LEN); if (err != ESP_OK) return err; err = load_string(KEY_WIFI_PASS, s_config.wifi.password, CONFIG_MAX_PASSWORD_LEN); if (err != ESP_OK) return err; uint8_t ip_mode = 0; err = nvs_get_u8(s_nvs_handle, KEY_WIFI_IP_MODE, &ip_mode); if (err == ESP_ERR_NVS_NOT_FOUND) { s_config.wifi.ip_mode = IP_MODE_DHCP; } else if (err == ESP_OK) { s_config.wifi.ip_mode = (ip_mode_t)ip_mode; } else { return err; } load_string(KEY_WIFI_STATIC_IP, s_config.wifi.static_ip, CONFIG_MAX_IP_LEN); load_string(KEY_WIFI_GATEWAY, s_config.wifi.gateway, CONFIG_MAX_IP_LEN); load_string(KEY_WIFI_NETMASK, s_config.wifi.netmask, CONFIG_MAX_IP_LEN); load_string(KEY_WIFI_DNS, s_config.wifi.dns, CONFIG_MAX_IP_LEN); // Konfiguriert wenn SSID vorhanden s_config.wifi.configured = (strlen(s_config.wifi.ssid) > 0); return ESP_OK; } static esp_err_t load_sip_config(void) { esp_err_t err; err = load_string(KEY_SIP_SERVER, s_config.sip.server, CONFIG_MAX_SIP_SERVER_LEN); if (err != ESP_OK) return err; uint16_t port = CONFIG_BSC_SIP_DEFAULT_PORT; nvs_get_u16(s_nvs_handle, KEY_SIP_PORT, &port); s_config.sip.port = port; load_string(KEY_SIP_USER, s_config.sip.username, CONFIG_MAX_SIP_USER_LEN); load_string(KEY_SIP_PASS, s_config.sip.password, CONFIG_MAX_PASSWORD_LEN); load_string(KEY_SIP_DISPLAY, s_config.sip.display_name, CONFIG_MAX_SIP_USER_LEN); // Konfiguriert wenn Server und User vorhanden s_config.sip.configured = (strlen(s_config.sip.server) > 0 && strlen(s_config.sip.username) > 0); return ESP_OK; } static esp_err_t load_bt_config(void) { // Bluetooth-Gerätename esp_err_t err = load_string(KEY_BT_NAME, s_config.bluetooth.device_name, CONFIG_MAX_BT_NAME_LEN); if (err != ESP_OK || strlen(s_config.bluetooth.device_name) == 0) { strncpy(s_config.bluetooth.device_name, CONFIG_BSC_BT_DEVICE_NAME, CONFIG_MAX_BT_NAME_LEN); } // Discoverable Status uint8_t disc = 1; nvs_get_u8(s_nvs_handle, KEY_BT_DISCOVERABLE, &disc); s_config.bluetooth.discoverable = (disc != 0); // Gepaarte Geräte laden uint8_t dev_count = 0; nvs_get_u8(s_nvs_handle, KEY_BT_DEV_COUNT, &dev_count); s_config.bluetooth.device_count = 0; for (int i = 0; i < dev_count && i < CONFIG_BSC_MAX_BT_DEVICES; i++) { char key[32]; char data[128]; snprintf(key, sizeof(key), "%s%d", KEY_BT_DEV_PREFIX, i); size_t len = sizeof(data); if (nvs_get_str(s_nvs_handle, key, data, &len) == ESP_OK) { // Format: "address|name|auto_connect|priority" bt_device_config_t* dev = &s_config.bluetooth.devices[s_config.bluetooth.device_count]; char* token = strtok(data, "|"); if (token) strncpy(dev->address, token, CONFIG_MAX_BT_ADDR_LEN); token = strtok(NULL, "|"); if (token) strncpy(dev->name, token, CONFIG_MAX_BT_NAME_LEN); token = strtok(NULL, "|"); if (token) dev->auto_connect = (atoi(token) != 0); token = strtok(NULL, "|"); if (token) dev->priority = (uint8_t)atoi(token); dev->paired = true; s_config.bluetooth.device_count++; } } return ESP_OK; } static esp_err_t save_bt_devices(void) { esp_err_t err; // Anzahl speichern err = nvs_set_u8(s_nvs_handle, KEY_BT_DEV_COUNT, s_config.bluetooth.device_count); if (err != ESP_OK) return err; // Jedes Gerät speichern for (int i = 0; i < s_config.bluetooth.device_count; i++) { char key[32]; char data[128]; bt_device_config_t* dev = &s_config.bluetooth.devices[i]; snprintf(key, sizeof(key), "%s%d", KEY_BT_DEV_PREFIX, i); snprintf(data, sizeof(data), "%s|%s|%d|%d", dev->address, dev->name, dev->auto_connect ? 1 : 0, dev->priority); err = nvs_set_str(s_nvs_handle, key, data); if (err != ESP_OK) return err; } return nvs_commit(s_nvs_handle); } // Public API esp_err_t config_manager_init(void) { if (s_initialized) { return ESP_OK; } ESP_LOGI(TAG, "Initialisiere Config Manager"); // NVS öffnen esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &s_nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "NVS öffnen fehlgeschlagen: %s", esp_err_to_name(err)); return err; } // Konfiguration initialisieren memset(&s_config, 0, sizeof(s_config)); // Laden err = load_wifi_config(); if (err != ESP_OK) { ESP_LOGW(TAG, "WiFi-Config laden fehlgeschlagen: %s", esp_err_to_name(err)); } err = load_sip_config(); if (err != ESP_OK) { ESP_LOGW(TAG, "SIP-Config laden fehlgeschlagen: %s", esp_err_to_name(err)); } err = load_bt_config(); if (err != ESP_OK) { ESP_LOGW(TAG, "BT-Config laden fehlgeschlagen: %s", esp_err_to_name(err)); } ESP_LOGI(TAG, "Konfiguration geladen:"); ESP_LOGI(TAG, " WiFi: %s", s_config.wifi.configured ? s_config.wifi.ssid : "(nicht konfiguriert)"); ESP_LOGI(TAG, " SIP: %s", s_config.sip.configured ? s_config.sip.server : "(nicht konfiguriert)"); ESP_LOGI(TAG, " BT: %d gepaarte Geräte", s_config.bluetooth.device_count); s_initialized = true; return ESP_OK; } const device_config_t* config_get(void) { return &s_config; } esp_err_t config_save_wifi(const wifi_config_data_t* wifi_config) { if (!wifi_config) return ESP_ERR_INVALID_ARG; ESP_LOGI(TAG, "Speichere WiFi-Konfiguration: SSID=%s", wifi_config->ssid); esp_err_t err; err = save_string(KEY_WIFI_SSID, wifi_config->ssid); if (err != ESP_OK) return err; err = save_string(KEY_WIFI_PASS, wifi_config->password); if (err != ESP_OK) return err; err = nvs_set_u8(s_nvs_handle, KEY_WIFI_IP_MODE, (uint8_t)wifi_config->ip_mode); if (err != ESP_OK) return err; if (wifi_config->ip_mode == IP_MODE_STATIC) { save_string(KEY_WIFI_STATIC_IP, wifi_config->static_ip); save_string(KEY_WIFI_GATEWAY, wifi_config->gateway); save_string(KEY_WIFI_NETMASK, wifi_config->netmask); save_string(KEY_WIFI_DNS, wifi_config->dns); } err = nvs_commit(s_nvs_handle); if (err != ESP_OK) return err; // Lokale Kopie aktualisieren memcpy(&s_config.wifi, wifi_config, sizeof(wifi_config_data_t)); s_config.wifi.configured = (strlen(s_config.wifi.ssid) > 0); return ESP_OK; } esp_err_t config_save_sip(const sip_config_data_t* sip_config) { if (!sip_config) return ESP_ERR_INVALID_ARG; ESP_LOGI(TAG, "Speichere SIP-Konfiguration: %s@%s:%d", sip_config->username, sip_config->server, sip_config->port); esp_err_t err; err = save_string(KEY_SIP_SERVER, sip_config->server); if (err != ESP_OK) return err; err = nvs_set_u16(s_nvs_handle, KEY_SIP_PORT, sip_config->port); if (err != ESP_OK) return err; err = save_string(KEY_SIP_USER, sip_config->username); if (err != ESP_OK) return err; err = save_string(KEY_SIP_PASS, sip_config->password); if (err != ESP_OK) return err; save_string(KEY_SIP_DISPLAY, sip_config->display_name); err = nvs_commit(s_nvs_handle); if (err != ESP_OK) return err; // Lokale Kopie aktualisieren memcpy(&s_config.sip, sip_config, sizeof(sip_config_data_t)); s_config.sip.configured = (strlen(s_config.sip.server) > 0 && strlen(s_config.sip.username) > 0); return ESP_OK; } esp_err_t config_save_bt_device(const bt_device_config_t* device) { if (!device) return ESP_ERR_INVALID_ARG; // Prüfen ob Gerät bereits existiert for (int i = 0; i < s_config.bluetooth.device_count; i++) { if (strcmp(s_config.bluetooth.devices[i].address, device->address) == 0) { // Update memcpy(&s_config.bluetooth.devices[i], device, sizeof(bt_device_config_t)); return save_bt_devices(); } } // Neues Gerät if (s_config.bluetooth.device_count >= CONFIG_BSC_MAX_BT_DEVICES) { ESP_LOGW(TAG, "Maximale Anzahl BT-Geräte erreicht"); return ESP_ERR_NO_MEM; } memcpy(&s_config.bluetooth.devices[s_config.bluetooth.device_count], device, sizeof(bt_device_config_t)); s_config.bluetooth.device_count++; ESP_LOGI(TAG, "BT-Gerät hinzugefügt: %s (%s)", device->name, device->address); return save_bt_devices(); } esp_err_t config_remove_bt_device(const char* address) { if (!address) return ESP_ERR_INVALID_ARG; for (int i = 0; i < s_config.bluetooth.device_count; i++) { if (strcmp(s_config.bluetooth.devices[i].address, address) == 0) { // Gefunden - entfernen durch Verschieben ESP_LOGI(TAG, "Entferne BT-Gerät: %s", address); for (int j = i; j < s_config.bluetooth.device_count - 1; j++) { memcpy(&s_config.bluetooth.devices[j], &s_config.bluetooth.devices[j + 1], sizeof(bt_device_config_t)); } s_config.bluetooth.device_count--; return save_bt_devices(); } } return ESP_ERR_NOT_FOUND; } esp_err_t config_clear_bt_devices(void) { ESP_LOGI(TAG, "Lösche alle BT-Geräte"); s_config.bluetooth.device_count = 0; return save_bt_devices(); } esp_err_t config_factory_reset(void) { ESP_LOGW(TAG, "Werksreset durchführen!"); esp_err_t err = nvs_erase_all(s_nvs_handle); if (err != ESP_OK) return err; err = nvs_commit(s_nvs_handle); if (err != ESP_OK) return err; // Konfiguration zurücksetzen memset(&s_config, 0, sizeof(s_config)); strncpy(s_config.bluetooth.device_name, CONFIG_BSC_BT_DEVICE_NAME, CONFIG_MAX_BT_NAME_LEN); s_config.bluetooth.discoverable = true; s_config.sip.port = CONFIG_BSC_SIP_DEFAULT_PORT; return ESP_OK; } bool config_wifi_is_configured(void) { return s_config.wifi.configured; } bool config_sip_is_configured(void) { return s_config.sip.configured; }