ssid_manager_c.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include "ssid_manager_c.h"
  2. #include <string.h>
  3. #include <esp_log.h>
  4. #include <nvs_flash.h>
  5. #include <stdlib.h>
  6. #define TAG "SsidManager"
  7. #define NVS_NAMESPACE "wifi"
  8. #define MAX_WIFI_SSID_COUNT 10
  9. #define MAX_SSID_LEN 32
  10. #define MAX_PASS_LEN 64
  11. // 内部结构体定义
  12. typedef struct {
  13. char ssid[MAX_SSID_LEN + 1];
  14. char password[MAX_PASS_LEN + 1];
  15. } SsidEntry;
  16. struct SsidManager {
  17. SsidEntry entries[MAX_WIFI_SSID_COUNT];
  18. int count;
  19. };
  20. // 函数实现
  21. SsidManager* ssid_manager_create() {
  22. SsidManager* manager = (SsidManager*)malloc(sizeof(SsidManager));
  23. if (manager) {
  24. manager->count = 0;
  25. ssid_manager_load_from_nvs(manager);
  26. }
  27. return manager;
  28. }
  29. void ssid_manager_destroy(SsidManager* manager) {
  30. if (manager) {
  31. free(manager);
  32. }
  33. }
  34. void ssid_manager_clear(SsidManager* manager) {
  35. manager->count = 0;
  36. ssid_manager_save_to_nvs(manager);
  37. }
  38. void ssid_manager_load_from_nvs(SsidManager* manager) {
  39. manager->count = 0;
  40. nvs_handle_t nvs_handle;
  41. esp_err_t ret = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle);
  42. if (ret != ESP_OK) {
  43. ESP_LOGW(TAG, "NVS namespace %s doesn't exist", NVS_NAMESPACE);
  44. return;
  45. }
  46. for (int i = 0; i < MAX_WIFI_SSID_COUNT; i++) {
  47. char ssid_key[12];
  48. char password_key[12];
  49. // 安全生成键名
  50. if (i == 0) {
  51. strncpy(ssid_key, "ssid", sizeof(ssid_key));
  52. strncpy(password_key, "password", sizeof(password_key));
  53. } else {
  54. // 使用更安全的格式化方式
  55. int written = snprintf(ssid_key, sizeof(ssid_key), "ssid%d", i);
  56. if (written < 0 || written >= sizeof(ssid_key)) {
  57. ESP_LOGE(TAG, "ssid_key truncation for index %d", i);
  58. continue;
  59. }
  60. written = snprintf(password_key, sizeof(password_key), "password%d", i);
  61. if (written < 0 || written >= sizeof(password_key)) {
  62. ESP_LOGE(TAG, "password_key truncation for index %d", i);
  63. continue;
  64. }
  65. }
  66. char ssid[MAX_SSID_LEN + 1] = {0};
  67. char password[MAX_PASS_LEN + 1] = {0};
  68. size_t len = sizeof(ssid);
  69. // 获取SSID
  70. if (nvs_get_str(nvs_handle, ssid_key, ssid, &len) != ESP_OK) {
  71. continue;
  72. }
  73. // 获取密码
  74. len = sizeof(password);
  75. if (nvs_get_str(nvs_handle, password_key, password, &len) != ESP_OK) {
  76. continue;
  77. }
  78. // 添加到管理器
  79. if (manager->count < MAX_WIFI_SSID_COUNT) {
  80. strncpy(manager->entries[manager->count].ssid, ssid, MAX_SSID_LEN);
  81. manager->entries[manager->count].ssid[MAX_SSID_LEN] = '\0'; // 确保空终止
  82. strncpy(manager->entries[manager->count].password, password, MAX_PASS_LEN);
  83. manager->entries[manager->count].password[MAX_PASS_LEN] = '\0'; // 确保空终止
  84. manager->count++;
  85. }
  86. }
  87. nvs_close(nvs_handle);
  88. }
  89. void ssid_manager_save_to_nvs(SsidManager* manager) {
  90. nvs_handle_t nvs_handle;
  91. ESP_ERROR_CHECK(nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle));
  92. // 安全清除所有旧键值
  93. for (int i = 0; i < MAX_WIFI_SSID_COUNT; i++) {
  94. char ssid_key[12];
  95. char password_key[12];
  96. // 安全生成键名
  97. if (i == 0) {
  98. strncpy(ssid_key, "ssid", sizeof(ssid_key));
  99. strncpy(password_key, "password", sizeof(password_key));
  100. } else {
  101. // 使用更安全的格式化方式
  102. int written = snprintf(ssid_key, sizeof(ssid_key), "ssid%d", i);
  103. if (written < 0 || written >= sizeof(ssid_key)) {
  104. ESP_LOGE(TAG, "ssid_key truncation for index %d", i);
  105. continue;
  106. }
  107. written = snprintf(password_key, sizeof(password_key), "password%d", i);
  108. if (written < 0 || written >= sizeof(password_key)) {
  109. ESP_LOGE(TAG, "password_key truncation for index %d", i);
  110. continue;
  111. }
  112. }
  113. // 清除键值
  114. nvs_erase_key(nvs_handle, ssid_key);
  115. nvs_erase_key(nvs_handle, password_key);
  116. }
  117. // 安全保存新数据
  118. for (int i = 0; i < manager->count; i++) {
  119. char ssid_key[12];
  120. char password_key[12];
  121. // 安全生成键名
  122. if (i == 0) {
  123. strncpy(ssid_key, "ssid", sizeof(ssid_key));
  124. strncpy(password_key, "password", sizeof(password_key));
  125. } else {
  126. // 使用更安全的格式化方式
  127. int written = snprintf(ssid_key, sizeof(ssid_key), "ssid%d", i);
  128. if (written < 0 || written >= sizeof(ssid_key)) {
  129. ESP_LOGE(TAG, "ssid_key truncation for index %d", i);
  130. continue;
  131. }
  132. written = snprintf(password_key, sizeof(password_key), "password%d", i);
  133. if (written < 0 || written >= sizeof(password_key)) {
  134. ESP_LOGE(TAG, "password_key truncation for index %d", i);
  135. continue;
  136. }
  137. }
  138. // 设置键值
  139. nvs_set_str(nvs_handle, ssid_key, manager->entries[i].ssid);
  140. nvs_set_str(nvs_handle, password_key, manager->entries[i].password);
  141. }
  142. nvs_commit(nvs_handle);
  143. nvs_close(nvs_handle);
  144. }
  145. void ssid_manager_add_ssid(SsidManager* manager, const char* ssid, const char* password) {
  146. // 检查是否已存在
  147. for (int i = 0; i < manager->count; i++) {
  148. if (strcmp(manager->entries[i].ssid, ssid) == 0) {
  149. ESP_LOGW(TAG, "SSID %s already exists, overwrite it", ssid);
  150. strncpy(manager->entries[i].password, password, MAX_PASS_LEN);
  151. manager->entries[i].password[MAX_PASS_LEN] = '\0'; // 确保空终止
  152. ssid_manager_save_to_nvs(manager);
  153. return;
  154. }
  155. }
  156. // 处理列表已满的情况
  157. if (manager->count >= MAX_WIFI_SSID_COUNT) {
  158. ESP_LOGW(TAG, "SSID list is full, removing last entry");
  159. manager->count--;
  160. }
  161. // 移动现有条目(为新条目腾出空间)
  162. for (int i = manager->count; i > 0; i--) {
  163. memcpy(&manager->entries[i], &manager->entries[i-1], sizeof(SsidEntry));
  164. }
  165. // 添加新条目到开头
  166. strncpy(manager->entries[0].ssid, ssid, MAX_SSID_LEN);
  167. manager->entries[0].ssid[MAX_SSID_LEN] = '\0'; // 确保空终止
  168. strncpy(manager->entries[0].password, password, MAX_PASS_LEN);
  169. manager->entries[0].password[MAX_PASS_LEN] = '\0'; // 确保空终止
  170. manager->count++;
  171. ssid_manager_save_to_nvs(manager);
  172. }
  173. void ssid_manager_remove_ssid(SsidManager* manager, int index) {
  174. if (index < 0 || index >= manager->count) {
  175. ESP_LOGW(TAG, "Invalid index %d", index);
  176. return;
  177. }
  178. // 移动后续条目覆盖要删除的条目
  179. for (int i = index; i < manager->count - 1; i++) {
  180. memcpy(&manager->entries[i], &manager->entries[i+1], sizeof(SsidEntry));
  181. }
  182. manager->count--;
  183. ssid_manager_save_to_nvs(manager);
  184. }
  185. void ssid_manager_set_default_ssid(SsidManager* manager, int index) {
  186. if (index < 0 || index >= manager->count) {
  187. ESP_LOGW(TAG, "Invalid index %d", index);
  188. return;
  189. }
  190. if (index == 0) {
  191. return; // 已经是默认
  192. }
  193. // 保存目标条目
  194. SsidEntry target;
  195. memcpy(&target, &manager->entries[index], sizeof(SsidEntry));
  196. // 移动前面的条目
  197. for (int i = index; i > 0; i--) {
  198. memcpy(&manager->entries[i], &manager->entries[i-1], sizeof(SsidEntry));
  199. }
  200. // 将目标条目放在开头
  201. memcpy(&manager->entries[0], &target, sizeof(SsidEntry));
  202. ssid_manager_save_to_nvs(manager);
  203. }
  204. // 辅助函数
  205. int ssid_manager_get_count(SsidManager* manager) {
  206. return manager->count;
  207. }
  208. const char* ssid_manager_get_ssid(SsidManager* manager, int index) {
  209. if (index < 0 || index >= manager->count) return NULL;
  210. return manager->entries[index].ssid;
  211. }
  212. const char* ssid_manager_get_password(SsidManager* manager, int index) {
  213. if (index < 0 || index >= manager->count) return NULL;
  214. return manager->entries[index].password;
  215. }