[tests] Fail component test merge on conflicting duplicate IDs (#16849)

This commit is contained in:
J. Nick Koston
2026-06-08 12:49:25 -05:00
committed by GitHub
parent 54c73bf1bc
commit 36e043debb
125 changed files with 836 additions and 372 deletions

View File

@@ -113,6 +113,7 @@ jobs:
script/build_language_schema.py --check
script/generate-esp32-boards.py --check
script/generate-rp2040-boards.py --check
script/ci_check_duplicate_test_ids.py
import-time:
name: Check import esphome.__main__ time

View File

@@ -39,8 +39,13 @@ from helpers import BASE_BUS_COMPONENTS, is_validate_only_file
from esphome import yaml_util
from esphome.config_helpers import Extend, Remove
# Path to common bus configs
COMMON_BUS_PATH = Path("tests/test_build_components/common")
# Path to common bus configs (resolved relative to this file, not the CWD)
COMMON_BUS_PATH = (
Path(__file__).resolve().parent.parent
/ "tests"
/ "test_build_components"
/ "common"
)
# Package dependencies - maps packages to the packages they include
# When a component uses a package on the left, it automatically gets

View File

@@ -0,0 +1,214 @@
#!/usr/bin/env python3
"""Fail when two component test fixtures define the same id with different content.
Component tests are merged and built in groups in CI (see
``script/merge_component_configs.py``). When two components declare the same id
under the same section but with different content, the merge keeps the first and
drops the rest, which can make a cross-reference resolve to an incompatible
entity (this is what broke the i2s_audio speaker tests). That only surfaces when
the two components happen to land in the same group, often in an unrelated PR
long after the duplicate was written.
This script is the complete, batch-independent guard: it scans every component's
``test.<platform>.yaml`` per platform and reports any id that is defined by more
than one component with differing content, so a collision fails the PR that
introduces it and names the exact id and components.
To stay byte-for-byte consistent with what the merge actually does (so the guard
never disagrees with the build), it reuses the merge's own helpers:
* ``prefix_substitutions_in_dict`` -- the merge prefixes every component's
substitution references with the component name before deduplicating, so e.g.
``pin: ${pin}`` in two components becomes ``${a_pin}`` and ``${b_pin}`` and
conflicts. We apply the same prefixing; otherwise a shared id whose only
difference is a substitution looks identical here but conflicts at merge time.
* ``deduplicate_by_id`` -- the actual merge comparison (including the
``INTENTIONALLY_SHARED_IDS`` allowlist for deliberately shared singletons such
as ``sntp_time``). We feed each shared id's prefixed items straight through it
and treat a raised ``ValueError`` as a conflict, so this check and the merge
can never diverge.
``packages:`` are left as opaque ``!include`` objects by the loader -- exactly as
the merge sees them at dedup time -- so package-provided bus ids (``i2c_bus`` ...)
are not compared here, matching the merge, which re-adds those packages once.
"""
from __future__ import annotations
from collections import defaultdict
from collections.abc import Iterator
from dataclasses import dataclass, field
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
from esphome.core import EsphomeError # noqa: E402
from script.merge_component_configs import ( # noqa: E402
deduplicate_by_id,
load_yaml_file,
prepare_component_body,
)
# Resolved relative to this file (not the CWD) so the scan cannot silently cover
# nothing when run from a different directory.
TESTS_DIR = Path(__file__).resolve().parent.parent / "tests" / "components"
def _collect_ids(
data: object,
path: tuple[str, ...],
out: dict[tuple[tuple[str, ...], object], object],
) -> None:
"""Record (dict_path, id) -> item for id-bearing items in dict-reachable lists.
Keyed by the full dict path (not just the immediate key) so items under
different paths that happen to share a list key name are never compared. Only
lists reached purely through dict keys are recorded: once the merge
concatenates a list, items from different components live in separate elements,
so anything deeper is never compared across components (matching how
``merge_config`` combines bodies). Ids keep their original type so ``5`` and
``"5"`` stay distinct, exactly as ``deduplicate_by_id`` treats them; an
unhashable id (rare) falls back to its ``repr`` so it can still be grouped.
"""
if not isinstance(data, dict):
return
for key, value in data.items():
new_path = path + (key,)
if isinstance(value, list):
for item in value:
if isinstance(item, dict) and "id" in item:
item_id = item["id"]
try:
hash(item_id)
except TypeError:
item_id = repr(item_id)
out[(new_path, item_id)] = item
elif isinstance(value, dict):
_collect_ids(value, new_path, out)
def _discover_platforms() -> set[str]:
platforms: set[str] = set()
for test_file in TESTS_DIR.glob("*/test.*.yaml"):
# test.<platform>.yaml -> platform is the middle dotted part
parts = test_file.name.split(".")
if len(parts) == 3:
platforms.add(parts[1])
return platforms
def _load_components(
platform: str, parse_errors: list[str]
) -> Iterator[tuple[str, object]]:
"""Yield (component, prefixed config) for each component testing this platform.
Each body is prepared with ``prepare_component_body`` (the same helper the
merge uses: it expands component-specific package includes and prefixes
substitutions), so the comparison sees what the build merges. Fixtures that
fail to parse are recorded in ``parse_errors`` so the run can fail rather than
silently skip them.
"""
for comp_dir in sorted(TESTS_DIR.iterdir()):
test_file = comp_dir / f"test.{platform}.yaml"
if not comp_dir.is_dir() or not test_file.exists():
continue
try:
data = load_yaml_file(test_file)
except EsphomeError as err:
parse_errors.append(str(test_file))
print(f"ERROR: could not parse {test_file}: {err}", file=sys.stderr)
continue
yield comp_dir.name, prepare_component_body(data, comp_dir.name, comp_dir)
@dataclass
class ScanResult:
"""Outcome of a scan. A caller cannot observe a clean result while files were
skipped or nothing was scanned -- all three fields are reported together."""
conflicts: list[str] = field(default_factory=list)
parse_errors: list[str] = field(default_factory=list)
components_scanned: int = 0
def scan() -> ScanResult:
"""Scan every component's base test fixture and report cross-component id conflicts.
Only base ``test.<platform>.yaml`` fixtures are scanned because only those are
combined by ``merge_component_configs`` in grouped CI builds; variant
(``test-*.yaml``) fixtures are built individually and never cross-merged.
"""
result = ScanResult()
for platform in sorted(_discover_platforms()):
# (dict_path, id) -> {component: prefixed_item}
groups: dict[tuple[tuple[str, ...], object], dict[str, object]] = defaultdict(
dict
)
for component, data in _load_components(platform, result.parse_errors):
result.components_scanned += 1
collected: dict[tuple[tuple[str, ...], object], object] = {}
_collect_ids(data, (), collected)
for key, item in collected.items():
groups[key][component] = item
for (path, id_), by_component in sorted(
groups.items(), key=lambda kv: (kv[0][0], str(kv[0][1]))
):
if len(by_component) < 2:
continue
# Delegate the decision to the merge's own deduplication so this guard
# can never disagree with what the build does.
try:
deduplicate_by_id({path[-1]: list(by_component.values())})
except ValueError:
result.conflicts.append(
f"[{platform}] id '{id_}' under '{'.'.join(path)}' is defined "
f"differently by: {', '.join(sorted(by_component))}"
)
return result
def main() -> int:
result = scan()
if result.conflicts:
print("Conflicting test component ids found:\n")
for line in result.conflicts:
print(f" - {line}")
print(
"\nGive each component a unique id (e.g. '<component>_<id>'), or add the "
"id to INTENTIONALLY_SHARED_IDS in script/merge_component_configs.py if "
"it is a deliberately shared singleton."
)
if result.parse_errors:
# A fixture we could not parse was never scanned, so the run is not a
# clean pass even if no conflicts were found among the rest.
print(
f"\n{len(result.parse_errors)} test fixture(s) could not be parsed and "
"were not checked:"
)
for path in result.parse_errors:
print(f" - {path}")
if result.components_scanned == 0:
# A scan that covered nothing is a false green -- the whole point of the
# guard is defeated. Fail loudly (wrong working directory or layout change).
print(
f"\nERROR: scanned 0 component test fixtures under {TESTS_DIR}; "
"the guard covered nothing.",
file=sys.stderr,
)
if result.conflicts or result.parse_errors or result.components_scanned == 0:
return 1
print(
f"No conflicting test component ids found "
f"({result.components_scanned} fixtures scanned)."
)
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -161,18 +161,46 @@ def prefix_substitutions_in_dict(
return data
# (section, id) pairs that several components intentionally share. ESPHome
# treats these as a single instance when merged, so duplicates with differing
# content are expected and must not be flagged as accidental collisions. Keyed on
# the section as well as the id so a generic name (e.g. `ldo_id`) is only exempt
# in its intended section -- an accidental collision on the same name elsewhere
# is still caught.
INTENTIONALLY_SHARED_IDS = frozenset(
{
# Several components each declare an `sntp_time` clock; ESPHome merges
# them into one time source.
("time", "sntp_time"),
# esp_ldo and mipi_dsi both configure the channel-3 internal LDO on the
# ESP32-P4; only one LDO per channel may exist, so the shared id lets the
# merge collapse them into a single LDO.
("esp_ldo", "ldo_id"),
}
)
def deduplicate_by_id(data: dict) -> dict:
"""Deduplicate list items with the same ID.
Keeps only the first occurrence of each ID. If items with the same ID
are identical, this silently deduplicates. If they differ, the first
one is kept (ESPHome's validation will catch if this causes issues).
Identical items sharing an ID (e.g. a shared bus from a common package pulled
in by several components) are collapsed to the first occurrence. Two items
that share an ID but differ in content are a real conflict: when merged, the
first silently wins and the others are dropped, which can make a
cross-reference resolve to an incompatible entity. Rather than defer that to
downstream validation (where it surfaces as a confusing, order-dependent
failure in an unrelated build), raise immediately so the offending ID is
named. Ids in ``INTENTIONALLY_SHARED_IDS`` are deliberately shared singletons
and keep their collapse behaviour.
Args:
data: Parsed config dictionary
Returns:
Config with deduplicated lists
Raises:
ValueError: If two items share an ID but have different content.
"""
if not isinstance(data, dict):
return data
@@ -181,16 +209,25 @@ def deduplicate_by_id(data: dict) -> dict:
for key, value in data.items():
if isinstance(value, list):
# Check for items with 'id' field
seen_ids = set()
seen_items: dict[str, Any] = {}
deduped_list = []
for item in value:
if isinstance(item, dict) and "id" in item:
item_id = item["id"]
if item_id not in seen_ids:
seen_ids.add(item_id)
if item_id not in seen_items:
seen_items[item_id] = item
deduped_list.append(item)
# else: skip duplicate ID (keep first occurrence)
elif (key, item_id) in INTENTIONALLY_SHARED_IDS:
# Deliberately shared singleton -> keep first occurrence.
pass
elif item != seen_items[item_id]:
raise ValueError(
f"Conflicting definitions for id '{item_id}' under "
f"'{key}' when merging test configs; give each "
f"component a unique id"
)
# else: identical duplicate (e.g. shared bus package) -> skip
else:
# No ID, just add it
deduped_list.append(item)
@@ -205,6 +242,55 @@ def deduplicate_by_id(data: dict) -> dict:
return result
def prepare_component_body(comp_data: dict, comp_name: str, comp_dir: Path) -> dict:
"""Return a component's test body as it enters the merge.
Expands component-specific package includes inline (common bus packages are
left for the merge to re-add once), applies ESPHome's top-level-substitutions
-override-package-substitutions rule, then prefixes every substitution
reference with the component name. Shared by ``merge_component_configs`` and
the duplicate-id guard (``script/ci_check_duplicate_test_ids.py``) so the
guard compares exactly what the build merges.
"""
# $component_dir resolves to the component's absolute path.
comp_abs_dir = str(comp_dir.absolute())
# Top-level substitutions override package substitutions, so capture them
# before expanding packages can introduce their own.
top_level_subs = (
comp_data["substitutions"].copy()
if isinstance(comp_data.get("substitutions"), dict)
else {}
)
packages_value = comp_data.get("packages")
if isinstance(packages_value, dict):
common_bus_packages = get_common_bus_packages()
for pkg_name, pkg_value in list(packages_value.items()):
if pkg_name in common_bus_packages:
continue
if isinstance(pkg_value, yaml_util.IncludeFile):
pkg_value = pkg_value.load()
if isinstance(pkg_value, dict):
comp_data = merge_config(comp_data, pkg_value)
elif isinstance(packages_value, list):
for pkg_value in packages_value:
if isinstance(pkg_value, yaml_util.IncludeFile):
pkg_value = pkg_value.load()
if isinstance(pkg_value, dict):
comp_data = merge_config(comp_data, pkg_value)
# Common bus packages are re-added once by the caller; drop them here.
comp_data.pop("packages", None)
subs = comp_data.get("substitutions") or {}
subs.update(top_level_subs)
prefixed_subs = {f"{comp_name}_{name}": value for name, value in subs.items()}
prefixed_subs[f"{comp_name}_component_dir"] = comp_abs_dir
comp_data["substitutions"] = prefixed_subs
return prefix_substitutions_in_dict(comp_data, comp_name)
def merge_component_configs(
component_names: list[str],
platform: str,
@@ -266,67 +352,9 @@ def merge_component_configs(
# New package type - add it
all_packages[pkg_name] = pkg_config
# Handle $component_dir by replacing with absolute path
# This allows components that use local file references to be grouped
comp_abs_dir = str(comp_dir.absolute())
# Save top-level substitutions BEFORE expanding packages
# In ESPHome, top-level substitutions override package substitutions
top_level_subs = (
comp_data["substitutions"].copy()
if "substitutions" in comp_data and comp_data["substitutions"] is not None
else {}
)
# Expand packages - but we'll restore substitution priority after
if "packages" in comp_data:
packages_value = comp_data["packages"]
if isinstance(packages_value, dict):
# Dict format - check each package
common_bus_packages = get_common_bus_packages()
for pkg_name, pkg_value in list(packages_value.items()):
if pkg_name in common_bus_packages:
continue
# Resolve deferred !include files before checking type
if isinstance(pkg_value, yaml_util.IncludeFile):
pkg_value = pkg_value.load()
if not isinstance(pkg_value, dict):
continue
# Component-specific package - expand its content into top level
comp_data = merge_config(comp_data, pkg_value)
elif isinstance(packages_value, list):
# List format - expand all package includes
for pkg_value in packages_value:
# Resolve deferred !include files before checking type
if isinstance(pkg_value, yaml_util.IncludeFile):
pkg_value = pkg_value.load()
if not isinstance(pkg_value, dict):
continue
comp_data = merge_config(comp_data, pkg_value)
# Remove all packages (common will be re-added at the end)
del comp_data["packages"]
# Restore top-level substitution priority
# Top-level substitutions override any from packages
if "substitutions" not in comp_data or comp_data["substitutions"] is None:
comp_data["substitutions"] = {}
# Merge: package subs as base, top-level subs override
comp_data["substitutions"].update(top_level_subs)
# Now prefix the final merged substitutions
comp_data["substitutions"] = {
f"{comp_name}_{sub_name}": sub_value
for sub_name, sub_value in comp_data["substitutions"].items()
}
# Add component_dir substitution with absolute path for this component
comp_data["substitutions"][f"{comp_name}_component_dir"] = comp_abs_dir
# Prefix substitution references throughout the config
comp_data = prefix_substitutions_in_dict(comp_data, comp_name)
# Expand component-specific packages and prefix substitutions, exactly as
# the duplicate-id guard does, so both see the same body.
comp_data = prepare_component_body(comp_data, comp_name, comp_dir)
# Use ESPHome's merge_config to merge this component into the result
# merge_config handles list merging with ID-based deduplication automatically

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: P23
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: GPIO1
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: GPIO1
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: A0
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: GPIO16
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: GPIO1
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: GPIO1
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: VCC
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: A5
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: VCC
name: ADC Test sensor

View File

@@ -1,5 +1,5 @@
sensor:
- id: my_sensor
- id: adc_my_sensor
platform: adc
pin: VCC
name: ADC Test sensor

View File

@@ -1,6 +1,6 @@
binary_sensor:
- platform: gpio
id: bin1
id: alarm_control_panel_bin1
pin: 1
alarm_control_panel:
@@ -18,7 +18,7 @@ alarm_control_panel:
pending_time: 15s
trigger_time: 30s
binary_sensors:
- input: bin1
- input: alarm_control_panel_bin1
bypass_armed_home: true
bypass_armed_night: true
bypass_auto: true
@@ -39,7 +39,7 @@ alarm_control_panel:
pending_time: 15s
trigger_time: 30s
binary_sensors:
- input: bin1
- input: alarm_control_panel_bin1
bypass_armed_home: true
bypass_armed_night: true
bypass_auto: true

View File

@@ -4,7 +4,7 @@ packages:
display:
- platform: ili9xxx
id: main_lcd
id: animation_main_lcd
spi_id: spi_bus
model: ili9342
cs_pin: 12

View File

@@ -4,7 +4,7 @@ packages:
display:
- platform: ili9xxx
id: main_lcd
id: animation_main_lcd
spi_id: spi_bus
model: ili9342
cs_pin: 5

View File

@@ -4,7 +4,7 @@ packages:
display:
- platform: ili9xxx
id: main_lcd
id: animation_main_lcd
spi_id: spi_bus
model: ili9342
cs_pin: 20

View File

@@ -296,7 +296,7 @@ api:
event:
- platform: template
name: Test Event
id: test_event
id: api_test_event
event_types:
- single_click
- double_click

View File

@@ -1,5 +1,5 @@
audio_file:
- id: test_audio
- id: audio_file_test_audio
file:
type: local
path: $component_dir/test.wav

View File

@@ -1,5 +1,5 @@
audio_file:
- id: test_audio
- id: audio_file_test_audio
file:
type: local
path: $component_dir/test.wav

View File

@@ -1,7 +1,7 @@
display:
- platform: ssd1306_i2c
i2c_id: i2c_bus
id: ssd1306_i2c_display
id: axs15231_ssd1306_i2c_display
model: SSD1306_128X64
reset_pin: 19
pages:
@@ -13,6 +13,6 @@ touchscreen:
- platform: axs15231
i2c_id: i2c_bus
id: axs15231_touchscreen
display: ssd1306_i2c_display
display: axs15231_ssd1306_i2c_display
interrupt_pin: 20
reset_pin: 18

View File

@@ -4,7 +4,7 @@ packages:
display:
- platform: ssd1306_i2c
i2c_id: i2c_bus
id: ssd1306_display
id: axs15231_ssd1306_display
model: SSD1306_128X64
reset_pin: 13
pages:
@@ -15,5 +15,5 @@ display:
touchscreen:
- platform: axs15231
i2c_id: i2c_bus
display: ssd1306_display
display: axs15231_ssd1306_display
interrupt_pin: 12

View File

@@ -1,6 +1,6 @@
switch:
- platform: template
id: template_switch1
id: bang_bang_template_switch1
optimistic: true
- platform: template
id: template_switch2
@@ -8,7 +8,7 @@ switch:
sensor:
- platform: template
id: template_sensor1
id: bang_bang_template_sensor1
lambda: |-
if (millis() > 10000) {
return 42.0;
@@ -20,16 +20,16 @@ sensor:
climate:
- platform: bang_bang
name: Bang Bang Climate
sensor: template_sensor1
humidity_sensor: template_sensor1
sensor: bang_bang_template_sensor1
humidity_sensor: bang_bang_template_sensor1
default_target_temperature_low: 18°C
default_target_temperature_high: 24°C
idle_action:
- switch.turn_on: template_switch1
- switch.turn_on: bang_bang_template_switch1
cool_action:
- switch.turn_on: template_switch2
heat_action:
- switch.turn_on: template_switch1
- switch.turn_on: bang_bang_template_switch1
away_config:
default_target_temperature_low: 16°C
default_target_temperature_high: 20°C

View File

@@ -1,7 +1,7 @@
binary_sensor:
- platform: template
trigger_on_initial_state: true
id: some_binary_sensor
id: binary_sensor_some_binary_sensor
name: "Random binary"
lambda: return (random_uint32() & 1) == 0;
filters:
@@ -21,7 +21,7 @@ binary_sensor:
time_off: 100ms
time_on: 400ms
- lambda: |-
if (id(some_binary_sensor).state) {
if (id(binary_sensor_some_binary_sensor).state) {
return x;
}
return {};
@@ -36,7 +36,7 @@ binary_sensor:
- logger.log:
format: "New state is %s"
args: ['x.has_value() ? ONOFF(x) : "Unknown"']
- binary_sensor.invalidate_state: some_binary_sensor
- binary_sensor.invalidate_state: binary_sensor_some_binary_sensor
# Test autorepeat with default configuration (no timings)
- platform: template

View File

@@ -1,20 +1,20 @@
binary_sensor:
- platform: template
id: bin1
id: binary_sensor_map_bin1
lambda: |-
if (millis() > 10000) {
return true;
}
return false;
- platform: template
id: bin2
id: binary_sensor_map_bin2
lambda: |-
if (millis() > 20000) {
return true;
}
return false;
- platform: template
id: bin3
id: binary_sensor_map_bin3
lambda: |-
if (millis() > 30000) {
return true;
@@ -26,33 +26,33 @@ sensor:
name: Binary Sensor Map Group
type: group
channels:
- binary_sensor: bin1
- binary_sensor: binary_sensor_map_bin1
value: 10.0
- binary_sensor: bin2
- binary_sensor: binary_sensor_map_bin2
value: 15.0
- binary_sensor: bin3
- binary_sensor: binary_sensor_map_bin3
value: 100.0
- platform: binary_sensor_map
name: Binary Sensor Map Sum
type: sum
channels:
- binary_sensor: bin1
- binary_sensor: binary_sensor_map_bin1
value: 10.0
- binary_sensor: bin2
- binary_sensor: binary_sensor_map_bin2
value: 15.0
- binary_sensor: bin3
- binary_sensor: binary_sensor_map_bin3
value: 100.0
- platform: binary_sensor_map
name: Binary Sensor Map Bayesian
type: bayesian
prior: 0.4
observations:
- binary_sensor: bin1
- binary_sensor: binary_sensor_map_bin1
prob_given_true: 0.9
prob_given_false: 0.4
- binary_sensor: bin2
- binary_sensor: binary_sensor_map_bin2
prob_given_true: 0.7
prob_given_false: 0.05
- binary_sensor: bin3
- binary_sensor: binary_sensor_map_bin3
prob_given_true: 0.8
prob_given_false: 0.2

View File

@@ -56,7 +56,7 @@ sensor:
number:
- platform: template
name: "Test Number"
id: test_number
id: ble_client_test_number
optimistic: true
min_value: 0
max_value: 255
@@ -72,5 +72,5 @@ button:
service_uuid: "abcd1234-abcd-1234-abcd-abcd12345678"
characteristic_uuid: "abcd1235-abcd-1234-abcd-abcd12345678"
value: !lambda |-
uint8_t val = (uint8_t)id(test_number).state;
uint8_t val = (uint8_t)id(ble_client_test_number).state;
return std::vector<uint8_t>{0xAA, val, 0xBB};

View File

@@ -1,6 +1,6 @@
canbus:
- platform: esp32_can
id: esp32_internal_can
id: canbus_esp32_internal_can
rx_pin: 4
tx_pin: 5
can_id: 4
@@ -40,7 +40,7 @@ canbus:
number:
- platform: template
name: "Test Number"
id: test_number
id: canbus_test_number
optimistic: true
min_value: 0
max_value: 255
@@ -62,5 +62,5 @@ button:
- canbus.send: !lambda return {0, 1, 2};
# Test canbus.send with lambda that references a component (function pointer)
- canbus.send: !lambda |-
uint8_t val = (uint8_t)id(test_number).state;
uint8_t val = (uint8_t)id(canbus_test_number).state;
return std::vector<uint8_t>{0xAA, val, 0xBB};

View File

@@ -6,13 +6,13 @@ cd74hc4067:
sensor:
- platform: adc
id: esp_adc_sensor
id: cd74hc4067_esp_adc_sensor
pin: ${pin}
- platform: cd74hc4067
id: cd74hc4067_adc_0
number: 0
sensor: esp_adc_sensor
sensor: cd74hc4067_esp_adc_sensor
- platform: cd74hc4067
id: cd74hc4067_adc_1
number: 1
sensor: esp_adc_sensor
sensor: cd74hc4067_esp_adc_sensor

View File

@@ -1,6 +1,6 @@
sensor:
- platform: template
id: temp_sensor
id: climate_ir_lg_temp_sensor
lambda: return 22.0;
update_interval: 60s
- platform: template
@@ -12,5 +12,5 @@ climate:
- platform: climate_ir_lg
name: LG Climate
transmitter_id: xmitr
sensor: temp_sensor
sensor: climate_ir_lg_temp_sensor
humidity_sensor: humidity_sensor

View File

@@ -1,15 +1,15 @@
output:
- platform: ${light_platform}
id: light_output_1
id: color_temperature_light_output_1
pin: ${pin_o1}
- platform: ${light_platform}
id: light_output_2
id: color_temperature_light_output_2
pin: ${pin_o2}
light:
- platform: color_temperature
name: Lights
color_temperature: light_output_1
brightness: light_output_2
color_temperature: color_temperature_light_output_1
brightness: color_temperature_light_output_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds

View File

@@ -1,17 +1,17 @@
output:
- platform: ${pwm_platform}
id: fan_output_1
id: copy_fan_output_1
pin: ${pin}
fan:
- platform: speed
id: fan_speed
output: fan_output_1
id: copy_fan_speed
output: copy_fan_output_1
preset_modes:
- Eco
- Turbo
- platform: copy
source_id: fan_speed
source_id: copy_fan_speed
name: Fan Speed Copy
select:

View File

@@ -1,9 +1,9 @@
sensor:
- platform: adc
id: esp_adc_sensor
id: ct_clamp_esp_adc_sensor
pin: ${pin}
- platform: ct_clamp
sensor: esp_adc_sensor
sensor: ct_clamp_esp_adc_sensor
name: CT Clamp
sample_duration: 500ms
update_interval: 5s

View File

@@ -31,7 +31,7 @@ sensor:
switch:
- platform: template
id: template_switch1
id: current_based_template_switch1
optimistic: true
- platform: template
id: template_switch2
@@ -46,7 +46,7 @@ cover:
open_obstacle_current_threshold: 0.8
open_duration: 12s
open_action:
- switch.turn_on: template_switch1
- switch.turn_on: current_based_template_switch1
close_sensor: ade7953_current_b
close_moving_current_threshold: 0.5
close_obstacle_current_threshold: 0.8
@@ -54,7 +54,7 @@ cover:
close_action:
- switch.turn_on: template_switch2
stop_action:
- switch.turn_off: template_switch1
- switch.turn_off: current_based_template_switch1
- switch.turn_off: template_switch2
obstacle_rollback: 30%
start_sensing_delay: 0.8s

View File

@@ -1,8 +1,8 @@
light:
- platform: cwww
name: CWWW Light
cold_white: light_output_1
warm_white: light_output_2
cold_white: cwww_light_output_1
warm_white: cwww_light_output_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true

View File

@@ -5,11 +5,11 @@ substitutions:
output:
- platform: ${light_platform}
id: light_output_1
id: cwww_light_output_1
pin: ${pin_o1}
channel: 0
- platform: ${light_platform}
id: light_output_2
id: cwww_light_output_2
pin: ${pin_o2}
channel: 1
phase_angle: 180°

View File

@@ -5,10 +5,10 @@ substitutions:
output:
- platform: ${light_platform}
id: light_output_1
id: cwww_light_output_1
pin: ${pin_o1}
- platform: ${light_platform}
id: light_output_2
id: cwww_light_output_2
pin: ${pin_o2}
<<: !include common.yaml

View File

@@ -5,10 +5,10 @@ substitutions:
output:
- platform: ${light_platform}
id: light_output_1
id: cwww_light_output_1
pin: ${pin_o1}
- platform: ${light_platform}
id: light_output_2
id: cwww_light_output_2
pin: ${pin_o2}
<<: !include common.yaml

View File

@@ -1,6 +1,6 @@
binary_sensor:
- platform: template
id: bin1
id: duty_time_bin1
lambda: |-
if (millis() > 10000) {
return true;
@@ -10,4 +10,4 @@ binary_sensor:
sensor:
- platform: duty_time
name: Duty Time
sensor: bin1
sensor: duty_time_bin1

View File

@@ -2,7 +2,7 @@
light:
- platform: rp2040_pio_led_strip
id: led_strip
id: e131_led_strip
pin: 2
pio: 0
num_leds: 256

View File

@@ -1,7 +1,7 @@
display:
- platform: ssd1306_i2c
i2c_id: i2c_bus
id: ssd1306_i2c_display
id: ektf2232_ssd1306_i2c_display
model: SSD1306_128X64
reset_pin: ${display_reset_pin}
pages:
@@ -15,7 +15,7 @@ touchscreen:
id: ektf2232_touchscreen
interrupt_pin: ${interrupt_pin}
reset_pin: ${touch_reset_pin}
display: ssd1306_i2c_display
display: ektf2232_ssd1306_i2c_display
on_touch:
- logger.log:
format: Touch at (%d, %d)

View File

@@ -1,6 +1,6 @@
binary_sensor:
- platform: template
id: bin1
id: endstop_bin1
lambda: |-
if (millis() > 10000) {
return true;
@@ -9,7 +9,7 @@ binary_sensor:
switch:
- platform: template
id: template_switch1
id: endstop_template_switch1
optimistic: true
- platform: template
id: template_switch2
@@ -20,12 +20,12 @@ cover:
id: endstop_cover
name: Endstop Cover
stop_action:
- switch.turn_on: template_switch1
open_endstop: bin1
- switch.turn_on: endstop_template_switch1
open_endstop: endstop_bin1
open_action:
- switch.turn_on: template_switch1
- switch.turn_on: endstop_template_switch1
open_duration: 5min
close_endstop: bin1
close_endstop: endstop_bin1
close_action:
- switch.turn_on: template_switch2
close_duration: 4.5min

View File

@@ -13,7 +13,7 @@ esphome:
canbus:
- platform: esp32_can
id: esp32_internal_can
id: esp32_can_esp32_internal_can
rx_pin: ${rx_pin}
tx_pin: ${tx_pin}
can_id: 4

View File

@@ -3,20 +3,20 @@ esphome:
then:
- canbus.send:
# Extended ID explicit
canbus_id: esp32_internal_can
canbus_id: esp32_can_esp32_internal_can
use_extended_id: true
can_id: 0x100
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
- canbus.send:
# Standard ID by default
canbus_id: esp32_internal_can
canbus_id: esp32_can_esp32_internal_can
can_id: 0x100
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
# Note: esp32_internal_can_2 uses LISTENONLY mode, so no send actions
canbus:
- platform: esp32_can
id: esp32_internal_can
id: esp32_can_esp32_internal_can
rx_pin: GPIO8
tx_pin: GPIO7
can_id: 4

View File

@@ -62,7 +62,7 @@ packet_transport:
encryption:
key: "0123456789abcdef0123456789abcdef"
sensors:
- temp_sensor
- espnow_temp_sensor
providers:
- name: test-provider
encryption:
@@ -70,9 +70,9 @@ packet_transport:
sensor:
- platform: internal_temperature
id: temp_sensor
id: espnow_temp_sensor
- platform: packet_transport
provider: test-provider
remote_id: temp_sensor
remote_id: espnow_temp_sensor
id: remote_temp

View File

@@ -1,6 +1,6 @@
light:
- platform: fastled_clockless
id: addr1
id: fastled_clockless_addr1
chipset: WS2811
pin: 13
num_leds: 100
@@ -59,13 +59,13 @@ light:
name: Custom Effect
sequence:
- light.addressable_set:
id: addr1
id: fastled_clockless_addr1
red: 100%
green: 100%
blue: 0%
- delay: 100ms
- light.addressable_set:
id: addr1
id: fastled_clockless_addr1
red: 0%
green: 100%
blue: 0%

View File

@@ -1,6 +1,6 @@
light:
- platform: fastled_spi
id: addr1
id: fastled_spi_addr1
chipset: WS2801
clock_pin: 22
data_pin: 23
@@ -59,13 +59,13 @@ light:
name: Custom Effect
sequence:
- light.addressable_set:
id: addr1
id: fastled_spi_addr1
red: 100%
green: 100%
blue: 0%
- delay: 100ms
- light.addressable_set:
id: addr1
id: fastled_spi_addr1
red: 0%
green: 100%
blue: 0%

View File

@@ -8,7 +8,7 @@ font:
id: roboto32
- file: "gfonts://Roboto"
id: roboto
id: font_roboto
size: 20
glyphs: "0123456789."
extras:
@@ -50,11 +50,11 @@ font:
display:
- platform: ssd1306_i2c
i2c_id: i2c_bus
id: ssd1306_display
id: font_ssd1306_display
model: SSD1306_128X64
reset_pin: ${display_reset_pin}
lambda: |-
it.print(0, 0, id(roboto), "Hello, World!");
it.print(0, 0, id(font_roboto), "Hello, World!");
it.print(0, 20, id(roboto_web), "Hello, World!");
it.print(0, 40, id(monocraft), "Hello, World!");
it.print(0, 60, id(monocraft2), "Hello, World!");

View File

@@ -8,7 +8,7 @@ font:
id: roboto32
- file: "gfonts://Roboto"
id: roboto
id: font_roboto
size: 20
glyphs: "0123456789."
extras:
@@ -44,12 +44,12 @@ font:
display:
- platform: sdl
id: sdl_display
id: font_sdl_display
dimensions:
width: 800
height: 600
lambda: |-
it.print(0, 0, id(roboto), "Hello, World!");
it.print(0, 0, id(font_roboto), "Hello, World!");
it.print(0, 20, id(roboto_web), "Hello, World!");
it.print(0, 40, id(roboto_greek), "Hello κόσμε!");
it.print(0, 60, id(monocraft), "Hello, World!");

View File

@@ -12,7 +12,7 @@ graph:
display:
- platform: ssd1306_i2c
i2c_id: i2c_bus
id: ssd1306_display
id: graph_ssd1306_display
model: SSD1306_128X64
reset_pin: ${reset_pin}
pages:

View File

@@ -1,6 +1,7 @@
display:
- platform: ssd1306_i2c
id: ssd1306_i2c_display
i2c_id: i2c_bus
id: graphical_display_menu_ssd1306_i2c_display
model: SSD1306_128X64
reset_pin: ${reset_pin}
pages:
@@ -10,12 +11,12 @@ display:
font:
- file: "gfonts://Roboto"
id: roboto
id: graphical_display_menu_roboto
size: 20
number:
- platform: template
id: test_number
id: graphical_display_menu_test_number
min_value: 0
step: 1
max_value: 10
@@ -31,13 +32,13 @@ select:
switch:
- platform: template
id: test_switch
id: graphical_display_menu_test_switch
optimistic: true
graphical_display_menu:
id: test_graphical_display_menu
display: ssd1306_i2c_display
font: roboto
display: graphical_display_menu_ssd1306_i2c_display
font: graphical_display_menu_roboto
active: false
mode: rotary
on_enter:
@@ -80,7 +81,7 @@ graphical_display_menu:
lambda: 'ESP_LOGI("graphical_display_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());'
- type: number
text: "Number"
number: test_number
number: graphical_display_menu_test_number
on_enter:
then:
lambda: 'ESP_LOGI("graphical_display_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());'
@@ -97,7 +98,7 @@ graphical_display_menu:
- display_menu.hide: test_graphical_display_menu
- type: switch
text: "Switch"
switch: test_switch
switch: graphical_display_menu_test_switch
on_text: "Bright"
off_text: "Dark"
immediate_edit: false

View File

@@ -1,7 +1,7 @@
display:
- platform: ssd1306_i2c
i2c_id: i2c_bus
id: ssd1306_i2c_display
id: gt911_ssd1306_i2c_display
model: SSD1306_128X64
reset_pin: ${display_reset_pin}
pages:
@@ -13,7 +13,7 @@ touchscreen:
- platform: gt911
i2c_id: i2c_bus
id: gt911_touchscreen
display: ssd1306_i2c_display
display: gt911_ssd1306_i2c_display
interrupt_pin: ${interrupt_pin}
reset_pin: ${reset_pin}

View File

@@ -93,12 +93,12 @@ text_sensor:
event:
- platform: template
name: Test Event
id: test_event
id: homeassistant_test_event
event_types:
- test_event_type
on_event:
- homeassistant.event:
event: esphome.test_event
event: esphome.homeassistant_test_event
data:
event_name: !lambda |-
return event_type;

View File

@@ -3,7 +3,7 @@ packages:
display:
- platform: ili9xxx
id: main_lcd
id: image_main_lcd
spi_id: spi_bus
model: ili9342
cs_pin: 15

View File

@@ -3,7 +3,7 @@ packages:
display:
- platform: ili9xxx
id: main_lcd
id: image_main_lcd
spi_id: spi_bus
model: ili9342
cs_pin: 5

View File

@@ -3,7 +3,7 @@ packages:
display:
- platform: ili9xxx
id: main_lcd
id: image_main_lcd
spi_id: spi_bus
model: ili9342
cs_pin: 20

View File

@@ -23,7 +23,7 @@ infrared:
# Infrared receiver
- platform: ir_rf_proxy
id: ir_rx
id: infrared_ir_rx
name: "IR Receiver"
remote_receiver_id: ir_receiver

View File

@@ -9,11 +9,11 @@ esphome:
sensor:
- platform: adc
id: my_sensor
id: integration_my_sensor
pin: ${pin}
attenuation: 12db
- platform: integration
id: integration_sensor
sensor: my_sensor
sensor: integration_my_sensor
name: Integration Sensor
time_unit: s

View File

@@ -1,8 +1,8 @@
sensor:
- platform: adc
id: my_sensor
id: integration_my_sensor
pin: VCC
- platform: integration
sensor: my_sensor
sensor: integration_my_sensor
name: Integration Sensor
time_unit: s

View File

@@ -1,8 +1,8 @@
sensor:
- platform: adc
id: my_sensor
id: integration_my_sensor
pin: VCC
- platform: integration
sensor: my_sensor
sensor: integration_my_sensor
name: Integration Sensor
time_unit: s

View File

@@ -6,7 +6,7 @@ remote_receiver:
infrared:
# Infrared receiver
- platform: ir_rf_proxy
id: ir_rx
id: ir_rf_proxy_ir_rx
name: "IR Receiver"
receiver_frequency: 38kHz
remote_receiver_id: ir_receiver

View File

@@ -1,6 +1,6 @@
display:
- platform: lcd_gpio
id: my_lcd_gpio
id: lcd_gpio_my_lcd_gpio
dimensions: 18x4
data_pins:
- number: ${d0_pin}

View File

@@ -1,6 +1,6 @@
number:
- platform: template
id: test_number
id: lcd_menu_test_number
min_value: 0
step: 1
max_value: 10
@@ -22,7 +22,7 @@ switch:
display:
- platform: lcd_gpio
id: my_lcd_gpio
id: lcd_menu_my_lcd_gpio
dimensions: 18x4
data_pins:
- number: ${d0_pin}
@@ -36,7 +36,7 @@ display:
lcd_menu:
id: test_lcd_menu
display_id: my_lcd_gpio
display_id: lcd_menu_my_lcd_gpio
mark_back: 0x5e
mark_selected: 0x3e
mark_editing: 0x2a
@@ -83,7 +83,7 @@ lcd_menu:
lambda: 'ESP_LOGI("lcd_menu", "select value: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());'
- type: number
text: Number
number: test_number
number: lcd_menu_test_number
on_enter:
then:
lambda: 'ESP_LOGI("lcd_menu", "number enter: %s, %s", it->get_text().c_str(), it->get_value_text().c_str());'

View File

@@ -156,7 +156,7 @@ light:
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
output: light_test_binary
effects:
- strobe:
on_state:

View File

@@ -1,6 +1,6 @@
output:
- platform: gpio
id: test_binary
id: light_test_binary
pin: 12
- platform: ledc
id: test_ledc_1

View File

@@ -1,6 +1,6 @@
output:
- platform: gpio
id: test_binary
id: light_test_binary
pin: 4
- platform: esp8266_pwm
id: test_ledc_1

View File

@@ -5,14 +5,14 @@ esphome:
output:
- platform: gpio
id: test_binary
id: light_test_binary
pin: 0
light:
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
output: light_test_binary
effects:
- strobe:
on_state:

View File

@@ -5,14 +5,14 @@ esphome:
output:
- platform: gpio
id: test_binary
id: light_test_binary
pin: 0
light:
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
output: light_test_binary
effects:
- strobe:
on_state:

View File

@@ -1,6 +1,6 @@
output:
- platform: gpio
id: test_binary
id: light_test_binary
pin: 0
- platform: rp2040_pwm
id: test_ledc_1

View File

@@ -1,7 +1,7 @@
display:
- platform: ssd1306_i2c
i2c_id: i2c_bus
id: ssd1306_i2c_display
id: lilygo_t5_47_ssd1306_i2c_display
model: SSD1306_128X64
reset_pin: ${reset_pin}
pages:
@@ -14,7 +14,7 @@ touchscreen:
i2c_id: i2c_bus
id: lilygo_touchscreen
interrupt_pin: ${interrupt_pin}
display: ssd1306_i2c_display
display: lilygo_t5_47_ssd1306_i2c_display
on_touch:
- logger.log:
format: Touch at (%d, %d)

View File

@@ -7,7 +7,7 @@ esphome:
output:
- platform: gpio
id: test_binary
id: lock_test_binary
pin: 4
lock:
@@ -32,4 +32,4 @@ lock:
- platform: output
name: Generic Output Lock
id: test_lock2
output: test_binary
output: lock_test_binary

View File

@@ -1,13 +1,13 @@
output:
- platform: ${light_platform}
id: light_output_1
id: monochromatic_light_output_1
pin: ${pin}
light:
- platform: monochromatic
name: Monochromatic Light
id: monochromatic_light
output: light_output_1
output: monochromatic_light_output_1
gamma_correct: 2.8
default_transition_length: 2s
effects:

View File

@@ -9,15 +9,15 @@ binary_sensor:
name: touchkey0
channel: 0
- platform: mpr121
id: bin1
id: mpr121_bin1
name: touchkey1
channel: 1
- platform: mpr121
id: bin2
id: mpr121_bin2
name: touchkey2
channel: 2
- platform: mpr121
id: bin3
id: mpr121_bin3
name: touchkey3
channel: 6

View File

@@ -74,7 +74,7 @@ binary_sensor:
state_topic: some/topic/binary_sensor
qos: 2
lambda: |-
if (id(template_sens).state > 30) {
if (id(mqtt_template_sens).state > 30) {
// Garage Door is open.
return true;
}
@@ -105,8 +105,8 @@ button:
climate:
- platform: thermostat
name: Test Thermostat
sensor: template_sens
humidity_sensor: template_sens
sensor: mqtt_template_sens
humidity_sensor: mqtt_template_sens
action_state_topic: some/topicaction_state
current_temperature_state_topic: some/topiccurrent_temperature_state
current_humidity_state_topic: some/topiccurrent_humidity_state
@@ -283,10 +283,10 @@ cover:
datetime:
- platform: template
name: Date
id: test_date
id: mqtt_test_date
type: date
state_topic: some/topic/date
command_topic: test_date/custom_command_topic
command_topic: mqtt_test_date/custom_command_topic
qos: 2
subscribe_qos: 2
set_action:
@@ -300,7 +300,7 @@ datetime:
- x.day_of_month
- platform: template
name: Time
id: test_time
id: mqtt_test_time
type: time
state_topic: some/topic/time
qos: 2
@@ -315,7 +315,7 @@ datetime:
- x.second
- platform: template
name: DateTime
id: test_datetime
id: mqtt_test_datetime
type: datetime
state_topic: some/topic/datetime
qos: 2
@@ -407,7 +407,7 @@ select:
sensor:
- platform: template
name: Template Sensor
id: template_sens
id: mqtt_template_sens
lambda: |-
if (id(some_binary_sensor).state) {
return 42.0;
@@ -423,13 +423,13 @@ sensor:
- platform: mqtt_subscribe
name: MQTT Subscribe Sensor
topic: mqtt/topic
id: the_sensor
id: mqtt_the_sensor
qos: 2
on_value:
- mqtt.publish_json:
topic: the/topic
payload: |-
root["key"] = id(template_sens).state;
root["key"] = id(mqtt_template_sens).state;
root["greeting"] = "Hello World";
switch:

View File

@@ -18,13 +18,13 @@ sensor:
- platform: mqtt_subscribe
name: MQTT Subscribe Sensor
topic: mqtt/topic
id: the_sensor
id: mqtt_subscribe_the_sensor
qos: 2
on_value:
- mqtt.publish_json:
topic: the/topic
payload: |-
root["key"] = id(the_sensor).state;
root["key"] = id(mqtt_subscribe_the_sensor).state;
root["greeting"] = "Hello World";
text_sensor:

View File

@@ -19,13 +19,13 @@ sensor:
- platform: mqtt_subscribe
name: MQTT Subscribe Sensor
topic: mqtt/topic
id: the_sensor
id: mqtt_subscribe_the_sensor
qos: 2
on_value:
- mqtt.publish_json:
topic: the/topic
payload: |-
root["key"] = id(the_sensor).state;
root["key"] = id(mqtt_subscribe_the_sensor).state;
root["greeting"] = "Hello World";
text_sensor:

View File

@@ -1,23 +1,23 @@
sensor:
- platform: adc
id: my_sensor
id: ntc_my_sensor
pin: ${pin}
- platform: resistance
sensor: my_sensor
sensor: ntc_my_sensor
configuration: DOWNSTREAM
resistor: 10kΩ
reference_voltage: 3.3V
name: Resistance
id: resist
id: ntc_resist
- platform: ntc
sensor: resist
sensor: ntc_resist
name: NTC Sensor
calibration:
b_constant: 3950
reference_resistance: 10k
reference_temperature: 25°C
- platform: ntc
sensor: resist
sensor: ntc_resist
name: NTC Sensor2
calibration:
- 10.0kOhm -> 25°C

View File

@@ -1,7 +1,7 @@
number:
- platform: template
name: "Test Number"
id: test_number
id: number_test_number
optimistic: true
min_value: 0
max_value: 100
@@ -10,4 +10,4 @@ number:
sensor:
- platform: number
name: "Test Number Value"
source_id: test_number
source_id: number_test_number

View File

@@ -6,7 +6,7 @@ packages:
display:
- platform: ili9xxx
spi_id: spi_bus
id: main_lcd
id: online_image_main_lcd
model: ili9342
cs_pin: 20
dc_pin: 13

View File

@@ -6,7 +6,7 @@ packages:
display:
- platform: ili9xxx
spi_id: spi_bus
id: main_lcd
id: online_image_main_lcd
model: ili9342
cs_pin: 15
dc_pin: 3

View File

@@ -6,7 +6,7 @@ packages:
display:
- platform: ili9xxx
spi_id: spi_bus
id: main_lcd
id: online_image_main_lcd
model: ili9342
data_rate: 20MHz
cs_pin: 20

View File

@@ -8,7 +8,7 @@ http_request:
display:
- platform: ili9xxx
spi_id: spi_bus
id: main_lcd
id: online_image_main_lcd
model: ili9342
cs_pin: 20
dc_pin: 13

View File

@@ -8,7 +8,7 @@ http_request:
display:
- platform: ili9xxx
spi_id: spi_bus
id: main_lcd
id: online_image_main_lcd
model: ili9342
cs_pin: 20
dc_pin: 13

View File

@@ -1,19 +1,19 @@
esphome:
on_boot:
then:
- output.turn_off: light_output_1
- output.turn_on: light_output_1
- output.turn_off: output_light_output_1
- output.turn_on: output_light_output_1
- output.set_level:
id: light_output_1
id: output_light_output_1
level: 50%
- output.set_min_power:
id: light_output_1
id: output_light_output_1
min_power: 20%
- output.set_max_power:
id: light_output_1
id: output_light_output_1
max_power: 80%
output:
- platform: ${output_platform}
id: light_output_1
id: output_light_output_1
pin: ${pin}

View File

@@ -9,7 +9,7 @@ pi4ioe5v6408:
switch:
- platform: gpio
id: switch1
id: pi4ioe5v6408_switch1
pin:
pi4ioe5v6408: pi4ioe1
number: 0

View File

@@ -23,7 +23,7 @@ output:
sensor:
- platform: template
id: template_sensor1
id: pid_template_sensor1
lambda: |-
if (millis() > 10000) {
return 42.0;
@@ -35,8 +35,8 @@ climate:
- platform: pid
id: pid_climate
name: PID Climate Controller
sensor: template_sensor1
humidity_sensor: template_sensor1
sensor: pid_template_sensor1
humidity_sensor: pid_template_sensor1
default_target_temperature: 21°C
heat_output: pid_slow_pwm
control_parameters:

View File

@@ -31,7 +31,7 @@ update:
sensor:
- platform: template
id: template_sensor1
id: prometheus_template_sensor1
lambda: |-
if (millis() > 10000) {
return 42.0;
@@ -91,7 +91,7 @@ binary_sensor:
switch:
- platform: template
id: template_switch1
id: prometheus_template_switch1
lambda: |-
if (millis() > 10000) {
return true;
@@ -185,7 +185,7 @@ climate:
prometheus:
include_internal: true
relabel:
template_sensor1:
prometheus_template_sensor1:
id: hellow_world
name: Hello World
template_text_sensor1:

View File

@@ -16,7 +16,7 @@ display:
- platform: qspi_dbi
model: CUSTOM
id: main_lcd
id: qspi_dbi_main_lcd
draw_from_origin: true
dimensions:
height: 240

View File

@@ -1,6 +1,6 @@
number:
- platform: template
id: test_number
id: remote_transmitter_test_number
optimistic: true
min_value: 0
max_value: 255
@@ -151,7 +151,7 @@ button:
on_press:
remote_transmitter.transmit_raw:
code: !lambda |-
return {(int32_t)id(test_number).state * 100, -1000};
return {(int32_t)id(remote_transmitter_test_number).state * 100, -1000};
- platform: template
name: AEHA
id: eaha_hitachi_climate_power_on
@@ -253,7 +253,7 @@ button:
destination_address: 0x5678
message_type: 0x01
data: !lambda |-
return {(uint8_t)id(test_number).state, 0x20, 0x30};
return {(uint8_t)id(remote_transmitter_test_number).state, 0x20, 0x30};
- platform: template
name: Digital Write
on_press:

View File

@@ -1,11 +1,11 @@
sensor:
- platform: adc
id: my_sensor
id: resistance_my_sensor
pin: ${pin}
- platform: resistance
sensor: my_sensor
sensor: resistance_my_sensor
configuration: DOWNSTREAM
resistor: 10kΩ
reference_voltage: 3.3V
name: Resistance
id: resist
id: resistance_resist

View File

@@ -1,18 +1,18 @@
output:
- platform: ${light_platform}
id: light_output_1
id: rgb_light_output_1
pin: ${pin1}
- platform: ${light_platform}
id: light_output_2
id: rgb_light_output_2
pin: ${pin2}
- platform: ${light_platform}
id: light_output_3
id: rgb_light_output_3
pin: ${pin3}
light:
- platform: rgb
name: RGB Light
id: rgb_light
red: light_output_1
green: light_output_2
blue: light_output_3
red: rgb_light_output_1
green: rgb_light_output_2
blue: rgb_light_output_3

View File

@@ -1,28 +1,28 @@
output:
- platform: ${light_platform}
id: light_output_1
id: rgbct_light_output_1
pin: ${pin1}
- platform: ${light_platform}
id: light_output_2
id: rgbct_light_output_2
pin: ${pin2}
- platform: ${light_platform}
id: light_output_3
id: rgbct_light_output_3
pin: ${pin3}
- platform: ${light_platform}
id: light_output_4
id: rgbct_light_output_4
pin: ${pin4}
- platform: ${light_platform}
id: light_output_5
id: rgbct_light_output_5
pin: ${pin5}
light:
- platform: rgbct
name: RGBCT Light
red: light_output_1
green: light_output_2
blue: light_output_3
color_temperature: light_output_4
white_brightness: light_output_5
red: rgbct_light_output_1
green: rgbct_light_output_2
blue: rgbct_light_output_3
color_temperature: rgbct_light_output_4
white_brightness: rgbct_light_output_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true

View File

@@ -1,22 +1,22 @@
output:
- platform: ${light_platform}
id: light_output_1
id: rgbw_light_output_1
pin: ${pin1}
- platform: ${light_platform}
id: light_output_2
id: rgbw_light_output_2
pin: ${pin2}
- platform: ${light_platform}
id: light_output_3
id: rgbw_light_output_3
pin: ${pin3}
- platform: ${light_platform}
id: light_output_4
id: rgbw_light_output_4
pin: ${pin4}
light:
- platform: rgbw
name: RGBW Light
red: light_output_1
green: light_output_2
blue: light_output_3
white: light_output_4
red: rgbw_light_output_1
green: rgbw_light_output_2
blue: rgbw_light_output_3
white: rgbw_light_output_4
color_interlock: true

View File

@@ -1,28 +1,28 @@
output:
- platform: ${light_platform}
id: light_output_1
id: rgbww_light_output_1
pin: ${pin1}
- platform: ${light_platform}
id: light_output_2
id: rgbww_light_output_2
pin: ${pin2}
- platform: ${light_platform}
id: light_output_3
id: rgbww_light_output_3
pin: ${pin3}
- platform: ${light_platform}
id: light_output_4
id: rgbww_light_output_4
pin: ${pin4}
- platform: ${light_platform}
id: light_output_5
id: rgbww_light_output_5
pin: ${pin5}
light:
- platform: rgbww
name: RGBWW Light
red: light_output_1
green: light_output_2
blue: light_output_3
cold_white: light_output_4
warm_white: light_output_5
red: rgbww_light_output_1
green: rgbww_light_output_2
blue: rgbww_light_output_3
cold_white: rgbww_light_output_4
warm_white: rgbww_light_output_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true

View File

@@ -1,6 +1,6 @@
light:
- platform: rp2040_pio_led_strip
id: led_strip
id: rp2040_pio_led_strip_led_strip
pin: 4
num_leds: 60
pio: 0

View File

@@ -1,7 +1,7 @@
output:
- platform: rp2040_pwm
id: light_output_1
id: rp2040_pwm_light_output_1
pin: 2
- platform: rp2040_pwm
id: light_output_2
id: rp2040_pwm_light_output_2
pin: 3

View File

@@ -3,7 +3,7 @@ host:
display:
- platform: sdl
id: sdl_display
id: sdl_sdl_display
update_interval: 1s
auto_clear_enabled: false
show_test_card: true
@@ -35,14 +35,14 @@ display:
binary_sensor:
- platform: sdl
sdl_id: sdl_display
sdl_id: sdl_sdl_display
id: key_up
key: SDLK_UP
- platform: sdl
sdl_id: sdl_display
sdl_id: sdl_sdl_display
id: key_down
key: SDLK_DOWN
- platform: sdl
sdl_id: sdl_display
sdl_id: sdl_sdl_display
id: key_enter
key: SDLK_RETURN

View File

@@ -1,7 +1,7 @@
number:
- platform: template
name: "Speaker Number"
id: my_number
id: speaker_my_number
optimistic: true
min_value: 0
max_value: 100
@@ -46,7 +46,7 @@ button:
- speaker.play:
id: speaker_id
data: !lambda |-
return {0x01, 0x02, (uint8_t)id(my_number).state};
return {0x01, 0x02, (uint8_t)id(speaker_my_number).state};
speaker:
- platform: i2s_audio

View File

@@ -13,7 +13,7 @@ speaker:
- id: media_mixer_speaker_id
audio_file:
- id: test_audio
- id: speaker_source_test_audio
file:
type: local
path: $component_dir/test.wav

Some files were not shown because too many files have changed in this diff Show More