From 4c396314286bc459ceb780891698488fb7dbfda2 Mon Sep 17 00:00:00 2001 From: Bella Coola <31868524+BellaCoola@users.noreply.github.com> Date: Thu, 20 Apr 2023 03:53:42 +0000 Subject: [PATCH] Add support for passive WiFi scanning (#4666) * Add support for passive WiFi scanning. * Apply suggestions from code review Made changes suggested by @jesserockz Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --------- Co-authored-by: BellaCoola Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/wifi/__init__.py | 3 +++ esphome/components/wifi/wifi_component.cpp | 4 +++- esphome/components/wifi/wifi_component.h | 5 ++++- .../wifi/wifi_component_esp32_arduino.cpp | 4 ++-- .../wifi/wifi_component_esp8266.cpp | 20 +++++++++++++------ .../wifi/wifi_component_esp_idf.cpp | 12 +++++++---- .../components/wifi/wifi_component_pico_w.cpp | 3 ++- 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index f5684f06f7..c9da07795c 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -252,6 +252,7 @@ def _validate(config): CONF_OUTPUT_POWER = "output_power" +CONF_PASSIVE_SCAN = "passive_scan" CONFIG_SCHEMA = cv.All( cv.Schema( { @@ -280,6 +281,7 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ENABLE_RRM, esp32_idf=False): cv.All( cv.boolean, cv.only_with_esp_idf ), + cv.Optional(CONF_PASSIVE_SCAN, default=False): cv.boolean, cv.Optional("enable_mdns"): cv.invalid( "This option has been removed. Please use the [disabled] option under the " "new mdns component instead." @@ -379,6 +381,7 @@ async def to_code(config): cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) cg.add(var.set_power_save_mode(config[CONF_POWER_SAVE_MODE])) cg.add(var.set_fast_connect(config[CONF_FAST_CONNECT])) + cg.add(var.set_passive_scan(config[CONF_PASSIVE_SCAN])) if CONF_OUTPUT_POWER in config: cg.add(var.set_output_power(config[CONF_OUTPUT_POWER])) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index efb1af171d..9f047dd5ed 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -385,7 +385,7 @@ void WiFiComponent::print_connect_params_() { void WiFiComponent::start_scanning() { this->action_started_ = millis(); ESP_LOGD(TAG, "Starting scan..."); - this->wifi_scan_start_(); + this->wifi_scan_start_(this->passive_scan_); this->state_ = WIFI_COMPONENT_STATE_STA_SCANNING; } @@ -615,6 +615,8 @@ bool WiFiComponent::is_connected() { } void WiFiComponent::set_power_save_mode(WiFiPowerSaveMode power_save) { this->power_save_ = power_save; } +void WiFiComponent::set_passive_scan(bool passive) { this->passive_scan_ = passive; } + std::string WiFiComponent::format_mac_addr(const uint8_t *mac) { char buf[20]; sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 544cb3dc61..3f81b94cce 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -217,6 +217,8 @@ class WiFiComponent : public Component { void set_power_save_mode(WiFiPowerSaveMode power_save); void set_output_power(float output_power) { output_power_ = output_power; } + void set_passive_scan(bool passive); + void save_wifi_sta(const std::string &ssid, const std::string &password); // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) @@ -294,7 +296,7 @@ class WiFiComponent : public Component { bool wifi_sta_connect_(const WiFiAP &ap); void wifi_pre_setup_(); WiFiSTAConnectStatus wifi_sta_connect_status_(); - bool wifi_scan_start_(); + bool wifi_scan_start_(bool passive); bool wifi_ap_ip_config_(optional manual_ip); bool wifi_start_ap_(const WiFiAP &ap); bool wifi_disconnect_(); @@ -349,6 +351,7 @@ class WiFiComponent : public Component { bool scan_done_{false}; bool ap_setup_{false}; optional output_power_; + bool passive_scan_{false}; ESPPreferenceObject pref_; bool has_saved_wifi_settings_{false}; #ifdef USE_WIFI_11KV_SUPPORT diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index ab04224161..f35f5dfc43 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -618,13 +618,13 @@ WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { } return WiFiSTAConnectStatus::IDLE; } -bool WiFiComponent::wifi_scan_start_() { +bool WiFiComponent::wifi_scan_start_(bool passive) { // enable STA if (!this->wifi_mode_(true, {})) return false; // need to use WiFi because of WiFiScanClass allocations :( - int16_t err = WiFi.scanNetworks(true, true, false, 200); + int16_t err = WiFi.scanNetworks(true, true, passive, 200); if (err != WIFI_SCAN_RUNNING) { ESP_LOGV(TAG, "WiFi.scanNetworks failed! %d", err); return false; diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index de4253fe41..8b38297b17 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -601,7 +601,7 @@ WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { return WiFiSTAConnectStatus::IDLE; } } -bool WiFiComponent::wifi_scan_start_() { +bool WiFiComponent::wifi_scan_start_(bool passive) { static bool first_scan = false; // enable STA @@ -615,13 +615,21 @@ bool WiFiComponent::wifi_scan_start_() { config.channel = 0; config.show_hidden = 1; #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 4, 0) - config.scan_type = WIFI_SCAN_TYPE_ACTIVE; + config.scan_type = passive ? WIFI_SCAN_TYPE_PASSIVE : WIFI_SCAN_TYPE_ACTIVE; if (first_scan) { - config.scan_time.active.min = 100; - config.scan_time.active.max = 200; + if (passive) { + config.scan_time.passive = 200; + } else { + config.scan_time.active.min = 100; + config.scan_time.active.max = 200; + } } else { - config.scan_time.active.min = 400; - config.scan_time.active.max = 500; + if (passive) { + config.scan_time.passive = 500; + } else { + config.scan_time.active.min = 400; + config.scan_time.active.max = 500; + } } #endif first_scan = false; diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 1edde74743..9b2fdaf500 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -736,7 +736,7 @@ WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { } return WiFiSTAConnectStatus::IDLE; } -bool WiFiComponent::wifi_scan_start_() { +bool WiFiComponent::wifi_scan_start_(bool passive) { // enable STA if (!this->wifi_mode_(true, {})) return false; @@ -746,9 +746,13 @@ bool WiFiComponent::wifi_scan_start_() { config.bssid = nullptr; config.channel = 0; config.show_hidden = true; - config.scan_type = WIFI_SCAN_TYPE_ACTIVE; - config.scan_time.active.min = 100; - config.scan_time.active.max = 300; + config.scan_type = passive ? WIFI_SCAN_TYPE_PASSIVE : WIFI_SCAN_TYPE_ACTIVE; + if (passive) { + config.scan_time.passive = 300; + } else { + config.scan_time.active.min = 100; + config.scan_time.active.max = 300; + } esp_err_t err = esp_wifi_scan_start(&config, false); if (err != ESP_OK) { diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 8e64878f8e..489ebc3699 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -125,10 +125,11 @@ void WiFiComponent::wifi_scan_result(void *env, const cyw43_ev_scan_result_t *re } } -bool WiFiComponent::wifi_scan_start_() { +bool WiFiComponent::wifi_scan_start_(bool passive) { this->scan_result_.clear(); this->scan_done_ = false; cyw43_wifi_scan_options_t scan_options = {0}; + scan_options.scan_type = passive ? 1 : 0; int err = cyw43_wifi_scan(&cyw43_state, &scan_options, nullptr, &s_wifi_scan_result); if (err) { ESP_LOGV(TAG, "cyw43_wifi_scan failed!");