ble_nvs.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. //
  2. // Created by kindring on 2025/12/25.
  3. //
  4. #include "ble_nvs.h"
  5. #include <string.h>
  6. #include "esp_err.h"
  7. #include "esp_log.h"
  8. #include "nvs_flash.h"
  9. static const char *TAG = "BLE_NVS";
  10. esp_err_t bt_device_load_config(device_config_t *device_config)
  11. {
  12. if (device_config == NULL) {
  13. ESP_LOGE(TAG, "device_config is NULL");
  14. return ESP_ERR_INVALID_ARG;
  15. }
  16. nvs_handle_t nvs_handle;
  17. esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle);
  18. if (err != ESP_OK) {
  19. ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err));
  20. return err;
  21. }
  22. size_t len = sizeof(device_config->device_name);
  23. err = nvs_get_str(nvs_handle, DEVICE_NAME_KEY, device_config->device_name, &len);
  24. if (err != ESP_OK) {
  25. ESP_LOGW(TAG, "Failed to read device name, using default: %s", esp_err_to_name(err));
  26. strncpy(device_config->device_name, DEFAULT_DEVICE_NAME, sizeof(device_config->device_name) - 1);
  27. device_config->device_name[sizeof(device_config->device_name) - 1] = '\0';
  28. }
  29. // 读取自动重连设置
  30. int8_t auto_reconnect;
  31. err = nvs_get_i8(nvs_handle, AUTO_RECONNECT_KEY, &auto_reconnect);
  32. if (err == ESP_OK) {
  33. device_config->auto_reconnect = (bool)auto_reconnect;
  34. } else {
  35. ESP_LOGW(TAG, "Failed to read auto_reconnect, using default: %s", esp_err_to_name(err));
  36. device_config->auto_reconnect = true; // 默认开启自动重连
  37. }
  38. // 读取音频模式
  39. int8_t audio_mode;
  40. err = nvs_get_i8(nvs_handle, AUDIO_MODE_KEY, &audio_mode);
  41. if (err == ESP_OK && audio_mode >= 0 && audio_mode < AUDIO_MODE_MAX) {
  42. device_config->audio_mode = (audio_mode_t)audio_mode;
  43. } else {
  44. ESP_LOGW(TAG, "Failed to read audio_mode, using default: %s", esp_err_to_name(err));
  45. device_config->audio_mode = AUDIO_MODE_AUX; // 默认为aux模式
  46. }
  47. // 读取WiFi模式
  48. int8_t wifi_mode;
  49. err = nvs_get_i8(nvs_handle, WIFI_MODE_KEY, &wifi_mode);
  50. if (err == ESP_OK && wifi_mode >= 0 && wifi_mode < WIFI_MODE_MAX) {
  51. device_config->wifi_mode = (wifi_mode_t)wifi_mode;
  52. } else {
  53. ESP_LOGW(TAG, "Failed to read wifi_mode, using default: %s", esp_err_to_name(err));
  54. device_config->wifi_mode = WIFI_MODE_STA; // 默认为STA模式
  55. }
  56. // 读取WiFi SSID
  57. len = sizeof(device_config->wifi_ssid);
  58. err = nvs_get_str(nvs_handle, WIFI_SSID_KEY, device_config->wifi_ssid, &len);
  59. if (err != ESP_OK) {
  60. ESP_LOGW(TAG, "Failed to read wifi_ssid, using default: %s", esp_err_to_name(err));
  61. device_config->wifi_ssid[0] = '\0';
  62. }
  63. // 读取WiFi密码
  64. len = sizeof(device_config->wifi_password);
  65. err = nvs_get_str(nvs_handle, WIFI_PASSWORD_KEY, device_config->wifi_password, &len);
  66. if (err != ESP_OK) {
  67. ESP_LOGW(TAG, "Failed to read wifi_password, using default: %s", esp_err_to_name(err));
  68. device_config->wifi_password[0] = '\0';
  69. }
  70. // 读取AP SSID
  71. len = sizeof(device_config->ap_ssid);
  72. err = nvs_get_str(nvs_handle, AP_SSID_KEY, device_config->ap_ssid, &len);
  73. if (err != ESP_OK) {
  74. ESP_LOGW(TAG, "Failed to read ap_ssid, using default: %s", esp_err_to_name(err));
  75. strncpy(device_config->ap_ssid, DEFAULT_DEVICE_NAME, sizeof(device_config->ap_ssid) - 1);
  76. device_config->ap_ssid[sizeof(device_config->ap_ssid) - 1] = '\0';
  77. }
  78. // 读取AP密码
  79. len = sizeof(device_config->ap_password);
  80. err = nvs_get_str(nvs_handle, AP_PASSWORD_KEY, device_config->ap_password, &len);
  81. if (err != ESP_OK) {
  82. ESP_LOGW(TAG, "Failed to read ap_password, using default: %s", esp_err_to_name(err));
  83. device_config->ap_password[0] = '\0';
  84. }
  85. nvs_close(nvs_handle);
  86. ESP_LOGI(TAG, "Device configuration loaded successfully");
  87. return ESP_OK;
  88. }
  89. esp_err_t bt_device_save_config(const device_config_t *device_config)
  90. {
  91. if (device_config == NULL) {
  92. ESP_LOGE(TAG, "device_config is NULL");
  93. return ESP_ERR_INVALID_ARG;
  94. }
  95. nvs_handle_t nvs_handle;
  96. esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle);
  97. if (err != ESP_OK) {
  98. ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err));
  99. return err;
  100. }
  101. // 保存设备名称
  102. err = nvs_set_str(nvs_handle, DEVICE_NAME_KEY, device_config->device_name);
  103. if (err != ESP_OK) {
  104. ESP_LOGE(TAG, "Failed to save device name: %s", esp_err_to_name(err));
  105. goto cleanup;
  106. }
  107. // 保存自动重连设置
  108. int8_t auto_reconnect = (int8_t)device_config->auto_reconnect;
  109. err = nvs_set_i8(nvs_handle, AUTO_RECONNECT_KEY, auto_reconnect);
  110. if (err != ESP_OK) {
  111. ESP_LOGE(TAG, "Failed to save auto_reconnect: %s", esp_err_to_name(err));
  112. goto cleanup;
  113. }
  114. // 保存音频模式模式
  115. int8_t audio_mode = (int8_t)device_config->audio_mode;
  116. err = nvs_set_i8(nvs_handle, AUDIO_MODE_KEY, audio_mode);
  117. if (err != ESP_OK) {
  118. ESP_LOGE(TAG, "Failed to save audio_mode: %s", esp_err_to_name(err));
  119. goto cleanup;
  120. }
  121. // 保存WiFi模式
  122. int8_t wifi_mode = (int8_t)device_config->wifi_mode;
  123. err = nvs_set_i8(nvs_handle, WIFI_MODE_KEY, wifi_mode);
  124. if (err != ESP_OK) {
  125. ESP_LOGE(TAG, "Failed to save wifi_mode: %s", esp_err_to_name(err));
  126. goto cleanup;
  127. }
  128. // 保存WiFi SSID
  129. err = nvs_set_str(nvs_handle, WIFI_SSID_KEY, device_config->wifi_ssid);
  130. if (err != ESP_OK) {
  131. ESP_LOGE(TAG, "Failed to save wifi_ssid: %s", esp_err_to_name(err));
  132. goto cleanup;
  133. }
  134. // 保存WiFi密码
  135. err = nvs_set_str(nvs_handle, WIFI_PASSWORD_KEY, device_config->wifi_password);
  136. if (err != ESP_OK) {
  137. ESP_LOGE(TAG, "Failed to save wifi_password: %s", esp_err_to_name(err));
  138. goto cleanup;
  139. }
  140. // 保存AP SSID
  141. err = nvs_set_str(nvs_handle, AP_SSID_KEY, device_config->ap_ssid);
  142. if (err != ESP_OK) {
  143. ESP_LOGE(TAG, "Failed to save ap_ssid: %s", esp_err_to_name(err));
  144. goto cleanup;
  145. }
  146. // 保存AP密码
  147. err = nvs_set_str(nvs_handle, AP_PASSWORD_KEY, device_config->ap_password);
  148. if (err != ESP_OK) {
  149. ESP_LOGE(TAG, "Failed to save ap_password: %s", esp_err_to_name(err));
  150. goto cleanup;
  151. }
  152. err = nvs_commit(nvs_handle);
  153. if (err != ESP_OK) {
  154. ESP_LOGE(TAG, "Failed to commit changes: %s", esp_err_to_name(err));
  155. } else {
  156. ESP_LOGI(TAG, "Device configuration saved successfully");
  157. }
  158. cleanup:
  159. nvs_close(nvs_handle);
  160. return err;
  161. }
  162. esp_err_t bt_device_load_bt_info(bt_device_info_t *bt_info)
  163. {
  164. if (bt_info == NULL) {
  165. ESP_LOGE(TAG, "bt_info is NULL");
  166. return ESP_ERR_INVALID_ARG;
  167. }
  168. nvs_handle_t nvs_handle;
  169. esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle);
  170. if (err != ESP_OK) {
  171. ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err));
  172. return err;
  173. }
  174. // 读取蓝牙设备列表
  175. size_t required_size = 0;
  176. err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, NULL, &required_size);
  177. if (err == ESP_OK && required_size == sizeof(bt_device_list_t)) {
  178. bt_device_list_t device_list;
  179. err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, &device_list, &required_size);
  180. if (err != ESP_OK) {
  181. ESP_LOGE(TAG, "Failed to read bluetooth device list: %s", esp_err_to_name(err));
  182. } else {
  183. // 将第一个有效设备信息复制到输出参数
  184. for (int i = 0; i < MAX_BT_DEVICES; i++) {
  185. if (device_list.devices[i].is_valid) {
  186. memcpy(bt_info, &device_list.devices[i], sizeof(bt_device_info_t));
  187. ESP_LOGI(TAG, "Bluetooth device info loaded successfully");
  188. break;
  189. }
  190. }
  191. }
  192. } else if (err == ESP_ERR_NVS_NOT_FOUND) {
  193. // 如果没有找到蓝牙设备信息,则初始化为默认值
  194. memset(bt_info, 0, sizeof(bt_device_info_t));
  195. strncpy(bt_info->device_name, DEFAULT_DEVICE_NAME, sizeof(bt_info->device_name) - 1);
  196. bt_info->device_name[sizeof(bt_info->device_name) - 1] = '\0';
  197. ESP_LOGI(TAG, "Bluetooth device info not found, using default values");
  198. err = ESP_OK;
  199. } else {
  200. ESP_LOGE(TAG, "Error getting size for bluetooth device list: %s", esp_err_to_name(err));
  201. }
  202. nvs_close(nvs_handle);
  203. return err;
  204. }
  205. esp_err_t bt_device_get_list(bt_device_list_t *device_list)
  206. {
  207. if (device_list == NULL) {
  208. ESP_LOGE(TAG, "device_list is NULL");
  209. return ESP_ERR_INVALID_ARG;
  210. }
  211. nvs_handle_t nvs_handle;
  212. esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle);
  213. if (err != ESP_OK) {
  214. ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err));
  215. return err;
  216. }
  217. // 读取蓝牙设备列表
  218. size_t required_size = 0;
  219. err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, NULL, &required_size);
  220. if (err == ESP_OK && required_size == sizeof(bt_device_list_t)) {
  221. err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, device_list, &required_size);
  222. if (err != ESP_OK) {
  223. ESP_LOGE(TAG, "Failed to read bluetooth device list: %s", esp_err_to_name(err));
  224. } else {
  225. ESP_LOGI(TAG, "Bluetooth device list loaded successfully");
  226. }
  227. } else if (err == ESP_ERR_NVS_NOT_FOUND) {
  228. // 如果没有找到蓝牙设备列表,则初始化为默认值
  229. memset(device_list, 0, sizeof(bt_device_list_t));
  230. ESP_LOGI(TAG, "Bluetooth device list not found, using default values");
  231. err = ESP_OK;
  232. } else {
  233. ESP_LOGE(TAG, "Error getting size for bluetooth device list: %s", esp_err_to_name(err));
  234. }
  235. nvs_close(nvs_handle);
  236. return err;
  237. }
  238. esp_err_t bt_device_add_or_update(const bt_device_info_t *bt_info)
  239. {
  240. if (bt_info == NULL) {
  241. ESP_LOGE(TAG, "[bt_info] is NULL");
  242. return ESP_ERR_INVALID_ARG;
  243. }
  244. nvs_handle_t nvs_handle;
  245. esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle);
  246. if (err != ESP_OK) {
  247. ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err));
  248. return err;
  249. }
  250. // 读取现有蓝牙设备列表
  251. bt_device_list_t device_list;
  252. size_t required_size = 0;
  253. err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, NULL, &required_size);
  254. if (err == ESP_OK && required_size == sizeof(bt_device_list_t)) {
  255. err = nvs_get_blob(nvs_handle, BT_DEVICE_LIST_KEY, &device_list, &required_size);
  256. if (err != ESP_OK) {
  257. ESP_LOGE(TAG, "Failed to read existing bluetooth device list: %s", esp_err_to_name(err));
  258. // 初始化为空列表
  259. memset(&device_list, 0, sizeof(bt_device_list_t));
  260. }
  261. } else if (err == ESP_ERR_NVS_NOT_FOUND) {
  262. // 如果没有找到现有列表,初始化为空列表
  263. memset(&device_list, 0, sizeof(bt_device_list_t));
  264. } else {
  265. ESP_LOGE(TAG, "Error getting size for bluetooth device list: %s", esp_err_to_name(err));
  266. nvs_close(nvs_handle);
  267. return err;
  268. }
  269. // 检查是否已存在相同BDA的设备
  270. bool found_existing = false;
  271. for (int i = 0; i < MAX_BT_DEVICES; i++) {
  272. if (device_list.devices[i].is_valid &&
  273. memcmp(device_list.devices[i].bda, bt_info->bda, 6) == 0) {
  274. // 更新现有设备信息
  275. memcpy(&device_list.devices[i], bt_info, sizeof(bt_device_info_t));
  276. device_list.devices[i].is_valid = true;
  277. found_existing = true;
  278. ESP_LOGI(TAG, "Updated existing bluetooth device with BDA");
  279. break;
  280. }
  281. }
  282. if (!found_existing) {
  283. // 寻找空闲位置
  284. int empty_slot = -1;
  285. for (int i = 0; i < MAX_BT_DEVICES; i++) {
  286. if (!device_list.devices[i].is_valid) {
  287. empty_slot = i;
  288. break;
  289. }
  290. }
  291. if (empty_slot != -1) {
  292. // 在空闲位置添加新设备
  293. memcpy(&device_list.devices[empty_slot], bt_info, sizeof(bt_device_info_t));
  294. device_list.devices[empty_slot].is_valid = true;
  295. ESP_LOGI(TAG, "Added new bluetooth device at slot %d", empty_slot);
  296. } else {
  297. // 超过最大设备数,需要覆盖最久未连接的设备
  298. int oldest_idx = -1;
  299. uint64_t oldest_time = UINT64_MAX;
  300. for (int i = 0; i < MAX_BT_DEVICES; i++) {
  301. if (device_list.devices[i].last_connect_time < oldest_time) {
  302. oldest_time = device_list.devices[i].last_connect_time;
  303. oldest_idx = i;
  304. }
  305. }
  306. if (oldest_idx != -1) {
  307. memcpy(&device_list.devices[oldest_idx], bt_info, sizeof(bt_device_info_t));
  308. device_list.devices[oldest_idx].is_valid = true;
  309. ESP_LOGI(TAG, "Replaced oldest bluetooth device at slot %d", oldest_idx);
  310. }
  311. }
  312. }
  313. // 保存更新后的设备列表
  314. err = nvs_set_blob(nvs_handle, BT_DEVICE_LIST_KEY, &device_list, sizeof(bt_device_list_t));
  315. if (err != ESP_OK) {
  316. ESP_LOGE(TAG, "Failed to save bluetooth device list: %s", esp_err_to_name(err));
  317. nvs_close(nvs_handle);
  318. return err;
  319. }
  320. err = nvs_commit(nvs_handle);
  321. if (err != ESP_OK) {
  322. ESP_LOGE(TAG, "Failed to commit bluetooth device list: %s", esp_err_to_name(err));
  323. } else {
  324. ESP_LOGI(TAG, "Bluetooth device list saved successfully");
  325. }
  326. nvs_close(nvs_handle);
  327. return err;
  328. }
  329. esp_err_t bt_device_reset_config(void)
  330. {
  331. nvs_handle_t nvs_handle;
  332. esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle);
  333. if (err != ESP_OK) {
  334. ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(err));
  335. return err;
  336. }
  337. err = nvs_erase_all(nvs_handle);
  338. if (err != ESP_OK) {
  339. ESP_LOGE(TAG, "Failed to erase all config: %s", esp_err_to_name(err));
  340. } else {
  341. ESP_LOGI(TAG, "All configuration erased successfully");
  342. }
  343. nvs_close(nvs_handle);
  344. return err;
  345. }
  346. // 初始化nv参数
  347. esp_err_t ble_nvs_init(device_config_t *device_config) {
  348. esp_err_t err = nvs_flash_init();
  349. if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  350. ESP_ERROR_CHECK(nvs_flash_erase());
  351. err = nvs_flash_init();
  352. }
  353. ESP_ERROR_CHECK(err);
  354. // 如果传入了device_config,加载配置
  355. if (device_config != NULL) {
  356. err = bt_device_load_config(device_config);
  357. if (err != ESP_OK) {
  358. ESP_LOGE(TAG, "Failed to load device config: %s", esp_err_to_name(err));
  359. // 即使加载失败,也返回ESP_OK,因为NVS已初始化
  360. }
  361. }
  362. ESP_LOGI(TAG, "BLE NVS initialized successfully");
  363. return ESP_OK;
  364. }