From 1876c21e3e9a2c9c6c9121dc072ac71034eeaefc Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 3 Jul 2019 20:42:46 +0200 Subject: [PATCH] WiFi networks priority (#658) * WiFi networks priority Fixes https://github.com/esphome/feature-requests/issues/136 * Print priority --- esphome/components/wifi/__init__.py | 5 ++- esphome/components/wifi/wifi_component.cpp | 20 ++++++++++++ esphome/components/wifi/wifi_component.h | 36 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 545f6a7de7..4f9764f320 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -5,7 +5,7 @@ from esphome.automation import Condition from esphome.const import CONF_AP, CONF_BSSID, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_DOMAIN, \ CONF_FAST_CONNECT, CONF_GATEWAY, CONF_HIDDEN, CONF_ID, CONF_MANUAL_IP, CONF_NETWORKS, \ CONF_PASSWORD, CONF_POWER_SAVE_MODE, CONF_REBOOT_TIMEOUT, CONF_SSID, CONF_STATIC_IP, \ - CONF_SUBNET, CONF_USE_ADDRESS + CONF_SUBNET, CONF_USE_ADDRESS, CONF_PRIORITY from esphome.core import CORE, HexInt, coroutine_with_priority AUTO_LOAD = ['network'] @@ -72,6 +72,7 @@ WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend({ WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend({ cv.Optional(CONF_BSSID): cv.mac_address, cv.Optional(CONF_HIDDEN): cv.boolean, + cv.Optional(CONF_PRIORITY, default=0.0): cv.float_, }) @@ -161,6 +162,8 @@ def wifi_network(config, static_ip): cg.add(ap.set_channel(config[CONF_CHANNEL])) if static_ip is not None: cg.add(ap.set_manual_ip(manual_ip(static_ip))) + if CONF_PRIORITY in config: + cg.add(ap.set_priority(config[CONF_PRIORITY])) return ap diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 7af6176402..1f705e507f 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -273,6 +273,9 @@ void WiFiComponent::print_connect_params_() { int8_t rssi = WiFi.RSSI(); print_signal_bars(rssi, signal_bars); ESP_LOGCONFIG(TAG, " Signal strength: %d dB %s", rssi, signal_bars); + if (this->selected_ap_.get_bssid().has_value()) { + ESP_LOGV(TAG, " Priority: %.1f", this->get_sta_priority(*this->selected_ap_.get_bssid())); + } ESP_LOGCONFIG(TAG, " Channel: %d", WiFi.channel()); ESP_LOGCONFIG(TAG, " Subnet: %s", WiFi.subnetMask().toString().c_str()); ESP_LOGCONFIG(TAG, " Gateway: %s", WiFi.gatewayIP().toString().c_str()); @@ -308,6 +311,10 @@ void WiFiComponent::check_scanning_finished() { for (auto &ap : this->sta_) { if (res.matches(ap)) { res.set_matches(true); + if (!this->has_sta_priority(res.get_bssid())) { + this->set_sta_priority(res.get_bssid(), ap.get_priority()); + } + res.set_priority(this->get_sta_priority(res.get_bssid())); break; } } @@ -315,11 +322,18 @@ void WiFiComponent::check_scanning_finished() { std::stable_sort(this->scan_result_.begin(), this->scan_result_.end(), [](const WiFiScanResult &a, const WiFiScanResult &b) { + // return true if a is better than b if (a.get_matches() && !b.get_matches()) return true; if (!a.get_matches() && b.get_matches()) return false; + if (a.get_matches() && b.get_matches()) { + // if both match, check priority + if (a.get_priority() != b.get_priority()) + return a.get_priority() > b.get_priority(); + } + return a.get_rssi() > b.get_rssi(); }); @@ -443,6 +457,12 @@ void WiFiComponent::check_connecting_finished() { } void WiFiComponent::retry_connect() { + if (this->selected_ap_.get_bssid()) { + auto bssid = *this->selected_ap_.get_bssid(); + float priority = this->get_sta_priority(bssid); + this->set_sta_priority(bssid, priority - 1.0f); + } + delay(10); if (!this->is_captive_portal_active_() && (this->num_retried_ > 5 || this->error_from_callback_)) { // If retry failed for more than 5 times, let's restart STA diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index cbdde7245f..04866ef8e2 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -66,12 +66,14 @@ class WiFiAP { void set_bssid(optional bssid); void set_password(const std::string &password); void set_channel(optional channel); + void set_priority(float priority) { priority_ = priority; } void set_manual_ip(optional manual_ip); void set_hidden(bool hidden); const std::string &get_ssid() const; const optional &get_bssid() const; const std::string &get_password() const; const optional &get_channel() const; + float get_priority() const { return priority_; } const optional &get_manual_ip() const; bool get_hidden() const; @@ -80,6 +82,7 @@ class WiFiAP { optional bssid_; std::string password_; optional channel_; + float priority_{0}; optional manual_ip_; bool hidden_{false}; }; @@ -99,6 +102,8 @@ class WiFiScanResult { int8_t get_rssi() const; bool get_with_auth() const; bool get_is_hidden() const; + float get_priority() const { return priority_; } + void set_priority(float priority) { priority_ = priority; } protected: bool matches_{false}; @@ -108,6 +113,12 @@ class WiFiScanResult { int8_t rssi_; bool with_auth_; bool is_hidden_; + float priority_{0.0f}; +}; + +struct WiFiSTAPriority { + bssid_t bssid; + float priority; }; enum WiFiPowerSaveMode { @@ -175,6 +186,30 @@ class WiFiComponent : public Component { IPAddress wifi_soft_ap_ip(); + bool has_sta_priority(const bssid_t &bssid) { + for (auto &it : this->sta_priorities_) + if (it.bssid == bssid) + return true; + return false; + } + float get_sta_priority(const bssid_t bssid) { + for (auto &it : this->sta_priorities_) + if (it.bssid == bssid) + return it.priority; + return 0.0f; + } + void set_sta_priority(const bssid_t bssid, float priority) { + for (auto &it : this->sta_priorities_) + if (it.bssid == bssid) { + it.priority = priority; + return; + } + this->sta_priorities_.push_back(WiFiSTAPriority{ + .bssid = bssid, + .priority = priority, + }); + } + protected: static std::string format_mac_addr(const uint8_t mac[6]); void setup_ap_config_(); @@ -209,6 +244,7 @@ class WiFiComponent : public Component { std::string use_address_; std::vector sta_; + std::vector sta_priorities_; WiFiAP selected_ap_; bool fast_connect_{false};