mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 09:17:46 +01:00
Initial stab at importing idf components (#4000)
* Initial stab at importing idf components * Handle repo with multiple components Allow components directly from yaml * Actually use the refresh config var * Update esphome/components/esp32/__init__.py
This commit is contained in:
parent
f98d93efa8
commit
23f47d0ad2
5 changed files with 163 additions and 68 deletions
|
@ -4,29 +4,43 @@ from pathlib import Path
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from esphome.helpers import copy_file_if_changed, write_file_if_changed
|
from esphome.helpers import copy_file_if_changed, write_file_if_changed, mkdir_p
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_BOARD,
|
CONF_BOARD,
|
||||||
|
CONF_COMPONENTS,
|
||||||
CONF_FRAMEWORK,
|
CONF_FRAMEWORK,
|
||||||
|
CONF_NAME,
|
||||||
CONF_SOURCE,
|
CONF_SOURCE,
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
CONF_VARIANT,
|
CONF_VARIANT,
|
||||||
CONF_VERSION,
|
CONF_VERSION,
|
||||||
CONF_ADVANCED,
|
CONF_ADVANCED,
|
||||||
|
CONF_REFRESH,
|
||||||
|
CONF_PATH,
|
||||||
|
CONF_URL,
|
||||||
|
CONF_REF,
|
||||||
CONF_IGNORE_EFUSE_MAC_CRC,
|
CONF_IGNORE_EFUSE_MAC_CRC,
|
||||||
KEY_CORE,
|
KEY_CORE,
|
||||||
KEY_FRAMEWORK_VERSION,
|
KEY_FRAMEWORK_VERSION,
|
||||||
KEY_TARGET_FRAMEWORK,
|
KEY_TARGET_FRAMEWORK,
|
||||||
KEY_TARGET_PLATFORM,
|
KEY_TARGET_PLATFORM,
|
||||||
|
TYPE_GIT,
|
||||||
|
TYPE_LOCAL,
|
||||||
__version__,
|
__version__,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, HexInt
|
from esphome.core import CORE, HexInt, TimePeriod
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
from esphome import git
|
||||||
|
|
||||||
from .const import ( # noqa
|
from .const import ( # noqa
|
||||||
KEY_BOARD,
|
KEY_BOARD,
|
||||||
|
KEY_COMPONENTS,
|
||||||
KEY_ESP32,
|
KEY_ESP32,
|
||||||
|
KEY_PATH,
|
||||||
|
KEY_REF,
|
||||||
|
KEY_REFRESH,
|
||||||
|
KEY_REPO,
|
||||||
KEY_SDKCONFIG_OPTIONS,
|
KEY_SDKCONFIG_OPTIONS,
|
||||||
KEY_VARIANT,
|
KEY_VARIANT,
|
||||||
VARIANT_ESP32C3,
|
VARIANT_ESP32C3,
|
||||||
|
@ -51,6 +65,7 @@ def set_core_data(config):
|
||||||
if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF:
|
if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF:
|
||||||
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "esp-idf"
|
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "esp-idf"
|
||||||
CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] = {}
|
CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] = {}
|
||||||
|
CORE.data[KEY_ESP32][KEY_COMPONENTS] = {}
|
||||||
elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
|
elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
|
||||||
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino"
|
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = "arduino"
|
||||||
CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse(
|
CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse(
|
||||||
|
@ -104,6 +119,21 @@ def add_idf_sdkconfig_option(name: str, value: SdkconfigValueType):
|
||||||
CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS][name] = value
|
CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS][name] = value
|
||||||
|
|
||||||
|
|
||||||
|
def add_idf_component(
|
||||||
|
name: str, repo: str, ref: str = None, path: str = None, refresh: TimePeriod = None
|
||||||
|
):
|
||||||
|
"""Add an esp-idf component to the project."""
|
||||||
|
if not CORE.using_esp_idf:
|
||||||
|
raise ValueError("Not an esp-idf project")
|
||||||
|
if name not in CORE.data[KEY_ESP32][KEY_COMPONENTS]:
|
||||||
|
CORE.data[KEY_ESP32][KEY_COMPONENTS][name] = {
|
||||||
|
KEY_REPO: repo,
|
||||||
|
KEY_REF: ref,
|
||||||
|
KEY_PATH: path,
|
||||||
|
KEY_REFRESH: refresh,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _format_framework_arduino_version(ver: cv.Version) -> str:
|
def _format_framework_arduino_version(ver: cv.Version) -> str:
|
||||||
# format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to
|
# format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to
|
||||||
# a PIO platformio/framework-arduinoespressif32 value
|
# a PIO platformio/framework-arduinoespressif32 value
|
||||||
|
@ -270,6 +300,18 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
|
||||||
cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC, default=False): cv.boolean,
|
cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC, default=False): cv.boolean,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_NAME): cv.string_strict,
|
||||||
|
cv.Required(CONF_SOURCE): cv.SOURCE_SCHEMA,
|
||||||
|
cv.Optional(CONF_PATH): cv.string,
|
||||||
|
cv.Optional(CONF_REFRESH, default="1d"): cv.All(
|
||||||
|
cv.string, cv.source_refresh
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
_esp_idf_check_versions,
|
_esp_idf_check_versions,
|
||||||
|
@ -372,6 +414,19 @@ async def to_code(config):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for component in conf[CONF_COMPONENTS]:
|
||||||
|
source = component[CONF_SOURCE]
|
||||||
|
if source[CONF_TYPE] == TYPE_GIT:
|
||||||
|
add_idf_component(
|
||||||
|
name=component[CONF_NAME],
|
||||||
|
repo=source[CONF_URL],
|
||||||
|
ref=source.get(CONF_REF),
|
||||||
|
path=component.get(CONF_PATH),
|
||||||
|
refresh=component[CONF_REFRESH],
|
||||||
|
)
|
||||||
|
elif source[CONF_TYPE] == TYPE_LOCAL:
|
||||||
|
_LOGGER.warning("Local components are not implemented yet.")
|
||||||
|
|
||||||
elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
|
elif conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
|
||||||
cg.add_platformio_option("framework", "arduino")
|
cg.add_platformio_option("framework", "arduino")
|
||||||
cg.add_build_flag("-DUSE_ARDUINO")
|
cg.add_build_flag("-DUSE_ARDUINO")
|
||||||
|
@ -468,6 +523,33 @@ def copy_files():
|
||||||
__version__,
|
__version__,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if CORE.data[KEY_ESP32][KEY_COMPONENTS]:
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
shutil.rmtree(CORE.relative_build_path("components"), ignore_errors=True)
|
||||||
|
|
||||||
|
components: dict = CORE.data[KEY_ESP32][KEY_COMPONENTS]
|
||||||
|
|
||||||
|
for name, component in components.items():
|
||||||
|
|
||||||
|
repo_dir, _ = git.clone_or_update(
|
||||||
|
url=component[KEY_REPO],
|
||||||
|
ref=component[KEY_REF],
|
||||||
|
refresh=component[KEY_REFRESH],
|
||||||
|
domain="idf_components",
|
||||||
|
)
|
||||||
|
mkdir_p(CORE.relative_build_path("components"))
|
||||||
|
component_dir = repo_dir
|
||||||
|
if component[KEY_PATH] is not None:
|
||||||
|
component_dir = component_dir / component[KEY_PATH]
|
||||||
|
|
||||||
|
shutil.copytree(
|
||||||
|
component_dir,
|
||||||
|
CORE.relative_build_path(f"components/{name}"),
|
||||||
|
dirs_exist_ok=True,
|
||||||
|
ignore=shutil.ignore_patterns(".git", ".github"),
|
||||||
|
)
|
||||||
|
|
||||||
dir = os.path.dirname(__file__)
|
dir = os.path.dirname(__file__)
|
||||||
post_build_file = os.path.join(dir, "post_build.py.script")
|
post_build_file = os.path.join(dir, "post_build.py.script")
|
||||||
copy_file_if_changed(
|
copy_file_if_changed(
|
||||||
|
|
|
@ -4,6 +4,11 @@ KEY_ESP32 = "esp32"
|
||||||
KEY_BOARD = "board"
|
KEY_BOARD = "board"
|
||||||
KEY_VARIANT = "variant"
|
KEY_VARIANT = "variant"
|
||||||
KEY_SDKCONFIG_OPTIONS = "sdkconfig_options"
|
KEY_SDKCONFIG_OPTIONS = "sdkconfig_options"
|
||||||
|
KEY_COMPONENTS = "components"
|
||||||
|
KEY_REPO = "repo"
|
||||||
|
KEY_REF = "ref"
|
||||||
|
KEY_REFRESH = "refresh"
|
||||||
|
KEY_PATH = "path"
|
||||||
|
|
||||||
VARIANT_ESP32 = "ESP32"
|
VARIANT_ESP32 = "ESP32"
|
||||||
VARIANT_ESP32S2 = "ESP32S2"
|
VARIANT_ESP32S2 = "ESP32S2"
|
||||||
|
|
|
@ -1,90 +1,32 @@
|
||||||
import re
|
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
|
from esphome import git, loader
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_COMPONENTS,
|
CONF_COMPONENTS,
|
||||||
|
CONF_EXTERNAL_COMPONENTS,
|
||||||
|
CONF_PASSWORD,
|
||||||
|
CONF_PATH,
|
||||||
CONF_REF,
|
CONF_REF,
|
||||||
CONF_REFRESH,
|
CONF_REFRESH,
|
||||||
CONF_SOURCE,
|
CONF_SOURCE,
|
||||||
CONF_URL,
|
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
CONF_EXTERNAL_COMPONENTS,
|
CONF_URL,
|
||||||
CONF_PATH,
|
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
CONF_PASSWORD,
|
TYPE_GIT,
|
||||||
|
TYPE_LOCAL,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
from esphome import git, loader
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = CONF_EXTERNAL_COMPONENTS
|
DOMAIN = CONF_EXTERNAL_COMPONENTS
|
||||||
|
|
||||||
TYPE_GIT = "git"
|
|
||||||
TYPE_LOCAL = "local"
|
|
||||||
|
|
||||||
|
|
||||||
GIT_SCHEMA = {
|
|
||||||
cv.Required(CONF_URL): cv.url,
|
|
||||||
cv.Optional(CONF_REF): cv.git_ref,
|
|
||||||
cv.Optional(CONF_USERNAME): cv.string,
|
|
||||||
cv.Optional(CONF_PASSWORD): cv.string,
|
|
||||||
}
|
|
||||||
LOCAL_SCHEMA = {
|
|
||||||
cv.Required(CONF_PATH): cv.directory,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def validate_source_shorthand(value):
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise cv.Invalid("Shorthand only for strings")
|
|
||||||
try:
|
|
||||||
return SOURCE_SCHEMA({CONF_TYPE: TYPE_LOCAL, CONF_PATH: value})
|
|
||||||
except cv.Invalid:
|
|
||||||
pass
|
|
||||||
# Regex for GitHub repo name with optional branch/tag
|
|
||||||
# Note: git allows other branch/tag names as well, but never seen them used before
|
|
||||||
m = re.match(
|
|
||||||
r"github://(?:([a-zA-Z0-9\-]+)/([a-zA-Z0-9\-\._]+)(?:@([a-zA-Z0-9\-_.\./]+))?|pr#([0-9]+))",
|
|
||||||
value,
|
|
||||||
)
|
|
||||||
if m is None:
|
|
||||||
raise cv.Invalid(
|
|
||||||
"Source is not a file system path, in expected github://username/name[@branch-or-tag] or github://pr#1234 format!"
|
|
||||||
)
|
|
||||||
if m.group(4):
|
|
||||||
conf = {
|
|
||||||
CONF_TYPE: TYPE_GIT,
|
|
||||||
CONF_URL: "https://github.com/esphome/esphome.git",
|
|
||||||
CONF_REF: f"pull/{m.group(4)}/head",
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
conf = {
|
|
||||||
CONF_TYPE: TYPE_GIT,
|
|
||||||
CONF_URL: f"https://github.com/{m.group(1)}/{m.group(2)}.git",
|
|
||||||
}
|
|
||||||
if m.group(3):
|
|
||||||
conf[CONF_REF] = m.group(3)
|
|
||||||
|
|
||||||
return SOURCE_SCHEMA(conf)
|
|
||||||
|
|
||||||
|
|
||||||
SOURCE_SCHEMA = cv.Any(
|
|
||||||
validate_source_shorthand,
|
|
||||||
cv.typed_schema(
|
|
||||||
{
|
|
||||||
TYPE_GIT: cv.Schema(GIT_SCHEMA),
|
|
||||||
TYPE_LOCAL: cv.Schema(LOCAL_SCHEMA),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.ensure_list(
|
CONFIG_SCHEMA = cv.ensure_list(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_SOURCE): SOURCE_SCHEMA,
|
cv.Required(CONF_SOURCE): cv.SOURCE_SCHEMA,
|
||||||
cv.Optional(CONF_REFRESH, default="1d"): cv.All(cv.string, cv.source_refresh),
|
cv.Optional(CONF_REFRESH, default="1d"): cv.All(cv.string, cv.source_refresh),
|
||||||
cv.Optional(CONF_COMPONENTS, default="all"): cv.Any(
|
cv.Optional(CONF_COMPONENTS, default="all"): cv.Any(
|
||||||
"all", cv.ensure_list(cv.string)
|
"all", cv.ensure_list(cv.string)
|
||||||
|
|
|
@ -39,6 +39,11 @@ from esphome.const import (
|
||||||
CONF_UPDATE_INTERVAL,
|
CONF_UPDATE_INTERVAL,
|
||||||
CONF_TYPE_ID,
|
CONF_TYPE_ID,
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
|
CONF_REF,
|
||||||
|
CONF_URL,
|
||||||
|
CONF_PATH,
|
||||||
|
CONF_USERNAME,
|
||||||
|
CONF_PASSWORD,
|
||||||
ENTITY_CATEGORY_CONFIG,
|
ENTITY_CATEGORY_CONFIG,
|
||||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
ENTITY_CATEGORY_NONE,
|
ENTITY_CATEGORY_NONE,
|
||||||
|
@ -46,6 +51,8 @@ from esphome.const import (
|
||||||
KEY_FRAMEWORK_VERSION,
|
KEY_FRAMEWORK_VERSION,
|
||||||
KEY_TARGET_FRAMEWORK,
|
KEY_TARGET_FRAMEWORK,
|
||||||
KEY_TARGET_PLATFORM,
|
KEY_TARGET_PLATFORM,
|
||||||
|
TYPE_GIT,
|
||||||
|
TYPE_LOCAL,
|
||||||
)
|
)
|
||||||
from esphome.core import (
|
from esphome.core import (
|
||||||
CORE,
|
CORE,
|
||||||
|
@ -1820,3 +1827,59 @@ def suppress_invalid():
|
||||||
yield
|
yield
|
||||||
except vol.Invalid:
|
except vol.Invalid:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
GIT_SCHEMA = {
|
||||||
|
Required(CONF_URL): url,
|
||||||
|
Optional(CONF_REF): git_ref,
|
||||||
|
Optional(CONF_USERNAME): string,
|
||||||
|
Optional(CONF_PASSWORD): string,
|
||||||
|
}
|
||||||
|
LOCAL_SCHEMA = {
|
||||||
|
Required(CONF_PATH): directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_source_shorthand(value):
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise Invalid("Shorthand only for strings")
|
||||||
|
try:
|
||||||
|
return SOURCE_SCHEMA({CONF_TYPE: TYPE_LOCAL, CONF_PATH: value})
|
||||||
|
except Invalid:
|
||||||
|
pass
|
||||||
|
# Regex for GitHub repo name with optional branch/tag
|
||||||
|
# Note: git allows other branch/tag names as well, but never seen them used before
|
||||||
|
m = re.match(
|
||||||
|
r"github://(?:([a-zA-Z0-9\-]+)/([a-zA-Z0-9\-\._]+)(?:@([a-zA-Z0-9\-_.\./]+))?|pr#([0-9]+))",
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
if m is None:
|
||||||
|
raise Invalid(
|
||||||
|
"Source is not a file system path, in expected github://username/name[@branch-or-tag] or github://pr#1234 format!"
|
||||||
|
)
|
||||||
|
if m.group(4):
|
||||||
|
conf = {
|
||||||
|
CONF_TYPE: TYPE_GIT,
|
||||||
|
CONF_URL: "https://github.com/esphome/esphome.git",
|
||||||
|
CONF_REF: f"pull/{m.group(4)}/head",
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
conf = {
|
||||||
|
CONF_TYPE: TYPE_GIT,
|
||||||
|
CONF_URL: f"https://github.com/{m.group(1)}/{m.group(2)}.git",
|
||||||
|
}
|
||||||
|
if m.group(3):
|
||||||
|
conf[CONF_REF] = m.group(3)
|
||||||
|
|
||||||
|
return SOURCE_SCHEMA(conf)
|
||||||
|
|
||||||
|
|
||||||
|
SOURCE_SCHEMA = Any(
|
||||||
|
validate_source_shorthand,
|
||||||
|
typed_schema(
|
||||||
|
{
|
||||||
|
TYPE_GIT: Schema(GIT_SCHEMA),
|
||||||
|
TYPE_LOCAL: Schema(LOCAL_SCHEMA),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
|
@ -797,6 +797,9 @@ CONF_X_GRID = "x_grid"
|
||||||
CONF_Y_GRID = "y_grid"
|
CONF_Y_GRID = "y_grid"
|
||||||
CONF_ZERO = "zero"
|
CONF_ZERO = "zero"
|
||||||
|
|
||||||
|
TYPE_GIT = "git"
|
||||||
|
TYPE_LOCAL = "local"
|
||||||
|
|
||||||
ENV_NOGITIGNORE = "ESPHOME_NOGITIGNORE"
|
ENV_NOGITIGNORE = "ESPHOME_NOGITIGNORE"
|
||||||
ENV_QUICKWIZARD = "ESPHOME_QUICKWIZARD"
|
ENV_QUICKWIZARD = "ESPHOME_QUICKWIZARD"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue