// // Created by kindring on 2025/12/25. // #include "ble_nvs.h" #include #include "esp_err.h" #include "esp_log.h" #include "nvs_flash.h" static const char *TAG = "BLE_NVS"; esp_err_t bt_device_load_config(device_config_t *device_config) { if (device_config == NULL) { ESP_LOGE(TAG, "device_config is NULL"); return ESP_ERR_INVALID_ARG; } nvs_handle_t nvs_handle; esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err)); return err; } size_t len = sizeof(device_config->device_name); err = nvs_get_str(nvs_handle, DEVICE_NAME_KEY, device_config->device_name, &len); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to read device name, using default: %s", esp_err_to_name(err)); strncpy(device_config->device_name, DEFAULT_DEVICE_NAME, sizeof(device_config->device_name) - 1); device_config->device_name[sizeof(device_config->device_name) - 1] = '\0'; } // 读取自动重连设置 int8_t auto_reconnect; err = nvs_get_i8(nvs_handle, AUTO_RECONNECT_KEY, &auto_reconnect); if (err == ESP_OK) { device_config->auto_reconnect = (bool)auto_reconnect; } else { ESP_LOGW(TAG, "Failed to read auto_reconnect, using default: %s", esp_err_to_name(err)); device_config->auto_reconnect = true; // 默认开启自动重连 } // 读取音频模式 int8_t audio_mode; err = nvs_get_i8(nvs_handle, AUDIO_MODE_KEY, &audio_mode); if (err == ESP_OK && audio_mode >= 0 && audio_mode < AUDIO_MODE_MAX) { device_config->audio_mode = (audio_mode_t)audio_mode; } else { ESP_LOGW(TAG, "Failed to read audio_mode, using default: %s", esp_err_to_name(err)); device_config->audio_mode = AUDIO_MODE_AUX; // 默认为aux模式 } // 读取WiFi模式 int8_t wifi_mode; err = nvs_get_i8(nvs_handle, WIFI_MODE_KEY, &wifi_mode); if (err == ESP_OK && wifi_mode >= 0 && wifi_mode < WIFI_MODE_MAX) { device_config->wifi_mode = (wifi_mode_t)wifi_mode; } else { ESP_LOGW(TAG, "Failed to read wifi_mode, using default: %s", esp_err_to_name(err)); device_config->wifi_mode = WIFI_MODE_STA; // 默认为STA模式 } // 读取WiFi SSID len = sizeof(device_config->wifi_ssid); err = nvs_get_str(nvs_handle, WIFI_SSID_KEY, device_config->wifi_ssid, &len); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to read wifi_ssid, using default: %s", esp_err_to_name(err)); device_config->wifi_ssid[0] = '\0'; } // 读取WiFi密码 len = sizeof(device_config->wifi_password); err = nvs_get_str(nvs_handle, WIFI_PASSWORD_KEY, device_config->wifi_password, &len); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to read wifi_password, using default: %s", esp_err_to_name(err)); device_config->wifi_password[0] = '\0'; } // 读取AP SSID len = sizeof(device_config->ap_ssid); err = nvs_get_str(nvs_handle, AP_SSID_KEY, device_config->ap_ssid, &len); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to read ap_ssid, using default: %s", esp_err_to_name(err)); strncpy(device_config->ap_ssid, DEFAULT_DEVICE_NAME, sizeof(device_config->ap_ssid) - 1); device_config->ap_ssid[sizeof(device_config->ap_ssid) - 1] = '\0'; } // 读取AP密码 len = sizeof(device_config->ap_password); err = nvs_get_str(nvs_handle, AP_PASSWORD_KEY, device_config->ap_password, &len); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to read ap_password, using default: %s", esp_err_to_name(err)); device_config->ap_password[0] = '\0'; } nvs_close(nvs_handle); ESP_LOGI(TAG, "Device configuration loaded successfully"); return ESP_OK; } esp_err_t bt_device_save_config(const device_config_t *device_config) { if (device_config == NULL) { ESP_LOGE(TAG, "device_config is NULL"); return ESP_ERR_INVALID_ARG; } nvs_handle_t nvs_handle; esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err)); return err; } // 保存设备名称 err = nvs_set_str(nvs_handle, DEVICE_NAME_KEY, device_config->device_name); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save device name: %s", esp_err_to_name(err)); goto cleanup; } // 保存自动重连设置 int8_t auto_reconnect = (int8_t)device_config->auto_reconnect; err = nvs_set_i8(nvs_handle, AUTO_RECONNECT_KEY, auto_reconnect); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save auto_reconnect: %s", esp_err_to_name(err)); goto cleanup; } // 保存音频模式模式 int8_t audio_mode = (int8_t)device_config->audio_mode; err = nvs_set_i8(nvs_handle, AUDIO_MODE_KEY, audio_mode); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save audio_mode: %s", esp_err_to_name(err)); goto cleanup; } // 保存WiFi模式 int8_t wifi_mode = (int8_t)device_config->wifi_mode; err = nvs_set_i8(nvs_handle, WIFI_MODE_KEY, wifi_mode); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save wifi_mode: %s", esp_err_to_name(err)); goto cleanup; } // 保存WiFi SSID err = nvs_set_str(nvs_handle, WIFI_SSID_KEY, device_config->wifi_ssid); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save wifi_ssid: %s", esp_err_to_name(err)); goto cleanup; } // 保存WiFi密码 err = nvs_set_str(nvs_handle, WIFI_PASSWORD_KEY, device_config->wifi_password); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save wifi_password: %s", esp_err_to_name(err)); goto cleanup; } // 保存AP SSID err = nvs_set_str(nvs_handle, AP_SSID_KEY, device_config->ap_ssid); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save ap_ssid: %s", esp_err_to_name(err)); goto cleanup; } // 保存AP密码 err = nvs_set_str(nvs_handle, AP_PASSWORD_KEY, device_config->ap_password); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save ap_password: %s", esp_err_to_name(err)); goto cleanup; } err = nvs_commit(nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to commit changes: %s", esp_err_to_name(err)); } else { ESP_LOGI(TAG, "Device configuration saved successfully"); } cleanup: nvs_close(nvs_handle); return err; } esp_err_t bt_device_load_bt_info(bt_device_info_t *bt_info) { if (bt_info == NULL) { ESP_LOGE(TAG, "bt_info is NULL"); return ESP_ERR_INVALID_ARG; } nvs_handle_t nvs_handle; esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err)); return err; } // 读取蓝牙设备列表 size_t required_size = 0; err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, NULL, &required_size); if (err == ESP_OK && required_size == sizeof(bt_device_list_t)) { bt_device_list_t device_list; err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, &device_list, &required_size); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to read bluetooth device list: %s", esp_err_to_name(err)); } else { // 将第一个有效设备信息复制到输出参数 for (int i = 0; i < MAX_BT_DEVICES; i++) { if (device_list.devices[i].is_valid) { memcpy(bt_info, &device_list.devices[i], sizeof(bt_device_info_t)); ESP_LOGI(TAG, "Bluetooth device info loaded successfully"); break; } } } } else if (err == ESP_ERR_NVS_NOT_FOUND) { // 如果没有找到蓝牙设备信息,则初始化为默认值 memset(bt_info, 0, sizeof(bt_device_info_t)); strncpy(bt_info->device_name, DEFAULT_DEVICE_NAME, sizeof(bt_info->device_name) - 1); bt_info->device_name[sizeof(bt_info->device_name) - 1] = '\0'; ESP_LOGI(TAG, "Bluetooth device info not found, using default values"); err = ESP_OK; } else { ESP_LOGE(TAG, "Error getting size for bluetooth device list: %s", esp_err_to_name(err)); } nvs_close(nvs_handle); return err; } esp_err_t bt_device_get_list(bt_device_list_t *device_list) { if (device_list == NULL) { ESP_LOGE(TAG, "device_list is NULL"); return ESP_ERR_INVALID_ARG; } nvs_handle_t nvs_handle; esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err)); return err; } // 读取蓝牙设备列表 size_t required_size = 0; err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, NULL, &required_size); if (err == ESP_OK && required_size == sizeof(bt_device_list_t)) { err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, device_list, &required_size); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to read bluetooth device list: %s", esp_err_to_name(err)); } else { ESP_LOGI(TAG, "Bluetooth device list loaded successfully"); } } else if (err == ESP_ERR_NVS_NOT_FOUND) { // 如果没有找到蓝牙设备列表,则初始化为默认值 memset(device_list, 0, sizeof(bt_device_list_t)); ESP_LOGI(TAG, "Bluetooth device list not found, using default values"); err = ESP_OK; } else { ESP_LOGE(TAG, "Error getting size for bluetooth device list: %s", esp_err_to_name(err)); } nvs_close(nvs_handle); return err; } esp_err_t bt_device_add_or_update(const bt_device_info_t *bt_info) { if (bt_info == NULL) { ESP_LOGE(TAG, "[bt_info] is NULL"); return ESP_ERR_INVALID_ARG; } nvs_handle_t nvs_handle; esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err)); return err; } // 读取现有蓝牙设备列表 bt_device_list_t device_list; size_t required_size = 0; err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, NULL, &required_size); if (err == ESP_OK && required_size == sizeof(bt_device_list_t)) { err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, &device_list, &required_size); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to read existing bluetooth device list: %s", esp_err_to_name(err)); // 初始化为空列表 memset(&device_list, 0, sizeof(bt_device_list_t)); } } else if (err == ESP_ERR_NVS_NOT_FOUND) { // 如果没有找到现有列表,初始化为空列表 memset(&device_list, 0, sizeof(bt_device_list_t)); } else { ESP_LOGE(TAG, "Error getting size for bluetooth device list: %s", esp_err_to_name(err)); nvs_close(nvs_handle); return err; } // 检查是否已存在相同BDA的设备 bool found_existing = false; for (int i = 0; i < MAX_BT_DEVICES; i++) { if (device_list.devices[i].is_valid && memcmp(device_list.devices[i].bda, bt_info->bda, 6) == 0) { // 更新现有设备信息 memcpy(&device_list.devices[i], bt_info, sizeof(bt_device_info_t)); device_list.devices[i].is_valid = true; found_existing = true; ESP_LOGI(TAG, "Updated existing bluetooth device with BDA"); break; } } if (!found_existing) { // 寻找空闲位置 int empty_slot = -1; for (int i = 0; i < MAX_BT_DEVICES; i++) { if (!device_list.devices[i].is_valid) { empty_slot = i; break; } } if (empty_slot != -1) { // 在空闲位置添加新设备 memcpy(&device_list.devices[empty_slot], bt_info, sizeof(bt_device_info_t)); device_list.devices[empty_slot].is_valid = true; ESP_LOGI(TAG, "Added new bluetooth device at slot %d", empty_slot); } else { // 超过最大设备数,需要覆盖最久未连接的设备 int oldest_idx = -1; uint64_t oldest_time = UINT64_MAX; for (int i = 0; i < MAX_BT_DEVICES; i++) { if (device_list.devices[i].last_connect_time < oldest_time) { oldest_time = device_list.devices[i].last_connect_time; oldest_idx = i; } } if (oldest_idx != -1) { memcpy(&device_list.devices[oldest_idx], bt_info, sizeof(bt_device_info_t)); device_list.devices[oldest_idx].is_valid = true; ESP_LOGI(TAG, "Replaced oldest bluetooth device at slot %d", oldest_idx); } } } // 保存更新后的设备列表 err = nvs_set_blob(nvs_handle, BT_DEVICE_LIST_KEY, &device_list, sizeof(bt_device_list_t)); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save bluetooth device list: %s", esp_err_to_name(err)); nvs_close(nvs_handle); return err; } err = nvs_commit(nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to commit bluetooth device list: %s", esp_err_to_name(err)); } else { ESP_LOGI(TAG, "Bluetooth device list saved successfully"); } nvs_close(nvs_handle); return err; } esp_err_t bt_device_reset_config(void) { nvs_handle_t nvs_handle; esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err)); return err; } err = nvs_erase_all(nvs_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to erase all config: %s", esp_err_to_name(err)); } else { ESP_LOGI(TAG, "All configuration erased successfully"); } nvs_close(nvs_handle); return err; } // 初始化nv参数 esp_err_t ble_nvs_init(device_config_t *device_config) { esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK(err); // 如果传入了device_config,加载配置 if (device_config != NULL) { err = bt_device_load_config(device_config); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to load device config: %s", esp_err_to_name(err)); // 即使加载失败,也返回ESP_OK,因为NVS已初始化 } } ESP_LOGI(TAG, "BLE NVS initialized successfully"); return ESP_OK; }