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

This commit is contained in:
J. Nick Koston
2026-06-05 17:57:42 -05:00
committed by GitHub
parent f18cf954ba
commit 70d9ab25f3
115 changed files with 482 additions and 252 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

@@ -0,0 +1,122 @@
#!/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 silently 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). The merge
now raises on such a collision, but only when the two components land in the same
group. 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.
Ids that are intentionally shared across components (e.g. a singleton
``sntp_time`` clock) are listed in ``INTENTIONALLY_SHARED_IDS`` and skipped.
"""
from __future__ import annotations
from collections import defaultdict
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
from script.merge_component_configs import ( # noqa: E402
INTENTIONALLY_SHARED_IDS,
load_yaml_file,
)
TESTS_DIR = Path("tests/components")
def _normalize(value: object) -> object:
"""Return a hashable, order-independent representation for comparison."""
if isinstance(value, dict):
return tuple(sorted((str(k), _normalize(v)) for k, v in value.items()))
if isinstance(value, (list, tuple)):
return tuple(_normalize(v) for v in value)
# Scalars (and ESPHome tag objects like !lambda) compare by their text form
return str(value)
def _collect_ids(
data: object, section: str, out: dict[tuple[str, str], object]
) -> None:
"""Walk a parsed config and record (section, id) -> normalized content."""
if isinstance(data, dict):
for key, value in data.items():
if isinstance(value, list):
for item in value:
if isinstance(item, dict) and "id" in item:
out[(key, str(item["id"]))] = _normalize(item)
_collect_ids(item, key, out)
else:
_collect_ids(value, key, out)
elif isinstance(data, list):
for item in data:
_collect_ids(item, section, 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 main() -> int:
conflicts: list[str] = []
for platform in sorted(_discover_platforms()):
# (section, id) -> {normalized_content: [components]}
by_id: dict[tuple[str, str], dict[object, list[str]]] = defaultdict(
lambda: defaultdict(list)
)
for comp_dir in sorted(TESTS_DIR.iterdir()):
if not comp_dir.is_dir():
continue
test_file = comp_dir / f"test.{platform}.yaml"
if not test_file.exists():
continue
try:
data = load_yaml_file(test_file)
except Exception as err: # noqa: BLE001
print(f"WARNING: could not parse {test_file}: {err}", file=sys.stderr)
continue
ids: dict[tuple[str, str], object] = {}
_collect_ids(data, "", ids)
for (section, id_), content in ids.items():
if id_ in INTENTIONALLY_SHARED_IDS:
continue
by_id[(section, id_)][content].append(comp_dir.name)
for (section, id_), variants in sorted(by_id.items()):
if len(variants) < 2:
continue
components = sorted({c for comps in variants.values() for c in comps})
conflicts.append(
f"[{platform}] id '{id_}' under '{section}' is defined "
f"differently by: {', '.join(components)}"
)
if conflicts:
print("Conflicting test component ids found:\n")
for line in 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."
)
return 1
print("No conflicting test component ids found.")
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -161,18 +161,42 @@ def prefix_substitutions_in_dict(
return data
# Ids that several components intentionally share. ESPHome treats these as a
# single instance when merged (e.g. multiple components each declaring the same
# `sntp_time` clock collapse into one), so duplicates with differing content are
# expected and must not be flagged as accidental collisions.
INTENTIONALLY_SHARED_IDS = frozenset(
{
# Several components each declare an `sntp_time` clock; ESPHome merges
# them into one time source.
"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.
"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
one silently wins and the others are dropped, which can make cross-references
resolve to an incompatible entity. Rather than defer that to downstream
validation (where it surfaces as a confusing, order-dependent failure), raise
immediately so the offending ID is named.
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 +205,26 @@ 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 = {}
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 item_id in INTENTIONALLY_SHARED_IDS:
# Designed singleton shared by several components (e.g. an
# `sntp_time` clock); ESPHome collapses these, so keep first.
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)

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

@@ -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

@@ -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

@@ -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 @@
display:
- platform: ili9xxx
id: main_lcd
id: display_main_lcd
model: ili9342
cs_pin: 12
dc_pin: 13

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

@@ -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

@@ -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

@@ -1,6 +1,6 @@
number:
- platform: template
id: test_number
id: lcd_menu_test_number
min_value: 0
step: 1
max_value: 10
@@ -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

@@ -5,7 +5,7 @@ packages:
display:
spi_id: spi_bus
platform: mipi_spi
id: main_lcd
id: mapping_main_lcd
model: ili9342
cs_pin: 12
dc_pin: 13

View File

@@ -5,7 +5,7 @@ packages:
display:
spi_id: spi_bus
platform: mipi_spi
id: main_lcd
id: mapping_main_lcd
model: ili9342
cs_pin: 5
dc_pin: 15

View File

@@ -5,7 +5,7 @@ packages:
display:
spi_id: spi_bus
platform: mipi_spi
id: main_lcd
id: mapping_main_lcd
model: ili9342
data_rate: 31.25MHz
cs_pin: 20

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

@@ -1,6 +1,6 @@
esphome:
on_boot:
- lambda: 'ESP_LOGD("display","is_connected(): %s", YESNO(id(main_lcd).is_connected()));'
- lambda: 'ESP_LOGD("display","is_connected(): %s", YESNO(id(nextion_main_lcd).is_connected()));'
- display.nextion.set_brightness: 80%
@@ -272,7 +272,7 @@ text_sensor:
display:
- platform: nextion
id: main_lcd
id: nextion_main_lcd
auto_wake_on_touch: true
brightness: 80%
command_spacing: 5ms

View File

@@ -1,5 +1,5 @@
display:
- id: !extend main_lcd
- id: !extend nextion_main_lcd
tft_url: http://esphome.io/default35.tft
tft_upload_http_timeout: 20s
tft_upload_http_retries: 10

View File

@@ -1,3 +1,3 @@
display:
- id: !extend main_lcd
- id: !extend nextion_main_lcd
tft_upload_watchdog_timeout: 30s

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,9 +1,9 @@
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
@@ -13,6 +13,6 @@ light:
- platform: rgb
name: RGB Light
id: rgb_light
red: light_output_1
green: light_output_2
red: rgb_light_output_1
green: rgb_light_output_2
blue: light_output_3

View File

@@ -1,9 +1,9 @@
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
@@ -18,8 +18,8 @@ output:
light:
- platform: rgbct
name: RGBCT Light
red: light_output_1
green: light_output_2
red: rgbct_light_output_1
green: rgbct_light_output_2
blue: light_output_3
color_temperature: light_output_4
white_brightness: light_output_5

View File

@@ -1,9 +1,9 @@
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
@@ -15,8 +15,8 @@ output:
light:
- platform: rgbw
name: RGBW Light
red: light_output_1
green: light_output_2
red: rgbw_light_output_1
green: rgbw_light_output_2
blue: light_output_3
white: light_output_4
color_interlock: true

View File

@@ -1,9 +1,9 @@
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
@@ -18,8 +18,8 @@ output:
light:
- platform: rgbww
name: RGBWW Light
red: light_output_1
green: light_output_2
red: rgbww_light_output_1
green: rgbww_light_output_2
blue: light_output_3
cold_white: light_output_4
warm_white: light_output_5

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

@@ -1,9 +1,9 @@
output:
- platform: ${output_platform}
id: fan_output_1
id: speed_fan_output_1
pin: ${pin}
fan:
- platform: speed
id: fan_speed
output: fan_output_1
id: speed_fan_speed
output: speed_fan_output_1

View File

@@ -34,7 +34,7 @@ esphome:
switch:
- platform: template
id: switch1
id: sprinkler_switch1
optimistic: true
- platform: template
id: switch2
@@ -52,17 +52,17 @@ sprinkler:
valves:
- valve_switch: Yard Valve 0
enable_switch: Enable Yard Valve 0
pump_switch_id: switch1
pump_switch_id: sprinkler_switch1
run_duration: 10s
valve_switch_id: switch2
- valve_switch: Yard Valve 1
enable_switch: Enable Yard Valve 1
pump_switch_id: switch1
pump_switch_id: sprinkler_switch1
run_duration: 10s
valve_switch_id: switch2
- valve_switch: Yard Valve 2
enable_switch: Enable Yard Valve 2
pump_switch_id: switch1
pump_switch_id: sprinkler_switch1
run_duration: 10s
valve_switch_id: switch2
- id: garden_sprinkler_ctrlr
@@ -73,11 +73,11 @@ sprinkler:
valves:
- valve_switch: Garden Valve 0
enable_switch: Enable Garden Valve 0
pump_switch_id: switch1
pump_switch_id: sprinkler_switch1
run_duration: 10s
valve_switch_id: switch2
- valve_switch: Garden Valve 1
enable_switch: Enable Garden Valve 1
pump_switch_id: switch1
pump_switch_id: sprinkler_switch1
run_duration: 10s
valve_switch_id: switch2

View File

@@ -4,7 +4,7 @@ display:
model: SSD1306_128X64
reset_pin: ${reset_pin}
address: 0x3C
id: ssd1306_i2c_display
id: ssd1306_i2c_ssd1306_i2c_display
contrast: 60%
pages:
- id: ssd1306_i2c_page1

View File

@@ -1,6 +1,6 @@
binary_sensor:
- platform: switch
id: some_binary_sensor
id: switch_some_binary_sensor
name: "Template Switch State"
source_id: the_switch

View File

@@ -29,7 +29,7 @@ sx126x:
number:
- platform: template
name: "SX126x Number"
id: my_number
id: sx126x_my_number
optimistic: true
min_value: 0
max_value: 100
@@ -47,4 +47,4 @@ button:
- sx126x.send_packet:
data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C]
- sx126x.send_packet: !lambda |-
return {0x01, 0x02, (uint8_t)id(my_number).state};
return {0x01, 0x02, (uint8_t)id(sx126x_my_number).state};

View File

@@ -29,7 +29,7 @@ sx127x:
number:
- platform: template
name: "SX127x Number"
id: my_number
id: sx127x_my_number
optimistic: true
min_value: 0
max_value: 100
@@ -48,4 +48,4 @@ button:
- sx127x.send_packet:
data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C]
- sx127x.send_packet: !lambda |-
return {0x01, 0x02, (uint8_t)id(my_number).state};
return {0x01, 0x02, (uint8_t)id(sx127x_my_number).state};

View File

@@ -52,7 +52,7 @@ esphome:
binary_sensor:
- platform: template
id: some_binary_sensor
id: template_some_binary_sensor
name: "Garage Door Open"
lambda: |-
if (id(template_sens).state > 30) {
@@ -108,7 +108,7 @@ sensor:
name: "Template Sensor"
id: template_sens
lambda: |-
if (id(some_binary_sensor).state) {
if (id(template_some_binary_sensor).state) {
return 42.0;
}
return 0.0;
@@ -230,7 +230,7 @@ switch:
id: test_switch
name: "Template Switch"
lambda: |-
if (id(some_binary_sensor).state) {
if (id(template_some_binary_sensor).state) {
return true;
}
return false;
@@ -249,7 +249,7 @@ cover:
- platform: template
name: "Template Cover"
lambda: |-
if (id(some_binary_sensor).state) {
if (id(template_some_binary_sensor).state) {
return COVER_OPEN;
}
return COVER_CLOSED;
@@ -264,7 +264,7 @@ cover:
name: "Template Cover with Triggers"
id: template_cover_with_triggers
lambda: |-
if (id(some_binary_sensor).state) {
if (id(template_some_binary_sensor).state) {
return COVER_OPEN;
}
return COVER_CLOSED;
@@ -442,7 +442,7 @@ lock:
- platform: template
name: "Template Lock"
lambda: |-
if (id(some_binary_sensor).state) {
if (id(template_some_binary_sensor).state) {
return LOCK_STATE_LOCKED;
}
return LOCK_STATE_UNLOCKED;
@@ -458,7 +458,7 @@ valve:
id: template_valve
name: "Template Valve"
lambda: |-
if (id(some_binary_sensor).state) {
if (id(template_some_binary_sensor).state) {
return VALVE_OPEN;
}
return VALVE_CLOSED;

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