Compare commits

..
Author SHA1 Message Date
J. Nick Koston 479500a68d Merge remote-tracking branch 'origin/dev' into declcfg-migrate
# Conflicts:
#	esphome/pins.py
2026-10-25 07:53:07 -10:00
J. Nick Koston 030d39f2cf Merge branch 'dev' into declcfg-migrate 2026-10-23 19:05:58 -10:00
J. Nick Koston f55a3dbf76 Merge remote-tracking branch 'origin/dev' into declcfg-migrate 2026-10-23 15:14:53 -10:00
J. Nick Koston 3500ecc1c1 Merge remote-tracking branch 'origin/dev' into declcfg-migrate
# Conflicts:
#	esphome/pins.py
2026-10-18 14:51:26 -10:00
J. Nick Koston 8e4592fa87 Merge branch 'declcfg' into declcfg-migrate 2026-10-18 14:21:18 -10:00
J. Nick Koston 76addfec20 Raise TypeError when an ID is not declared in a config block 2026-10-18 14:21:15 -10:00
J. Nick Koston c7073b9a0b Drop unused CONF_ID import in dfrobot_sen0609 2026-10-18 14:13:48 -10:00
pre-commit-ci-lite[bot] 480577e2f4 apply automatic formatting fixes 2026-10-19 00:12:56 +00:00
J. Nick Koston 3808c767fd Merge branch 'declcfg' into declcfg-migrate
# Conflicts:
#	esphome/components/display/__init__.py
2026-10-18 14:10:51 -10:00
J. Nick Koston d6a9292c41 Merge remote-tracking branch 'origin/dev' into declcfg 2026-10-18 14:10:43 -10:00
J. Nick Koston e38ee35cd8 [core] Use get_declaring_config in ID matching 2026-10-16 10:58:44 -10:00
J. Nick Koston 81fecf2106 [core] Use get_declaring_config for parent config lookups 2026-10-16 10:48:34 -10:00
J. Nick Koston 76e5b07416 [core] Add final_validate.get_declaring_config helper 2026-10-16 10:42:44 -10:00
113 changed files with 204 additions and 1909 deletions

No files matched your search

+13 -30
View File
@@ -7,7 +7,6 @@ import re
import textwrap
from esphome.build_helpers import pch
from esphome.build_helpers.ccache import CCACHE_PCH_MIN_VERSION
from esphome.components.esp32 import (
KEY_SRC_CMAKE,
get_esp32_variant,
@@ -516,7 +515,7 @@ target_link_options(${{COMPONENT_LIB}} PUBLIC
# Where CMake puts the .gch of the src component; ccache reads the checksum
# next to it in place of the .gch
_PCH_SUM_PATH = "build/esp-idf/src/CMakeFiles/__idf_src.dir/cmake_pch.hxx.gch.sum"
# Where the CMake gate records its choice
# Where the Windows gate records its choice
_PCH_CHOICE_VAR = "ESPHOME_PCH"
@@ -532,32 +531,16 @@ def _pch_cmake_block() -> str:
block = f"""target_precompile_headers(${{COMPONENT_LIB}} PRIVATE
{headers}
)"""
if pch.pch_forced():
if not pch.pch_needs_gcc_check():
return f"\n# ESPHome precompiled header\n{block}\n"
# Only CMake knows the compiler version before the first configure, and
# the ccache IDF found is the one the build runs
gcc_gate = ""
if pch.pch_needs_gcc_check():
gcc_gate = f"""if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND ({pch.PCH_WINDOWS_CMAKE_OLD_GCC}))
message(STATUS "ESPHome: GCC ${{CMAKE_CXX_COMPILER_VERSION}} cannot load a precompiled header on Windows; compiling without it")
set(_esphome_pch OFF)
endif()
"""
min_ccache = ".".join(map(str, CCACHE_PCH_MIN_VERSION))
# Before the first configure only CMake knows the compiler version
return f"""
# ESPHome precompiled header, unless a check below rules it out
set(_esphome_pch ON)
{gcc_gate}if(CCACHE_ENABLE AND CCACHE_FOUND)
execute_process(COMMAND "${{CCACHE_FOUND}}" --version OUTPUT_VARIABLE _esphome_ccache ERROR_QUIET)
if(_esphome_ccache MATCHES "ccache version ([0-9.]+)")
if(CMAKE_MATCH_1 VERSION_LESS {min_ccache})
message(STATUS "ESPHome: ccache ${{CMAKE_MATCH_1}} can reuse stale objects with a precompiled header; compiling without it (upgrade ccache to {min_ccache} or newer, or set ESPHOME_PCH_ENABLE=1 to force)")
set(_esphome_pch OFF)
endif()
endif()
endif()
set({_PCH_CHOICE_VAR} ${{_esphome_pch}} CACHE BOOL "ESPHome precompiled header in use" FORCE)
if(_esphome_pch)
# ESPHome precompiled header, unless GCC bug 14940 keeps it from loading
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND ({pch.PCH_WINDOWS_CMAKE_OLD_GCC}))
message(STATUS "ESPHome: GCC ${{CMAKE_CXX_COMPILER_VERSION}} cannot load a precompiled header on Windows; compiling without it")
set({_PCH_CHOICE_VAR} OFF CACHE BOOL "ESPHome precompiled header in use" FORCE)
else()
set({_PCH_CHOICE_VAR} ON CACHE BOOL "ESPHome precompiled header in use" FORCE)
{textwrap.indent(block, " ")}
endif()
"""
@@ -574,10 +557,10 @@ def write_pch_checksum() -> None:
if not pch.pch_enabled():
return
# Written whatever the gate chose last time: a build tree without that
# choice, or a reconfigure that turns the pch on, must not see a stale sum
if pch.pch_forced() or get_cmake_cache_value(_PCH_CHOICE_VAR) == "ON":
pch.log_pch_in_use()
# The gate's choice, cached by configure
if pch.pch_needs_gcc_check() and get_cmake_cache_value(_PCH_CHOICE_VAR) != "ON":
return
pch.log_pch_in_use()
checksum = pch.pch_checksum(
CORE.relative_src_path(),
pch.PCH_DEFAULT_HEADERS,
+1 -48
View File
@@ -3,68 +3,21 @@ resolution, and default ``CCACHE_*`` values."""
from __future__ import annotations
import functools
import logging
import os
from pathlib import Path
import re
from esphome.framework_helpers import (
strip_win_long_path_prefix,
tool_version_probe,
tool_version_runs,
)
from esphome.framework_helpers import strip_win_long_path_prefix, tool_version_runs
from esphome.helpers import FALSY_ENV_STRINGS, TRUTHY_ENV_STRINGS
_LOGGER = logging.getLogger(__name__)
# Before 4.7 ccache stores a pch consumer whose header is newer than one
# second without that header, so a later build reuses it after the header
# changed (#21621)
CCACHE_PCH_MIN_VERSION = (4, 7)
_VERSION_RE = re.compile(r"ccache version (\d+(?:\.\d+)*)")
@functools.cache
def _ccache_probe(ccache: str) -> str | Exception:
"""``ccache --version``, run once per binary per process."""
return tool_version_probe(ccache)
def _ccache_runs(ccache: str) -> bool:
"""Return True when the ``ccache`` found on PATH actually runs."""
return tool_version_runs(
ccache,
"Ignoring ccache at %s because it failed to run; compiling without ccache",
probe=_ccache_probe,
)
@functools.cache
def _ccache_too_old_for_pch(ccache: str) -> bool:
output = _ccache_probe(ccache)
if not isinstance(output, str) or (found := _VERSION_RE.search(output)) is None:
return False
if tuple(map(int, found[1].split("."))) >= CCACHE_PCH_MIN_VERSION:
return False
_LOGGER.info(
"ccache %s at %s can reuse stale objects with a precompiled header; "
"compiling without it (upgrade ccache to %s or newer, or set "
"ESPHOME_PCH_ENABLE=1 to force)",
found[1],
ccache,
".".join(map(str, CCACHE_PCH_MIN_VERSION)),
)
return True
def ccache_breaks_pch() -> bool:
"""Whether the ccache this build uses is too old for a precompiled header.
ESP-IDF builds check the ccache IDF finds in CMake instead (build_gen.espidf)."""
return (ccache := resolve_ccache_path()) is not None and _ccache_too_old_for_pch(
ccache
)
+4 -19
View File
@@ -12,11 +12,7 @@ import re
import subprocess
import sys
from esphome.build_helpers.ccache import (
ccache_breaks_pch,
effective_ccache_basedir,
parse_enable_env,
)
from esphome.build_helpers.ccache import effective_ccache_basedir, parse_enable_env
from esphome.const import PLATFORM_NRF52
from esphome.helpers import write_file_if_changed
@@ -121,16 +117,9 @@ def pch_needs_gcc_check() -> bool:
return sys.platform == "win32" and parse_enable_env("ESPHOME_PCH_ENABLE") is None
def _ccache_rules_out_pch() -> bool:
"""An old ccache, unless ``ESPHOME_PCH_ENABLE=1`` forces the pch on.
ESP-IDF runs the same check in CMake (build_gen.espidf)."""
return not pch_forced() and ccache_breaks_pch()
def pch_usable(cxx: Sequence[Path | str]) -> bool:
"""The knob plus the ccache and host rules; ``ESPHOME_PCH_ENABLE=1``
skips the rules."""
if not pch_enabled() or _ccache_rules_out_pch():
"""The knob plus the host rule; ``ESPHOME_PCH_ENABLE=1`` skips the rule."""
if not pch_enabled():
return False
if not pch_needs_gcc_check():
return True
@@ -173,11 +162,7 @@ def pch_script_enabled() -> bool:
"""Whether this PlatformIO build takes the pch script."""
from esphome.core import CORE
return (
pch_enabled()
and CORE.target_platform not in PCH_SCRIPT_EXCLUDED_PLATFORMS
and not _ccache_rules_out_pch()
)
return pch_enabled() and CORE.target_platform not in PCH_SCRIPT_EXCLUDED_PLATFORMS
def pch_header_text(include_headers: Iterable[str]) -> str:
+1 -2
View File
@@ -108,8 +108,7 @@ CONFIG_SCHEMA = cv.Schema(
def _final_validate(config: ConfigType) -> ConfigType:
full = fv.full_config.get()
hub = full.get_config_for_path(full.get_path_for_id(config[CONF_AS734X_ID])[:-1])
hub = fv.get_declaring_config(config[CONF_AS734X_ID])
if hub[CONF_TYPE] != "AS7341":
return config
for key in _BAND_KEYS:
+1 -3
View File
@@ -66,9 +66,7 @@ CONFIG_SCHEMA = cv.typed_schema(
def _final_validate(config: ConfigType) -> None:
if config[CONF_TYPE] not in _MAGNETIC_FIELDS:
return
full_config = fv.full_config.get()
bmi270_path = full_config.get_path_for_id(config[CONF_BMI270_ID])[:-1]
bmi270_config = full_config.get_config_for_path(bmi270_path)
bmi270_config = fv.get_declaring_config(config[CONF_BMI270_ID])
if bmi270_config.get(CONF_AUX_DEVICE) != "BMM150":
raise cv.Invalid(
"This sensor requires the parent bmi270's 'aux_device' to be set to 'BMM150'",
+2 -2
View File
@@ -7,6 +7,7 @@ from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_UPDATE_INTERVAL, CONF_WATCHDOG
from esphome.core import CORE, ID, EsphomeError, Lambda, TimePeriod
import esphome.final_validate as fv
from esphome.types import ConfigType, TemplateArgsType
CODEOWNERS = ["@Rapsssito"]
@@ -359,8 +360,7 @@ async def bq25186_configure_to_code(
parent = await cg.get_variable(config[CONF_ID])
# Options the action leaves out fall back to the component's configuration
path = CORE.config.get_path_for_id(config[CONF_ID])[:-1]
parent_config = CORE.config.get_config_for_path(path)
parent_config = fv.get_declaring_config(config[CONF_ID], CORE.config)
merged = {**parent_config, **config}
try:
_check_watchdog(merged)
+16 -5
View File
@@ -13,10 +13,19 @@ from esphome.const import (
from esphome.core.entity_helpers import inherit_property_from
from esphome.types import ConfigType
CONFIG_SCHEMA = sensor.sensor_schema(sensor.Sensor).extend(
{
cv.Required(CONF_SOURCE_ID): cv.use_id(sensor.Sensor),
}
from .. import copy_ns
CopySensor = copy_ns.class_("CopySensor", sensor.Sensor, cg.Component)
CONFIG_SCHEMA = (
sensor.sensor_schema(CopySensor)
.extend(
{
cv.Required(CONF_SOURCE_ID): cv.use_id(sensor.Sensor),
}
)
.extend(cv.COMPONENT_SCHEMA)
)
FINAL_VALIDATE_SCHEMA = cv.All(
@@ -31,4 +40,6 @@ FINAL_VALIDATE_SCHEMA = cv.All(
async def to_code(config: ConfigType) -> None:
var = await sensor.new_sensor(config)
sensor.follow_sensor(var, await cg.get_variable(config[CONF_SOURCE_ID]))
await cg.register_component(var, config)
await cg.add_variable(var.set_source, config[CONF_SOURCE_ID])
@@ -0,0 +1,16 @@
#include "copy_sensor.h"
#include "esphome/core/log.h"
namespace esphome::copy {
ESPHOME_LOG_TAG(TAG, "copy.sensor");
void CopySensor::setup() {
source_->add_on_state_callback([this](float value) { this->publish_state(value); });
if (source_->has_state())
this->publish_state(source_->state);
}
void CopySensor::dump_config() { LOG_SENSOR("", "Copy Sensor", this); }
} // namespace esphome::copy
@@ -0,0 +1,18 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
namespace esphome::copy {
class CopySensor final : public sensor::Sensor, public Component {
public:
void set_source(sensor::Sensor *source) { source_ = source; }
void setup() override;
void dump_config() override;
protected:
sensor::Sensor *source_;
};
} // namespace esphome::copy
@@ -5,10 +5,19 @@ from esphome.const import CONF_ENTITY_CATEGORY, CONF_ICON, CONF_SOURCE_ID
from esphome.core.entity_helpers import inherit_property_from
from esphome.types import ConfigType
CONFIG_SCHEMA = text_sensor.text_sensor_schema(text_sensor.TextSensor).extend(
{
cv.Required(CONF_SOURCE_ID): cv.use_id(text_sensor.TextSensor),
}
from .. import copy_ns
CopyTextSensor = copy_ns.class_("CopyTextSensor", text_sensor.TextSensor, cg.Component)
CONFIG_SCHEMA = (
text_sensor.text_sensor_schema(CopyTextSensor)
.extend(
{
cv.Required(CONF_SOURCE_ID): cv.use_id(text_sensor.TextSensor),
}
)
.extend(cv.COMPONENT_SCHEMA)
)
FINAL_VALIDATE_SCHEMA = cv.All(
@@ -19,4 +28,6 @@ FINAL_VALIDATE_SCHEMA = cv.All(
async def to_code(config: ConfigType) -> None:
var = await text_sensor.new_text_sensor(config)
text_sensor.follow_text_sensor(var, await cg.get_variable(config[CONF_SOURCE_ID]))
await cg.register_component(var, config)
await cg.add_variable(var.set_source, config[CONF_SOURCE_ID])
@@ -0,0 +1,16 @@
#include "copy_text_sensor.h"
#include "esphome/core/log.h"
namespace esphome::copy {
ESPHOME_LOG_TAG(TAG, "copy.text_sensor");
void CopyTextSensor::setup() {
source_->add_on_state_callback([this](const std::string &value) { this->publish_state(value); });
if (source_->has_state())
this->publish_state(source_->state);
}
void CopyTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Copy Sensor", this); }
} // namespace esphome::copy
@@ -0,0 +1,18 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/text_sensor/text_sensor.h"
namespace esphome::copy {
class CopyTextSensor final : public text_sensor::TextSensor, public Component {
public:
void set_source(text_sensor::TextSensor *source) { source_ = source; }
void setup() override;
void dump_config() override;
protected:
text_sensor::TextSensor *source_;
};
} // namespace esphome::copy
@@ -3,8 +3,7 @@ from collections.abc import Callable
import esphome.codegen as cg
from esphome.components import uart
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_MODE, CONF_MODEL
from esphome.core import ID
from esphome.const import CONF_MODE, CONF_MODEL
import esphome.final_validate as fv
from esphome.types import ConfigType
@@ -59,16 +58,11 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
)
def get_hub_config(root: ConfigType, hub_id: ID) -> ConfigType:
"""Return the configuration of the hub with the given id."""
return next(conf for conf in root[DOMAIN] if conf[CONF_ID] == hub_id)
def final_validate_mode(keys: dict[str, str]) -> Callable[[ConfigType], None]:
"""Reject entity keys that need a different hub mode; `keys` maps each key to the mode it needs."""
def validator(config: ConfigType) -> None:
hub = get_hub_config(fv.full_config.get(), config[CONF_DFROBOT_SEN0609_ID])
hub = fv.get_declaring_config(config[CONF_DFROBOT_SEN0609_ID])
for key, mode in keys.items():
if key in config and hub[CONF_MODE] != mode:
raise cv.Invalid(
@@ -18,6 +18,7 @@ from esphome.const import (
UNIT_SECOND,
)
from esphome.core import CORE
import esphome.final_validate as fv
from esphome.types import ConfigType
from .. import (
@@ -28,7 +29,6 @@ from .. import (
DFRobotSEN0609Component,
dfrobot_sen0609_ns,
final_validate_mode,
get_hub_config,
)
DFRobotSEN0609Number = dfrobot_sen0609_ns.class_("DFRobotSEN0609Number", number.Number)
@@ -181,7 +181,7 @@ FINAL_VALIDATE_SCHEMA = final_validate_mode(
async def to_code(config: ConfigType) -> None:
hub_id = config[CONF_DFROBOT_SEN0609_ID]
hub = await cg.get_variable(hub_id)
max_range = MAX_RANGES[get_hub_config(CORE.config, hub_id)[CONF_MODEL]]
max_range = MAX_RANGES[fv.get_declaring_config(hub_id, CORE.config)[CONF_MODEL]]
numbers = number.sub_numbers(config, parent=hub)
for s in SETTINGS:
await numbers(
+2 -4
View File
@@ -28,7 +28,7 @@ from esphome.const import (
SCHEDULER_DONT_RUN,
)
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
from esphome.final_validate import full_config
from esphome.final_validate import full_config, get_declaring_config
from esphome.types import ConfigType
DOMAIN = "display"
@@ -225,9 +225,7 @@ def get_display_metadata(display_id: ID) -> DisplayMetaData:
return meta
# No metadata found, display driver may not yet support it.
# Read the raw config to populate the returned data
global_config = full_config.get()
path = global_config.get_path_for_id(display_id)[:-1]
disp_config = global_config.get_config_for_path(path)
disp_config = get_declaring_config(display_id)
dimensions = disp_config.get(CONF_DIMENSIONS, (0, 0))
if isinstance(dimensions, dict):
dimensions = (dimensions.get(CONF_WIDTH, 0), dimensions.get(CONF_HEIGHT, 0))
+1 -3
View File
@@ -32,9 +32,7 @@ CONFIG_SCHEMA = cv.Schema(
def _final_validate(config: ConfigType) -> None:
"""Validate that the channel is within the parent's channel count."""
fconf = fv.full_config.get()
path = fconf.get_path_for_id(config[CONF_DS248X_ID])[:-1]
parent_config = fconf.get_config_for_path(path)
parent_config = fv.get_declaring_config(config[CONF_DS248X_ID])
channel_count = get_channel_count(parent_config)
channel = config[CONF_CHANNEL]
+1 -3
View File
@@ -63,9 +63,7 @@ CONFIG_SCHEMA = cv.Schema(
def _validate_model(config: ConfigType) -> None:
full_config = fv.full_config.get()
climate_path = full_config.get_path_for_id(config[CONF_GREE_ID])[:-1]
climate_conf = full_config.get_config_for_path(climate_path)
climate_conf = fv.get_declaring_config(config[CONF_GREE_ID])
if climate_conf[CONF_MODEL] not in SUPPORTED_MODELS:
raise cv.Invalid(
"Gree switches are only supported for the "
+1 -3
View File
@@ -61,12 +61,10 @@ CONFIG_SCHEMA = cv.Schema(
def _final_validate(config) -> None:
full_config = fv.full_config.get()
for switch_type in [CONF_BEEPER, CONF_QUIET_MODE]:
# Check switches that are only supported for HonClimate
if config.get(switch_type):
climate_path = full_config.get_path_for_id(config[CONF_HAIER_ID])[:-1]
climate_conf = full_config.get_config_for_path(climate_path)
climate_conf = fv.get_declaring_config(config[CONF_HAIER_ID])
protocol_type = climate_conf.get(CONF_PROTOCOL)
if protocol_type.casefold() != PROTOCOL_HON.casefold():
raise cv.Invalid(
+1 -3
View File
@@ -42,9 +42,7 @@ def _final_validate(config: dict[str, Any]) -> None:
# Get the transmitter configuration
transmitter_id = config[CONF_REMOTE_TRANSMITTER_ID]
full_config = fv.full_config.get()
transmitter_path = full_config.get_path_for_id(transmitter_id)[:-1]
transmitter_config = full_config.get_config_for_path(transmitter_path)
transmitter_config = fv.get_declaring_config(transmitter_id)
# Check if carrier_duty_percent set to 0 or 100
# Note: remote_transmitter schema requires this field and validates 1-100%,
@@ -35,11 +35,7 @@ def _final_validate(config: ConfigType) -> None:
if CONF_REMOTE_TRANSMITTER_ID not in config:
return
full_config = fv.full_config.get()
transmitter_path = full_config.get_path_for_id(config[CONF_REMOTE_TRANSMITTER_ID])[
:-1
]
transmitter_config = full_config.get_config_for_path(transmitter_path)
transmitter_config = fv.get_declaring_config(config[CONF_REMOTE_TRANSMITTER_ID])
duty_percent = transmitter_config.get(CONF_CARRIER_DUTY_PERCENT)
if duty_percent is not None and duty_percent != 100:
@@ -101,8 +101,7 @@ def final_validate(config: ConfigType) -> None:
)
if config.get(CONF_WAKE):
hub_path = full_config.get_path_for_id(hub_id)
hub_config = full_config.get_config_for_path(hub_path[:-1])
hub_config = fv.get_declaring_config(hub_id, full_config)
if hub_config.get(CONF_WAKEUP_PIN) is None:
raise cv.Invalid(
f"{CONF_WAKE} requires {CONF_WAKEUP_PIN} on the parent ld6002b component",
+2 -4
View File
@@ -380,8 +380,7 @@ def _final_validate(config: ConfigType) -> None:
for ref in refs:
try:
light_path = fconf.get_path_for_id(ref.light_id)[:-1]
light_config = fconf.get_config_for_path(light_path)
light_config = fv.get_declaring_config(ref.light_id, fconf)
except KeyError:
# Light ID not found — ID validation will have already reported this
continue
@@ -398,8 +397,7 @@ def _final_validate(config: ConfigType) -> None:
for ref in cycle_refs:
try:
light_path = fconf.get_path_for_id(ref.light_id)[:-1]
light_config = fconf.get_config_for_path(light_path)
light_config = fv.get_declaring_config(ref.light_id, fconf)
except KeyError:
continue
+2 -2
View File
@@ -34,6 +34,7 @@ from esphome.const import (
)
from esphome.core import CORE, ID, EsphomeError, Lambda
from esphome.cpp_generator import MockObj, TemplateArgsType
import esphome.final_validate as fv
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
from esphome.types import ConfigType
@@ -253,8 +254,7 @@ def _resolve_effect_index(config: ConfigType, original_name: str) -> int:
from . import effect_not_found_message, find_effect_index
light_id = config[CONF_ID]
light_path = CORE.config.get_path_for_id(light_id)[:-1]
light_config = CORE.config.get_config_for_path(light_path)
light_config = fv.get_declaring_config(light_id, CORE.config)
effects = light_config.get(CONF_EFFECTS, [])
index = find_effect_index(effects, original_name)
if index is not None:
+2 -16
View File
@@ -1,5 +1,3 @@
import logging
from esphome import automation, pins
import esphome.codegen as cg
import esphome.config_validation as cv
@@ -17,8 +15,6 @@ from esphome.core import CORE
from esphome.cpp_helpers import gpio_pin_expression
from esphome.types import ConfigType
_LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@max246"]
DOMAIN = "lightwaverf"
@@ -39,20 +35,10 @@ CONFIG_SCHEMA = cv.Schema(
).extend(cv.polling_component_schema("1s"))
def _drop_unused_name(config: ConfigType) -> ConfigType:
# Remove before 2027.5.0
if config.pop(CONF_NAME, None) is not None:
_LOGGER.warning(
"[lightwaverf] 'name' on lightwaverf.send_raw has no effect; remove it. "
"Removed in 2027.5.0"
)
return config
LIGHTWAVE_SEND_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.use_id(LIGHTWAVERFComponent),
cv.Optional(CONF_NAME): cv.string,
cv.Required(CONF_NAME): cv.string,
cv.Required(CONF_CODE): cv.All(
[cv.Any(cv.hex_uint8_t)],
cv.Length(min=10),
@@ -61,7 +47,7 @@ LIGHTWAVE_SEND_SCHEMA = cv.Schema(
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
cv.Optional(CONF_PULSE_LENGTH, default=330): cv.int_,
}
).add_extra(_drop_unused_name)
)
automation.register_apply_action(
@@ -41,9 +41,7 @@ CONFIG_SCHEMA = cv.All(
def _final_validate(config: ConfigType) -> None:
full_config = fv.full_config.get()
display_path = full_config.get_path_for_id(config[CONF_DISPLAY_ID])[:-1]
display_config = full_config.get_config_for_path(display_path)
display_config = fv.get_declaring_config(config[CONF_DISPLAY_ID])
if CONF_BRIGHTNESS not in display_config:
model = display_config[CONF_MODEL]
if model == "CUSTOM":
@@ -310,9 +310,7 @@ def migrate_custom_command(config: ConfigType) -> None:
frame = config.get(CONF_CUSTOM_COMMAND)
if frame is None:
return
fconf = fv.full_config.get()
path = fconf.get_path_for_id(config[CONF_MODBUS_CONTROLLER_ID])[:-1]
controller = fconf.get_config_for_path(path)
controller = fv.get_declaring_config(config[CONF_MODBUS_CONTROLLER_ID])
# the controller's DEVICE address (from modbus_device_schema)
address = controller[CONF_ADDRESS]
if frame[0] != address:
@@ -342,9 +340,7 @@ def _reject_continuous_write_custom_pdu(config: ConfigType) -> None:
pdu = config.get(CONF_CUSTOM_PDU)
if pdu is None or not modbus.is_function_code_write(pdu[0]):
return
fconf = fv.full_config.get()
path = fconf.get_path_for_id(config[CONF_MODBUS_CONTROLLER_ID])[:-1]
controller = fconf.get_config_for_path(path)
controller = fv.get_declaring_config(config[CONF_MODBUS_CONTROLLER_ID])
if controller.get(CONF_CONTINUOUS) is True:
raise cv.Invalid(
f"a '{CONF_CUSTOM_PDU}' with a write function code (0x{pdu[0] & 0x7F:02X}) can't be polled "
@@ -359,9 +355,7 @@ def _reject_broadcastable_custom_pdu(config: ConfigType) -> None:
pdu = config.get(CONF_CUSTOM_PDU)
if pdu is None or not modbus.is_function_code_broadcastable(pdu[0]):
return
fconf = fv.full_config.get()
path = fconf.get_path_for_id(config[CONF_MODBUS_CONTROLLER_ID])[:-1]
controller = fconf.get_config_for_path(path)
controller = fv.get_declaring_config(config[CONF_MODBUS_CONTROLLER_ID])
if (
controller.get(CONF_ADDRESS) == modbus.BROADCAST_ADDRESS
and controller.get(modbus.CONF_ALLOW_BROADCAST_READ) is True
@@ -384,9 +378,7 @@ def validate_custom_pdu_item(config: ConfigType) -> None:
def _reject_write_option_off_broadcast(config: ConfigType) -> None:
if not any(config.get(key) is True for key in modbus.broadcast_only_option_keys()):
return
fconf = fv.full_config.get()
path = fconf.get_path_for_id(config[CONF_MODBUS_CONTROLLER_ID])[:-1]
controller = fconf.get_config_for_path(path)
controller = fv.get_declaring_config(config[CONF_MODBUS_CONTROLLER_ID])
if controller.get(CONF_ADDRESS) != modbus.BROADCAST_ADDRESS:
raise cv.Invalid(
f"'{modbus.CONF_EXPECT_BROADCAST_WRITE_RESPONSE}' only applies when the "
+1 -3
View File
@@ -50,9 +50,7 @@ MAX_RECOMMENDED_UPDATE_INTERVAL_MS = 100
def get_motion_config(motion_id: ID) -> dict:
"""Look up the (already-validated) config of the motion hub referenced by motion_id."""
full_config = fv.full_config.get()
motion_path = full_config.get_path_for_id(motion_id)[:-1]
return full_config.get_config_for_path(motion_path)
return fv.get_declaring_config(motion_id)
def check_update_interval(motion_id: ID, feature_name: str) -> None:
+1 -2
View File
@@ -67,8 +67,7 @@ def _final_validate(config: ConfigType) -> None:
"Max touch channel must equal the highest binary sensor channel or be removed for auto calculation",
path=[CONF_MAX_TOUCH_CHANNEL],
)
path = fconf.get_path_for_id(config[CONF_ID])[:-1]
this_config = fconf.get_config_for_path(path)
this_config = fv.get_declaring_config(config[CONF_ID], fconf)
this_config[CONF_MAX_TOUCH_CHANNEL] = max_touch_channel
@@ -48,9 +48,7 @@ def _final_validate(config: ConfigType) -> None:
if config[CONF_TYPE] != CONF_STATUS:
# Only run this validation if a status sensor is being configured
return
full_config = fv.full_config.get()
transport_path = full_config.get_path_for_id(config[CONF_TRANSPORT_ID])[:-1]
transport_config = full_config.get_config_for_path(transport_path)
transport_config = fv.get_declaring_config(config[CONF_TRANSPORT_ID])
if transport_config[CONF_PING_PONG_ENABLE] and any(
CONF_ENCRYPTION in p
for p in transport_config[CONF_PROVIDERS]
+1 -4
View File
@@ -35,11 +35,8 @@ def validate_from_to(value: ConfigType) -> ConfigType:
def validate_segment(config: ConfigType) -> None:
fconf = fv.full_config.get()
if CONF_ID in config: # only validate addressable segments
path = fconf.get_path_for_id(config[CONF_ID])[:-1]
segment_light_config = fconf.get_config_for_path(path)
segment_light_config = fv.get_declaring_config(config[CONF_ID])
if CONF_NUM_LEDS in segment_light_config:
segment_len = segment_light_config[CONF_NUM_LEDS]
-5
View File
@@ -124,7 +124,6 @@ from esphome.core import (
)
from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH
from esphome.core.entity_helpers import (
FollowEntity,
SubEntities,
entity_duplicate_validator,
lazy_load_validator,
@@ -1110,10 +1109,6 @@ def sub_sensors(
return SubEntities(new_sensor, config, parent)
# Makes a plain sensor follow another sensor: follow_sensor(entity, source)
follow_sensor = FollowEntity("add_on_state_callback", ((cg.float_, "x"),), "x")
SENSOR_IN_RANGE_CONDITION_SCHEMA = cv.All(
{
cv.Required(CONF_ID): cv.use_id(Sensor),
+1 -3
View File
@@ -56,9 +56,7 @@ CONFIG_SCHEMA = cv.Schema(
def _final_validate(config: ConfigType) -> ConfigType:
fconf = fv.full_config.get()
hub_path = fconf.get_path_for_id(config[CONF_TAS58XX_ID])
hub_conf = fconf.get_config_for_path(hub_path[:-1])
hub_conf = fv.get_declaring_config(config[CONF_TAS58XX_ID])
if hub_conf[CONF_MODEL] == DAC_TAS5825M:
return config
@@ -65,9 +65,7 @@ CONFIG_SCHEMA = cv.All(
def _final_validate(config: ConfigType) -> None:
"""Resolve the key to the number the device reports, checked against the keypad's matrix."""
full_config = fv.full_config.get()
keypad_path = full_config.get_path_for_id(config[CONF_KEYPAD_ID])[:-1]
keypad = full_config.get_config_for_path(keypad_path)
keypad = fv.get_declaring_config(config[CONF_KEYPAD_ID])
rows = keypad.get(CONF_ROWS, 0)
columns = keypad.get(CONF_COLUMNS, 0)
@@ -22,7 +22,6 @@ from esphome.const import (
)
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import (
FollowEntity,
SubEntities,
entity_duplicate_validator,
queue_entity_register,
@@ -239,12 +238,6 @@ def sub_text_sensors(
return SubEntities(new_text_sensor, config, parent)
# Makes a plain text sensor follow another text sensor: follow_text_sensor(entity, source)
follow_text_sensor = FollowEntity(
"add_on_state_callback", ((cg.std_string_ref.operator("const"), "x"),), "x"
)
@coroutine_with_priority(CoroPriority.CORE)
async def to_code(config):
cg.add_global(text_sensor_ns.using)
@@ -59,9 +59,7 @@ CONFIG_SCHEMA = cv.Schema(
def _final_validate(config: ConfigType) -> ConfigType:
if CONF_ACTUAL_CURRENT not in config:
return config
full_config = fv.full_config.get()
path = full_config.get_path_for_id(config[CONF_TMC2209_ID])[:-1]
if full_config.get_config_for_path(path).get(CONF_ANALOG_CURRENT_SCALE):
if fv.get_declaring_config(config[CONF_TMC2209_ID]).get(CONF_ANALOG_CURRENT_SCALE):
raise cv.Invalid(
f"'{CONF_ACTUAL_CURRENT}' can't be used with '{CONF_ANALOG_CURRENT_SCALE}', "
"the current then depends on VREF",
+1 -2
View File
@@ -56,8 +56,7 @@ _validate_unique = unique_child("number")
def _final_validate(config: ConfigType) -> ConfigType:
_validate_unique(config)
full = fv.full_config.get()
parent = full.get_config_for_path(full.get_path_for_id(config[CONF_TMP102_ID])[:-1])
parent = fv.get_declaring_config(config[CONF_TMP102_ID])
add_number_parent(config[CONF_TMP102_ID], parent.get(CONF_EXTENDED_MODE, False))
return config
+1 -3
View File
@@ -1136,9 +1136,7 @@ class IDPassValidationStep(ConfigValidationStep):
m
for m in matches
if isinstance(
candidate_conf := result.get_config_for_path(
result.get_path_for_id(m)[:-1]
),
candidate_conf := fv.get_declaring_config(m, result),
dict,
)
and all(
+3 -6
View File
@@ -416,13 +416,10 @@ void Application::teardown_components(uint32_t timeout_ms) {
}
}
void Application::add_looping_components_by_state_(bool inactive) {
void Application::add_looping_components_by_state_(bool match_loop_done) {
for (auto *obj : this->components_) {
if (!obj->has_overridden_loop()) {
continue;
}
const uint8_t state = obj->get_component_state() & COMPONENT_STATE_MASK;
if ((state == COMPONENT_STATE_LOOP_DONE || state == COMPONENT_STATE_FAILED) == inactive) {
if (obj->has_overridden_loop() &&
((obj->get_component_state() & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE) == match_loop_done) {
this->looping_components_.push_back(obj);
}
}
+6 -5
View File
@@ -433,15 +433,16 @@ class Application {
// FixedVector capacity was pre-initialized by codegen with the exact count
// of components that override loop(), computed at C++ compile time.
// Add all components with loop override that aren't already LOOP_DONE or FAILED
// Some components (like logger) may call disable_loop() during initialization,
// and some call mark_failed() from their constructor, before setup runs
// Add all components with loop override that aren't already LOOP_DONE
// Some components (like logger) may call disable_loop() during initialization
// before setup runs, so we need to respect their LOOP_DONE state
this->add_looping_components_by_state_(false);
this->looping_components_active_end_ = this->looping_components_.size();
// Then add any components that are already LOOP_DONE or FAILED to the inactive section
// Then add any components that are already LOOP_DONE to the inactive section
// This handles components that called disable_loop() during initialization
this->add_looping_components_by_state_(true);
}
void add_looping_components_by_state_(bool inactive);
void add_looping_components_by_state_(bool match_loop_done);
// These methods are called by Component::disable_loop() and Component::enable_loop()
// Components should not call these directly - use this->disable_loop() or this->enable_loop()
+1 -1
View File
@@ -169,7 +169,7 @@ struct Color {
uint8_t r = rand >> 16;
uint8_t g = rand >> 8;
uint8_t b = rand >> 0;
const uint16_t max_rgb = std::max({r, g, b, uint8_t(1)});
const uint16_t max_rgb = std::max({r, g, b});
return Color(uint8_t((uint16_t(r) * 255U / max_rgb)), uint8_t((uint16_t(g) * 255U / max_rgb)),
uint8_t((uint16_t(b) * 255U / max_rgb)), w);
}
+2 -22
View File
@@ -45,7 +45,6 @@ from esphome.core.config import (
UNIT_OF_MEASUREMENT_MAX_LENGTH,
)
from esphome.cpp_generator import (
LambdaExpression,
MockObj,
MockObjClass,
RawExpression,
@@ -520,23 +519,6 @@ class ApplyEntity:
_APPLY_DOMAIN = "entity_apply"
@dataclass(frozen=True, slots=True)
class FollowEntity:
"""A state callback, its parameters and the value an entity republishes from it."""
callback: str
params: tuple[tuple[SafeExpType, str], ...]
value: str
def __call__(self, entity: MockObj, source: MockObj, *args: SafeExpType) -> None:
"""Make ``entity`` publish every state of ``source``; ``args`` precede the callback."""
publish = f"{parent_ref(entity).publish_state(RawExpression(self.value))};"
callback = LambdaExpression(
[publish], list(self.params), capture="", return_type=cg.void
)
add(getattr(source, self.callback)(*args, callback))
@dataclass(frozen=True, slots=True)
class SubEntities:
"""Create the child entity configured under key, set parent (if bound) and pass it to setter.
@@ -664,14 +646,12 @@ def inherit_property_from(property_to_inherit, parent_id_property, transform=Non
# Get config for the parent entity
parent_id = _walk_config(config, parent_id_property)
parent_path = fconf.get_path_for_id(parent_id)[:-1]
parent_config = fconf.get_config_for_path(parent_path)
parent_config = fv.get_declaring_config(parent_id, fconf)
# If parent sensor has the property set, inherit it
if property in parent_config:
path = fconf.get_path_for_id(config[CONF_ID])[:-1]
this_config = _walk_config(
fconf.get_config_for_path(path), property_path
fv.get_declaring_config(config[CONF_ID], fconf), property_path
)
value = parent_config[property]
if transform:
-2
View File
@@ -331,8 +331,6 @@ class FloatLiteral(Literal):
def __str__(self):
if math.isnan(self.f):
return "NAN"
if math.isinf(self.f):
return "INFINITY" if self.f > 0 else "-INFINITY"
return f"{self.f}f"
+1 -7
View File
@@ -466,15 +466,9 @@ def receive_exactly(
while len(data) < amount:
try:
chunk = recv_decode(sock, amount - len(data), decode=decode)
data += recv_decode(sock, amount - len(data), decode=decode) # type: ignore[operator]
except OSError as err:
raise OTANetworkError(f"receiving {msg}: {err}") from err
if not chunk:
raise OTANetworkError(
f"receiving {msg}: device closed connection after "
f"{len(data)} of {amount} bytes"
)
data += chunk # type: ignore[operator]
return data
+9 -23
View File
@@ -205,42 +205,28 @@ def run_command(
return False, None, None
def tool_version_probe(binary: str) -> str | Exception:
"""Run ``binary --version``: its stdout, or the error when it fails to run.
def tool_version_runs(binary: str, warning: str) -> bool:
"""Probe ``binary --version``; on failure warn with ``warning`` % binary.
``shutil.which`` proves existence, not runnability (Windows .bat/.cmd
shims, stale package-manager shims).
"""
try:
result = subprocess.run(
subprocess.run(
[binary, "--version"],
check=True,
stdout=subprocess.PIPE,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
text=True,
errors="replace",
timeout=15,
# Repo-wide convention (posix_spawn fast path)
close_fds=False,
)
except (OSError, subprocess.SubprocessError) as err:
return err
return result.stdout
def tool_version_runs(
binary: str,
warning: str,
probe: Callable[[str], str | Exception] = tool_version_probe,
) -> bool:
"""Probe ``binary --version``; on failure warn with ``warning`` % binary.
``probe`` lets a caller supply a cached probe."""
if not isinstance(result := probe(binary), Exception):
return True
# The cause (permission denied, missing DLL, timeout) is the one detail
# the user needs to fix it
_LOGGER.warning("%s (%s)", warning % binary, result)
return False
# The cause (permission denied, missing DLL, timeout) is the one
# detail the user needs to fix it
_LOGGER.warning("%s (%s)", warning % binary, err)
return False
return True
def run_command_ok(*args, **kwargs) -> bool:
+2 -2
View File
@@ -23,6 +23,7 @@ from esphome.const import (
)
from esphome.core import CORE, ID
from esphome.cpp_generator import MockObj, MockObjClass
import esphome.final_validate as fv
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
from esphome.types import ConfigType, SafeExpType
@@ -231,8 +232,7 @@ class PinRegistry(dict):
with fconf.catch_error([cv.ROOT_CONFIG_PATH] + pin_path):
if final_val_fun is not None:
# Get the containing path of the config providing this pin.
parent_path = fconf.get_path_for_id(client_id)[:-1]
parent_config = fconf.get_config_for_path(parent_path)
parent_config = fv.get_declaring_config(client_id, fconf)
final_val_fun(pin_config, parent_config)
allow_others = pin_config.get(CONF_ALLOW_OTHER_USES, False)
if count != 1 and not allow_others and not CORE.testing_mode:
Whitespace-only changes.
@@ -1,24 +0,0 @@
"""lightwaverf.send_raw never used name; it is dropped with a warning until 2027.5.0."""
import pytest
from esphome.automation import ACTION_REGISTRY
import esphome.components.lightwaverf # noqa: F401
from esphome.const import CONF_NAME, CONF_REPEAT
CODE = [0x04, 0x00, 0x00, 0x00, 0x0F, 0x03, 0x0D, 0x09, 0x08, 0x08]
def test_name_is_dropped_with_a_warning(caplog: pytest.LogCaptureFixture) -> None:
config = ACTION_REGISTRY["lightwaverf.send_raw"].schema(
{"code": CODE, CONF_NAME: "Sofa"}
)
assert CONF_NAME not in config
assert "'name' on lightwaverf.send_raw has no effect" in caplog.text
assert "2027.5.0" in caplog.text
def test_name_is_no_longer_required(caplog: pytest.LogCaptureFixture) -> None:
config = ACTION_REGISTRY["lightwaverf.send_raw"].schema({"code": CODE})
assert config[CONF_REPEAT] == 10
assert "lightwaverf" not in caplog.text
-31
View File
@@ -36,30 +36,6 @@ esphome:
service: notify.html5
data:
message: Button was pressed
- homeassistant.service:
service: !lambda 'return std::string("notify.html5");'
data:
title: Title
data_template:
message: The value is {{ my_value }}
variables:
my_value: !lambda 'return std::string("42");'
capture_response: true
response_template: !lambda 'return std::string("{{ response.value }}");'
on_success:
- logger.log: "service succeeded"
on_error:
- logger.log:
format: "service failed: %s"
args: [error.c_str()]
- homeassistant.action:
action: weather.get_forecasts
data:
entity_id: weather.forecast_home
capture_response: true
response_template: !lambda 'return std::string("{{ response }}");'
on_success:
- logger.log: "forecast received"
- homeassistant.tag_scanned: pulse
- homeassistant.action:
action: weather.get_forecasts
@@ -331,13 +307,6 @@ api:
success: false
error_message: !lambda 'return error_msg;'
- action: test_respond_lambda_success
variables:
ok: bool
then:
- api.respond:
success: !lambda 'return ok;'
# ==========================================================================
# supports_response: optional (auto-detected - api.respond with data)
# Has call_id and return_response - client decides if it wants response
-8
View File
@@ -21,14 +21,6 @@ esphome:
id: waveradar
frequency: 5800MHz
power_consumption: 91uA
- at581x.settings:
id: waveradar
hw_frontend_reset: !lambda return true;
sensing_distance: !lambda return 300;
protect_time: !lambda return 1500;
trigger_base: !lambda return 600;
trigger_keep: !lambda return 12000;
stage_gain: !lambda return 4;
- at581x.reset:
id: waveradar
@@ -7,8 +7,6 @@ esphome:
- bk72xx_ble_tracker.start_scan
- bk72xx_ble_tracker.start_scan:
continuous: true
- bk72xx_ble_tracker.start_scan:
continuous: !lambda return false;
- bk72xx_ble_tracker.stop_scan
- bk72xx_ble_tracker.stop_scan: ble_tracker
-7
View File
@@ -109,10 +109,3 @@ button:
- logger.log: Level calibration failed
- motion.calibrate_heading:
id: bmi270_motion
- motion.calibrate_heading:
id: bmi270_motion
save: true
on_success:
- logger.log: Heading calibrated
on_error:
- logger.log: Heading calibration failed
-43
View File
@@ -9,49 +9,6 @@ esphome:
id: bq25186_charger
battery_regulation_voltage: 4.1V
fast_charge_current: 200mA
- bq25186.apply_configuration:
id: bq25186_charger
charge_enabled: false
flash_charging_mode: true
precharge_is_iterm: true
termination_percent: 5%
vindpm_mode: 4.7v
thermal_regulation: 80c
battery_ocp_limit: 1500ma
battery_uvlo: 3.0v
mask_charge_status_interrupt: false
mask_ilim_interrupt: false
mask_vindpm_interrupt: true
ts_auto_function: false
vlowv: 2.8v
recharge_threshold: 200mv
double_timer_during_dpm: true
safety_timer: 12h
watchdog: 160s_hardware_reset
long_press_duration: 15s
hw_reset_requires_vin: true
autowake: 2s
input_current_limit: 200ma
- bq25186.apply_configuration:
id: bq25186_charger
push_button_long_press_action: shutdown_mode
wake1_timer: 1s
wake2_timer: 3s
enable_push_button: false
system_regulation: 4.6v
sys_mode: battery_only
watchdog_15s_enable: false
disable_vdppm: true
ts_hot: 65c
ts_cold: 3c
ts_warm_disable: true
ts_cool_disable: true
ts_ichg: 0.2x
ts_vrcg: -200mv
mask_ts_interrupt: true
mask_treg_interrupt: false
mask_bat_interrupt: true
mask_pg_interrupt: true
bq25186:
- id: bq25186_charger
-3
View File
@@ -14,9 +14,6 @@ button:
id: bms
address: 0x09
- bq76972.program_i2c_address: !lambda "return 0x08;"
- bq76972.program_i2c_address:
id: bms
address: !lambda return 0x0A;
sensor:
- platform: bq76972
-4
View File
@@ -69,7 +69,3 @@ button:
- canbus.send: !lambda |-
uint8_t val = (uint8_t)id(canbus_test_number).state;
return std::vector<uint8_t>{0xAA, val, 0xBB};
- canbus.send:
can_id: 0x123
remote_transmission_request: true
data: []
-3
View File
@@ -5,9 +5,6 @@ esphome:
id: counter_sensor
value: 100
- counter.increment: counter_sensor
- counter.set_value:
id: counter_sensor
value: !lambda return 42LL;
- counter.increment:
id: counter_sensor
value: -5
-2
View File
@@ -14,8 +14,6 @@ esphome:
then:
- deep_sleep.enter:
sleep_duration: 60min
- deep_sleep.enter:
sleep_duration: !lambda return 60000;
- if:
condition:
lambda: 'return deep_sleep::woke_from_deep_sleep();'
@@ -2,8 +2,7 @@
# (the default on ESP-IDF). Entering deep sleep runs the safe shutdown hooks,
# where safe_mode confirms the running app image so the bootloader does not
# roll back a fresh OTA update when the device goes to sleep before
# boot_is_good_after has elapsed. The network this needs also serves the
# deep_sleep.enter until/time_id case, which requires a time source.
# boot_is_good_after has elapsed.
substitutions:
wakeup_pin: GPIO4
@@ -18,16 +17,3 @@ wifi:
ota:
- platform: esphome
password: "superlongpasswordthatnoonewillknow"
time:
- platform: sntp
id: sntp_time
button:
- platform: template
name: Sleep until
on_press:
- deep_sleep.enter:
id: deep_sleep_1
until: "06:30:00"
time_id: sntp_time
-6
View File
@@ -27,12 +27,6 @@ esphome:
- dfplayer.set_volume: !lambda "return id(dfplayer_test).is_playing() ? 10 : 5;"
- dfplayer.set_eq: ROCK
- dfplayer.set_eq: !lambda "return id(dfplayer_test).is_playing() ? dfplayer::JAZZ : dfplayer::BASS;"
- dfplayer.play_mp3:
file: 7
- dfplayer.set_volume:
volume: 12
- dfplayer.set_eq:
eq_preset: CLASSIC
- dfplayer.play_next
- dfplayer.play_previous
- dfplayer.reset
@@ -12,10 +12,6 @@ esphome:
delay_after_detect: 0s
delay_after_disappear: 0s
sensitivity: 6
- dfrobot_sen0395.settings:
id: mmwave
factory_reset: !lambda return false;
sensitivity: !lambda return 7;
- dfrobot_sen0395.reset
dfrobot_sen0395:
-30
View File
@@ -52,36 +52,6 @@ button:
minute: !lambda return 45;
- ds3231.set_alarm_2:
mode: every_minute
- ds3231.set_alarm_1:
mode: weekly
day_of_week: 3
hour: !lambda return 8;
second: !lambda return 30;
enabled: !lambda return true;
- ds3231.set_alarm_1:
mode: monthly
day_of_month: !lambda return 20;
minute: !lambda return 10;
- ds3231.set_alarm_2:
mode: monthly
day_of_month: 10
enabled: false
- ds3231.set_alarm_2:
mode: weekly
day_of_week: !lambda return 5;
hour: !lambda return 18;
- ds3231.enable_alarm:
alarm: !lambda return 2;
- ds3231.disable_alarm:
alarm: !lambda return 1;
- if:
condition:
ds3231.is_alarm_triggered:
alarm: !lambda return 1;
then:
- logger.log: alarm 1 triggered
- ds3231.set_32khz_output:
state: !lambda return false;
- ds3231.enable_alarm:
alarm: 1
- ds3231.disable_alarm:
-2
View File
@@ -3,8 +3,6 @@ esphome:
then:
- audio_adc.set_mic_gain: 0db
- audio_adc.set_mic_gain: !lambda 'return 4;'
- audio_adc.set_mic_gain:
mic_gain: 6db
audio_adc:
- platform: es7210
-12
View File
@@ -35,18 +35,6 @@ espnow:
data: [0x01, 0x02, 0x03, 0x04, 0x05]
- espnow.broadcast:
data: !lambda 'return {0x01, 0x02, 0x03, 0x04, 0x05};'
- espnow.broadcast:
address: FF:FF:FF:FF:FF:FF
data: "options"
wait_for_sent: true
continue_on_error: false
on_sent:
- logger.log: "broadcast sent"
on_error:
- logger.log: "broadcast failed"
- espnow.send:
address: !lambda 'return {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};'
data: "lambda address"
- espnow.send:
address: 11:22:33:44:55:66
data: !lambda 'return std::vector<uint8_t>(data, data + size);'
-7
View File
@@ -46,13 +46,6 @@ text_sensor:
- ezo_pmp.set_calibration_volume:
id: hcl_pump
volume: 10
- ezo_pmp.dose_with_constant_flow_rate:
id: hcl_pump
volume_per_minute: !lambda return 5.5f;
duration: !lambda return 3;
- ezo_pmp.set_calibration_volume:
id: hcl_pump
volume: !lambda return 12.5f;
- ezo_pmp.find: hcl_pump
- ezo_pmp.dose_continuously: hcl_pump
- ezo_pmp.clear_total_volume_dosed: hcl_pump
@@ -14,10 +14,3 @@ button:
speed: 200
color: BLUE
count: 2
- fingerprint_grow.aura_led_control:
state: !lambda return fingerprint_grow::FLASHING;
speed: !lambda return 100;
color: !lambda return fingerprint_grow::RED;
count: !lambda return 3;
- fingerprint_grow.delete:
finger_id: !lambda return 2;
-3
View File
@@ -9,9 +9,6 @@ hdmi_cec:
- hdmi_cec.send:
destination: !lambda return source;
data: [0x90, 0x01] # Report Power Status: standby
- hdmi_cec.send:
destination: 0x0
data: !lambda return {0x90, 0x01};
- opcode: 0x8C # Give Device Vendor ID
then:
- lambda: |-
-2
View File
@@ -5,8 +5,6 @@ esphome:
name: "Test"
direction: 1
- hlk_fm22x.delete: 5
- hlk_fm22x.delete:
face_id: 7
- hlk_fm22x.delete_all:
- hlk_fm22x.reset:
- hlk_fm22x.scan:
@@ -35,59 +35,6 @@ esphome:
- http_request.get:
url: https://esphome.io
timeout: !lambda "return 10000;"
- http_request.get:
url: !lambda 'return std::string("https://esphome.io/get");'
method: GET
collect_headers:
- Content-Type
- X-Request-Id
max_response_buffer_size: 2kB
capture_response: true
on_response:
then:
- logger.log:
format: "Content-Type %s, body %zu bytes"
args:
- response->get_response_header("content-type").c_str()
- body.size()
- http_request.post:
url: !lambda 'return std::string("https://esphome.io/post");'
method: POST
body: !lambda 'return std::string("{\"key\": \"value\"}");'
timeout: 5s
collect_headers:
- Location
max_response_buffer_size: 512
on_error:
- logger.log: "POST failed"
- http_request.post:
url: https://esphome.io
body: "plain body"
timeout: !lambda "return 2500;"
- http_request.send:
method: PATCH
url: !lambda 'return std::string("https://esphome.io/send");'
json:
key: value
dynamic: !lambda 'return std::string("x");'
collect_headers:
- ETag
max_response_buffer_size: 4kB
capture_response: true
timeout: !lambda "return 3000;"
on_response:
then:
- logger.log:
format: "Send status %d, body %s"
args:
- response->status_code
- body.c_str()
on_error:
- logger.log: "Send failed"
- http_request.send:
method: DELETE
url: https://esphome.io/item
body: !lambda 'return std::string("id=1");'
- http_request.post:
url: https://esphome.io
request_headers:
-6
View File
@@ -21,9 +21,3 @@ button:
- htu21d.set_heater_level:
id: htu21d_sensor
level: 5
- htu21d.set_heater:
id: htu21d_sensor
status: !lambda return false;
- htu21d.set_heater_level:
id: htu21d_sensor
level: !lambda return 3;
-3
View File
@@ -10,6 +10,3 @@ esphome:
- hub75.set_brightness:
id: my_hub75
brightness: 50
- hub75.set_brightness:
id: my_hub75
brightness: !lambda return 150;
@@ -108,6 +108,3 @@ interval:
id: m5epd_display
mode: A2
- it8951.update: m5epd_display
- it8951.update:
id: m5epd_display
mode: !lambda return it8951::UPDATE_MODE_GL16;
-27
View File
@@ -155,33 +155,6 @@ esphome:
- light.turn_off:
id: test_rgb_light
transition_length: 300ms
- light.turn_off:
id: test_rgb_light
state: false
transition_length: !lambda return 200;
- light.turn_on:
id: test_rgb_light
red: !lambda return 0.2f;
green: !lambda return 0.4f;
blue: !lambda return 0.6f;
transition_length: !lambda return 350;
- light.turn_on:
id: test_cwww_light
color_temperature: 300 mireds
- light.turn_on:
id: test_cwww_light
color_temperature: !lambda return 250.0f;
- light.control:
id: test_rgbww_light
cold_white: !lambda return 0.6f;
warm_white: !lambda return 0.2f;
- light.control:
id: test_monochromatic_light
effect: !lambda return "My Flicker";
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: !lambda return 0.1f;
transition_length: !lambda return 150;
# Test static effect name resolution at codegen time
- light.turn_on:
id: test_monochromatic_light
+1 -8
View File
@@ -9,12 +9,5 @@ button:
on_press:
lightwaverf.send_raw:
code: [0x04, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x0d, 0x09, 0x08, 0x08]
name: "Sofa"
repeat: 1
- platform: template
name: "Turn off sofa inverted"
on_press:
lightwaverf.send_raw:
code: [0x04, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x0d, 0x09, 0x08, 0x08]
name: "Sofa inverted"
inverted: true
pulse_length: 300
@@ -5,10 +5,6 @@ esphome:
level: warn
format: "Warning: Logger level is %d"
args: [id(logger_id).get_log_level()]
- logger.log:
tag: custom.tag
level: info
format: "Tagged log entry"
- logger.set_level: WARN
- logger.set_level:
level: ERROR
-52
View File
@@ -41,10 +41,6 @@ script:
id: test_list_id
label:
text: row
- lvgl.list.add:
id: test_list_id
checkbox:
text: list checkbox
esphome:
on_boot:
@@ -113,7 +109,6 @@ lvgl:
end_value: 180
- lvgl.indicator.update:
id: meter_arc_indicator
value: 90
opa: 50%
- lvgl.indicator.update:
id: minute_hand
@@ -125,14 +120,6 @@ lvgl:
- anim_color
duration: 3s
loop: true
- lvgl.animation.start:
id: anim_slide
start_delay: 250ms
- lvgl.update:
disp_bg_color: 0x101010
disp_bg_opa: 80%
- lvgl.update:
disp_bg_image: cat_image
on_invalidate_area:
logger.log: Invalidate area
on_resolution_change:
@@ -704,11 +691,8 @@ lvgl:
on_long_press:
lvgl.matrix.button.update:
id: [button_a, button_e, button_c]
width: 2
selected: true
control:
disabled: true
checkable: true
on_click:
logger.log:
format: "matrix button clicked: %d, is button_a = %u"
@@ -1087,13 +1071,6 @@ lvgl:
outline_width: 4
outline_pad: 4
outline_opa: cover
- lvgl.canvas.draw_rectangle:
x: 10
y: 10
width: !lambda return 120;
height: !lambda return 80;
shadow_ofs_x: 3
shadow_ofs_y: 3
- lvgl.canvas.set_pixels:
color: red
points:
@@ -1127,12 +1104,6 @@ lvgl:
text: Canvas Text
align: center
max_width: 150
- lvgl.canvas.draw_text:
x: 20
y: 150
font: montserrat_18
text: Lambda Width
max_width: !lambda return 120;
- lvgl.canvas.draw_image:
src: cat_image
x: 100
@@ -1144,20 +1115,6 @@ lvgl:
skew_y: 5
pivot_x: 25
pivot_y: 25
- lvgl.canvas.draw_image:
src: cat_image
x: 50
y: 50
angle: 45
scale: 1.5
opa: 70%
recolor: red
recolor_opa: 30%
- lvgl.canvas.draw_image:
src: cat_image
x: 60
y: 60
zoom: 2.0
- lvgl.canvas.draw_rectangle:
x: 10
y: 10
@@ -1396,12 +1353,6 @@ lvgl:
column: 1
text: !lambda return str_sprintf("%.1f", (float) rand() / RAND_MAX * 100);
merge_right: false
- lvgl.table.cell.update:
id: table_id
row: 0
column: 1
text: cropped
text_crop: true
- lvgl.table.update:
id: table_id
selected_row: !lambda return (int) ((float) rand() / RAND_MAX * 2);
@@ -1433,9 +1384,6 @@ lvgl:
- 180, 60
- 240, 10
- lvgl.page.next:
- lvgl.page.next:
animation: move_left
time: 200ms
- switch:
align: right_mid
- checkbox:
@@ -75,8 +75,6 @@ lvgl:
on_draw_end:
- logger.log: draw ended
- lvgl.pause:
- lvgl.pause:
show_snow: true
- component.update: tft_display
- delay: 60s
- lvgl.resume:
@@ -20,6 +20,3 @@ esphome:
- max7219digit.reverse_on:
- max7219digit.reverse_off:
- max7219digit.intensity: 10
- max7219digit.intensity:
intensity: 7
- max7219digit.intensity: !lambda return 3;
-58
View File
@@ -53,60 +53,6 @@ media_player:
- media_player.unshuffle: test_media_player
- media_player.group_join: test_media_player
- media_player.clear_playlist: test_media_player
- media_player.play:
id: test_media_player
announcement: true
- media_player.pause:
id: test_media_player
announcement: true
- media_player.toggle:
id: test_media_player
announcement: true
- media_player.turn_on:
id: test_media_player
announcement: true
- media_player.turn_off:
id: test_media_player
announcement: true
- media_player.next:
id: test_media_player
announcement: true
- media_player.previous:
id: test_media_player
announcement: true
- media_player.mute:
id: test_media_player
announcement: true
- media_player.unmute:
id: test_media_player
announcement: true
- media_player.repeat_off:
id: test_media_player
announcement: true
- media_player.repeat_one:
id: test_media_player
announcement: true
- media_player.repeat_all:
id: test_media_player
announcement: true
- media_player.shuffle:
id: test_media_player
announcement: true
- media_player.unshuffle:
id: test_media_player
announcement: true
- media_player.group_join:
id: test_media_player
announcement: true
- media_player.clear_playlist:
id: test_media_player
announcement: true
- media_player.volume_up:
id: test_media_player
announcement: true
- media_player.volume_down:
id: test_media_player
announcement: true
- wait_until:
media_player.is_idle: test_media_player
- wait_until:
@@ -140,7 +86,3 @@ media_player:
id: test_media_player
media_url: http://localhost/media.mp3
announcement: true
- media_player.enqueue:
id: test_media_player
media_url: http://localhost/media.mp3
announcement: !lambda return true;
@@ -10,10 +10,6 @@ button:
id: midea_unit
temperature: !lambda return id(midea_unit).target_temperature + 1.0f;
use_fahrenheit: !lambda return false;
- midea_ac.follow_me:
id: midea_unit
temperature: 24.0
beeper: !lambda return true;
- midea_ac.display_toggle:
id: midea_unit
- midea_ac.swing_step:
@@ -30,9 +30,6 @@ esphome:
temperature: 22.0
- mitsubishi_cn105.clear_remote_temperature:
id: ac
- mitsubishi_cn105.set_remote_temperature:
id: ac
temperature: !lambda return 21.5f;
- mitsubishi_cn105.vane.control:
id: ac
vertical:
-209
View File
@@ -186,215 +186,6 @@ button:
read_address: 0x0420
read_count: 1
- platform: template
name: "Typed Handlers"
on_press:
- modbus_client.read_coils:
address: !lambda "return 1;"
start_address: !lambda "return 0x03;"
count: !lambda "return 8;"
continuous: !lambda "return false;"
allow_broadcast_read: !lambda "return false;"
on_sent:
then:
- logger.log: "coils sent"
on_not_sent:
then:
- lambda: 'ESP_LOGW("modbus_client.test", "coils not sent fc 0x%X", request.empty() ? 0 : request[0]);'
on_no_response:
then:
- logger.log: "coils timeout"
retry: !lambda "return false;"
on_custom_response:
then:
- lambda: 'ESP_LOGW("modbus_client.test", "coils custom reply %u bytes", (unsigned) response.size());'
- modbus_client.read_coils:
address: 0
start_address: 0x03
allow_broadcast_read: true
on_response:
then:
- lambda: 'ESP_LOGI("modbus_client.test", "broadcast coil0=%d", bits[0]);'
- modbus_client.read_discrete_inputs:
address: !lambda "return 1;"
start_address: !lambda "return 0x00;"
count: 4
continuous: !lambda "return true;"
on_sent:
then:
- logger.log: "inputs sent"
on_not_sent:
then:
- logger.log: "inputs not sent"
on_no_response: !lambda "return false;"
on_response:
then:
- lambda: 'ESP_LOGI("modbus_client.test", "input0=%d n=%u", bits[0], (unsigned) bits.size());'
on_custom_response:
then:
- logger.log: "inputs custom reply"
- modbus_client.read_discrete_inputs:
address: 0
start_address: 0x00
allow_broadcast_read: true
- modbus_client.read_holding_registers:
address: 0x01
start_address: !lambda "return 0x10;"
continuous: !lambda "return true;"
on_sent:
then:
- logger.log: "holding sent"
on_custom_response:
then:
- lambda: 'ESP_LOGW("modbus_client.test", "holding custom reply fc 0x%X", response.empty() ? 0 : response[0]);'
- modbus_client.read_input_registers:
address: !lambda "return 1;"
start_address: !lambda "return 0x20;"
count: 3
on_sent:
then:
- logger.log: "inputs regs sent"
on_not_sent:
then:
- logger.log: "input regs not sent"
on_error:
then:
- lambda: 'ESP_LOGW("modbus_client.test", "input regs exception %d", (int) exception_code);'
on_no_response:
then:
- logger.log: "input regs timeout"
on_response:
then:
- lambda: 'ESP_LOGI("modbus_client.test", "input reg0=%u n=%u", values[0], (unsigned) values.size());'
- modbus_client.read_input_registers:
address: 0
start_address: 0x20
allow_broadcast_read: true
- modbus_client.read_write_multiple_registers:
address: !lambda "return 1;"
write_address: !lambda "return 0x0300;"
values: [1, 2]
read_address: !lambda "return 0x0400;"
read_count: !lambda "return 2;"
allow_broadcast_read: !lambda "return false;"
on_sent:
then:
- logger.log: "rw sent"
on_not_sent:
then:
- logger.log: "rw not sent"
on_error:
then:
- lambda: 'ESP_LOGW("modbus_client.test", "rw exception %d", (int) exception_code);'
on_no_response:
then:
- logger.log: "rw timeout"
on_custom_response:
then:
- logger.log: "rw custom reply"
- modbus_client.send:
address: 0
pdu: [0x03, 0x00, 0x10, 0x00, 0x01]
allow_broadcast_read: true
- modbus_client.send:
address: !lambda "return 1;"
pdu: [0x06, 0x01, 0x02, 0x00, 0x2A]
continuous: !lambda "return false;"
expect_broadcast_write_response: !lambda "return false;"
- modbus_client.write_multiple_coils:
address: !lambda "return 1;"
start_address: !lambda "return 0x0010;"
values: [true, false]
expect_broadcast_write_response: !lambda "return false;"
on_sent:
then:
- logger.log: "coils write sent"
on_not_sent:
then:
- logger.log: "coils write not sent"
on_no_response:
then:
- logger.log: "coils write timeout"
on_response:
then:
- logger.log: "coils write acked"
on_custom_response:
then:
- logger.log: "coils write custom reply"
- modbus_client.write_multiple_coils:
address: 0
start_address: 0x0010
values: [true]
expect_broadcast_write_response: true
- modbus_client.write_multiple_registers:
address: !lambda "return 1;"
start_address: !lambda "return 0x0200;"
values: [1, 2]
on_sent:
then:
- logger.log: "regs write sent"
on_not_sent:
then:
- logger.log: "regs write not sent"
on_error:
then:
- lambda: 'ESP_LOGW("modbus_client.test", "regs write exception %d", (int) exception_code);'
on_no_response:
then:
- logger.log: "regs write timeout"
on_custom_response:
then:
- logger.log: "regs write custom reply"
- modbus_client.write_multiple_registers:
address: 0
start_address: 0x0200
values: [7]
expect_broadcast_write_response: true
- modbus_client.write_single_coil:
address: !lambda "return 1;"
start_address: !lambda "return 0x01;"
value: !lambda "return false;"
expect_broadcast_write_response: !lambda "return false;"
on_sent:
then:
- logger.log: "coil sent"
on_not_sent:
then:
- logger.log: "coil not sent"
on_error:
then:
- lambda: 'ESP_LOGW("modbus_client.test", "coil exception %d", (int) exception_code);'
on_no_response:
then:
- logger.log: "coil timeout"
on_response:
then:
- logger.log: "coil acked"
on_custom_response:
then:
- logger.log: "coil custom reply"
- modbus_client.write_single_coil:
address: 0
start_address: 0x01
value: true
expect_broadcast_write_response: true
- modbus_client.write_single_register:
address: 0x01
start_address: !lambda "return 0x0102;"
value: 42
expect_broadcast_write_response: !lambda "return false;"
on_sent:
then:
- logger.log: "register sent"
on_not_sent:
then:
- logger.log: "register not sent"
on_no_response:
then:
- logger.log: "register timeout"
on_custom_response:
then:
- logger.log: "register custom reply"
number:
- platform: template
name: "Modbus Client Write Value"
+1 -3
View File
@@ -8,9 +8,7 @@ esphome:
condition:
modem.enabled:
then:
- modem.send_at: "AT+CGSN"
- modem.send_at:
command: !lambda 'return std::string("AT+CSQ");'
modem.send_at: "AT+CGSN"
else:
modem.enable:
- if:
-12
View File
@@ -109,18 +109,6 @@ button:
return payload;
qos: !lambda return 1;
retain: !lambda return false;
- mqtt.publish_json:
topic: some/topic/json
payload: |-
root["key"] = "value";
qos: 1
retain: true
- mqtt.publish_json:
topic: !lambda return "some/topic/json/lambda";
payload: |-
root["key"] = 1;
qos: !lambda return 2;
retain: !lambda return false;
climate:
- platform: thermostat
-13
View File
@@ -42,19 +42,6 @@ button:
cycle: false
- number.to_min: number_test_number
- number.to_max: number_test_number
- number.increment:
id: number_test_number
mode: INCREMENT
cycle: true
- number.decrement:
id: number_test_number
mode: DECREMENT
- number.to_min:
id: number_test_number
mode: TO_MIN
- number.to_max:
id: number_test_number
mode: TO_MAX
- number.operation:
id: number_test_number
operation: increment
@@ -18,5 +18,3 @@ switch:
turn_off_action:
then:
- openthread.set_poll_period: 5s
- openthread.set_poll_period:
poll_period: !lambda return 10000;
-6
View File
@@ -15,12 +15,6 @@ esphome:
- output.set_max_power:
id: output_light_output_1
max_power: 80%
- output.set_min_power:
id: output_light_output_1
min_power: !lambda return 0.1f;
- output.set_max_power:
id: output_light_output_1
max_power: !lambda return 0.9f;
output:
- platform: ${output_platform}
-5
View File
@@ -11,11 +11,6 @@ esphome:
- tag.set_emulation_message:
message: https://www.home-assistant.io/tag/pulse
include_android_app_record: false
- tag.set_write_message:
message: !lambda return std::string("https://www.home-assistant.io/tag/lambda");
- tag.set_emulation_message:
message: !lambda return std::string("https://www.home-assistant.io/tag/lambda");
include_android_app_record: true
- tag.emulation_off: nfcc_pn7150
- tag.emulation_on: nfcc_pn7150
- tag.polling_off: nfcc_pn7150
@@ -564,482 +564,3 @@ button:
on_press:
- remote_transmitter.transmit_pd_pioneer:
code: [0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x80]
- platform: template
name: Repeat on every protocol
on_press:
- remote_transmitter.transmit_abbwelcome:
source_address: 0x1234
destination_address: 0x5678
message_type: 0x01
data: [0x10]
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_aeha:
address: 0x8008
data: [0x00, 0x02]
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_beo4:
source: 0x01
command: 0x0C
command_repeats: 3
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_brennenstuhl:
code: 0xBD2E2C
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_byronsx:
address: 0x12
command: 0x05
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_canalsat:
device: 0x25
address: 0x01
command: 0x1C
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_canalsatld:
device: 0x25
address: 0x02
command: 0x1C
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_coolix:
first: 0xB2BF40
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_dish:
address: 1
command: 16
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_dooya:
id: 0x123456
channel: 1
button: 1
check: 1
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_drayton:
address: 0x1234
channel: 0x01
command: 0x05
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_dyson:
code: 0x1215
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_gobox:
code: 1
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_haier:
code: [0xA6, 0xDA, 0x00, 0x00, 0x40, 0x40, 0x00, 0x80]
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_hob2hood:
command: fan_low
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_ira211:
command: power
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_jvc:
data: 0x10EF
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_keeloq:
address: 0x57ffe7b
command: 0x02
code: 0xd19ef0a9
level: true
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_lg:
data: 0x20DF10EF
nbits: 32
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_magiquest:
wand_id: 0x01234567
magnitude: 0x1234
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_midea:
code: [0xA2, 0x08, 0xFF, 0xFF, 0xFF]
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_mirage:
code: [0x56, 0x77, 0x00, 0x00, 0x22, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_nec:
address: 0x4242
command: 0x8484
command_repeats: 3
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_nexa:
device: 0x38DDB5A
group: 0
state: 1
channel: 15
level: 0
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_nexus:
channel: 1
address: 0x42
temperature: 21.5
humidity: 50
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_onkyori:
data: 0xD9
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_panasonic:
address: 0x4004
command: 0x1000BCD
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_pd_pioneer:
code: [0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x80]
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_pioneer_wyt:
code: [0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x80]
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_pronto:
data: "0000 006D 0001 0000 0015 0016"
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_raw:
code: [1000, -1000]
carrier_frequency: 38kHz
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc5:
address: 0x00
command: 0x0B
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc5x:
address: 0x10
command: 0x0
extension: 0x6
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc6:
address: 0x00
command: 0x0C
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc_switch_raw:
code: "001010011001111101010000"
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc_switch_type_a:
group: "11001"
device: "01000"
state: true
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc_switch_type_b:
address: 4
channel: 2
state: true
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc_switch_type_c:
family: "a"
group: 1
device: 2
state: true
protocol: 2
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_rc_switch_type_d:
group: "a"
device: 2
state: true
protocol:
pulse_length: 350
sync: [1, 31]
zero: [1, 3]
one: [3, 1]
inverted: true
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_roomba:
data: 0x88
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_samsung:
data: 0xABCDEF0123
nbits: 40
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_samsung36:
address: 0x0400
command: 0x000E00FF
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_sony:
data: 0xABCDEF
nbits: 12
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_symphony:
data: 0xE88
nbits: 12
command_repeats: 4
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_toshiba_ac:
rc_code_1: 0xB24DBF4050AF
repeat:
times: 2
wait_time: 10ms
- remote_transmitter.transmit_jvc:
data: 0x10EF
repeat: 3
- remote_transmitter.transmit_nec:
address: 0x4242
command: 0x8484
repeat:
times: !lambda return 2;
wait_time: !lambda return 10000;
- platform: template
name: Lambda fields on every protocol
on_press:
- remote_transmitter.transmit_abbwelcome:
source_address: !lambda return 0x1234;
destination_address: !lambda return 0x5678;
three_byte_address: !lambda return false;
retransmission: !lambda return true;
message_type: !lambda return 0x01;
message_id: !lambda return 0x42;
data: [0x10, 0x20]
- remote_transmitter.transmit_aeha:
address: !lambda return 0x8008;
carrier_frequency: !lambda return 38000;
data: [0x00, 0x02]
- remote_transmitter.transmit_aok:
remote_id: !lambda return 0x123456;
channels: 0x00A1
command: !lambda return 0x0B;
- remote_transmitter.transmit_beo4:
source: !lambda return 0x01;
command: !lambda return 0x0C;
command_repeats: !lambda return 2;
- remote_transmitter.transmit_brennenstuhl:
code: !lambda return 0xBD2E2C;
- remote_transmitter.transmit_byronsx:
address: !lambda return 0x12;
command: !lambda return 0x05;
- remote_transmitter.transmit_canalsat:
device: !lambda return 0x25;
address: !lambda return 0x01;
command: !lambda return 0x1C;
- remote_transmitter.transmit_canalsatld:
device: !lambda return 0x25;
address: !lambda return 0x01;
command: 0x1C
- remote_transmitter.transmit_coolix:
first: !lambda return 0xB2BF40;
second: !lambda return 0xB2BF40;
- remote_transmitter.transmit_dish:
address: !lambda return 1;
command: !lambda return 16;
- remote_transmitter.transmit_dooya:
id: !lambda return 0x123456;
channel: !lambda return 1;
button: !lambda return 1;
check: !lambda return 1;
- remote_transmitter.transmit_drayton:
address: !lambda return 0x1230;
data: !lambda return 0x8;
- remote_transmitter.transmit_drayton:
address: 0x1234
channel: !lambda return 0x01;
command: !lambda return 0x05;
- remote_transmitter.transmit_dyson:
code: !lambda return 0x1215;
index: !lambda return 0x0;
- remote_transmitter.transmit_gobox:
code: !lambda return 1;
- remote_transmitter.transmit_hob2hood:
command: !lambda return remote_base::HOB2HOOD_COMMAND_FAN_HIGH;
- remote_transmitter.transmit_ira211:
command: !lambda return remote_base::IRA211Command::IRA211_COMMAND_POWER;
temperature: !lambda return 21.5;
mode: !lambda return remote_base::IRA211Mode::IRA211_MODE_TIMER;
fan_mode: !lambda return remote_base::IRA211Fan::IRA211_FAN_LOW;
- remote_transmitter.transmit_jvc:
data: !lambda return 0x10EF;
- remote_transmitter.transmit_keeloq:
address: 0x57ffe7b
command: !lambda return 0x02;
code: !lambda return 0xd19ef0a9;
level: !lambda return true;
- remote_transmitter.transmit_keeloq:
address: 0x1234500
command: 0x8
code: 0xF94A09F2
group: !lambda return 0x0F;
- remote_transmitter.transmit_keeloq:
address: 0x116ea01
command: 0x08
code: 0xd19ef0a9
suffix: !lambda return 0x00;
suffix_bits: !lambda return 8;
- remote_transmitter.transmit_lg:
data: !lambda return 0xFFFFFFFF;
nbits: !lambda return 28;
- remote_transmitter.transmit_magiquest:
wand_id: !lambda return 0x01234567;
magnitude: !lambda return 0xFFFF;
- remote_transmitter.transmit_nec:
address: !lambda return 0x4242;
command: !lambda return 0x8484;
command_repeats: !lambda return 1;
- remote_transmitter.transmit_nexa:
device: !lambda return 0x38DDB5A;
group: !lambda return 0;
state: !lambda return 1;
channel: !lambda return 15;
level: !lambda return 0;
- remote_transmitter.transmit_nexus:
channel: !lambda return 1;
address: !lambda return 0x42;
temperature: !lambda return -12.3f;
humidity: !lambda return 69;
battery_level: !lambda return false;
force_update: !lambda return true;
- remote_transmitter.transmit_onkyori:
data: !lambda return 0xD9;
- remote_transmitter.transmit_panasonic:
nbits: !lambda return 56;
address: !lambda return 0x4004;
address_2: !lambda return 0x12;
command: 0x1000BCD
carrier_frequency: !lambda return 36000;
- remote_transmitter.transmit_pd_pioneer:
code: !lambda return {0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x80};
- remote_transmitter.transmit_pioneer:
rc_code_1: !lambda return 0xA556;
rc_code_2: !lambda return 0xA506;
- remote_transmitter.transmit_pioneer_wyt:
code: !lambda return {0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x80};
- remote_transmitter.transmit_pronto:
data: !lambda return std::string("0000 006D 0001 0000 0015 0016");
- remote_transmitter.transmit_rc5:
address: !lambda return 0x00;
command: !lambda return 0x0B;
- remote_transmitter.transmit_rc5x:
address: !lambda return 0x10;
command: !lambda return 0x0;
extension: !lambda return 0x6;
- remote_transmitter.transmit_rc6:
address: !lambda return 0x00;
command: 0x0C
- remote_transmitter.transmit_rc_switch_raw:
code: !lambda return std::string("001010011001111101010000");
- remote_transmitter.transmit_rc_switch_type_a:
group: !lambda return std::string("11001");
device: !lambda return std::string("01000");
state: !lambda return true;
- remote_transmitter.transmit_rc_switch_type_b:
address: !lambda return 4;
channel: !lambda return 2;
state: !lambda return false;
- remote_transmitter.transmit_rc_switch_type_c:
family: !lambda return std::string("a");
group: !lambda return 1;
device: !lambda return 2;
state: !lambda return true;
- remote_transmitter.transmit_rc_switch_type_d:
group: !lambda return std::string("a");
device: !lambda return 2;
state: !lambda return true;
- remote_transmitter.transmit_roomba:
data: !lambda return 0x88;
- remote_transmitter.transmit_samsung:
data: !lambda return 0xABCDEF;
nbits: !lambda return 32;
- remote_transmitter.transmit_samsung36:
address: !lambda return 0x0400;
command: !lambda return 0x000E00FF;
- remote_transmitter.transmit_somfy_rts:
address: !lambda return 0x630139;
control: !lambda return 0x08;
key: !lambda return 0xA0;
rolling_code: 1234
control_in_key: !lambda return false;
- remote_transmitter.transmit_sony:
data: !lambda return 0xABCDEF;
nbits: !lambda return 15;
- remote_transmitter.transmit_symphony:
data: !lambda return 0xE88;
nbits: !lambda return 12;
command_repeats: !lambda return 2;
- remote_transmitter.transmit_toshiba_ac:
rc_code_1: !lambda return 0xB24DBF4050AF;
rc_code_2: !lambda return 0xD5660001003C;
- remote_transmitter.transmit_toto:
command: !lambda return 0xEC;
rc_code_1: !lambda return 0x0D;
rc_code_2: !lambda return 0x0D;
- remote_transmitter.transmit_raw:
code: [1000, -1000]
carrier_frequency: !lambda return 38000;
-11
View File
@@ -12,11 +12,6 @@ rf_bridge:
high: 0x1234
code: 0x123456
- rf_bridge.learn
- rf_bridge.send_code:
sync: !lambda return 0x1234;
low: !lambda return 0x1234;
high: !lambda return 0x1234;
code: !lambda return 0x123456;
on_advanced_code_received:
- lambda: |-
uint32_t test;
@@ -32,12 +27,6 @@ rf_bridge:
code: "ABC123"
- rf_bridge.send_raw:
raw: "AAA5070008001000ABC12355"
- rf_bridge.send_advanced_code:
length: !lambda return 0x04;
protocol: !lambda return 0x01;
code: !lambda return std::string("ABC123");
- rf_bridge.send_raw:
raw: !lambda return std::string("AAA5070008001000ABC12355");
- rf_bridge.start_bucket_sniffing:
- rf_bridge.beep:
duration: !lambda return 100;
-8
View File
@@ -21,14 +21,6 @@ esphome:
- rx8111.schedule_alarm_in:
id: rtc
duration: !lambda return uint32_t{60};
- rx8111.set_alarm:
id: rtc
second: !lambda return uint16_t{30};
hour: !lambda return uint16_t{6};
weekday: !lambda return uint16_t{3};
- rx8111.set_alarm:
id: rtc
day: !lambda return uint16_t{20};
- rx8111.clear_alarm_flag: rtc
- rx8111.clear_timer_flag: rtc
- rx8111.clear_event_flag: rtc
-22
View File
@@ -29,28 +29,6 @@ esphome:
then:
- logger.log: a script is running
- script.execute: my_script_stops_itself
- delay:
minutes: 1
seconds: 2
milliseconds: 3
- delay:
hours: 1
- if:
all:
- script.is_running: my_script
- lambda: return true;
then:
- logger.log: all conditions true
- wait_until:
condition:
not:
script.is_running: my_script
timeout: !lambda return 2000;
- wait_until:
condition:
not:
script.is_running: my_script
timeout: 500ms
- choose:
- if:
script.is_running: my_script
@@ -21,7 +21,3 @@ button:
name: seeed_multi_channel_relay change address
on_press:
- seeed_multi_channel_relay.change_address: 0x12
- seeed_multi_channel_relay.change_address:
address: 0x13
- seeed_multi_channel_relay.change_address:
address: !lambda return 0x14;
-13
View File
@@ -37,19 +37,6 @@ button:
cycle: false
- select.first: select_test_select
- select.last: select_test_select
- select.next:
id: select_test_select
mode: NEXT
cycle: true
- select.previous:
id: select_test_select
mode: PREVIOUS
- select.first:
id: select_test_select
mode: FIRST
- select.last:
id: select_test_select
mode: LAST
- if:
condition:
select.is:
-7
View File
@@ -10,13 +10,6 @@ esphome:
- sim800l.disconnect
- sim800l.send_ussd:
ussd: test_ussd
- sim800l.send_sms:
recipient: !lambda return std::string("+15550000000");
message: !lambda return std::string("Lambda message");
- sim800l.dial:
recipient: !lambda return std::string("+15550000001");
- sim800l.send_ussd:
ussd: !lambda return std::string("*100#");
sim800l:
on_sms_received:
@@ -57,10 +57,6 @@ media_player:
id: media_player_id
pipeline: media
delay: 500ms
- speaker_source.set_playlist_delay:
id: media_player_id
pipeline: announcement
delay: !lambda return 250;
- speaker_source.set_announcement_volume:
id: media_player_id
volume: !lambda return x;
-10
View File
@@ -43,16 +43,6 @@ esphome:
id: yard_sprinkler_ctrlr
valve_number: !lambda return 1;
run_duration: !lambda return 120;
- sprinkler.set_divider:
id: yard_sprinkler_ctrlr
divider: !lambda return 3;
- sprinkler.set_repeat:
id: yard_sprinkler_ctrlr
repeat: !lambda return 1;
- sprinkler.start_single_valve:
id: yard_sprinkler_ctrlr
valve_number: !lambda return 1;
run_duration: !lambda return 240;
switch:
- platform: template
-9
View File
@@ -34,12 +34,3 @@ switch:
- stepper.set_deceleration:
id: test_stepper
deceleration: 250 steps/s^2
- stepper.report_position:
id: test_stepper
position: !lambda return 100;
- stepper.set_speed:
id: test_stepper
speed: !lambda return 200.0f;
- stepper.set_deceleration:
id: test_stepper
deceleration: !lambda return 180.0f;
-6
View File
@@ -19,9 +19,3 @@ button:
elevation: !lambda return 10.0;
then:
- logger.log: High sun
- if:
condition:
sun.is_below_horizon:
elevation: !lambda return -12.0;
then:
- logger.log: Deep night
-6
View File
@@ -25,12 +25,6 @@ esphome:
vol_range_min: 0.2
vol_range_max: 0.9
channel: left
- tas2780.update_config:
id: tas2780_amp
amp_level: !lambda return 12;
vol_range_min: !lambda return 0.1f;
vol_range_max: !lambda return 0.8f;
channel: !lambda return tas2780::RIGHT_CHANNEL;
- tas2780.deactivate:
id: tas2780_amp
- tas2780.reset:
@@ -30,9 +30,6 @@ binary_sensor:
id: kb
key: 0x28 # Enter
modifiers: !lambda return 0;
- tinyusb_keyboard.press:
id: kb
key: !lambda return 0x04;
on_release:
- tinyusb_keyboard.release: kb
@@ -42,8 +39,5 @@ binary_sensor:
- tinyusb_keyboard.media_press:
id: kb
usage: 0xE9 # Volume Up
- tinyusb_keyboard.media_press:
id: kb
usage: !lambda return 0xEA;
on_release:
- tinyusb_keyboard.media_release: kb
-9
View File
@@ -15,15 +15,6 @@ esphome:
- tm1651.set_brightness:
id: tm1651_battery
brightness: 2
- tm1651.set_level_percent:
id: tm1651_battery
level_percent: !lambda return 75;
- tm1651.set_level:
id: tm1651_battery
level: !lambda return 3;
- tm1651.set_brightness:
id: tm1651_battery
brightness: !lambda return 1;
- tm1651.turn_on:
id: tm1651_battery
- tm1651.turn_off:
Loaded 100 of 113 files, more files were not shown because too many files have changed in this diff. Show more