From fad05d5a2e681bd6c2c51da827b9496e45c948ee Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Tue, 12 Nov 2019 17:39:27 +0100 Subject: [PATCH] Add wifi output_power setting (#853) * Add wifi output_power setting See also: - https://github.com/esphome/feature-requests/issues/471#issuecomment-552350467 - https://github.com/esp8266/Arduino/issues/6366 - https://github.com/esp8266/Arduino/issues/6471 - https://github.com/xoseperez/espurna/blob/849f8cf920096fa4b804e70913dab0917ee18ad9/code/espurna/config/general.h#L593-L599 - https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/network/esp_wifi.html#_CPPv425esp_wifi_set_max_tx_power6int8_t * Lint --- esphome/components/wifi/__init__.py | 4 ++++ esphome/components/wifi/wifi_component.cpp | 6 ++++++ esphome/components/wifi/wifi_component.h | 3 +++ esphome/components/wifi/wifi_component_esp32.cpp | 4 ++++ esphome/components/wifi/wifi_component_esp8266.cpp | 5 +++++ esphome/config_validation.py | 1 + 6 files changed, 23 insertions(+) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 818d3c84e0..818fb70105 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -110,6 +110,7 @@ def validate(config): return config +CONF_OUTPUT_POWER = 'output_power' CONFIG_SCHEMA = cv.All(cv.Schema({ cv.GenerateID(): cv.declare_id(WiFiComponent), cv.Optional(CONF_NETWORKS): cv.ensure_list(WIFI_NETWORK_STA), @@ -125,6 +126,7 @@ CONFIG_SCHEMA = cv.All(cv.Schema({ cv.enum(WIFI_POWER_SAVE_MODES, upper=True), cv.Optional(CONF_FAST_CONNECT, default=False): cv.boolean, cv.Optional(CONF_USE_ADDRESS): cv.string_strict, + cv.Optional(CONF_OUTPUT_POWER): cv.All(cv.decibel, cv.float_range(min=10.0, max=20.5)), cv.Optional('hostname'): cv.invalid("The hostname option has been removed in 1.11.0"), }), validate) @@ -186,6 +188,8 @@ 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])) + if CONF_OUTPUT_POWER in config: + cg.add(var.set_output_power(config[CONF_OUTPUT_POWER])) if CORE.is_esp8266: cg.add_library('ESP8266WiFi', None) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index cb664d3cc3..60b7fb8945 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -36,6 +36,9 @@ void WiFiComponent::setup() { if (this->has_sta()) { this->wifi_sta_pre_setup_(); + if (this->output_power_.has_value() && !this->wifi_apply_output_power_(*this->output_power_)) { + ESP_LOGV(TAG, "Setting Power Save Option failed!"); + } if (!this->wifi_apply_power_save_()) { ESP_LOGV(TAG, "Setting Power Save Option failed!"); @@ -49,6 +52,9 @@ void WiFiComponent::setup() { } } else if (this->has_ap()) { this->setup_ap_config_(); + if (this->output_power_.has_value() && !this->wifi_apply_output_power_(*this->output_power_)) { + ESP_LOGV(TAG, "Setting Power Save Option failed!"); + } #ifdef USE_CAPTIVE_PORTAL if (captive_portal::global_captive_portal != nullptr) captive_portal::global_captive_portal->start(); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 04866ef8e2..d04e1c2ce0 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -162,6 +162,7 @@ class WiFiComponent : public Component { bool is_connected(); void set_power_save_mode(WiFiPowerSaveMode power_save); + void set_output_power(float output_power) { output_power_ = output_power; } // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) @@ -217,6 +218,7 @@ class WiFiComponent : public Component { bool wifi_mode_(optional sta, optional ap); bool wifi_sta_pre_setup_(); + bool wifi_apply_output_power_(float output_power); bool wifi_apply_power_save_(); bool wifi_sta_ip_config_(optional manual_ip); IPAddress wifi_sta_ip_(); @@ -260,6 +262,7 @@ class WiFiComponent : public Component { std::vector scan_result_; bool scan_done_{false}; bool ap_setup_{false}; + optional output_power_; }; extern WiFiComponent *global_wifi_component; diff --git a/esphome/components/wifi/wifi_component_esp32.cpp b/esphome/components/wifi/wifi_component_esp32.cpp index 353a51040a..7fc459d858 100644 --- a/esphome/components/wifi/wifi_component_esp32.cpp +++ b/esphome/components/wifi/wifi_component_esp32.cpp @@ -53,6 +53,10 @@ bool WiFiComponent::wifi_mode_(optional sta, optional ap) { return ret; } +bool WiFiComponent::wifi_apply_output_power_(float output_power) { + int8_t val = static_cast(output_power * 4); + return esp_wifi_set_max_tx_power(val) == ESP_OK; +} bool WiFiComponent::wifi_sta_pre_setup_() { if (!this->wifi_mode_(true, {})) return false; diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index ff0dd57ed4..ee67fd36df 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -390,6 +390,11 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { WiFiMockClass::_event_callback(event); } +bool WiFiComponent::wifi_apply_output_power_(float output_power) { + uint8_t val = static_cast(output_power * 4); + system_phy_set_max_tpw(val); + return true; +} bool WiFiComponent::wifi_sta_pre_setup_() { if (!this->wifi_mode_(true, {})) return false; diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 956779f655..5c7255a874 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -616,6 +616,7 @@ angle = float_with_unit("angle", u"(°|deg)", optional_unit=True) _temperature_c = float_with_unit("temperature", u"(°C|° C|°|C)?") _temperature_k = float_with_unit("temperature", u"(° K|° K|K)?") _temperature_f = float_with_unit("temperature", u"(°F|° F|F)?") +decibel = float_with_unit("decibel", u"(dB|dBm|db|dbm)", optional_unit=True) if IS_PY2: # Override voluptuous invalid to unicode for py2