From bfca3f242a4bc5535899f23074bfd0e8770d22aa Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Tue, 22 Jun 2021 10:53:10 +0200 Subject: [PATCH] Disallow power_save_mode NONE if used together with BLE (#1950) --- esphome/components/http_request/__init__.py | 19 ++++------- esphome/components/wifi/__init__.py | 36 ++++++++++++++++++++- esphome/final_validate.py | 24 ++++++++++++++ tests/test1.yaml | 2 +- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index f4475060df..7dffdae27f 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -7,10 +7,7 @@ from esphome import automation from esphome.const import ( CONF_ID, CONF_TIMEOUT, - CONF_ESPHOME, CONF_METHOD, - CONF_ARDUINO_VERSION, - ARDUINO_VERSION_ESP8266, CONF_TRIGGER_ID, CONF_URL, ) @@ -78,23 +75,19 @@ CONFIG_SCHEMA = cv.Schema( ).extend(cv.COMPONENT_SCHEMA) -def validate_framework(config): - if CORE.is_esp32: +def validate_framework(value): + if not CORE.is_esp8266: + # only for ESP8266 return - # only for ESP8266 - path = [CONF_ESPHOME, CONF_ARDUINO_VERSION] - version: str = fv.full_config.get().get_config_for_path(path) - - reverse_map = {v: k for k, v in ARDUINO_VERSION_ESP8266.items()} - framework_version = reverse_map.get(version) + framework_version = fv.get_arduino_framework_version() if framework_version is None or framework_version == "dev": return if framework_version < "2.5.1": raise cv.Invalid( - "This component is not supported on arduino framework version below 2.5.1", - path=[cv.ROOT_CONFIG_PATH] + path, + "This component is not supported on arduino framework version below 2.5.1, ", + "please check esphome->arduino_version", ) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 54307388d6..7a1a01bcc4 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -148,7 +148,41 @@ def final_validate(config): ) -FINAL_VALIDATE_SCHEMA = cv.Schema(final_validate) +def final_validate_power_esp32_ble(value): + if not CORE.is_esp32: + return + if value != "NONE": + # WiFi should be in modem sleep (!=NONE) with BLE coexistence + # https://docs.espressif.com/projects/esp-idf/en/v3.3.5/api-guides/wifi.html#station-sleep + return + framework_version = fv.get_arduino_framework_version() + if framework_version not in (None, "dev") and framework_version < "1.0.5": + # Only frameworks 1.0.5+ impacted + return + full = fv.full_config.get() + for conflicting in [ + "esp32_ble", + "esp32_ble_beacon", + "esp32_ble_server", + "esp32_ble_tracker", + ]: + if conflicting in full: + raise cv.Invalid( + f"power_save_mode NONE is incompatible with {conflicting}. " + f"Please remove the power save mode. See also " + f"https://github.com/esphome/issues/issues/2141#issuecomment-865688582" + ) + + +FINAL_VALIDATE_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_POWER_SAVE_MODE): final_validate_power_esp32_ble, + }, + extra=cv.ALLOW_EXTRA, + ), + final_validate, +) def _validate(config): diff --git a/esphome/final_validate.py b/esphome/final_validate.py index 50fdbaf3f4..47071b5391 100644 --- a/esphome/final_validate.py +++ b/esphome/final_validate.py @@ -4,6 +4,13 @@ import contextvars from esphome.types import ConfigFragmentType, ID, ConfigPathType import esphome.config_validation as cv +from esphome.const import ( + ARDUINO_VERSION_ESP32, + ARDUINO_VERSION_ESP8266, + CONF_ESPHOME, + CONF_ARDUINO_VERSION, +) +from esphome.core import CORE class FinalValidateConfig(ABC): @@ -55,3 +62,20 @@ def id_declaration_match_schema(schema): return schema(declaration_config) return validator + + +def get_arduino_framework_version(): + path = [CONF_ESPHOME, CONF_ARDUINO_VERSION] + # This is run after core validation, so the property is set even if user didn't + version: str = full_config.get().get_config_for_path(path) + + if CORE.is_esp32: + version_map = ARDUINO_VERSION_ESP32 + elif CORE.is_esp8266: + version_map = ARDUINO_VERSION_ESP8266 + else: + raise ValueError("Platform not supported yet for this validator") + + reverse_map = {v: k for k, v in version_map.items()} + framework_version = reverse_map.get(version) + return framework_version diff --git a/tests/test1.yaml b/tests/test1.yaml index 29df5857d3..08e1d63534 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -80,7 +80,7 @@ wifi: dns2: 1.2.2.1 domain: .local reboot_timeout: 120s - power_save_mode: none + power_save_mode: light http_request: useragent: esphome/device