New AP list implementation

- AP List now uses cJSON, which should be more robust than sprintf.
- Max number of access points reported now aligned with espressif's max.
- WiFi logs no longer suppressed by the wifi_manager
This commit is contained in:
Sebastien
2019-10-28 15:04:08 -04:00
parent fc1c0a4bd2
commit e4374f8554
5 changed files with 67 additions and 243 deletions

View File

@@ -38,7 +38,6 @@ Contains the freeRTOS task and all necessary support
#include "dns_server.h"
#include "http_server.h"
#include "json.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -82,8 +81,8 @@ SemaphoreHandle_t wifi_manager_json_mutex = NULL;
SemaphoreHandle_t wifi_manager_sta_ip_mutex = NULL;
char *wifi_manager_sta_ip = NULL;
uint16_t ap_num = MAX_AP_NUM;
wifi_ap_record_t *accessp_records;
char *accessp_json = NULL;
wifi_ap_record_t *accessp_records=NULL;
cJSON * accessp_cjson=NULL;
char *ip_info_json = NULL;
char *host_name = NULL;
cJSON * ip_info_cjson=NULL;
@@ -161,16 +160,10 @@ void wifi_manager_disconnect_async(){
void wifi_manager_start(){
/* disable the default wifi logging */
esp_log_level_set("wifi", ESP_LOG_NONE);
/* memory allocation */
wifi_manager_queue = xQueueCreate( 3, sizeof( queue_message) );
wifi_manager_json_mutex = xSemaphoreCreateMutex();
accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * MAX_AP_NUM);
accessp_json = (char*)malloc(MAX_AP_NUM * JSON_ONE_APP_SIZE + 4); /* 4 bytes for json encapsulation of "[\n" and "]\0" */
wifi_manager_clear_access_points_json();
accessp_cjson = wifi_manager_clear_ap_list_json(&accessp_cjson);
ip_info_json = NULL;
ip_info_cjson = wifi_manager_clear_ip_info_json(&ip_info_cjson);
wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t));
@@ -323,6 +316,16 @@ cJSON * wifi_manager_get_new_json(cJSON **old){
ESP_LOGD(TAG,"wifi_manager_get_new_json done");
return cJSON_CreateObject();
}
cJSON * wifi_manager_get_new_array_json(cJSON **old){
ESP_LOGD(TAG,"wifi_manager_get_new_array_json called");
cJSON * root=*old;
if(root!=NULL){
cJSON_Delete(root);
*old=NULL;
}
ESP_LOGD(TAG,"wifi_manager_get_new_array_json done");
return cJSON_CreateArray();
}
cJSON * wifi_manager_get_basic_info(cJSON **old){
const esp_app_desc_t* desc = esp_ota_get_app_description();
ESP_LOGD(TAG,"wifi_manager_get_basic_info called");
@@ -343,6 +346,13 @@ cJSON * wifi_manager_clear_ip_info_json(cJSON **old){
ESP_LOGD(TAG,"wifi_manager_clear_ip_info_json done");
return root;
}
cJSON * wifi_manager_clear_ap_list_json(cJSON **old){
ESP_LOGD(TAG,"wifi_manager_clear_ap_list_json called");
cJSON *root = wifi_manager_get_new_array_json(old);
ESP_LOGD(TAG,"wifi_manager_clear_ap_list_json done");
return root;
}
void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code){
@@ -372,38 +382,39 @@ void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code)
ESP_LOGD(TAG,"wifi_manager_generate_ip_info_json done");
}
void wifi_manager_clear_access_points_json(){
strcpy(accessp_json, "[]\n");
}
void wifi_manager_generate_acess_points_json(){
strcpy(accessp_json, "[");
const char oneap_str[] = ",\"chan\":%d,\"rssi\":%d,\"auth\":%d}%c\n";
/* stack buffer to hold on to one AP until it's copied over to accessp_json */
char one_ap[JSON_ONE_APP_SIZE];
void wifi_manager_generate_access_points_json(cJSON ** ap_list){
char szMacStr[15]={0};
*ap_list = wifi_manager_get_new_array_json(ap_list);
if(*ap_list==NULL) return;
for(int i=0; i<ap_num;i++){
wifi_ap_record_t ap = accessp_records[i];
/* ssid needs to be json escaped. To save on heap memory it's directly printed at the correct address */
strcat(accessp_json, "{\"ssid\":");
json_print_string( (unsigned char*)ap.ssid, (unsigned char*)(accessp_json+strlen(accessp_json)) );
/* print the rest of the json for this access point: no more string to escape */
snprintf(one_ap, (size_t)JSON_ONE_APP_SIZE, oneap_str,
ap.primary,
ap.rssi,
ap.authmode,
i==ap_num-1?']':',');
/* add it to the list */
strcat(accessp_json, one_ap);
cJSON * ap = cJSON_CreateObject();
if(ap == NULL) {
ESP_LOGE(TAG,"Unable to allocate memory for access point entry #%d",i);
return;
}
cJSON * radio = cJSON_CreateObject();
if(radio == NULL) {
ESP_LOGE(TAG,"Unable to allocate memory for access point entry #%d",i);
cJSON_Delete(ap);
return;
}
wifi_ap_record_t ap_rec = accessp_records[i];
cJSON_AddNumberToObject(ap, "chan", ap_rec.primary);
cJSON_AddNumberToObject(ap, "rssi", ap_rec.rssi);
cJSON_AddNumberToObject(ap, "auth", ap_rec.authmode);
cJSON_AddItemToObject(ap, "ssid", cJSON_CreateString((char *)ap_rec.ssid));
memset(szMacStr, 0x00, sizeof(szMacStr));
snprintf(szMacStr, sizeof(szMacStr)-1,MACSTR, MAC2STR(ap_rec.bssid));
cJSON_AddItemToObject(ap, "bssid", cJSON_CreateString(szMacStr));
cJSON_AddNumberToObject(radio, "b", ap_rec.phy_11b?1:0);
cJSON_AddNumberToObject(radio, "g", ap_rec.phy_11g?1:0);
cJSON_AddNumberToObject(radio, "n", ap_rec.phy_11n?1:0);
cJSON_AddNumberToObject(radio, "low_rate", ap_rec.phy_lr?1:0);
cJSON_AddItemToObject(ap,"radio", radio);
cJSON_AddItemToArray(*ap_list, ap);
ESP_LOGD(TAG,"New access point found: %s", cJSON_Print(ap));
}
ESP_LOGD(TAG,"Full access point list: %s", cJSON_Print(*ap_list));
}
bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait){
@@ -470,7 +481,7 @@ void wifi_manager_unlock_json_buffer(){
}
char* wifi_manager_get_ap_list_json(){
return accessp_json;
return cJSON_Print(accessp_cjson);
}
esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event)
@@ -589,13 +600,11 @@ void wifi_manager_destroy(){
task_wifi_manager = NULL;
free(host_name);
/* heap buffers */
free(accessp_records);
accessp_records = NULL;
free(accessp_json);
accessp_json = NULL;
free(ip_info_json);
cJSON_Delete(ip_info_cjson);
cJSON_Delete(accessp_cjson);
ip_info_cjson=NULL;
accessp_cjson=NULL;
free(wifi_manager_sta_ip);
wifi_manager_sta_ip = NULL;
if(wifi_manager_config_sta){
@@ -786,20 +795,25 @@ void wifi_manager( void * pvParameters ){
/* As input param, it stores max AP number ap_records can hold. As output param, it receives the actual AP number this API returns.
* As a consequence, ap_num MUST be reset to MAX_AP_NUM at every scan */
ESP_LOGD(TAG,"Getting AP list records");
ap_num = MAX_AP_NUM;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, accessp_records));
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_num));
if(ap_num>0){
accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * ap_num);
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, accessp_records));
}
/* make sure the http server isn't trying to access the list while it gets refreshed */
ESP_LOGD(TAG,"Preparing to build ap JSON list");
if(wifi_manager_lock_json_buffer( pdMS_TO_TICKS(1000) )){
/* Will remove the duplicate SSIDs from the list and update ap_num */
wifi_manager_filter_unique(accessp_records, &ap_num);
wifi_manager_generate_acess_points_json();
wifi_manager_generate_access_points_json(&accessp_cjson);
wifi_manager_unlock_json_buffer();
ESP_LOGD(TAG,"Done building ap JSON list");
}
else{
ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan");
}
free(accessp_records);
/* callback */
if(cb_ptr_arr[msg.code]) {