From c3f4e8f651b853269433d0fd5ccb692573301b0e Mon Sep 17 00:00:00 2001 From: kerms Date: Fri, 12 Jul 2024 17:00:24 +0800 Subject: [PATCH] feat(wifi ap) ap ssid and password can be changed and saved to flash --- project_components/wifi_manager/wifi_api.c | 24 +++++-- project_components/wifi_manager/wifi_api.h | 17 ++++- .../wifi_manager/wifi_api_json.c | 49 +++++++++++--- .../wifi_manager/wifi_json_utils.c | 22 ++++++- .../wifi_manager/wifi_json_utils.h | 3 +- .../wifi_manager/wifi_manager.c | 45 +++++++++---- .../wifi_manager/wifi_manager.h | 3 +- .../wifi_manager/wifi_storage.c | 64 ++++++++++++++++++- .../wifi_manager/wifi_storage.h | 10 ++- .../wifi_manager/wifi_storage_priv.h | 6 +- 10 files changed, 199 insertions(+), 44 deletions(-) diff --git a/project_components/wifi_manager/wifi_api.c b/project_components/wifi_manager/wifi_api.c index 5189daf..ecac048 100644 --- a/project_components/wifi_manager/wifi_api.c +++ b/project_components/wifi_manager/wifi_api.c @@ -1,6 +1,7 @@ #include "wifi_api.h" #include "wifi_manager.h" #include "wifi_configuration.h" +#include "wifi_storage.h" #include void wifi_api_sta_get_ap_info(wifi_api_ap_info_t *ap_info) @@ -10,6 +11,7 @@ void wifi_api_sta_get_ap_info(wifi_api_ap_info_t *ap_info) strncpy(ap_info->ssid, (char *)ap_record.ssid, sizeof(ap_info->ssid)); strncpy(ap_info->mac, (char *)ap_record.bssid, sizeof(ap_info->mac)); ap_info->rssi = ap_record.rssi; + ap_info->password[0] = '\0'; esp_netif_t *sta_netif = wifi_manager_get_sta_netif(); esp_netif_ip_info_t ip_info; @@ -21,7 +23,15 @@ void wifi_api_sta_get_ap_info(wifi_api_ap_info_t *ap_info) void wifi_api_ap_get_info(wifi_api_ap_info_t *ap_info) { - strncpy(ap_info->ssid, WIFI_DEFAULT_AP_SSID, strlen(WIFI_DEFAULT_AP_SSID)+1); + wifi_credential_t credential; + int err = wifi_data_get_ap_credential(&credential); + if (err) { + strncpy(ap_info->ssid, WIFI_DEFAULT_AP_SSID, strlen(WIFI_DEFAULT_AP_SSID)+1); + strncpy(ap_info->password, WIFI_DEFAULT_AP_PASS, strlen(WIFI_DEFAULT_AP_PASS)+1); + } else { + strncpy(ap_info->ssid, credential.ssid, sizeof(ap_info->ssid)); + strncpy(ap_info->password, credential.password, sizeof(ap_info->password)); + } esp_wifi_get_mac(WIFI_IF_AP, (uint8_t *) &ap_info->mac); IP4_ADDR_EXPAND(&ap_info->ip, WIFI_DEFAULT_AP_IP); IP4_ADDR_EXPAND(&ap_info->gateway, WIFI_DEFAULT_AP_GATEWAY); @@ -31,15 +41,15 @@ void wifi_api_ap_get_info(wifi_api_ap_info_t *ap_info) static int rssi_comp(const void *a, const void *b) { - const wifi_api_ap_info_t *r1 = a; - const wifi_api_ap_info_t *r2 = b; + const wifi_api_ap_scan_info_t *r1 = a; + const wifi_api_ap_scan_info_t *r2 = b; return r2->rssi - r1->rssi; } /** * @brief blocking function */ -int wifi_api_get_scan_list(uint16_t *number, wifi_api_ap_info_t *ap_info) +int wifi_api_get_scan_list(uint16_t *number, wifi_api_ap_scan_info_t *ap_info) { wifi_ap_record_t *records; int err; @@ -64,7 +74,7 @@ int wifi_api_get_scan_list(uint16_t *number, wifi_api_ap_info_t *ap_info) } free(records); - qsort(ap_info, *number, sizeof(wifi_api_ap_info_t), rssi_comp); + qsort(ap_info, *number, sizeof(wifi_api_ap_scan_info_t), rssi_comp); return 0; } @@ -72,9 +82,9 @@ static wifi_api_scan_done_cb scan_done_cb; static void wifi_manager_scan_done(uint16_t ap_found, wifi_ap_record_t *records, void *arg) { - wifi_api_ap_info_t *ap_info; + wifi_api_ap_scan_info_t *ap_info; - ap_info = malloc(ap_found * sizeof(wifi_api_ap_info_t)); + ap_info = malloc(ap_found * sizeof(wifi_api_ap_scan_info_t)); for (int i = 0; i < ap_found; ++i) { strncpy(ap_info[i].ssid, (char *) records[i].ssid, sizeof(ap_info[i].ssid)); strncpy(ap_info[i].mac, (char *) records[i].bssid, sizeof(ap_info[i].mac)); diff --git a/project_components/wifi_manager/wifi_api.h b/project_components/wifi_manager/wifi_api.h index 45ac535..5f00c57 100644 --- a/project_components/wifi_manager/wifi_api.h +++ b/project_components/wifi_manager/wifi_api.h @@ -14,17 +14,28 @@ typedef enum wifi_api_json_cmd_t { WIFI_API_JSON_AP_GET_INFO = 5, WIFI_API_JSON_GET_MODE = 6, /* req:{ }, ret:{mode, [delay_off], [delay_on]} */ WIFI_API_JSON_SET_MODE = 7, /* req:{mode, [delay_off], [delay_on]} */ + WIFI_API_JSON_SET_AP_CRED = 8, /* ssid[32] + password[64] */ } wifi_api_json_cmd_t; typedef struct wifi_api_ap_info_t { ip4_addr_t ip; ip4_addr_t gateway; ip4_addr_t netmask; - char ssid[33]; + char ssid[32+1]; + char password[64+1]; char mac[6]; signed char rssi; } wifi_api_ap_info_t; +typedef struct wifi_api_ap_scan_info_t { + ip4_addr_t ip; + ip4_addr_t gateway; + ip4_addr_t netmask; + char ssid[32+1]; + char mac[6]; + signed char rssi; +} wifi_api_ap_scan_info_t; + typedef enum wifi_apsta_mode_e { /* permanent */ WIFI_AP_AUTO_STA_ON = 0, @@ -45,11 +56,11 @@ void wifi_api_sta_get_ap_info(wifi_api_ap_info_t *ap_info); void wifi_api_ap_get_info(wifi_api_ap_info_t *ap_info); -typedef void (*wifi_api_scan_done_cb)(uint16_t found, wifi_api_ap_info_t *aps, void *arg); +typedef void (*wifi_api_scan_done_cb)(uint16_t found, wifi_api_ap_scan_info_t *aps, void *arg); int wifi_api_trigger_scan(uint16_t *max_ap_count, wifi_api_scan_done_cb cb, void *cb_arg); -int wifi_api_get_scan_list(uint16_t *number, wifi_api_ap_info_t *ap_info); +int wifi_api_get_scan_list(uint16_t *number, wifi_api_ap_scan_info_t *ap_info); int wifi_api_connect(const char *ssid, const char *password); diff --git a/project_components/wifi_manager/wifi_api_json.c b/project_components/wifi_manager/wifi_api_json.c index 0559c0d..98434e6 100644 --- a/project_components/wifi_manager/wifi_api_json.c +++ b/project_components/wifi_manager/wifi_api_json.c @@ -6,6 +6,8 @@ #include #include +#include "wifi_storage.h" + #define TAG __FILENAME__ static int wifi_api_json_sta_get_ap_info(api_json_req_t *req); @@ -21,6 +23,7 @@ static int wifi_api_json_ap_get_info(api_json_req_t *req); static int wifi_api_json_set_mode(api_json_req_t *req); static int wifi_api_json_get_mode(api_json_req_t *req); +static int wifi_api_json_set_ap_cred(api_json_req_t *req); /* the upper caller call cb() with void *, this let us use custom function arg */ static int async_helper_cb(void *arg) @@ -59,12 +62,27 @@ static int on_json_req(uint16_t cmd, api_json_req_t *req, api_json_module_async_ return wifi_api_json_get_mode(req); case WIFI_API_JSON_SET_MODE: return wifi_api_json_set_mode(req); + case WIFI_API_JSON_SET_AP_CRED: + return wifi_api_json_set_ap_cred(req); } ESP_LOGI(TAG, "cmd %d not executed\n", cmd); return API_JSON_UNSUPPORTED_CMD; } +/* **** + * register module + * */ +static int wifi_api_json_init(api_json_module_cfg_t *cfg) +{ + cfg->on_req = on_json_req; + cfg->module_id = WIFI_MODULE_ID; + return 0; +} + +API_JSON_MODULE_REGISTER(wifi_api_json_init) + + static int wifi_api_json_sta_get_ap_info(api_json_req_t *req) { wifi_api_ap_info_t ap_info; @@ -83,7 +101,7 @@ static int wifi_api_json_ap_get_info(api_json_req_t *req) static int wifi_api_json_get_scan(api_json_req_t *req) { - wifi_api_ap_info_t ap_info[20]; + wifi_api_ap_scan_info_t ap_info[20]; uint16_t max_count = 20; int err; @@ -133,7 +151,6 @@ int wifi_api_json_set_mode(api_json_req_t *req) return API_JSON_OK; } wifi_apsta_mode_e mode = value; - wifi_mode_t status; err = wifi_manager_change_mode(mode); if (err) { @@ -181,15 +198,27 @@ int wifi_api_json_disconnect(api_json_req_t *req) return wifi_api_disconnect(); } -/* **** - * register module - * */ -static int wifi_api_json_init(api_json_module_cfg_t *cfg) +int wifi_api_json_set_ap_cred(api_json_req_t *req) { - cfg->on_req = on_json_req; - cfg->module_id = WIFI_MODULE_ID; + wifi_credential_t credential; + int err; + + err = wifi_api_json_get_credential(req->in, (char *)&credential.ssid, (char *)&credential.password); + if (err) { + return API_JSON_PROPERTY_ERR; + } + + if (strlen(credential.password) < 8) { + req->out = wifi_api_json_create_err_rsp(req->in, "password < 8"); + return API_JSON_OK; + } + + err = wifi_data_save_ap_credential(&credential); + if (err) { + return API_JSON_INTERNAL_ERR; + } + + wifi_manager_set_ap_credential(&credential); return 0; } - -API_JSON_MODULE_REGISTER(wifi_api_json_init) diff --git a/project_components/wifi_manager/wifi_json_utils.c b/project_components/wifi_manager/wifi_json_utils.c index a9ba399..e9ccb11 100644 --- a/project_components/wifi_manager/wifi_json_utils.c +++ b/project_components/wifi_manager/wifi_json_utils.c @@ -21,6 +21,9 @@ cJSON *wifi_api_json_serialize_ap_info(wifi_api_ap_info_t *ap_info, wifi_api_jso cJSON_AddStringToObject(root, "netmask", ip4addr_ntoa(&ap_info->netmask)); cJSON_AddNumberToObject(root, "rssi", ap_info->rssi); cJSON_AddStringToObject(root, "ssid", ap_info->ssid); + if (ap_info->password[0]) { + cJSON_AddStringToObject(root, "password", ap_info->password); + } char mac_str[18]; char *m = ap_info->mac; @@ -31,7 +34,7 @@ cJSON *wifi_api_json_serialize_ap_info(wifi_api_ap_info_t *ap_info, wifi_api_jso return root; } -cJSON *wifi_api_json_serialize_scan_list(wifi_api_ap_info_t *aps_info, uint16_t count) +cJSON *wifi_api_json_serialize_scan_list(wifi_api_ap_scan_info_t *aps_info, uint16_t count) { cJSON *root; char mac_str[18]; @@ -110,3 +113,20 @@ cJSON *wifi_api_json_add_int_item(cJSON *root, const char *name, int item) cJSON_AddNumberToObject(root, name, item); return root; } + +int wifi_api_json_get_credential(cJSON *root, char *ssid, char *password) +{ + cJSON *json_ssid = cJSON_GetObjectItem(root, "ssid"); + cJSON *json_password = cJSON_GetObjectItem(root, "password"); + + if (!cJSON_IsString(json_ssid) || !cJSON_IsString(json_password)) { + return 1; + } + + strncpy(ssid, cJSON_GetStringValue(json_ssid), 31); + strncpy(password, cJSON_GetStringValue(json_password), 63); + + ssid[31] = '\0'; + password[64] = '\0'; + return 0; +} diff --git a/project_components/wifi_manager/wifi_json_utils.h b/project_components/wifi_manager/wifi_json_utils.h index df44ae5..7b84669 100644 --- a/project_components/wifi_manager/wifi_json_utils.h +++ b/project_components/wifi_manager/wifi_json_utils.h @@ -4,7 +4,7 @@ #include "wifi_api.h" cJSON *wifi_api_json_serialize_ap_info(wifi_api_ap_info_t *ap_info, wifi_api_json_cmd_t cmd); -cJSON *wifi_api_json_serialize_scan_list(wifi_api_ap_info_t *aps_info, uint16_t count); +cJSON *wifi_api_json_serialize_scan_list(wifi_api_ap_scan_info_t *aps_info, uint16_t count); cJSON *wifi_api_json_serialize_ap_auto(wifi_apsta_mode_e mode, int ap_on_delay, int ap_off_delay); cJSON *wifi_api_json_serialize_get_mode(wifi_apsta_mode_e mode, int status, int ap_on_delay, int ap_off_delay); @@ -13,5 +13,6 @@ cJSON *wifi_api_json_create_err_rsp(cJSON *req, const char *msg); cJSON *wifi_api_json_add_int_item(cJSON *root, const char *name, int item); int wifi_api_json_utils_get_int(cJSON *req, const char *name, int *out_value); +int wifi_api_json_get_credential(cJSON *root, char *ssid, char *password); #endif //WIFI_JSON_UTILS_H_GUARD \ No newline at end of file diff --git a/project_components/wifi_manager/wifi_manager.c b/project_components/wifi_manager/wifi_manager.c index b021c07..c8b1c14 100644 --- a/project_components/wifi_manager/wifi_manager.c +++ b/project_components/wifi_manager/wifi_manager.c @@ -94,29 +94,33 @@ void wifi_manager_init(void) ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, &ip_event_handler, NULL, NULL)); ctx.is_sta_connected = false; - ctx.permanent_mode = WIFI_AP_AUTO_STA_ON; - ctx.mode = WIFI_MODE_APSTA; ctx.ap_on_delay_tick = pdMS_TO_TICKS(5000); ctx.ap_off_delay_tick = pdMS_TO_TICKS(10000); ctx.delayed_stopAP_task = NULL; ctx.delayed_startAP_task = NULL; ctx.try_connect_count = 0; + err = wifi_data_get_wifi_mode(&ctx.permanent_mode); + if (err) { + ESP_LOGI(TAG, "use default mode: %d", ctx.permanent_mode); + ctx.permanent_mode = WIFI_AP_AUTO_STA_ON; + ctx.mode = WIFI_MODE_APSTA; + } else { + ctx.mode = ctx.permanent_mode & 0x3; /* 0b1XX */ + } + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); ESP_ERROR_CHECK(esp_wifi_set_mode(ctx.mode)); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); - { - wifi_config_t ap_config = {0}; - - strncpy((char *)ap_config.ap.ssid, WIFI_DEFAULT_AP_SSID, 32); - strncpy((char *)ap_config.ap.password, WIFI_DEFAULT_AP_PASS, 64); - ap_config.ap.authmode = WIFI_AUTH_WPA2_WPA3_PSK; - ap_config.ap.max_connection = 4; - ap_config.ap.channel = 6; - ap_config.ap.ssid_hidden = 0; - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); + wifi_credential_t cred; + err = wifi_data_get_ap_credential(&cred); + if (err || strlen(cred.password) < 8) { + ESP_LOGI(TAG, "used default AP credential"); + strncpy((char *)cred.ssid, WIFI_DEFAULT_AP_SSID, 32); + strncpy((char *)cred.password, WIFI_DEFAULT_AP_PASS, 64); } + wifi_manager_set_ap_credential(&cred); if (set_default_sta_cred() == 0) { ESP_LOGI(TAG, "STA connect to saved cred"); @@ -318,7 +322,7 @@ int set_default_sta_cred() { int err; wifi_credential_t credential; - err = wifi_data_get_last_conn_cred(&credential); + err = wifi_data_get_sta_last_conn_cred(&credential); if (err) { return err; } @@ -362,7 +366,7 @@ int wifi_manager_connect(const char *ssid, const char *password) wifi_credential_t credential; memcpy(credential.ssid, ssid, 32); memcpy(credential.password, password, 64); - ret = wifi_save_ap_credential(&credential); + ret = wifi_data_save_sta_ap_credential(&credential); if (ret) { ESP_LOGE(TAG, "nvs save error: %s", esp_err_to_name(ret)); } @@ -632,3 +636,16 @@ int wifi_manager_get_mode(wifi_apsta_mode_e *mode, wifi_mode_t *status) *status = ctx.mode; return 0; } + +int wifi_manager_set_ap_credential(wifi_credential_t *cred) +{ + wifi_config_t ap_config = {0}; + strncpy((char *)ap_config.ap.ssid, cred->ssid, 32); + strncpy((char *)ap_config.ap.password, cred->password, 64); + ap_config.ap.authmode = WIFI_AUTH_WPA2_WPA3_PSK; + ap_config.ap.max_connection = 4; + ap_config.ap.channel = 6; + ap_config.ap.ssid_hidden = 0; + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); + return 0; +} diff --git a/project_components/wifi_manager/wifi_manager.h b/project_components/wifi_manager/wifi_manager.h index b6bf217..15feb0f 100644 --- a/project_components/wifi_manager/wifi_manager.h +++ b/project_components/wifi_manager/wifi_manager.h @@ -3,6 +3,7 @@ #include #include "wifi_api.h" +#include "wifi_storage.h" void wifi_manager_init(); @@ -18,7 +19,7 @@ int wifi_manager_change_mode(wifi_apsta_mode_e mode); int wifi_manager_get_mode(wifi_apsta_mode_e *mode, wifi_mode_t *status); int wifi_manager_get_ap_auto_delay(int *ap_on_delay, int *ap_off_delay); int wifi_manager_set_ap_auto_delay(int *ap_on_delay, int *ap_off_delay); - +int wifi_manager_set_ap_credential(wifi_credential_t *cred); #endif //WIFI_MANAGER_H_GUARD \ No newline at end of file diff --git a/project_components/wifi_manager/wifi_storage.c b/project_components/wifi_manager/wifi_storage.c index 9e2c44d..218caf6 100644 --- a/project_components/wifi_manager/wifi_storage.c +++ b/project_components/wifi_manager/wifi_storage.c @@ -7,7 +7,7 @@ #define WIFI_NVS_NAMESPACE "wt_wifi" -int wifi_data_get_last_conn_cred(wifi_credential_t *ap_credential) +int wifi_data_get_sta_last_conn_cred(wifi_credential_t *ap_credential) { uint32_t ap_bitmap = 0; nvs_handle_t handle; @@ -36,7 +36,7 @@ int wifi_data_get_last_conn_cred(wifi_credential_t *ap_credential) /* * Called when connect to an AP, */ -int wifi_save_ap_credential(wifi_credential_t *ap_credential) +int wifi_data_save_sta_ap_credential(wifi_credential_t *ap_credential) { uint32_t ap_bitmap; int err; @@ -97,3 +97,63 @@ int wifi_data_save_wifi_mode(wifi_apsta_mode_e mode) wt_nvs_close(handle); return WT_NVS_OK; } + +int wifi_data_get_wifi_mode(wifi_apsta_mode_e *mode) +{ + nvs_handle_t handle; + int err; + + uint8_t mode_u8; + + err = wt_nvs_open(WIFI_NVS_NAMESPACE, &handle); + if (err) { + return err; + } + + err = wt_nvs_get(handle, KEY_WIFI_APSTA_MODE, &mode_u8, sizeof(mode_u8)); + if (err) { + return err; + } + + *mode = mode_u8; + wt_nvs_close(handle); + return WT_NVS_OK; +} + +int wifi_data_save_ap_credential(wifi_credential_t *ap_credential) +{ + nvs_handle_t handle; + int err; + + err = wt_nvs_open(WIFI_NVS_NAMESPACE, &handle); + if (err) { + return err; + } + + err = wt_nvs_set(handle, KEY_WIFI_AP_CRED, ap_credential, sizeof(wifi_credential_t)); + if (err) { + return err; + } + + wt_nvs_close(handle); + return 0; +} + +int wifi_data_get_ap_credential(wifi_credential_t *ap_credential) +{ + nvs_handle_t handle; + int err; + + err = wt_nvs_open(WIFI_NVS_NAMESPACE, &handle); + if (err) { + return err; + } + + err = wt_nvs_get(handle, KEY_WIFI_AP_CRED, ap_credential, sizeof(wifi_credential_t)); + if (err) { + return err; + } + + wt_nvs_close(handle); + return 0; +} diff --git a/project_components/wifi_manager/wifi_storage.h b/project_components/wifi_manager/wifi_storage.h index a4129ff..1d61251 100644 --- a/project_components/wifi_manager/wifi_storage.h +++ b/project_components/wifi_manager/wifi_storage.h @@ -9,10 +9,16 @@ typedef struct nvs_wifi_credential_t { char password[64]; } wifi_credential_t; -int wifi_data_get_last_conn_cred(wifi_credential_t *ap_credential); +int wifi_data_get_sta_last_conn_cred(wifi_credential_t *ap_credential); -int wifi_save_ap_credential(wifi_credential_t *ap_credential); +int wifi_data_save_sta_ap_credential(wifi_credential_t *ap_credential); int wifi_data_save_wifi_mode(wifi_apsta_mode_e mode); +int wifi_data_get_wifi_mode(wifi_apsta_mode_e *mode); + +int wifi_data_get_ap_credential(wifi_credential_t *ap_credential); + +int wifi_data_save_ap_credential(wifi_credential_t *ap_credential); + #endif //WIFI_STORAGE_H_GUARD \ No newline at end of file diff --git a/project_components/wifi_manager/wifi_storage_priv.h b/project_components/wifi_manager/wifi_storage_priv.h index 38254ec..9ce072c 100644 --- a/project_components/wifi_manager/wifi_storage_priv.h +++ b/project_components/wifi_manager/wifi_storage_priv.h @@ -11,8 +11,8 @@ typedef struct w_cache_t { typedef enum wt_wifi_key_enum { KEY_WIFI_RESERVED = 0x000, /* WIFI */ - KEY_WIFI_AP_SSID = 0x1, - KEY_WIFI_AP_PASSWORD = 0x02, + KEY_WIFI_AP_CRED = 0x1, + /* TODO: should have 1 for each AP */ KEY_WIFI_STA_USE_STATIC = 0x03, /* bit[0:31]=[IP, MASK, GATEWAY, DNS] */ @@ -25,7 +25,7 @@ typedef enum wt_wifi_key_enum { KEY_WIFI_STA_LAST_AP_CRED = 0x08, /*!< ssid[32] + password[64] */ KEY_WIFI_STA_AP_BITMAP = 0x09, /* 32 bit */ - KEY_UNUSED_100 = 0x0100, + KEY_UNUSED_100 = 0x0100, /* avoid: same as 0x1 */ KEY_WIFI_APSTA_MODE = 0x0101, /* 1B */ } wt_wifi_key;