From 6ca7897fa07541b6be1e7bf8a1e369168f94e720 Mon Sep 17 00:00:00 2001 From: Slider0007 <115730895+Slider0007@users.noreply.github.com> Date: Sat, 4 Mar 2023 11:49:08 +0100 Subject: [PATCH] "WIFI roaming" by channel scan (AP switching at low RSSI) (#2120) * Activate 802.11kv wifi mesh roaming * Activate roaming by scanning * Revert stack reducation --- .../jomjol_flowcontroll/ClassFlowControll.cpp | 4 +- .../jomjol_tfliteclass/server_tflite.cpp | 21 +- code/components/jomjol_wlan/connect_wlan.cpp | 254 ++++++++++++++---- code/components/jomjol_wlan/connect_wlan.h | 8 + code/components/jomjol_wlan/read_wlanini.cpp | 6 +- code/include/defines.h | 19 +- code/sdkconfig.defaults | 9 +- 7 files changed, 253 insertions(+), 68 deletions(-) diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index f493a0e8..57c6d026 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -611,8 +611,8 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph) } /* TimeServer and TimeZone got already read from the config, see setupTime () */ - - #ifdef WLAN_USE_MESH_ROAMING + + #if (defined WLAN_USE_ROAMING_BY_SCANNING || (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)) if ((toUpper(splitted[0]) == "RSSITHRESHOLD") && (splitted.size() > 1)) { int RSSIThresholdTMP = atoi(splitted[1].c_str()); diff --git a/code/components/jomjol_tfliteclass/server_tflite.cpp b/code/components/jomjol_tfliteclass/server_tflite.cpp index 309071ed..c22a30c2 100644 --- a/code/components/jomjol_tfliteclass/server_tflite.cpp +++ b/code/components/jomjol_tfliteclass/server_tflite.cpp @@ -909,11 +909,11 @@ void task_autodoFlow(void *pvParameter) LogFile.RemoveOldDataLog(); } - //Round finished -> Logfile + // Round finished -> Logfile LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Round #" + std::to_string(countRounds) + " completed (" + std::to_string(getUpTime() - roundStartTime) + " seconds)"); - //CPU Temp -> Logfile + // CPU Temp -> Logfile LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CPU Temperature: " + std::to_string((int)temperatureRead()) + "°C"); // WIFI Signal Strength (RSSI) -> Logfile @@ -925,6 +925,16 @@ void task_autodoFlow(void *pvParameter) StatusLED(TIME_CHECK, 1, false); } + #if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES) + wifiRoamingQuery(); + #endif + + // Scan channels and check if an AP with better RSSI is available, then disconnect and try to reconnect to AP with better RSSI + // NOTE: Keep this direct before the following task delay, because scan is done in blocking mode and this takes ca. 1,5 - 2s. + #ifdef WLAN_USE_ROAMING_BY_SCANNING + wifiRoamByScanning(); + #endif + fr_delta_ms = (esp_timer_get_time() - fr_start) / 1000; if (auto_interval > fr_delta_ms) { @@ -945,11 +955,12 @@ void TFliteDoAutoStart() ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str()); - xReturned = xTaskCreatePinnedToCore(&task_autodoFlow, "task_autodoFlow", 16 * 1024, NULL, tskIDLE_PRIORITY+2, &xHandletask_autodoFlow, 0); - //xReturned = xTaskCreate(&task_autodoFlow, "task_autodoFlow", 16 * 1024, NULL, tskIDLE_PRIORITY+2, &xHandletask_autodoFlow); + uint32_t stackSize = 16 * 1024; + xReturned = xTaskCreatePinnedToCore(&task_autodoFlow, "task_autodoFlow", stackSize, NULL, tskIDLE_PRIORITY+2, &xHandletask_autodoFlow, 0); if( xReturned != pdPASS ) { - ESP_LOGD(TAG, "ERROR task_autodoFlow konnte nicht erzeugt werden!"); + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Creation task_autodoFlow failed. Requested stack size:" + std::to_string(stackSize)); + LogFile.WriteHeapInfo("Creation task_autodoFlow failed"); } ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str()); } diff --git a/code/components/jomjol_wlan/connect_wlan.cpp b/code/components/jomjol_wlan/connect_wlan.cpp index 414f4e48..1a618236 100644 --- a/code/components/jomjol_wlan/connect_wlan.cpp +++ b/code/components/jomjol_wlan/connect_wlan.cpp @@ -39,26 +39,31 @@ static const char *TAG = "WIFI"; +static bool APWithBetterRSSI = false; +static bool WIFIConnected = false; +static int WIFIReconnectCnt = 0; -bool WIFIConnected = false; -int WIFIReconnectCnt = 0; + + +void strinttoip4(const char *ip, int &a, int &b, int &c, int &d) { + std::string zw = std::string(ip); + std::stringstream s(zw); + char ch; //to temporarily store the '.' + s >> a >> ch >> b >> ch >> c >> ch >> d; +} + + +std::string BssidToString(const char* c) { + char cBssid[25]; + sprintf(cBssid, "%02x:%02x:%02x:%02x:%02x:%02x", c[0], c[1], c[2], c[3], c[4], c[5]); + return std::string(cBssid); +} #ifdef WLAN_USE_MESH_ROAMING - -int RSSI_Threshold = WLAN_WIFI_RSSI_THRESHOLD; - /* rrm ctx */ int rrm_ctx = 0; -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* esp netif object representing the WIFI station */ -static esp_netif_t *sta_netif = NULL; - -//static const char *TAG = "roaming_example"; - static inline uint32_t WPA_GET_LE32(const uint8_t *a) { return ((uint32_t) a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]; @@ -81,6 +86,7 @@ static inline uint32_t WPA_GET_LE32(const uint8_t *a) #define ETH_ALEN 6 #endif + #define MAX_NEIGHBOR_LEN 512 static char * get_btm_neighbor_list(uint8_t *report, size_t report_len) { @@ -97,10 +103,10 @@ static char * get_btm_neighbor_list(uint8_t *report, size_t report_len) * PHY Type[1] * Optional Subelements[variable] */ -#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1) + #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1) if (!report || report_len == 0) { - ESP_LOGI(TAG, "RRM neighbor report is not valid"); + ESP_LOGD(TAG, "Roaming: RRM neighbor report is not valid"); return NULL; } @@ -116,14 +122,14 @@ static char * get_btm_neighbor_list(uint8_t *report, size_t report_len) if (pos[0] != WLAN_EID_NEIGHBOR_REPORT || nr_len < NR_IE_MIN_LEN) { - ESP_LOGI(TAG, "CTRL: Invalid Neighbor Report element: id=%u len=%u", + ESP_LOGD(TAG, "Roaming CTRL: Invalid Neighbor Report element: id=%u len=%u", data[0], nr_len); ret = -1; goto cleanup; } if (2U + nr_len > report_len) { - ESP_LOGI(TAG, "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u", + ESP_LOGD(TAG, "Roaming CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u", data[0], report_len, nr_len); ret = -1; goto cleanup; @@ -166,8 +172,8 @@ static char * get_btm_neighbor_list(uint8_t *report, size_t report_len) pos += s_len; } - - ESP_LOGI(TAG, "RMM neigbor report bssid=" MACSTR + + ESP_LOGI(TAG, "Roaming: RMM neigbor report bssid=" MACSTR " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s", MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN), nr[ETH_ALEN + 4], nr[ETH_ALEN + 5], @@ -175,6 +181,10 @@ static char * get_btm_neighbor_list(uint8_t *report, size_t report_len) lci[0] ? " lci=" : "", lci, civic[0] ? " civic=" : "", civic); + + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: RMM neigbor report BSSID: " + BssidToString((char*)nr) + + ", Channel: " + std::to_string(nr[ETH_ALEN + 5])); + /* neighbor start */ len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, " neighbor="); /* bssid */ @@ -212,18 +222,19 @@ void neighbor_report_recv_cb(void *ctx, const uint8_t *report, size_t report_len int *val = (int*) ctx; uint8_t *pos = (uint8_t *)report; int cand_list = 0; + int ret; if (!report) { - ESP_LOGE(TAG, "report is null"); + ESP_LOGD(TAG, "Roaming: Neighbor report is null"); return; } if (*val != rrm_ctx) { - ESP_LOGE(TAG, "rrm_ctx value didn't match, not initiated by us"); + ESP_LOGE(TAG, "Roaming: rrm_ctx value didn't match, not initiated by us"); return; } /* dump report info */ - ESP_LOGI(TAG, "rrm: neighbor report len=%d", report_len); - ESP_LOG_BUFFER_HEXDUMP(TAG, pos, report_len, ESP_LOG_INFO); + ESP_LOGD(TAG, "Roaming: RRM neighbor report len=%d", report_len); + ESP_LOG_BUFFER_HEXDUMP(TAG, pos, report_len, ESP_LOG_DEBUG); /* create neighbor list */ char *neighbor_list = get_btm_neighbor_list(pos + 1, report_len - 1); @@ -242,8 +253,10 @@ void neighbor_report_recv_cb(void *ctx, const uint8_t *report, size_t report_len esp_wifi_scan_get_ap_records(&number, &ap_records); cand_list = 1; } - /* send AP btm query, this will cause STA to roam as well */ - esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, neighbor_list, cand_list); + /* send AP btm query requesting to roam depending on candidate list of AP */ + // btm_query_reasons: https://github.com/espressif/esp-idf/blob/release/v4.4/components/wpa_supplicant/esp_supplicant/include/esp_wnm.h + ret = esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, neighbor_list, cand_list); // query reason 16 -> LOW RSSI --> (btm_query_reason)16 + ESP_LOGD(TAG, "neighbor_report_recv_cb retval - bss_transisition_query: %d", ret); cleanup: if (neighbor_list) @@ -251,28 +264,151 @@ cleanup: } -static void esp_bss_rssi_low_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void esp_bss_rssi_low_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { + int retval = -1; wifi_event_bss_rssi_low_t *event = (wifi_event_bss_rssi_low_t*) event_data; - ESP_LOGI(TAG, "%s:bss rssi is=%d", __func__, event->rssi); - /* Lets check channel conditions */ - rrm_ctx++; - if (esp_rrm_send_neighbor_rep_request(neighbor_report_recv_cb, &rrm_ctx) < 0) { - /* failed to send neighbor report request */ - ESP_LOGI(TAG, "failed to send neighbor report request"); - if (esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, NULL, 0) < 0) { - ESP_LOGI(TAG, "failed to send btm query"); - } + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming Event: RSSI " + std::to_string(event->rssi) + + " < RSSI_Threshold " + std::to_string(wlan_config.rssi_threshold)); + + /* If RRM is supported, call RRM and then send BTM query to AP */ + if (esp_rrm_is_rrm_supported_connection() && esp_wnm_is_btm_supported_connection()) + { + /* Lets check channel conditions */ + rrm_ctx++; + + retval = esp_rrm_send_neighbor_rep_request(neighbor_report_recv_cb, &rrm_ctx); + ESP_LOGD(TAG, "esp_rrm_send_neighbor_rep_request retval: %d", retval); + if (retval == 0) + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: RRM + BTM query sent"); + else + ESP_LOGD(TAG, "esp_rrm_send_neighbor_rep_request retval: %d", retval); + } + + /* If RRM is not supported or RRM request failed, send directly BTM query to AP */ + if (retval < 0 && esp_wnm_is_btm_supported_connection()) + { + // btm_query_reasons: https://github.com/espressif/esp-idf/blob/release/v4.4/components/wpa_supplicant/esp_supplicant/include/esp_wnm.h + retval = esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, NULL, 0); // query reason 16 -> LOW RSSI --> (btm_query_reason)16 + ESP_LOGD(TAG, "esp_wnm_send_bss_transition_mgmt_query retval: %d", retval); + if (retval == 0) + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: BTM query sent"); + else + ESP_LOGD(TAG, "esp_wnm_send_bss_transition_mgmt_query retval: %d", retval); } } -#endif +void printRoamingFeatureSupport(void) +{ + if (esp_rrm_is_rrm_supported_connection()) + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Roaming: RRM (802.11k) supported by AP"); + else + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Roaming: RRM (802.11k) NOT supported by AP"); -////////////////////////////////// -////////////////////////////////// + if (esp_wnm_is_btm_supported_connection()) + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Roaming: BTM (802.11v) supported by AP"); + else + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Roaming: BTM (802.11v) NOT supported by AP"); +} + + +#ifdef WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES +void wifiRoamingQuery(void) +{ + /* Query only if WIFI is connected and feature is supported by AP */ + if (WIFIConnected && (esp_rrm_is_rrm_supported_connection() || esp_wnm_is_btm_supported_connection())) { + /* Client is allowed to send query to AP for roaming request if RSSI is lower than threshold */ + /* Note 1: Set RSSI threshold funtion needs to be called to trigger WIFI_EVENT_STA_BSS_RSSI_LOW */ + /* Note 2: Additional querys will be sent after flow round is finshed --> server_tflite.cpp - function "task_autodoFlow" */ + /* Note 3: RSSI_Threshold = 0 --> Disable client query by application (WebUI parameter) */ + + if (wlan_config.rssi_threshold != 0 && get_WIFI_RSSI() != -127 && (get_WIFI_RSSI() < wlan_config.rssi_threshold)) + esp_wifi_set_rssi_threshold(wlan_config.rssi_threshold); + } +} +#endif // WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES +#endif // WLAN_USE_MESH_ROAMING + + +#ifdef WLAN_USE_ROAMING_BY_SCANNING +std::string getAuthModeName(const wifi_auth_mode_t auth_mode) +{ + std::string AuthModeNames[] = {"OPEN", "WEP", "WPA PSK", "WPA2 PSK", "WPA WPA2 PSK", "WPA2 ENTERPRISE", + "WPA3 PSK", "WPA2 WPA3 PSK", "WAPI_PSK", "MAX"}; + return AuthModeNames[auth_mode]; +} + + +void wifi_scan(void) +{ + wifi_scan_config_t wifi_scan_config; + memset(&wifi_scan_config, 0, sizeof(wifi_scan_config)); + + wifi_scan_config.ssid = (uint8_t*)wlan_config.ssid.c_str(); // only scan for configured SSID + wifi_scan_config.show_hidden = true; // scan also hidden SSIDs + wifi_scan_config.channel = 0; // scan all channels + + esp_wifi_scan_start(&wifi_scan_config, true); // not using event handler SCAN_DONE by purpose to keep SYS_EVENT heap smaller + // and the calling task task_autodoFlow is after scan is finish in wait state anyway + // Scan duration: ca. (120ms + 30ms) * Number of channels -> ca. 1,5 - 2s + + uint16_t max_number_of_ap_found = 10; // max. number of APs, value will be updated by function "esp_wifi_scan_get_ap_num" + esp_wifi_scan_get_ap_num(&max_number_of_ap_found); // get actual found APs + wifi_ap_record_t* wifi_ap_records = new wifi_ap_record_t[max_number_of_ap_found]; // Allocate necessary record datasets + if (wifi_ap_records == NULL) { + esp_wifi_scan_get_ap_records(0, NULL); // free internal heap + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "wifi_scan: Failed to allocate heap for wifi_ap_records"); + return; + } + else { + if (esp_wifi_scan_get_ap_records(&max_number_of_ap_found, wifi_ap_records) != ESP_OK) { // Retrieve results (and free internal heap) + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "wifi_scan: esp_wifi_scan_get_ap_records: Error retrieving datasets"); + free(wifi_ap_records); + return; + } + } + + wifi_ap_record_t currentAP; + esp_wifi_sta_get_ap_info(¤tAP); + + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: Current AP BSSID=" + BssidToString((char*)currentAP.bssid)); + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: Scan completed, APs found with configured SSID: " + std::to_string(max_number_of_ap_found)); + for (int i = 0; i < max_number_of_ap_found; i++) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: " + std::to_string(i+1) + + ": SSID=" + std::string((char*)wifi_ap_records[i].ssid) + + ", BSSID=" + BssidToString((char*)wifi_ap_records[i].bssid) + + ", RSSI=" + std::to_string(wifi_ap_records[i].rssi) + + ", CH=" + std::to_string(wifi_ap_records[i].primary) + + ", AUTH=" + getAuthModeName(wifi_ap_records[i].authmode)); + if (wifi_ap_records[i].rssi > (currentAP.rssi + 5) && // RSSI is better than actual RSSI + 5 --> Avoid switching to AP with roughly same RSSI + (strcmp(BssidToString((char*)wifi_ap_records[i].bssid).c_str(), BssidToString((char*)currentAP.bssid).c_str()) != 0)) + { + APWithBetterRSSI = true; + } + } + free(wifi_ap_records); +} + + +void wifiRoamByScanning(void) +{ + if (wlan_config.rssi_threshold != 0 && get_WIFI_RSSI() != -127 && (get_WIFI_RSSI() < wlan_config.rssi_threshold)) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: Start scan of all channels for SSID " + wlan_config.ssid); + wifi_scan(); + + if (APWithBetterRSSI) { + APWithBetterRSSI = false; + LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Roaming: AP with better RSSI in range, disconnecting to switch AP..."); + esp_wifi_disconnect(); + } + else { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Roaming: Scan completed, stay on current AP"); + } + } +} +#endif // WLAN_USE_ROAMING_BY_SCANNING std::string* getIPAddress() @@ -294,13 +430,12 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_ WIFIConnected = false; esp_wifi_connect(); } - else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { /* Disconnect reason: https://github.com/espressif/esp-idf/blob/d825753387c1a64463779bbd2369e177e5d59a79/components/esp_wifi/include/esp_wifi_types.h */ wifi_event_sta_disconnected_t *disconn = (wifi_event_sta_disconnected_t *)event_data; if (disconn->reason == WIFI_REASON_ROAMING) { - LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Roaming)"); + LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected (" + std::to_string(disconn->reason) + ", Roaming 802.11kv)"); // --> no reconnect neccessary, it should automatically reconnect to new AP } else { @@ -334,14 +469,21 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_ LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Disconnected, multiple reconnect attempts failed (" + std::to_string(disconn->reason) + "), still retrying..."); } - } - + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) { LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to: " + wlan_config.ssid + ", RSSI: " + std::to_string(get_WIFI_RSSI())); - } - + + #ifdef WLAN_USE_MESH_ROAMING + printRoamingFeatureSupport(); + + #ifdef WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES + // wifiRoamingQuery(); // Avoid client triggered query during processing flow (reduce risk of heap shortage). Request will be triggered at the end of every round anyway + #endif //WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES + + #endif //WLAN_USE_MESH_ROAMING + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { WIFIConnected = true; @@ -349,7 +491,7 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_ ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; wlan_config.ipaddress = std::string(ip4addr_ntoa((const ip4_addr*) &event->ip_info.ip)); - LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Got IP: " + wlan_config.ipaddress); + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Assigned IP: " + wlan_config.ipaddress); #ifdef ENABLE_MQTT if (getMQTTisEnabled()) { @@ -361,14 +503,6 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_ } -void strinttoip4(const char *ip, int &a, int &b, int &c, int &d) { - std::string zw = std::string(ip); - std::stringstream s(zw); - char ch; //to temporarily store the '.' - s >> a >> ch >> b >> ch >> c >> ch >> d; -} - - esp_err_t wifi_init_sta(void) { esp_err_t retval = esp_netif_init(); @@ -462,6 +596,18 @@ esp_err_t wifi_init_sta(void) wifi_config_t wifi_config = { }; + wifi_config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; // Scan all channels instead of stopping after first match + wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL; // Sort by signal strength and keep up to 4 best APs + //wifi_config.sta.failure_retry_cnt = 3; // IDF version 5.0 will support this + + #ifdef WLAN_USE_MESH_ROAMING + wifi_config.sta.rm_enabled = 1; // 802.11k (Radio Resource Management) + wifi_config.sta.btm_enabled = 1; // 802.11v (BSS Transition Management) + //wifi_config.sta.mbo_enabled = 1; // Multiband Operation (better use of Wi-Fi network resources in roaming decisions) -> not activated to save heap + wifi_config.sta.pmf_cfg.capable = 1; // 802.11w (Protected Management Frame, activated by default if other device also advertizes PMF capability) + //wifi_config.sta.ft_enabled = 1; // 802.11r (BSS Fast Transition) -> Upcoming IDF version 5.0 will support 11r + #endif + strcpy((char*)wifi_config.sta.ssid, (const char*)wlan_config.ssid.c_str()); strcpy((char*)wifi_config.sta.password, (const char*)wlan_config.password.c_str()); diff --git a/code/components/jomjol_wlan/connect_wlan.h b/code/components/jomjol_wlan/connect_wlan.h index c5374f8f..f635966f 100644 --- a/code/components/jomjol_wlan/connect_wlan.h +++ b/code/components/jomjol_wlan/connect_wlan.h @@ -12,4 +12,12 @@ int get_WIFI_RSSI(); bool getWIFIisConnected(); void WIFIDestroy(); +#if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES) +void wifiRoamingQuery(void); +#endif + +#ifdef WLAN_USE_ROAMING_BY_SCANNING +void wifiRoamByScanning(void); +#endif + #endif //CONNECT_WLAN_H \ No newline at end of file diff --git a/code/components/jomjol_wlan/read_wlanini.cpp b/code/components/jomjol_wlan/read_wlanini.cpp index 1e489460..1a9af227 100644 --- a/code/components/jomjol_wlan/read_wlanini.cpp +++ b/code/components/jomjol_wlan/read_wlanini.cpp @@ -145,8 +145,8 @@ int LoadWlanFromFile(std::string fn) wlan_config.dns = tmp; LogFile.WriteToFile(ESP_LOG_INFO, TAG, "DNS: " + wlan_config.dns); } - #ifdef WLAN_USE_MESH_ROAMING - else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHRESHOLD")) { + #if (defined WLAN_USE_ROAMING_BY_SCANNING || (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)) + else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHRESHOLD")){ tmp = trim(splitted[1]); if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){ tmp = tmp.substr(1, tmp.length()-2); @@ -266,7 +266,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname) return true; } -#ifdef WLAN_USE_MESH_ROAMING +#if (defined WLAN_USE_ROAMING_BY_SCANNING || (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES)) bool ChangeRSSIThreshold(std::string fn, int _newrssithreshold) { if (wlan_config.rssi_threshold == _newrssithreshold) diff --git a/code/include/defines.h b/code/include/defines.h index 0da3c8d4..7dc83127 100644 --- a/code/include/defines.h +++ b/code/include/defines.h @@ -161,9 +161,22 @@ } #define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE - //connect_wlan - #define WLAN_USE_MESH_ROAMING - #define WLAN_WIFI_RSSI_THRESHOLD -50 + + // connect_wlan.cpp + //****************************** + /* WIFI roaming functionalities 802.11k+v (uses ca. 6kB - 8kB internal RAM; if SCAN CACHE activated: + 1kB / beacon) + PLEASE BE AWARE: The following CONFIG parameters have to to be set in + sdkconfig.defaults before use of this function is possible!! + CONFIG_WPA_11KV_SUPPORT=y + CONFIG_WPA_SCAN_CACHE=n + CONFIG_WPA_MBO_SUPPORT=n + CONFIG_WPA_11R_SUPPORT=n + */ + //#define WLAN_USE_MESH_ROAMING // 802.11v (BSS Transition Management) + 802.11k (Radio Resource Management) (ca. 6kB - 8kB internal RAM neccessary) + //#define WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES // Client can send query to AP requesting to roam (if RSSI lower than RSSI threshold) + + /* WIFI roaming only client triggered by scanning the channels after each round (only if RSSI < RSSIThreshold) and trigger a disconnect to switch AP */ + #define WLAN_USE_ROAMING_BY_SCANNING //ClassFlowCNNGeneral diff --git a/code/sdkconfig.defaults b/code/sdkconfig.defaults index 978a4b48..da477884 100644 --- a/code/sdkconfig.defaults +++ b/code/sdkconfig.defaults @@ -135,7 +135,14 @@ CONFIG_BF3005_SUPPORT=n CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4864 -#only necessary for task analysis (include/defines -> TASK_ANALYSIS_ON) +#only necessary for WIFI mesh roaming (include/defines.h -> WLAN_USE_MESH_ROAMING) +#CONFIG_WPA_11KV_SUPPORT=y +#CONFIG_WPA_SCAN_CACHE=n +#CONFIG_WPA_MBO_SUPPORT=n +#CONFIG_WPA_11R_SUPPORT=n // Will be supported with ESP-IDF v5.0 +#CONFIG_WPA_DEBUG_PRINT=n + +#only necessary for task analysis (include/defines.h -> TASK_ANALYSIS_ON) #set in [env:esp32cam-dev-task-analysis] #CONFIG_FREERTOS_USE_TRACE_FACILITY=1 #CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y