mirror of
https://github.com/esphome/esphome.git
synced 2025-09-06 13:22:19 +01:00
ESP-IDF support and generic target platforms (#2303)
* Socket refactor and SSL * esp-idf temp * Fixes * Echo component and noise * Add noise API transport support * Updates * ESP-IDF * Complete * Fixes * Fixes * Versions update * New i2c APIs * Complete i2c refactor * SPI migration * Revert ESP Preferences migration, too complex for now * OTA support * Remove echo again * Remove ssl again * GPIOFlags updates * Rename esphal and ICACHE_RAM_ATTR * Make ESP32 arduino compilable again * Fix GPIO flags * Complete pin registry refactor and fixes * Fixes to make test1 compile * Remove sdkconfig file * Ignore sdkconfig file * Fixes in reviewing * Make test2 compile * Make test4 compile * Make test5 compile * Run clang-format * Fix lint errors * Use esp-idf APIs instead of btStart * Another round of fixes * Start implementing ESP8266 * Make test3 compile * Guard esp8266 code * Lint * Reformat * Fixes * Fixes v2 * more fixes * ESP-IDF tidy target * Convert ARDUINO_ARCH_ESPxx * Update WiFiSignalSensor * Update time ifdefs * OTA needs millis from hal * RestartSwitch needs delay from hal * ESP-IDF Uart * Fix OTA blank password * Allow setting sdkconfig * Fix idf partitions and allow setting sdkconfig from yaml * Re-add read/write compat APIs and fix esp8266 uart * Fix esp8266 store log strings in flash * Fix ESP32 arduino preferences not initialized * Update ifdefs * Change how sdkconfig change is detected * Add checks to ci-custom and fix them * Run clang-format * Add esp-idf clang-tidy target and fix errors * Fixes from clang-tidy idf round 2 * Fixes from compiling tests with esp-idf * Run clang-format * Switch test5.yaml to esp-idf * Implement ESP8266 Preferences * Lint * Re-do PIO package version selection a bit * Fix arduinoespressif32 package version * Fix unit tests * Lint * Lint fixes * Fix readv/writev not defined * Fix graphing component * Re-add all old options from core/config.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""Helpers for config validation using voluptuous."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
@@ -33,6 +34,9 @@ from esphome.const import (
|
||||
CONF_UPDATE_INTERVAL,
|
||||
CONF_TYPE_ID,
|
||||
CONF_TYPE,
|
||||
KEY_CORE,
|
||||
KEY_FRAMEWORK_VERSION,
|
||||
KEY_TARGET_FRAMEWORK,
|
||||
)
|
||||
from esphome.core import (
|
||||
CORE,
|
||||
@@ -492,20 +496,37 @@ def templatable(other_validators):
|
||||
|
||||
|
||||
def only_on(platforms):
|
||||
"""Validate that this option can only be specified on the given ESP platforms."""
|
||||
"""Validate that this option can only be specified on the given target platforms."""
|
||||
if not isinstance(platforms, list):
|
||||
platforms = [platforms]
|
||||
|
||||
def validator_(obj):
|
||||
if CORE.esp_platform not in platforms:
|
||||
if CORE.target_platform not in platforms:
|
||||
raise Invalid(f"This feature is only available on {platforms}")
|
||||
return obj
|
||||
|
||||
return validator_
|
||||
|
||||
|
||||
only_on_esp32 = only_on("ESP32")
|
||||
only_on_esp8266 = only_on("ESP8266")
|
||||
def only_with_framework(frameworks):
|
||||
"""Validate that this option can only be specified on the given frameworks."""
|
||||
if not isinstance(frameworks, list):
|
||||
frameworks = [frameworks]
|
||||
|
||||
def validator_(obj):
|
||||
if CORE.target_framework not in frameworks:
|
||||
raise Invalid(
|
||||
f"This feature is only available with frameworks {frameworks}"
|
||||
)
|
||||
return obj
|
||||
|
||||
return validator_
|
||||
|
||||
|
||||
only_on_esp32 = only_on("esp32")
|
||||
only_on_esp8266 = only_on("esp8266")
|
||||
only_with_arduino = only_with_framework("arduino")
|
||||
only_with_esp_idf = only_with_framework("esp-idf")
|
||||
|
||||
|
||||
# Adapted from:
|
||||
@@ -1025,7 +1046,7 @@ def requires_component(comp):
|
||||
# pylint: disable=unsupported-membership-test
|
||||
def validator(value):
|
||||
# pylint: disable=unsupported-membership-test
|
||||
if comp not in CORE.raw_config:
|
||||
if comp not in CORE.loaded_integrations:
|
||||
raise Invalid(f"This option requires component {comp}")
|
||||
return value
|
||||
|
||||
@@ -1401,18 +1422,32 @@ class GenerateID(Optional):
|
||||
class SplitDefault(Optional):
|
||||
"""Mark this key to have a split default for ESP8266/ESP32."""
|
||||
|
||||
def __init__(self, key, esp8266=vol.UNDEFINED, esp32=vol.UNDEFINED):
|
||||
def __init__(
|
||||
self,
|
||||
key,
|
||||
esp8266=vol.UNDEFINED,
|
||||
esp32=vol.UNDEFINED,
|
||||
esp32_arduino=vol.UNDEFINED,
|
||||
esp32_idf=vol.UNDEFINED,
|
||||
):
|
||||
super().__init__(key)
|
||||
self._esp8266_default = vol.default_factory(esp8266)
|
||||
self._esp32_default = vol.default_factory(esp32)
|
||||
self._esp32_arduino_default = vol.default_factory(
|
||||
esp32_arduino if esp32 is vol.UNDEFINED else esp32
|
||||
)
|
||||
self._esp32_idf_default = vol.default_factory(
|
||||
esp32_idf if esp32 is vol.UNDEFINED else esp32
|
||||
)
|
||||
|
||||
@property
|
||||
def default(self):
|
||||
if CORE.is_esp8266:
|
||||
return self._esp8266_default
|
||||
if CORE.is_esp32:
|
||||
return self._esp32_default
|
||||
raise ValueError
|
||||
if CORE.is_esp32 and CORE.using_arduino:
|
||||
return self._esp32_arduino_default
|
||||
if CORE.is_esp32 and CORE.using_esp_idf:
|
||||
return self._esp32_idf_default
|
||||
raise NotImplementedError
|
||||
|
||||
@default.setter
|
||||
def default(self, value):
|
||||
@@ -1431,7 +1466,7 @@ class OnlyWith(Optional):
|
||||
@property
|
||||
def default(self):
|
||||
# pylint: disable=unsupported-membership-test
|
||||
if self._component in CORE.raw_config:
|
||||
if self._component in CORE.loaded_integrations:
|
||||
return self._default
|
||||
return vol.UNDEFINED
|
||||
|
||||
@@ -1613,3 +1648,73 @@ def source_refresh(value: str):
|
||||
if value.lower() == "never":
|
||||
return source_refresh("1000y")
|
||||
return positive_time_period_seconds(value)
|
||||
|
||||
|
||||
@dataclass(frozen=True, order=True)
|
||||
class Version:
|
||||
major: int
|
||||
minor: int
|
||||
patch: int
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.major}.{self.minor}.{self.patch}"
|
||||
|
||||
@classmethod
|
||||
def parse(cls, value: str) -> "Version":
|
||||
match = re.match(r"(\d+).(\d+).(\d+)", value)
|
||||
if match is None:
|
||||
raise ValueError(f"Not a valid version number {value}")
|
||||
major = int(match[1])
|
||||
minor = int(match[2])
|
||||
patch = int(match[3])
|
||||
return Version(major=major, minor=minor, patch=patch)
|
||||
|
||||
|
||||
def version_number(value):
|
||||
value = string_strict(value)
|
||||
try:
|
||||
return str(Version.parse(value))
|
||||
except ValueError as e:
|
||||
raise Invalid("Not a version number") from e
|
||||
|
||||
|
||||
def require_framework_version(
|
||||
*,
|
||||
esp_idf=None,
|
||||
esp32_arduino=None,
|
||||
esp8266_arduino=None,
|
||||
):
|
||||
def validator(value):
|
||||
core_data = CORE.data[KEY_CORE]
|
||||
framework = core_data[KEY_TARGET_FRAMEWORK]
|
||||
if framework == "esp-idf":
|
||||
if esp_idf is None:
|
||||
raise Invalid("This feature is incompatible with esp-idf")
|
||||
required = esp_idf
|
||||
elif CORE.is_esp32 and framework == "arduino":
|
||||
if esp32_arduino is None:
|
||||
raise Invalid(
|
||||
"This feature is incompatible with ESP32 using arduino framework"
|
||||
)
|
||||
required = esp32_arduino
|
||||
elif CORE.is_esp8266 and framework == "arduino":
|
||||
if esp8266_arduino is None:
|
||||
raise Invalid("This feature is incompatible with ESP8266")
|
||||
required = esp8266_arduino
|
||||
else:
|
||||
raise NotImplementedError
|
||||
if core_data[KEY_FRAMEWORK_VERSION] < required:
|
||||
raise Invalid(
|
||||
f"This feature requires at least framework version {required}"
|
||||
)
|
||||
return value
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
@contextmanager
|
||||
def suppress_invalid():
|
||||
try:
|
||||
yield
|
||||
except vol.Invalid:
|
||||
pass
|
||||
|
Reference in New Issue
Block a user