diff --git a/src/ESPNetwork.cpp b/src/ESPNetwork.cpp index b8e9b83..e91c2a9 100644 --- a/src/ESPNetwork.cpp +++ b/src/ESPNetwork.cpp @@ -2,6 +2,7 @@ #include #endif #include +#include #include #include #include "esp_log.h" @@ -174,6 +175,7 @@ bool ESPNetwork::changeAP(const uint8_t *bssid, const int32_t channel) { this->connType = conn_types_t::unset; this->_connecting = true; this->connectStart = millis(); + WiFi.setScanMethod(WIFI_FAST_SCAN); WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase, channel, bssid); this->connectStart = millis(); return false; @@ -460,6 +462,11 @@ bool ESPNetwork::connectWiFi(const uint8_t *bssid, const int32_t channel) { this->connType = conn_types_t::unset; ESP_LOGI(TAG, "WiFi begin..."); this->_connecting = true; + // Our own scan already picked the AP. An all-channel scan here makes the + // driver sweep every channel again first, about 17s, before it even + // authenticates. A fast scan starts on the AP's channel and joins the + // first match. + WiFi.setScanMethod(WIFI_FAST_SCAN); WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase, channel, bssid); this->connectStart = millis(); } @@ -488,11 +495,14 @@ bool ESPNetwork::connectWiFi(const uint8_t *bssid, const int32_t channel) { int32_t _channel = 0; if(!settings.WIFI.hidden && this->getStrongestAP(settings.WIFI.ssid, _bssid, &_channel)) { ESP_LOGD(TAG, "Found strongest AP %02X:%02X:%02X:%02X:%02X:%02X CH:%d", _bssid[0], _bssid[1], _bssid[2], _bssid[3], _bssid[4], _bssid[5], _channel); + WiFi.setScanMethod(WIFI_FAST_SCAN); // The AP is known, see connectWiFi(bssid). WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase, _channel, _bssid); } - else + else { // If the user has the hidden flag set just connect to whatever the AP gives us. + WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase); + } } this->connectStart = millis(); return true; @@ -550,8 +560,9 @@ bool ESPNetwork::getStrongestAP(const char *ssid, uint8_t *bssid, int32_t *chann if(connected) { const uint8_t *b = WiFi.BSSID(i); const uint8_t *cur = WiFi.BSSID(); - ESP_LOGI(TAG, "AP %02X:%02X:%02X:%02X:%02X:%02X ch %ld %ld dBm%s", b[0], b[1], b[2], b[3], b[4], b[5], - (long)WiFi.channel(i), (long)WiFi.RSSI(i), (cur && memcmp(b, cur, 6) == 0) ? " (connected)" : ""); + ESP_LOGI(TAG, "AP %02X:%02X:%02X:%02X:%02X:%02X ch %ld %ld dBm %s%s", b[0], b[1], b[2], b[3], b[4], b[5], + (long)WiFi.channel(i), (long)WiFi.RSSI(i), wifiAuthModeName(WiFi.encryptionType(i)), + (cur && memcmp(b, cur, 6) == 0) ? " (connected)" : ""); } if(worthRoaming(connected, currentRssi, WiFi.RSSI(i), ROAM_MIN_GAIN_DB) && WiFi.RSSI(i) > strength) { strength = WiFi.RSSI(i); @@ -601,7 +612,15 @@ void ESPNetwork::networkEvent(WiFiEvent_t event) { if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname); break; case ARDUINO_EVENT_WIFI_STA_STOP: ESP_LOGI(TAG, "(evt) WiFi clients stopped"); break; - case ARDUINO_EVENT_WIFI_STA_CONNECTED: ESP_LOGI(TAG, "(evt) Connected to WiFi STA access point"); break; + case ARDUINO_EVENT_WIFI_STA_CONNECTED: { + // How long the join took and the security the AP offers, so a slow + // connect shows in the log. + wifi_ap_record_t ap; + const bool haveAp = esp_wifi_sta_get_ap_info(&ap) == ESP_OK; + ESP_LOGI(TAG, "(evt) Connected to WiFi STA access point after %lums (%s)", + (unsigned long)(millis() - net.connectStart), haveAp ? wifiAuthModeName(ap.authmode) : "?"); + break; + } case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: ESP_LOGI(TAG, "(evt) Disconnected from WiFi STA access point. Connecting: %d", net.connecting()); net.connType = conn_types_t::unset; diff --git a/src/Utils.cpp b/src/Utils.cpp index 98c1b88..f329951 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -147,6 +147,20 @@ void RssiBroadcast::sent(bool broadcast, int rssi, int channel, uint32_t now) { bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain) { return !connected || apRssi >= currentRssi + minGain; } +const char *wifiAuthModeName(uint8_t authMode) { + switch(authMode) { + case 0: return "OPEN"; + case 1: return "WEP"; + case 2: return "WPA"; + case 3: return "WPA2"; + case 4: return "WPA/WPA2"; + case 5: return "WPA2-ENT"; + case 6: return "WPA3"; + case 7: return "WPA2/WPA3"; + case 8: return "WAPI"; + default: return "UNKNOWN"; + } +} heap_emit_t heapEmitTarget(uint8_t num, uint32_t sinceLastMs, uint32_t intervalMs, bool roomHasClients) { if(num != 255) return heap_emit_t::client; if(sinceLastMs >= intervalMs) return heap_emit_t::broadcast; diff --git a/src/Utils.h b/src/Utils.h index e72e3c0..e182535 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -74,6 +74,9 @@ struct RssiBroadcast { // connected it has to be at least minGain dBm stronger than the current AP so // a small swing doesn't make the device hop between APs. bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain); +// A short name for a wifi_auth_mode_t value, for the logs. The values up to +// WAPI are the same in ESP-IDF 4.4 and 5.x. +const char *wifiAuthModeName(uint8_t authMode); // Who gets a memStatus event. enum class heap_emit_t : uint8_t { none, client, broadcast, room }; // num is the socket client asked for, 255 for everyone. A broadcast goes out diff --git a/test/test_utils/test_utils.cpp b/test/test_utils/test_utils.cpp index 8d21b54..f3c2c2c 100644 --- a/test/test_utils/test_utils.cpp +++ b/test/test_utils/test_utils.cpp @@ -257,6 +257,21 @@ static void test_worthRoaming_any_ap_while_disconnected() { TEST_ASSERT_TRUE(worthRoaming(false, 0, -90, 6)); } +/********************************************************************* + * wifiAuthModeName + ********************************************************************/ +static void test_wifiAuthModeName_matches_the_idf_enum() { + TEST_ASSERT_EQUAL_STRING("OPEN", wifiAuthModeName(0)); + TEST_ASSERT_EQUAL_STRING("WPA2", wifiAuthModeName(3)); + TEST_ASSERT_EQUAL_STRING("WPA3", wifiAuthModeName(6)); + TEST_ASSERT_EQUAL_STRING("WPA2/WPA3", wifiAuthModeName(7)); + TEST_ASSERT_EQUAL_STRING("WAPI", wifiAuthModeName(8)); +} +static void test_wifiAuthModeName_unknown_past_the_shared_values() { + TEST_ASSERT_EQUAL_STRING("UNKNOWN", wifiAuthModeName(9)); + TEST_ASSERT_EQUAL_STRING("UNKNOWN", wifiAuthModeName(255)); +} + /********************************************************************* * heapEmitTarget ********************************************************************/ @@ -369,6 +384,8 @@ int main(int argc, char **argv) { RUN_TEST(test_worthRoaming_needs_the_full_gain); RUN_TEST(test_worthRoaming_never_to_a_weaker_ap); RUN_TEST(test_worthRoaming_any_ap_while_disconnected); + RUN_TEST(test_wifiAuthModeName_matches_the_idf_enum); + RUN_TEST(test_wifiAuthModeName_unknown_past_the_shared_values); RUN_TEST(test_heapEmitTarget_one_client_always_gets_it); RUN_TEST(test_heapEmitTarget_broadcasts_once_per_interval); RUN_TEST(test_heapEmitTarget_room_in_between);