From d9792b0d923ef640019db418b21e78993b7be312 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 5 Dec 2023 10:56:53 +1100 Subject: [PATCH] Checks for pins used in multiple places (#5666) --- esphome/components/adc/__init__.py | 26 +- esphome/components/esp32/gpio.py | 37 +- esphome/components/esp8266/gpio.py | 27 +- esphome/components/host/gpio.py | 21 +- esphome/components/i2c/__init__.py | 5 +- esphome/components/libretiny/gpio.py | 24 +- esphome/components/max6956/__init__.py | 18 +- esphome/components/mcp23016/__init__.py | 18 +- esphome/components/mcp23xxx_base/__init__.py | 20 +- esphome/components/pca9554/__init__.py | 19 +- esphome/components/pcf8574/__init__.py | 18 +- esphome/components/rp2040/gpio.py | 22 +- esphome/components/sn74hc595/__init__.py | 22 +- esphome/config.py | 48 +- esphome/const.py | 1 + esphome/core/__init__.py | 3 + esphome/pins.py | 185 ++++++- esphome/util.py | 26 - tests/test1.1.yaml | 20 +- tests/test1.yaml | 539 ++++++++++++++----- tests/test11.5.yaml | 93 +++- tests/test2.yaml | 76 ++- tests/test3.1.yaml | 121 +++-- tests/test3.yaml | 169 ++++-- tests/test4.yaml | 289 +++++++--- tests/test5.yaml | 54 +- tests/test8.yaml | 9 +- 27 files changed, 1335 insertions(+), 575 deletions(-) diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index bad5cf74ef..952fbdd9b9 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import CONF_ANALOG, CONF_INPUT +from esphome.const import CONF_ANALOG, CONF_INPUT, CONF_NUMBER from esphome.core import CORE from esphome.components.esp32 import get_esp32_variant @@ -152,7 +152,8 @@ def validate_adc_pin(value): return cv.only_on_rp2040("TEMPERATURE") if CORE.is_esp32: - value = pins.internal_gpio_input_pin_number(value) + conf = pins.internal_gpio_input_pin_schema(value) + value = conf[CONF_NUMBER] variant = get_esp32_variant() if ( variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL @@ -166,24 +167,23 @@ def validate_adc_pin(value): ): raise cv.Invalid(f"{variant} doesn't support ADC on this pin") - return pins.internal_gpio_input_pin_schema(value) + return conf if CORE.is_esp8266: - value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})( - value - ) - - if value != 17: # A0 - raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC") - return pins.gpio_pin_schema( + conf = pins.gpio_pin_schema( {CONF_ANALOG: True, CONF_INPUT: True}, internal=True )(value) + if conf[CONF_NUMBER] != 17: # A0 + raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC") + return conf + if CORE.is_rp2040: - value = pins.internal_gpio_input_pin_number(value) - if value not in (26, 27, 28, 29): + conf = pins.internal_gpio_input_pin_schema(value) + number = conf[CONF_NUMBER] + if number not in (26, 27, 28, 29): raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC") - return pins.internal_gpio_input_pin_schema(value) + return conf if CORE.is_libretiny: return pins.gpio_pin_schema( diff --git a/esphome/components/esp32/gpio.py b/esphome/components/esp32/gpio.py index a53649e3e4..16f99f2b15 100644 --- a/esphome/components/esp32/gpio.py +++ b/esphome/components/esp32/gpio.py @@ -3,15 +3,13 @@ from typing import Any from esphome.const import ( CONF_ID, - CONF_INPUT, CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_OPEN_DRAIN, CONF_OUTPUT, - CONF_PULLDOWN, - CONF_PULLUP, CONF_IGNORE_STRAPPING_WARNING, + PLATFORM_ESP32, ) from esphome import pins from esphome.core import CORE @@ -33,7 +31,6 @@ from .const import ( esp32_ns, ) - from .gpio_esp32 import esp32_validate_gpio_pin, esp32_validate_supports from .gpio_esp32_s2 import esp32_s2_validate_gpio_pin, esp32_s2_validate_supports from .gpio_esp32_c3 import esp32_c3_validate_gpio_pin, esp32_c3_validate_supports @@ -42,7 +39,6 @@ from .gpio_esp32_c2 import esp32_c2_validate_gpio_pin, esp32_c2_validate_support from .gpio_esp32_c6 import esp32_c6_validate_gpio_pin, esp32_c6_validate_supports from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports - ESP32InternalGPIOPin = esp32_ns.class_("ESP32InternalGPIOPin", cg.InternalGPIOPin) @@ -161,33 +157,22 @@ DRIVE_STRENGTHS = { } gpio_num_t = cg.global_ns.enum("gpio_num_t") - CONF_DRIVE_STRENGTH = "drive_strength" ESP32_PIN_SCHEMA = cv.All( - { - cv.GenerateID(): cv.declare_id(ESP32InternalGPIOPin), - cv.Required(CONF_NUMBER): validate_gpio_pin, - cv.Optional(CONF_MODE, default={}): cv.Schema( - { - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, - cv.Optional(CONF_PULLUP, default=False): cv.boolean, - cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, - } - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, - cv.Optional(CONF_IGNORE_STRAPPING_WARNING, default=False): cv.boolean, - cv.Optional(CONF_DRIVE_STRENGTH, default="20mA"): cv.All( - cv.float_with_unit("current", "mA", optional_unit=True), - cv.enum(DRIVE_STRENGTHS), - ), - }, + pins.gpio_base_schema(ESP32InternalGPIOPin, validate_gpio_pin).extend( + { + cv.Optional(CONF_IGNORE_STRAPPING_WARNING, default=False): cv.boolean, + cv.Optional(CONF_DRIVE_STRENGTH, default="20mA"): cv.All( + cv.float_with_unit("current", "mA", optional_unit=True), + cv.enum(DRIVE_STRENGTHS), + ), + } + ), validate_supports, ) -@pins.PIN_SCHEMA_REGISTRY.register("esp32", ESP32_PIN_SCHEMA) +@pins.PIN_SCHEMA_REGISTRY.register(PLATFORM_ESP32, ESP32_PIN_SCHEMA) async def esp32_pin_to_code(config): var = cg.new_Pvariable(config[CONF_ID]) num = config[CONF_NUMBER] diff --git a/esphome/components/esp8266/gpio.py b/esphome/components/esp8266/gpio.py index e75578cc16..c42bc9204f 100644 --- a/esphome/components/esp8266/gpio.py +++ b/esphome/components/esp8266/gpio.py @@ -12,6 +12,7 @@ from esphome.const import ( CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, + PLATFORM_ESP8266, ) from esphome import pins from esphome.core import CORE, coroutine_with_priority @@ -21,10 +22,8 @@ import esphome.codegen as cg from . import boards from .const import KEY_BOARD, KEY_ESP8266, KEY_PIN_INITIAL_STATES, esp8266_ns - _LOGGER = logging.getLogger(__name__) - ESP8266GPIOPin = esp8266_ns.class_("ESP8266GPIOPin", cg.InternalGPIOPin) @@ -124,6 +123,8 @@ def validate_supports(value): (True, False, False, False, False), # OUTPUT (False, True, False, False, False), + # INPUT and OUTPUT, e.g. for i2c + (True, True, False, False, False), # INPUT_PULLUP (True, False, False, True, False), # INPUT_PULLDOWN_16 @@ -142,21 +143,11 @@ def validate_supports(value): ESP8266_PIN_SCHEMA = cv.All( - { - cv.GenerateID(): cv.declare_id(ESP8266GPIOPin), - cv.Required(CONF_NUMBER): validate_gpio_pin, - cv.Optional(CONF_MODE, default={}): cv.Schema( - { - cv.Optional(CONF_ANALOG, default=False): cv.boolean, - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, - cv.Optional(CONF_PULLUP, default=False): cv.boolean, - cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, - } - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, - }, + pins.gpio_base_schema( + ESP8266GPIOPin, + validate_gpio_pin, + modes=pins.GPIO_STANDARD_MODES + (CONF_ANALOG,), + ), validate_supports, ) @@ -167,7 +158,7 @@ class PinInitialState: level: int = 255 -@pins.PIN_SCHEMA_REGISTRY.register("esp8266", ESP8266_PIN_SCHEMA) +@pins.PIN_SCHEMA_REGISTRY.register(PLATFORM_ESP8266, ESP8266_PIN_SCHEMA) async def esp8266_pin_to_code(config): var = cg.new_Pvariable(config[CONF_ID]) num = config[CONF_NUMBER] diff --git a/esphome/components/host/gpio.py b/esphome/components/host/gpio.py index d523d28ee5..180919de4f 100644 --- a/esphome/components/host/gpio.py +++ b/esphome/components/host/gpio.py @@ -17,10 +17,8 @@ import esphome.codegen as cg from .const import host_ns - _LOGGER = logging.getLogger(__name__) - HostGPIOPin = host_ns.class_("HostGPIOPin", cg.InternalGPIOPin) @@ -45,21 +43,10 @@ def validate_gpio_pin(value): return _translate_pin(value) -HOST_PIN_SCHEMA = cv.All( - { - cv.GenerateID(): cv.declare_id(HostGPIOPin), - cv.Required(CONF_NUMBER): validate_gpio_pin, - cv.Optional(CONF_MODE, default={}): cv.Schema( - { - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, - cv.Optional(CONF_PULLUP, default=False): cv.boolean, - cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, - } - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, - }, +HOST_PIN_SCHEMA = pins.gpio_base_schema( + HostGPIOPin, + validate_gpio_pin, + modes=[CONF_INPUT, CONF_OUTPUT, CONF_OPEN_DRAIN, CONF_PULLUP, CONF_PULLDOWN], ) diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index 676190b0e5..0a1f049b93 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -39,9 +39,8 @@ def _bus_declare_type(value): raise NotImplementedError -pin_with_input_and_output_support = cv.All( - pins.internal_gpio_pin_number({CONF_INPUT: True}), - pins.internal_gpio_pin_number({CONF_OUTPUT: True}), +pin_with_input_and_output_support = pins.internal_gpio_pin_number( + {CONF_OUTPUT: True, CONF_INPUT: True} ) diff --git a/esphome/components/libretiny/gpio.py b/esphome/components/libretiny/gpio.py index ba9bfffcc9..1d7b37cc9b 100644 --- a/esphome/components/libretiny/gpio.py +++ b/esphome/components/libretiny/gpio.py @@ -186,25 +186,11 @@ def validate_gpio_usage(value): return value -BASE_PIN_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(ArduinoInternalGPIOPin), - cv.Required(CONF_NUMBER): validate_gpio_pin, - cv.Optional(CONF_MODE, default={}): cv.Schema( - { - cv.Optional(CONF_ANALOG, default=False): cv.boolean, - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, - cv.Optional(CONF_PULLUP, default=False): cv.boolean, - cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, - } - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, - }, -) - -BASE_PIN_SCHEMA.add_extra(validate_gpio_usage) +BASE_PIN_SCHEMA = pins.gpio_base_schema( + ArduinoInternalGPIOPin, + validate_gpio_pin, + modes=pins.GPIO_STANDARD_MODES + (CONF_ANALOG,), +).add_extra(validate_gpio_usage) async def component_pin_to_code(config): diff --git a/esphome/components/max6956/__init__.py b/esphome/components/max6956/__init__.py index 77e0d37e76..bb71dba8bf 100644 --- a/esphome/components/max6956/__init__.py +++ b/esphome/components/max6956/__init__.py @@ -74,20 +74,14 @@ def validate_mode(value): CONF_MAX6956 = "max6956" -MAX6956_PIN_SCHEMA = cv.All( +MAX6956_PIN_SCHEMA = pins.gpio_base_schema( + MAX6956GPIOPin, + cv.int_range(min=4, max=31), + modes=[CONF_INPUT, CONF_PULLUP, CONF_OUTPUT], + mode_validator=validate_mode, +).extend( { - cv.GenerateID(): cv.declare_id(MAX6956GPIOPin), cv.Required(CONF_MAX6956): cv.use_id(MAX6956), - cv.Required(CONF_NUMBER): cv.int_range(min=4, max=31), - cv.Optional(CONF_MODE, default={}): cv.All( - { - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_PULLUP, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - }, - validate_mode, - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, } ) diff --git a/esphome/components/mcp23016/__init__.py b/esphome/components/mcp23016/__init__.py index c1209a9627..55722e3ae0 100644 --- a/esphome/components/mcp23016/__init__.py +++ b/esphome/components/mcp23016/__init__.py @@ -45,19 +45,15 @@ def validate_mode(value): CONF_MCP23016 = "mcp23016" -MCP23016_PIN_SCHEMA = cv.All( +MCP23016_PIN_SCHEMA = pins.gpio_base_schema( + MCP23016GPIOPin, + cv.int_range(min=0, max=15), + modes=[CONF_INPUT, CONF_OUTPUT], + mode_validator=validate_mode, + invertable=True, +).extend( { - cv.GenerateID(): cv.declare_id(MCP23016GPIOPin), cv.Required(CONF_MCP23016): cv.use_id(MCP23016), - cv.Required(CONF_NUMBER): cv.int_range(min=0, max=15), - cv.Optional(CONF_MODE, default={}): cv.All( - { - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - }, - validate_mode, - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, } ) diff --git a/esphome/components/mcp23xxx_base/__init__.py b/esphome/components/mcp23xxx_base/__init__.py index 7bcd5c84fc..1e41a8ddff 100644 --- a/esphome/components/mcp23xxx_base/__init__.py +++ b/esphome/components/mcp23xxx_base/__init__.py @@ -54,20 +54,16 @@ def validate_mode(value): CONF_MCP23XXX = "mcp23xxx" -MCP23XXX_PIN_SCHEMA = cv.All( + +MCP23XXX_PIN_SCHEMA = pins.gpio_base_schema( + MCP23XXXGPIOPin, + cv.int_range(min=0, max=15), + modes=[CONF_INPUT, CONF_OUTPUT, CONF_PULLUP], + mode_validator=validate_mode, + invertable=True, +).extend( { - cv.GenerateID(): cv.declare_id(MCP23XXXGPIOPin), cv.Required(CONF_MCP23XXX): cv.use_id(MCP23XXXBase), - cv.Required(CONF_NUMBER): cv.int_range(min=0, max=15), - cv.Optional(CONF_MODE, default={}): cv.All( - { - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_PULLUP, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - }, - validate_mode, - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, cv.Optional(CONF_INTERRUPT, default="NO_INTERRUPT"): cv.enum( MCP23XXX_INTERRUPT_MODES, upper=True ), diff --git a/esphome/components/pca9554/__init__.py b/esphome/components/pca9554/__init__.py index fd52fafc5d..da31dbd9d9 100644 --- a/esphome/components/pca9554/__init__.py +++ b/esphome/components/pca9554/__init__.py @@ -52,20 +52,15 @@ def validate_mode(value): return value -PCA9554_PIN_SCHEMA = cv.All( +PCA9554_PIN_SCHEMA = pins.gpio_base_schema( + PCA9554GPIOPin, + cv.int_range(min=0, max=15), + modes=[CONF_INPUT, CONF_OUTPUT], + mode_validator=validate_mode, +).extend( { - cv.GenerateID(): cv.declare_id(PCA9554GPIOPin), cv.Required(CONF_PCA9554): cv.use_id(PCA9554Component), - cv.Required(CONF_NUMBER): cv.int_range(min=0, max=15), - cv.Optional(CONF_MODE, default={}): cv.All( - { - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - }, - validate_mode, - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, - }, + } ) diff --git a/esphome/components/pcf8574/__init__.py b/esphome/components/pcf8574/__init__.py index d44ac28364..ebf112b85b 100644 --- a/esphome/components/pcf8574/__init__.py +++ b/esphome/components/pcf8574/__init__.py @@ -48,19 +48,15 @@ def validate_mode(value): return value -PCF8574_PIN_SCHEMA = cv.All( +PCF8574_PIN_SCHEMA = pins.gpio_base_schema( + PCF8574GPIOPin, + cv.int_range(min=0, max=17), + modes=[CONF_INPUT, CONF_OUTPUT], + mode_validator=validate_mode, + invertable=True, +).extend( { - cv.GenerateID(): cv.declare_id(PCF8574GPIOPin), cv.Required(CONF_PCF8574): cv.use_id(PCF8574Component), - cv.Required(CONF_NUMBER): cv.int_range(min=0, max=17), - cv.Optional(CONF_MODE, default={}): cv.All( - { - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - }, - validate_mode, - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, } ) diff --git a/esphome/components/rp2040/gpio.py b/esphome/components/rp2040/gpio.py index 4823a6d22a..6ba0975a2c 100644 --- a/esphome/components/rp2040/gpio.py +++ b/esphome/components/rp2040/gpio.py @@ -1,7 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( - CONF_ANALOG, CONF_ID, CONF_INPUT, CONF_INVERTED, @@ -11,6 +10,7 @@ from esphome.const import ( CONF_OUTPUT, CONF_PULLDOWN, CONF_PULLUP, + CONF_ANALOG, ) from esphome.core import CORE from esphome import pins @@ -78,22 +78,10 @@ def validate_supports(value): RP2040_PIN_SCHEMA = cv.All( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(RP2040GPIOPin), - cv.Required(CONF_NUMBER): validate_gpio_pin, - cv.Optional(CONF_MODE, default={}): cv.Schema( - { - cv.Optional(CONF_ANALOG, default=False): cv.boolean, - cv.Optional(CONF_INPUT, default=False): cv.boolean, - cv.Optional(CONF_OUTPUT, default=False): cv.boolean, - cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean, - cv.Optional(CONF_PULLUP, default=False): cv.boolean, - cv.Optional(CONF_PULLDOWN, default=False): cv.boolean, - } - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, - } + pins.gpio_base_schema( + RP2040GPIOPin, + validate_gpio_pin, + modes=pins.GPIO_STANDARD_MODES + (CONF_ANALOG,), ), validate_supports, ) diff --git a/esphome/components/sn74hc595/__init__.py b/esphome/components/sn74hc595/__init__.py index e7ba45175c..11a6747656 100644 --- a/esphome/components/sn74hc595/__init__.py +++ b/esphome/components/sn74hc595/__init__.py @@ -5,7 +5,6 @@ from esphome.components import spi from esphome.const import ( CONF_ID, CONF_SPI_ID, - CONF_MODE, CONF_NUMBER, CONF_INVERTED, CONF_DATA_PIN, @@ -35,7 +34,6 @@ CONF_LATCH_PIN = "latch_pin" CONF_OE_PIN = "oe_pin" CONF_SR_COUNT = "sr_count" - CONFIG_SCHEMA = cv.Any( cv.Schema( { @@ -88,24 +86,20 @@ async def to_code(config): def _validate_output_mode(value): - if value is not True: + if value.get(CONF_OUTPUT) is not True: raise cv.Invalid("Only output mode is supported") return value -SN74HC595_PIN_SCHEMA = cv.All( +SN74HC595_PIN_SCHEMA = pins.gpio_base_schema( + SN74HC595GPIOPin, + cv.int_range(min=0, max=2047), + modes=[CONF_OUTPUT], + mode_validator=_validate_output_mode, + invertable=True, +).extend( { - cv.GenerateID(): cv.declare_id(SN74HC595GPIOPin), cv.Required(CONF_SN74HC595): cv.use_id(SN74HC595Component), - cv.Required(CONF_NUMBER): cv.int_range(min=0, max=2048, max_included=False), - cv.Optional(CONF_MODE, default={}): cv.All( - { - cv.Optional(CONF_OUTPUT, default=True): cv.All( - cv.boolean, _validate_output_mode - ), - }, - ), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, } ) diff --git a/esphome/config.py b/esphome/config.py index a980358186..6f644cee14 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -7,6 +7,7 @@ import re from typing import Optional, Union from contextlib import contextmanager +import contextvars import voluptuous as vol @@ -53,6 +54,7 @@ def iter_components(config): ConfigPath = list[Union[str, int]] +path_context = contextvars.ContextVar("Config path") def _path_begins_with(path: ConfigPath, other: ConfigPath) -> bool: @@ -489,6 +491,7 @@ class SchemaValidationStep(ConfigValidationStep): def run(self, result: Config) -> None: if self.comp.config_schema is None: return + token = path_context.set(self.path) with result.catch_error(self.path): if self.comp.is_platform: # Remove 'platform' key for validation @@ -507,6 +510,7 @@ class SchemaValidationStep(ConfigValidationStep): validated = schema(self.conf) result.set_by_path(self.path, validated) + path_context.reset(token) result.add_validation_step(FinalValidateValidationStep(self.path, self.comp)) @@ -652,37 +656,24 @@ class FinalValidateValidationStep(ConfigValidationStep): if self.comp.final_validate_schema is not None: self.comp.final_validate_schema(conf) - fconf = fv.full_config.get() - - def _check_pins(c): - for value in c.values(): - if not isinstance(value, dict): - continue - for key, ( - _, - _, - pin_final_validate, - ) in pins.PIN_SCHEMA_REGISTRY.items(): - if ( - key != CORE.target_platform - and key in value - and pin_final_validate is not None - ): - pin_final_validate(fconf, value) - - # Check for pin configs and a final_validate schema in the pin registry - confs = conf - if not isinstance( - confs, list - ): # Handle components like SPI that have a list instead of MULTI_CONF - confs = [conf] - for c in confs: - if c: # Some component have None or empty schemas - _check_pins(c) - fv.full_config.reset(token) +class PinUseValidationCheck(ConfigValidationStep): + """Check for pin reuse""" + + priority = -30 # Should happen after component final validations + + def __init__(self) -> None: + pass + + def run(self, result: Config) -> None: + if result.errors: + # If result already has errors, skip this step + return + pins.PIN_SCHEMA_REGISTRY.final_validate(result) + + def validate_config(config, command_line_substitutions) -> Config: result = Config() @@ -778,6 +769,7 @@ def validate_config(config, command_line_substitutions) -> Config: for domain, conf in config.items(): result.add_validation_step(LoadValidationStep(domain, conf)) result.add_validation_step(IDPassValidationStep()) + result.add_validation_step(PinUseValidationCheck()) result.run_validation_steps() diff --git a/esphome/const.py b/esphome/const.py index 2487d7b64c..2bc088c063 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -46,6 +46,7 @@ CONF_ADDRESS = "address" CONF_ADDRESSABLE_LIGHT_ID = "addressable_light_id" CONF_ADVANCED = "advanced" CONF_AFTER = "after" +CONF_ALLOW_OTHER_USES = "allow_other_uses" CONF_ALPHA = "alpha" CONF_ALTITUDE = "altitude" CONF_ANALOG = "analog" diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 3c3b27a79d..58ae23e139 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -526,6 +526,8 @@ class EsphomeCore: self.quiet = False def reset(self): + from esphome.pins import PIN_SCHEMA_REGISTRY + self.dashboard = False self.name = None self.friendly_name = None @@ -545,6 +547,7 @@ class EsphomeCore: self.platformio_options = {} self.loaded_integrations = set() self.component_ids = set() + PIN_SCHEMA_REGISTRY.reset() @property def address(self) -> Optional[str]: diff --git a/esphome/pins.py b/esphome/pins.py index 0035bea4f0..e2fd8e98e2 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -1,5 +1,7 @@ import operator from functools import reduce +import esphome.config_validation as cv +from esphome.core import CORE, ID from esphome.const import ( CONF_INPUT, @@ -10,16 +12,120 @@ from esphome.const import ( CONF_PULLDOWN, CONF_PULLUP, CONF_IGNORE_STRAPPING_WARNING, + CONF_ALLOW_OTHER_USES, + CONF_INVERTED, ) -from esphome.util import PinRegistry -from esphome.core import CORE + + +class PinRegistry(dict): + def __init__(self): + super().__init__() + self.pins_used = {} + + def reset(self): + self.pins_used = {} + + def get_count(self, key, number): + """ + Get the number of places a given pin is used. + :param key: The ID of the defining component + :param number: The pin number + :return: The number of places the pin is used. + """ + pin_key = (key, number) + return self.pins_used[pin_key] if pin_key in self.pins_used else 0 + + def register(self, name, schema, final_validate=None): + """ + Register a pin schema + :param name: + :param schema: + :param final_validate: + :return: + """ + + def decorator(fun): + self[name] = (fun, schema, final_validate) + return fun + + return decorator + + def validate(self, conf, key=None): + """ + Validate a pin against a registered schema + :param conf The pin config + :param key: an optional scalar key (e.g. platform) + :return: The transformed result + """ + from esphome.config import path_context + + key = self.get_key(conf) if key is None else key + # Element 1 is the pin validation function + # evaluate here so a validation failure skips the rest + result = self[key][1](conf) + if CONF_NUMBER in result: + # key maps to the pin schema + if isinstance(key, ID): + key = key.id + pin_key = (key, result[CONF_NUMBER]) + if pin_key not in self.pins_used: + self.pins_used[pin_key] = [] + # client_id identifies the instance of the providing component + client_id = result.get(key) + self.pins_used[pin_key].append((path_context.get(), client_id, result)) + # return the validated pin config + return result + + def get_key(self, conf): + """ + Is there a key in conf corresponding to a registered pin schema? + If not, fall back to the default platform schema. + :param conf The config for the component + :return: the schema key + """ + keys = list(filter(lambda k: k in conf, self)) + return keys[0] if keys else CORE.target_platform + + def get_to_code(self, key): + """ + Return the code generator function for a pin schema, stored as tuple element 0 + :param conf: The pin config + :param key An optional specific key + :return: The awaitable coroutine + """ + key = self.get_key(key) if isinstance(key, dict) else key + return self[key][0] + + def final_validate(self, fconf): + """ + Run the final validation for all pins, and check for reuse + :param fconf: The full config + """ + for (key, _), pin_list in self.pins_used.items(): + count = len(pin_list) # number of places same pin used. + final_val_fun = self[key][2] # final validation function + for pin_path, client_id, pin_config in pin_list: + 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) + final_val_fun(pin_config, parent_config) + allow_others = pin_config.get(CONF_ALLOW_OTHER_USES, False) + if count != 1 and not allow_others: + raise cv.Invalid( + f"Pin {pin_config[CONF_NUMBER]} is used in multiple places" + ) + if count == 1 and allow_others: + raise cv.Invalid( + f"Pin {pin_config[CONF_NUMBER]} incorrectly sets {CONF_ALLOW_OTHER_USES}: true" + ) + PIN_SCHEMA_REGISTRY = PinRegistry() def _set_mode(value, default_mode): - import esphome.config_validation as cv - if CONF_MODE not in value: return {**value, CONF_MODE: default_mode} mode = value[CONF_MODE] @@ -65,20 +171,26 @@ def _schema_creator(default_mode, internal: bool = False): if not isinstance(value, dict): return validator({CONF_NUMBER: value}) value = _set_mode(value, default_mode) - if not internal: - for key, entry in PIN_SCHEMA_REGISTRY.items(): - if key != CORE.target_platform and key in value: - return entry[1](value) - return PIN_SCHEMA_REGISTRY[CORE.target_platform][1](value) + if internal: + return PIN_SCHEMA_REGISTRY.validate(value, CORE.target_platform) + return PIN_SCHEMA_REGISTRY.validate(value) return validator def _internal_number_creator(mode): def validator(value): - value_d = {CONF_NUMBER: value} + if isinstance(value, dict): + if CONF_MODE in value or CONF_INVERTED in value: + raise cv.Invalid( + "This variable only supports pin numbers, not full pin schemas " + "(with inverted and mode)." + ) + value_d = value + else: + value_d = {CONF_NUMBER: value} value_d = _set_mode(value_d, mode) - return PIN_SCHEMA_REGISTRY[CORE.target_platform][1](value_d)[CONF_NUMBER] + return PIN_SCHEMA_REGISTRY.validate(value_d, CORE.target_platform)[CONF_NUMBER] return validator @@ -149,8 +261,6 @@ internal_gpio_input_pullup_pin_number = _internal_number_creator( def check_strapping_pin(conf, strapping_pin_list, logger): - import esphome.config_validation as cv - num = conf[CONF_NUMBER] if num in strapping_pin_list and not conf.get(CONF_IGNORE_STRAPPING_WARNING): logger.warning( @@ -161,3 +271,52 @@ def check_strapping_pin(conf, strapping_pin_list, logger): # mitigate undisciplined use of strapping: if num not in strapping_pin_list and conf.get(CONF_IGNORE_STRAPPING_WARNING): raise cv.Invalid(f"GPIO{num} is not a strapping pin") + + +GPIO_STANDARD_MODES = ( + CONF_INPUT, + CONF_OUTPUT, + CONF_OPEN_DRAIN, + CONF_PULLUP, + CONF_PULLDOWN, +) + + +def gpio_validate_modes(value): + if not value[CONF_INPUT] and not value[CONF_OUTPUT]: + raise cv.Invalid("Mode must be input or output") + return value + + +def gpio_base_schema( + pin_type, + number_validator, + modes=GPIO_STANDARD_MODES, + mode_validator=gpio_validate_modes, + invertable=True, +): + """ + Generate a base gpio pin schema + :param pin_type: The type for the pin variable + :param number_validator: A validator for the pin number + :param modes: The available modes, default is all standard modes + :param mode_validator: A validator function for the pin mode + :param invertable: If the pin supports hardware inversion + :return: A schema for the pin + """ + mode_default = len(modes) == 1 + mode_dict = dict( + map(lambda m: (cv.Optional(m, default=mode_default), cv.boolean), modes) + ) + + schema = cv.Schema( + { + cv.GenerateID(): cv.declare_id(pin_type), + cv.Required(CONF_NUMBER): number_validator, + cv.Optional(CONF_ALLOW_OTHER_USES): cv.boolean, + cv.Optional(CONF_MODE, default={}): cv.All(mode_dict, mode_validator), + } + ) + if invertable: + return schema.extend({cv.Optional(CONF_INVERTED, default=False): cv.boolean}) + return schema diff --git a/esphome/util.py b/esphome/util.py index d9c8502e0e..d5a4c60570 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -57,32 +57,6 @@ class SimpleRegistry(dict): return decorator -def _final_validate(parent_id_key, fun): - def validator(fconf, pin_config): - import esphome.config_validation as cv - - parent_path = fconf.get_path_for_id(pin_config[parent_id_key])[:-1] - parent_config = fconf.get_config_for_path(parent_path) - - pin_path = fconf.get_path_for_id(pin_config[const.CONF_ID])[:-1] - with cv.prepend_path([cv.ROOT_CONFIG_PATH] + pin_path): - fun(pin_config, parent_config) - - return validator - - -class PinRegistry(dict): - def register(self, name, schema, final_validate=None): - if final_validate is not None: - final_validate = _final_validate(name, final_validate) - - def decorator(fun): - self[name] = (fun, schema, final_validate) - return fun - - return decorator - - def safe_print(message="", end="\n"): from esphome.core import CORE diff --git a/tests/test1.1.yaml b/tests/test1.1.yaml index e2e7bd5d63..c71aa6e0ef 100644 --- a/tests/test1.1.yaml +++ b/tests/test1.1.yaml @@ -54,7 +54,9 @@ power_supply: i2c: sda: 21 - scl: 22 + scl: + number: 22 + allow_other_uses: true scan: true frequency: 100kHz setup_priority: -100 @@ -86,7 +88,9 @@ light: - platform: fastled_clockless id: addr1 chipset: WS2811 - pin: GPIO23 + pin: + allow_other_uses: true + number: GPIO23 num_leds: 60 rgb_order: BRG max_refresh_rate: 20ms @@ -168,8 +172,12 @@ light: - platform: fastled_spi id: addr2 chipset: WS2801 - data_pin: GPIO23 - clock_pin: GPIO22 + data_pin: + allow_other_uses: true + number: GPIO23 + clock_pin: + number: GPIO22 + allow_other_uses: true data_rate: 2MHz num_leds: 60 rgb_order: BRG @@ -190,7 +198,9 @@ light: variant: SK6812 method: ESP32_I2S_0 num_leds: 60 - pin: GPIO23 + pin: + allow_other_uses: true + number: GPIO23 - platform: partition name: Partition Light segments: diff --git a/tests/test1.yaml b/tests/test1.yaml index 0849d8aeb6..c90cdf6d90 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -181,8 +181,12 @@ mqtt: - light.turn_off: ${roomname}_lights i2c: - sda: 21 - scl: 22 + sda: + allow_other_uses: true + number: 21 + scl: + allow_other_uses: true + number: 22 scan: true frequency: 100kHz setup_priority: -100 @@ -190,15 +194,23 @@ i2c: spi: id: spi_bus - clk_pin: GPIO21 - mosi_pin: GPIO22 - miso_pin: GPIO23 + clk_pin: + allow_other_uses: true + number: GPIO21 + mosi_pin: + allow_other_uses: true + number: GPIO22 + miso_pin: + allow_other_uses: true + number: GPIO23 uart: - tx_pin: + allow_other_uses: true number: GPIO22 inverted: true rx_pin: + allow_other_uses: true number: GPIO23 inverted: true baud_rate: 115200 @@ -220,18 +232,30 @@ uart: - lambda: UARTDebug::log_int(direction, bytes, ','); - lambda: UARTDebug::log_binary(direction, bytes, ';'); - id: ld2410_uart - tx_pin: 18 - rx_pin: 23 + tx_pin: + allow_other_uses: true + number: 18 + rx_pin: + allow_other_uses: true + number: 23 baud_rate: 256000 parity: NONE stop_bits: 1 - id: dfrobot_mmwave_uart - tx_pin: 14 - rx_pin: 27 + tx_pin: + allow_other_uses: true + number: 14 + rx_pin: + allow_other_uses: true + number: 27 baud_rate: 115200 - id: ld2420_uart - tx_pin: 17 - rx_pin: 16 + tx_pin: + allow_other_uses: true + number: 17 + rx_pin: + allow_other_uses: true + number: 16 baud_rate: 115200 parity: NONE stop_bits: 1 @@ -282,12 +306,16 @@ power_supply: keep_on_time: 10s pin: number: 13 + allow_other_uses: true inverted: true deep_sleep: run_duration: 20s sleep_duration: 50s - wakeup_pin: GPIO2 + wakeup_pin: + allow_other_uses: true + number: GPIO2 + ignore_strapping_warning: true wakeup_pin_mode: INVERT_WAKEUP ads1115: @@ -295,11 +323,18 @@ ads1115: i2c_id: i2c_bus dallas: - pin: GPIO23 + pin: + allow_other_uses: true + number: GPIO23 as3935_spi: - cs_pin: GPIO12 - irq_pin: GPIO13 + cs_pin: + ignore_strapping_warning: true + allow_other_uses: true + number: GPIO12 + irq_pin: + allow_other_uses: true + number: GPIO13 esp32_ble: io_capability: keyboard_only @@ -339,16 +374,24 @@ bedjet: time_id: sntp_time mcp23s08: - id: mcp23s08_hub - cs_pin: GPIO12 + cs_pin: + ignore_strapping_warning: true + number: GPIO12 + allow_other_uses: true deviceaddress: 0 mcp23s17: - id: mcp23s17_hub - cs_pin: GPIO12 + cs_pin: + ignore_strapping_warning: true + number: GPIO12 + allow_other_uses: true deviceaddress: 1 micronova: - enable_rx_pin: 4 + enable_rx_pin: + allow_other_uses: true + number: 4 uart_id: uart_0 dfrobot_sen0395: @@ -539,7 +582,9 @@ sensor: name: NIR i2c_id: i2c_bus - platform: atm90e26 - cs_pin: 5 + cs_pin: + allow_other_uses: true + number: 5 voltage: name: Line Voltage current: @@ -558,7 +603,9 @@ sensor: gain_voltage: 26400 gain_ct: 31251 - platform: atm90e32 - cs_pin: 5 + cs_pin: + allow_other_uses: true + number: 5 phase_a: voltage: name: EMON Line Voltage A @@ -675,7 +722,9 @@ sensor: index: 1 name: Living Room Temperature 2 - platform: dht - pin: GPIO26 + pin: + allow_other_uses: true + number: GPIO26 temperature: id: dht_temperature name: Living Room Temperature 3 @@ -692,7 +741,9 @@ sensor: update_interval: 15s i2c_id: i2c_bus - platform: duty_cycle - pin: GPIO25 + pin: + allow_other_uses: true + number: GPIO25 name: Duty Cycle Sensor - platform: ee895 co2: @@ -721,9 +772,15 @@ sensor: update_interval: 15s i2c_id: i2c_bus - platform: hlw8012 - sel_pin: 5 - cf_pin: 14 - cf1_pin: 13 + sel_pin: + allow_other_uses: true + number: 5 + cf_pin: + allow_other_uses: true + number: 14 + cf1_pin: + allow_other_uses: true + number: 13 current: name: HLW8012 Current voltage: @@ -772,7 +829,9 @@ sensor: max_pressure: 15 temperature: name: Honeywell temperature - cs_pin: GPIO5 + cs_pin: + allow_other_uses: true + number: GPIO5 - platform: honeywellabp2_i2c pressure: name: Honeywell2 pressure @@ -806,8 +865,12 @@ sensor: i2c_id: i2c_bus - platform: hx711 name: HX711 Value - dout_pin: GPIO23 - clk_pin: GPIO25 + dout_pin: + allow_other_uses: true + number: GPIO23 + clk_pin: + allow_other_uses: true + number: GPIO25 gain: 128 update_interval: 15s - platform: ina219 @@ -880,22 +943,30 @@ sensor: i2c_id: i2c_bus - platform: max6675 name: Living Room Temperature - cs_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 update_interval: 15s - platform: max31855 name: Den Temperature - cs_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 update_interval: 15s reference_temperature: name: MAX31855 Internal Temperature - platform: max31856 name: BBQ Temperature - cs_pin: GPIO17 + cs_pin: + allow_other_uses: true + number: GPIO17 update_interval: 15s mains_filter: 50Hz - platform: max31865 name: Water Tank Temperature - cs_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 update_interval: 15s reference_resistance: 430 Ω rtd_nominal_resistance: 100 Ω @@ -1007,7 +1078,10 @@ sensor: i2c_id: i2c_bus - platform: pulse_counter name: Pulse Counter - pin: GPIO12 + pin: + ignore_strapping_warning: true + number: GPIO12 + allow_other_uses: true count_mode: rising_edge: INCREMENT falling_edge: DECREMENT @@ -1016,7 +1090,10 @@ sensor: - platform: pulse_meter name: Pulse Meter id: pulse_meter_sensor - pin: GPIO12 + pin: + ignore_strapping_warning: true + number: GPIO12 + allow_other_uses: true internal_filter: 100ms timeout: 2 min on_value: @@ -1039,9 +1116,15 @@ sensor: - platform: rotary_encoder name: Rotary Encoder id: rotary_encoder1 - pin_a: GPIO23 - pin_b: GPIO25 - pin_reset: GPIO25 + pin_a: + allow_other_uses: true + number: GPIO23 + pin_b: + allow_other_uses: true + number: GPIO25 + pin_reset: + allow_other_uses: true + number: GPIO25 filters: - or: - debounce: 0.1s @@ -1064,7 +1147,9 @@ sensor: - display_menu.up: - platform: pulse_width name: Pulse Width - pin: GPIO12 + pin: + allow_other_uses: true + number: GPIO12 - platform: sm300d2 uart_id: uart_0 co2: @@ -1247,9 +1332,12 @@ sensor: address: 0x48 i2c_id: i2c_bus - platform: ultrasonic - trigger_pin: GPIO25 + trigger_pin: + allow_other_uses: true + number: GPIO25 echo_pin: number: GPIO23 + allow_other_uses: true inverted: true name: Ultrasonic Sensor timeout: 5.5m @@ -1296,9 +1384,14 @@ sensor: pin: number: GPIO04 mode: INPUT + allow_other_uses: true - platform: zyaura - clock_pin: GPIO5 - data_pin: GPIO4 + clock_pin: + allow_other_uses: true + number: GPIO5 + data_pin: + allow_other_uses: true + number: GPIO4 co2: name: ZyAura CO2 temperature: @@ -1572,6 +1665,7 @@ binary_sensor: mcp23xxx: mcp23s08_hub # Use pin number 1 number: 1 + allow_other_uses: true # One of INPUT or INPUT_PULLUP mode: INPUT_PULLUP inverted: false @@ -1581,6 +1675,7 @@ binary_sensor: mcp23xxx: mcp23s17_hub # Use pin number 1 number: 1 + allow_other_uses: true # One of INPUT or INPUT_PULLUP mode: INPUT_PULLUP inverted: false @@ -1589,13 +1684,16 @@ binary_sensor: pin: mcp23xxx: mcp23s17_hub # Use pin number 1 + allow_other_uses: true number: 1 # One of INPUT or INPUT_PULLUP mode: INPUT_PULLUP inverted: false interrupt: FALLING - platform: gpio - pin: GPIO9 + pin: + allow_other_uses: true + number: GPIO9 name: Living Room Window device_class: window filters: @@ -1664,11 +1762,13 @@ binary_sensor: - platform: gpio pin: number: GPIO9 + allow_other_uses: true mode: INPUT_PULLUP name: Living Room Window 2 - platform: gpio pin: number: GPIO9 + allow_other_uses: true mode: INPUT_OUTPUT_OPEN_DRAIN name: Living Room Button - platform: status @@ -1747,6 +1847,7 @@ binary_sensor: pin: mcp23xxx: mcp23017_hub number: 1 + allow_other_uses: true mode: INPUT inverted: true - platform: gpio @@ -1767,6 +1868,7 @@ binary_sensor: name: Speed Fan Cycle binary sensor" pin: number: 18 + allow_other_uses: true mode: input: true pulldown: true @@ -1891,42 +1993,66 @@ tlc59208f: i2c_id: i2c_bus my9231: - data_pin: GPIO12 - clock_pin: GPIO14 + data_pin: + allow_other_uses: true + number: GPIO12 + clock_pin: + allow_other_uses: true + number: GPIO14 num_channels: 6 num_chips: 2 bit_depth: 16 sm2235: - data_pin: GPIO4 - clock_pin: GPIO5 + data_pin: + allow_other_uses: true + number: GPIO4 + clock_pin: + allow_other_uses: true + number: GPIO5 max_power_color_channels: 9 max_power_white_channels: 9 sm2335: - data_pin: GPIO4 - clock_pin: GPIO5 + data_pin: + allow_other_uses: true + number: GPIO4 + clock_pin: + allow_other_uses: true + number: GPIO5 max_power_color_channels: 9 max_power_white_channels: 9 bp1658cj: - data_pin: GPIO3 - clock_pin: GPIO5 + data_pin: + allow_other_uses: true + number: GPIO3 + clock_pin: + allow_other_uses: true + number: GPIO5 max_power_color_channels: 4 max_power_white_channels: 6 bp5758d: - data_pin: GPIO3 - clock_pin: GPIO5 + data_pin: + allow_other_uses: true + number: GPIO3 + clock_pin: + allow_other_uses: true + number: GPIO5 output: - platform: gpio - pin: GPIO26 + pin: + allow_other_uses: true + number: GPIO26 id: gpio_26 power_supply: atx_power_supply inverted: false - platform: ledc - pin: 19 + pin: + allow_other_uses: true + number: 19 id: gpio_19 frequency: 1500Hz channel: 14 @@ -1996,6 +2122,7 @@ output: pin: pcf8574: pcf8574_hub number: 0 + #allow_other_uses: true mode: OUTPUT inverted: false - platform: gpio @@ -2003,6 +2130,7 @@ output: pin: pca9554: pca9554_hub number: 0 + #allow_other_uses: true mode: OUTPUT inverted: false - platform: gpio @@ -2010,6 +2138,7 @@ output: pin: mcp23xxx: mcp23017_hub number: 0 + allow_other_uses: true mode: OUTPUT inverted: false - platform: gpio @@ -2017,6 +2146,7 @@ output: pin: mcp23xxx: mcp23008_hub number: 0 + allow_other_uses: true mode: OUTPUT inverted: false - platform: gpio @@ -2076,14 +2206,22 @@ output: channel: 3 - platform: slow_pwm id: id24 - pin: GPIO26 + pin: + allow_other_uses: true + number: GPIO26 period: 15s - platform: ac_dimmer id: dimmer1 - gate_pin: GPIO5 - zero_cross_pin: GPIO26 + gate_pin: + allow_other_uses: true + number: GPIO5 + zero_cross_pin: + allow_other_uses: true + number: GPIO26 - platform: esp32_dac - pin: GPIO25 + pin: + allow_other_uses: true + number: GPIO25 id: dac_output - platform: mcp4725 id: mcp4725_dac_output @@ -2147,9 +2285,15 @@ output: current: 10 - platform: x9c id: test_x9c - cs_pin: GPIO25 - inc_pin: GPIO26 - ud_pin: GPIO27 + cs_pin: + allow_other_uses: true + number: GPIO25 + inc_pin: + allow_other_uses: true + number: GPIO26 + ud_pin: + allow_other_uses: true + number: GPIO27 initial_value: 0.5 light: @@ -2256,7 +2400,9 @@ light: warm_white_color_temperature: 500 mireds remote_transmitter: - - pin: 32 + - pin: + allow_other_uses: true + number: 32 carrier_duty_percent: 100% climate: @@ -2440,6 +2586,7 @@ switch: mcp23xxx: mcp23s08_hub # Use pin number 0 number: 0 + allow_other_uses: true mode: OUTPUT inverted: false - platform: gpio @@ -2448,10 +2595,13 @@ switch: mcp23xxx: mcp23s17_hub # Use pin number 0 number: 1 + allow_other_uses: true mode: OUTPUT inverted: false - platform: gpio - pin: GPIO25 + pin: + allow_other_uses: true + number: GPIO25 name: Living Room Dehumidifier icon: "mdi:restart" inverted: true @@ -2834,12 +2984,24 @@ display: id: my_lcd_gpio dimensions: 18x4 data_pins: - - GPIO19 - - GPIO21 - - GPIO22 - - GPIO23 - enable_pin: GPIO23 - rs_pin: GPIO25 + - + allow_other_uses: true + number: GPIO19 + - + allow_other_uses: true + number: GPIO21 + - + allow_other_uses: true + number: GPIO22 + - + allow_other_uses: true + number: GPIO23 + enable_pin: + allow_other_uses: true + number: GPIO23 + rs_pin: + allow_other_uses: true + number: GPIO25 lambda: |- it.print("Hello World!"); - platform: lcd_pcf8574 @@ -2860,13 +3022,19 @@ display: it.print("Hello World!"); i2c_id: i2c_bus - platform: max7219 - cs_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 num_chips: 1 lambda: |- it.print("01234567"); - platform: tm1637 - clk_pin: GPIO23 - dio_pin: GPIO25 + clk_pin: + allow_other_uses: true + number: GPIO23 + dio_pin: + allow_other_uses: true + number: GPIO25 intensity: 3 lambda: |- it.print("1234"); @@ -2874,6 +3042,7 @@ display: clk_pin: mcp23xxx: mcp23017_hub number: 1 + allow_other_uses: true dio_pin: mcp23xxx: mcp23017_hub number: 2 @@ -2883,15 +3052,23 @@ display: lambda: |- it.print("1234"); - platform: pcd8544 - cs_pin: GPIO23 - dc_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 contrast: 60 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ssd1306_i2c model: SSD1306_128X64 - reset_pin: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 address: 0x3C id: display1 contrast: 60% @@ -2912,28 +3089,48 @@ display: i2c_id: i2c_bus - platform: ssd1306_spi model: SSD1306 128x64 - cs_pin: GPIO23 - dc_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ssd1322_spi model: SSD1322 256x64 - cs_pin: GPIO23 - dc_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ssd1325_spi model: SSD1325 128x64 - cs_pin: GPIO23 - dc_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ssd1327_i2c model: SSD1327 128X128 - reset_pin: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 address: 0x3D id: display1327 brightness: 60% @@ -2947,29 +3144,53 @@ display: i2c_id: i2c_bus - platform: ssd1327_spi model: SSD1327 128x128 - cs_pin: GPIO23 - dc_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ssd1331_spi - cs_pin: GPIO23 - dc_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ssd1351_spi model: SSD1351 128x128 - cs_pin: GPIO23 - dc_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: st7789v model: TTGO TDisplay 135x240 - cs_pin: GPIO5 - dc_pin: GPIO16 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO16 + reset_pin: + allow_other_uses: true + number: GPIO23 backlight_pin: no lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); @@ -2977,15 +3198,22 @@ display: width: 128 height: 64 cs_pin: + allow_other_uses: true number: GPIO23 inverted: true lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: st7735 model: INITR_BLACKTAB - cs_pin: GPIO5 - dc_pin: GPIO16 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO16 + reset_pin: + allow_other_uses: true + number: GPIO23 rotation: 0 device_width: 128 device_height: 160 @@ -3001,10 +3229,16 @@ display: mirror_x: true mirror_y: false model: TFT 2.4 - cs_pin: GPIO5 - dc_pin: GPIO4 + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO4 color_palette: GRAYSCALE - reset_pin: GPIO22 + reset_pin: + allow_other_uses: true + number: GPIO22 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: ili9xxx @@ -3014,9 +3248,15 @@ display: offset_width: 20 offset_height: 10 model: TFT 2.4 - cs_pin: GPIO5 - dc_pin: GPIO4 - reset_pin: GPIO22 + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO4 + reset_pin: + allow_other_uses: true + number: GPIO22 auto_clear_enabled: false rotation: 90 lambda: |- @@ -3041,10 +3281,18 @@ display: it.print_battery(true); - platform: tm1621 id: tm1621_display - cs_pin: GPIO17 - data_pin: GPIO5 - read_pin: GPIO23 - write_pin: GPIO18 + cs_pin: + allow_other_uses: true + number: GPIO17 + data_pin: + allow_other_uses: true + number: GPIO5 + read_pin: + allow_other_uses: true + number: GPIO23 + write_pin: + allow_other_uses: true + number: GPIO18 lambda: |- it.printf(0, "%.1f", id(dht_temperature).state); it.display_celsius(true); @@ -3053,12 +3301,18 @@ display: tm1651: id: tm1651_battery - clk_pin: GPIO23 - dio_pin: GPIO23 + clk_pin: + allow_other_uses: true + number: GPIO23 + dio_pin: + allow_other_uses: true + number: GPIO23 remote_receiver: id: rcvr - pin: GPIO32 + pin: + allow_other_uses: true + number: GPIO32 dump: all on_coolix: then: @@ -3068,11 +3322,16 @@ remote_receiver: delay: !lambda "return uint32_t(x.code) + x.protocol;" status_led: - pin: GPIO2 + pin: + allow_other_uses: true + number: GPIO2 + ignore_strapping_warning: true pn532_spi: id: pn532_bs - cs_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 update_interval: 1s on_tag: - lambda: |- @@ -3094,7 +3353,9 @@ rdm6300: uart_id: uart_0 rc522_spi: - cs_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 update_interval: 1s on_tag: - lambda: |- @@ -3287,9 +3548,15 @@ mcp23016: stepper: - platform: a4988 id: my_stepper - step_pin: GPIO23 - dir_pin: GPIO25 - sleep_pin: GPIO25 + step_pin: + allow_other_uses: true + number: GPIO23 + dir_pin: + allow_other_uses: true + number: GPIO25 + sleep_pin: + allow_other_uses: true + number: GPIO25 max_speed: 250 steps/s acceleration: 100 steps/s^2 deceleration: 200 steps/s^2 @@ -3397,14 +3664,26 @@ text_sensor: sn74hc595: - id: sn74hc595_hub - data_pin: GPIO21 - clock_pin: GPIO23 - latch_pin: GPIO22 - oe_pin: GPIO32 + data_pin: + allow_other_uses: true + number: GPIO21 + clock_pin: + allow_other_uses: true + number: GPIO23 + latch_pin: + allow_other_uses: true + number: GPIO22 + oe_pin: + allow_other_uses: true + number: GPIO32 sr_count: 2 - id: sn74hc595_hub_2 - latch_pin: GPIO22 - oe_pin: GPIO32 + latch_pin: + allow_other_uses: true + number: GPIO22 + oe_pin: + allow_other_uses: true + number: GPIO32 sr_count: 2 spi_id: spi_bus @@ -3456,8 +3735,12 @@ canbus: } - platform: esp32_can id: esp32_internal_can - rx_pin: GPIO04 - tx_pin: GPIO05 + rx_pin: + allow_other_uses: true + number: GPIO04 + tx_pin: + allow_other_uses: true + number: GPIO05 can_id: 4 bit_rate: 50kbps on_frame: diff --git a/tests/test11.5.yaml b/tests/test11.5.yaml index 685487e871..2a9b40c5c3 100644 --- a/tests/test11.5.yaml +++ b/tests/test11.5.yaml @@ -44,25 +44,42 @@ uart: rx_pin: 3 baud_rate: 9600 - id: uart_2 - tx_pin: 17 - rx_pin: 16 + tx_pin: + allow_other_uses: true + number: 17 + rx_pin: + allow_other_uses: true + number: 16 baud_rate: 19200 i2c: + sda: + number: 21 + allow_other_uses: true frequency: 100khz spi: - id: spi_1 - clk_pin: 12 - mosi_pin: 13 - miso_pin: 14 + clk_pin: + allow_other_uses: true + number: 12 + mosi_pin: + allow_other_uses: true + number: 13 + miso_pin: + allow_other_uses: true + number: 14 - id: spi_2 - clk_pin: 32 + clk_pin: + allow_other_uses: true + number: 32 mosi_pin: 33 modbus: uart_id: uart_1 - flow_control_pin: 5 + flow_control_pin: + allow_other_uses: true + number: 5 id: mod_bus1 modbus_controller: @@ -229,9 +246,15 @@ binary_sensor: lambda: return x[0] & 1; tlc5947: - data_pin: GPIO12 - clock_pin: GPIO14 - lat_pin: GPIO15 + data_pin: + allow_other_uses: true + number: GPIO12 + clock_pin: + allow_other_uses: true + number: GPIO14 + lat_pin: + allow_other_uses: true + number: GPIO15 gp8403: - id: gp8403_5v @@ -417,7 +440,9 @@ sensor: - platform: adc id: adc_sensor_p32 name: ADC pin 32 - pin: 32 + pin: + allow_other_uses: true + number: 32 attenuation: 11db update_interval: 1s - platform: internal_temperature @@ -584,7 +609,9 @@ sensor: name: Kuntze temperature - platform: ade7953_i2c - irq_pin: 16 + irq_pin: + allow_other_uses: true + number: 16 voltage: name: ADE7953 Voltage current_a: @@ -612,7 +639,9 @@ sensor: - platform: ade7953_spi spi_id: spi_1 cs_pin: 04 - irq_pin: 16 + irq_pin: + allow_other_uses: true + number: 16 voltage: name: ADE7953 Voltage current_a: @@ -683,7 +712,9 @@ switch: display: - platform: tm1638 id: primarydisplay - stb_pin: 5 #TM1638 STB + stb_pin: + allow_other_uses: true + number: 5 #TM1638 STB clk_pin: 18 #TM1638 CLK dio_pin: 23 #TM1638 DIO update_interval: 5s @@ -728,20 +759,32 @@ text_sensor: sn74hc165: id: sn74hc165_hub - data_pin: GPIO12 - clock_pin: GPIO14 - load_pin: GPIO27 - clock_inhibit_pin: GPIO26 + data_pin: + allow_other_uses: true + number: GPIO12 + clock_pin: + allow_other_uses: true + number: GPIO14 + load_pin: + number: GPIO27 + clock_inhibit_pin: + number: GPIO26 sr_count: 4 matrix_keypad: id: keypad rows: - - pin: 21 + - pin: + allow_other_uses: true + number: 21 - pin: 19 columns: - - pin: 17 - - pin: 16 + - pin: + allow_other_uses: true + number: 17 + - pin: + allow_other_uses: true + number: 16 keys: "1234" key_collector: @@ -753,14 +796,18 @@ key_collector: light: - platform: esp32_rmt_led_strip id: led_strip - pin: 13 + pin: + allow_other_uses: true + number: 13 num_leds: 60 rmt_channel: 6 rgb_order: GRB chipset: ws2812 - platform: esp32_rmt_led_strip id: led_strip2 - pin: 15 + pin: + allow_other_uses: true + number: 15 num_leds: 60 rmt_channel: 2 rgb_order: RGB diff --git a/tests/test2.yaml b/tests/test2.yaml index b258b103d3..e5358781df 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -17,11 +17,17 @@ substitutions: ethernet: type: LAN8720 - mdc_pin: GPIO23 - mdio_pin: GPIO25 + mdc_pin: + allow_other_uses: true + number: GPIO23 + mdio_pin: + allow_other_uses: true + number: GPIO25 clk_mode: GPIO0_IN phy_addr: 0 - power_pin: GPIO25 + power_pin: + allow_other_uses: true + number: GPIO25 manual_ip: static_ip: 192.168.178.56 gateway: 192.168.178.1 @@ -37,18 +43,32 @@ mdns: api: i2c: - sda: 21 - scl: 22 + sda: + allow_other_uses: true + number: 21 + scl: + allow_other_uses: true + number: 22 scan: false spi: - clk_pin: GPIO21 - mosi_pin: GPIO22 - miso_pin: GPIO23 + clk_pin: + allow_other_uses: true + number: GPIO21 + mosi_pin: + allow_other_uses: true + number: GPIO22 + miso_pin: + allow_other_uses: true + number: GPIO23 uart: - tx_pin: GPIO22 - rx_pin: GPIO23 + tx_pin: + allow_other_uses: true + number: GPIO22 + rx_pin: + allow_other_uses: true + number: GPIO23 baud_rate: 115200 # Specifically added for testing debug with no after: definition. debug: @@ -73,21 +93,29 @@ deep_sleep: gpio_wakeup_reason: 10s touch_wakeup_reason: 15s sleep_duration: 50s - wakeup_pin: GPIO2 + wakeup_pin: + allow_other_uses: true + number: GPIO2 wakeup_pin_mode: INVERT_WAKEUP as3935_i2c: - irq_pin: GPIO12 + irq_pin: + allow_other_uses: true + number: GPIO12 mcp3008: - id: mcp3008_hub - cs_pin: GPIO12 + cs_pin: + allow_other_uses: true + number: GPIO12 output: - platform: ac_dimmer id: dimmer1 gate_pin: GPIO5 - zero_cross_pin: GPIO12 + zero_cross_pin: + allow_other_uses: true + number: GPIO12 sensor: - platform: homeassistant @@ -534,7 +562,9 @@ binary_sensor: name: Mi Motion Sensor 2 Button - platform: gpio id: gpio_set_retry_test - pin: GPIO9 + pin: + allow_other_uses: true + number: GPIO9 on_press: then: - lambda: |- @@ -601,7 +631,9 @@ xiaomi_rtcgq02lm: bindkey: "48403ebe2d385db8d0c187f81e62cb64" status_led: - pin: GPIO2 + pin: + allow_other_uses: true + number: GPIO2 text_sensor: - platform: version @@ -704,9 +736,13 @@ script: stepper: - platform: uln2003 id: my_stepper - pin_a: GPIO23 + pin_a: + allow_other_uses: true + number: GPIO23 pin_b: GPIO27 - pin_c: GPIO25 + pin_c: + allow_other_uses: true + number: GPIO25 pin_d: GPIO26 sleep_when_done: false step_mode: HALF_STEP @@ -731,7 +767,9 @@ display: offset_height: 35 offset_width: 0 dc_pin: GPIO13 - reset_pin: GPIO9 + reset_pin: + allow_other_uses: true + number: GPIO9 image: - id: binary_image diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 9000636f63..63ef4e8ce0 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -29,14 +29,24 @@ web_server: version: 2 i2c: - sda: 4 - scl: 5 + sda: + allow_other_uses: true + number: 4 + scl: + allow_other_uses: true + number: 5 scan: false spi: - clk_pin: GPIO12 - mosi_pin: GPIO13 - miso_pin: GPIO14 + clk_pin: + allow_other_uses: true + number: GPIO12 + mosi_pin: + allow_other_uses: true + number: GPIO13 + miso_pin: + allow_other_uses: true + number: GPIO14 ota: @@ -52,7 +62,9 @@ sensor: name: VL53L0x Distance address: 0x29 update_interval: 60s - enable_pin: GPIO13 + enable_pin: + allow_other_uses: true + number: GPIO13 timeout: 200us - platform: apds9960 type: clear @@ -170,7 +182,9 @@ sensor: name: Custom Sensor - platform: ade7953_i2c - irq_pin: GPIO16 + irq_pin: + allow_other_uses: true + number: GPIO16 voltage: name: ADE7953 Voltage id: ade7953_voltage @@ -199,8 +213,12 @@ sensor: update_interval: 1s - platform: ade7953_spi - cs_pin: GPIO04 - irq_pin: GPIO16 + cs_pin: + allow_other_uses: true + number: GPIO04 + irq_pin: + allow_other_uses: true + number: GPIO16 voltage: name: ADE7953 Voltage current_a: @@ -360,8 +378,12 @@ text_sensor: name: Custom Text Sensor sm2135: - data_pin: GPIO12 - clock_pin: GPIO14 + data_pin: + allow_other_uses: true + number: GPIO12 + clock_pin: + allow_other_uses: true + number: GPIO14 rgb_current: 20mA cw_current: 60mA @@ -379,6 +401,7 @@ switch: pin: mcp23xxx: mcp23017_hub number: 0 + allow_other_uses: true mode: OUTPUT interlock: &interlock [gpio_switch1, gpio_switch2, gpio_switch3] - platform: gpio @@ -386,11 +409,14 @@ switch: pin: mcp23xxx: mcp23008_hub number: 0 + allow_other_uses: true mode: OUTPUT interlock: *interlock - platform: gpio id: gpio_switch3 - pin: GPIO1 + pin: + allow_other_uses: true + number: GPIO1 interlock: *interlock - platform: custom lambda: |- @@ -440,10 +466,18 @@ custom_component: stepper: - platform: uln2003 id: my_stepper - pin_a: GPIO12 - pin_b: GPIO13 - pin_c: GPIO14 - pin_d: GPIO15 + pin_a: + allow_other_uses: true + number: GPIO12 + pin_b: + allow_other_uses: true + number: GPIO13 + pin_c: + allow_other_uses: true + number: GPIO14 + pin_d: + allow_other_uses: true + number: GPIO15 sleep_when_done: false step_mode: HALF_STEP max_speed: 250 steps/s @@ -451,8 +485,12 @@ stepper: deceleration: inf - platform: a4988 id: my_stepper2 - step_pin: GPIO1 - dir_pin: GPIO2 + step_pin: + allow_other_uses: true + number: GPIO1 + dir_pin: + allow_other_uses: true + number: GPIO2 max_speed: 0.1 steps/s acceleration: 10 steps/s^2 deceleration: 10 steps/s^2 @@ -556,11 +594,14 @@ cover: output: - platform: esp8266_pwm id: out - pin: D3 + pin: + number: D3 frequency: 50Hz - platform: esp8266_pwm id: out2 - pin: D4 + pin: + allow_other_uses: true + number: D4 - platform: custom type: binary lambda: |- @@ -572,7 +613,9 @@ output: - platform: sigma_delta_output id: sddac update_interval: 60s - pin: D4 + pin: + allow_other_uses: true + number: D4 turn_on_action: then: - logger.log: "Turned on" @@ -593,7 +636,9 @@ output: outputs: - id: custom_float - platform: slow_pwm - pin: GPIO5 + pin: + allow_other_uses: true + number: GPIO5 id: my_slow_pwm period: 15s restart_cycle_on_state_change: false @@ -635,12 +680,18 @@ servo: ttp229_lsf: ttp229_bsf: - sdo_pin: D2 - scl_pin: D1 + sdo_pin: + allow_other_uses: true + number: D2 + scl_pin: + allow_other_uses: true + number: D1 display: - platform: max7219digit - cs_pin: GPIO15 + cs_pin: + allow_other_uses: true + number: GPIO15 num_chips: 4 rotate_chip: 0 intensity: 10 @@ -666,10 +717,20 @@ button: name: Restart Button (Factory Default Settings) cd74hc4067: - pin_s0: GPIO12 - pin_s1: GPIO13 - pin_s2: GPIO14 - pin_s3: GPIO15 + pin_s0: + allow_other_uses: true + number: GPIO12 + pin_s1: + allow_other_uses: true + number: GPIO13 + pin_s2: + allow_other_uses: true + number: GPIO14 + pin_s3: + allow_other_uses: true + number: GPIO15 adc128s102: - cs_pin: GPIO12 + cs_pin: + allow_other_uses: true + number: GPIO12 diff --git a/tests/test3.yaml b/tests/test3.yaml index 0a405a2841..6b1757c2ad 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -223,55 +223,102 @@ uart: tx_pin: number: GPIO1 inverted: true - rx_pin: GPIO3 + allow_other_uses: true + rx_pin: + allow_other_uses: true + number: GPIO3 baud_rate: 115200 - id: uart_2 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 - id: uart_3 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 4800 - id: uart_4 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 - id: uart_5 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 - id: uart_6 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 - id: uart_7 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 38400 - id: uart_8 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 4800 parity: NONE stop_bits: 2 # Specifically added for testing debug with no options at all. debug: - id: uart_9 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 - id: uart_10 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 - id: uart_11 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 - id: uart_12 - tx_pin: GPIO4 - rx_pin: GPIO5 + tx_pin: + allow_other_uses: true + number: GPIO4 + rx_pin: + allow_other_uses: true + number: GPIO5 baud_rate: 9600 modbus: @@ -748,13 +795,19 @@ binary_sensor: - platform: gpio id: bin1 - pin: 1 + pin: + allow_other_uses: true + number: 1 - platform: gpio id: bin2 - pin: 2 + pin: + allow_other_uses: true + number: 2 - platform: gpio id: bin3 - pin: 3 + pin: + allow_other_uses: true + number: 3 globals: - id: my_global_string @@ -762,11 +815,15 @@ globals: initial_value: '""' remote_receiver: - pin: GPIO12 + pin: + allow_other_uses: true + number: GPIO12 dump: [] status_led: - pin: GPIO2 + pin: + allow_other_uses: true + number: GPIO2 text_sensor: - platform: daly_bms @@ -819,13 +876,19 @@ script: switch: - platform: gpio id: gpio_switch1 - pin: 1 + pin: + allow_other_uses: true + number: 1 - platform: gpio id: gpio_switch2 - pin: 2 + pin: + allow_other_uses: true + number: 2 - platform: gpio id: gpio_switch3 - pin: 3 + pin: + allow_other_uses: true + number: 3 - platform: nextion id: r0 @@ -1023,13 +1086,18 @@ sprinkler: output: - platform: esp8266_pwm id: out - pin: D3 + pin: + number: D3 frequency: 50Hz - platform: esp8266_pwm id: out2 - pin: D4 + pin: + allow_other_uses: true + number: D4 - platform: slow_pwm - pin: GPIO5 + pin: + allow_other_uses: true + number: GPIO5 id: my_slow_pwm period: 15s restart_cycle_on_state_change: false @@ -1039,7 +1107,9 @@ e131: light: - platform: neopixelbus name: Neopixelbus Light - pin: GPIO1 + pin: + allow_other_uses: true + number: GPIO1 type: GRBW variant: SK6812 method: ESP8266_UART0 @@ -1071,6 +1141,12 @@ light: max_brightness: 500 firmware: "51.6" uart_id: uart_11 + nrst_pin: + number: 5 + allow_other_uses: true + boot0_pin: + number: 4 + allow_other_uses: true sim800l: uart_id: uart_4 @@ -1096,8 +1172,12 @@ dfplayer: logger.log: Playback finished event tm1651: id: tm1651_battery - clk_pin: D6 - dio_pin: D5 + clk_pin: + allow_other_uses: true + number: D6 + dio_pin: + allow_other_uses: true + number: D5 rf_bridge: uart_id: uart_5 @@ -1150,7 +1230,9 @@ display: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' fingerprint_grow: - sensing_pin: 4 + sensing_pin: + allow_other_uses: true + number: 4 password: 0x12FE37DC new_password: 0xA65B9840 on_finger_scan_matched: @@ -1184,7 +1266,9 @@ dsmr: decryption_key: 00112233445566778899aabbccddeeff uart_id: uart_6 max_telegram_length: 1000 - request_pin: D5 + request_pin: + allow_other_uses: true + number: D5 request_interval: 20s receive_timeout: 100ms @@ -1197,8 +1281,11 @@ qr_code: value: https://esphome.io/index.html lightwaverf: - read_pin: 13 - write_pin: 14 + read_pin: + number: 13 + write_pin: + allow_other_uses: true + number: 14 alarm_control_panel: - platform: template diff --git a/tests/test4.yaml b/tests/test4.yaml index 65aab7cdde..a3dfc6aceb 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -10,11 +10,17 @@ substitutions: ethernet: type: LAN8720 - mdc_pin: GPIO23 - mdio_pin: GPIO25 + mdc_pin: + allow_other_uses: true + number: GPIO23 + mdio_pin: + allow_other_uses: true + number: GPIO25 clk_mode: GPIO0_IN phy_addr: 0 - power_pin: GPIO25 + power_pin: + allow_other_uses: true + number: GPIO25 manual_ip: static_ip: 192.168.178.56 gateway: 192.168.178.1 @@ -34,29 +40,49 @@ mqtt: api: i2c: - sda: 21 - scl: 22 + sda: + allow_other_uses: true + number: 21 + scl: + allow_other_uses: true + number: 22 scan: false spi: - id: spi_id_1 - clk_pin: GPIO21 - mosi_pin: GPIO22 - miso_pin: GPIO23 + clk_pin: + allow_other_uses: true + number: GPIO21 + mosi_pin: + allow_other_uses: true + number: GPIO22 + miso_pin: + allow_other_uses: true + number: GPIO23 interface: hardware - id: spi_id_2 - clk_pin: GPIO32 - mosi_pin: GPIO33 + clk_pin: + number: GPIO32 + mosi_pin: + number: GPIO33 interface: hardware uart: - id: uart115200 - tx_pin: GPIO22 - rx_pin: GPIO23 + tx_pin: + allow_other_uses: true + number: GPIO22 + rx_pin: + allow_other_uses: true + number: GPIO23 baud_rate: 115200 - id: uart9600 - tx_pin: GPIO22 - rx_pin: GPIO23 + tx_pin: + allow_other_uses: true + number: GPIO22 + rx_pin: + allow_other_uses: true + number: GPIO23 baud_rate: 9600 - id: uart_he60r tx_pin: 22 @@ -91,6 +117,7 @@ tuya: status_pin: number: 14 inverted: true + allow_other_uses: true select: - platform: tuya @@ -117,7 +144,9 @@ sx1509: mcp3204: spi_id: spi_id_1 - cs_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 dac7678: address: 0x4A @@ -510,7 +539,9 @@ light: id: led_matrix_32x8 name: led_matrix_32x8 chipset: WS2812B - pin: GPIO15 + pin: + allow_other_uses: true + number: GPIO15 num_leds: 256 rgb_order: GRB default_transition_length: 0s @@ -566,20 +597,36 @@ display: - platform: waveshare_epaper spi_id: spi_id_1 - cs_pin: GPIO23 - dc_pin: GPIO23 - busy_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + busy_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 model: 2.13in-ttgo-b1 full_update_every: 30 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper spi_id: spi_id_1 - cs_pin: GPIO23 - dc_pin: GPIO23 - busy_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + busy_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 model: 2.90in full_update_every: 30 reset_duration: 200ms @@ -587,20 +634,36 @@ display: it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper spi_id: spi_id_1 - cs_pin: GPIO23 - dc_pin: GPIO23 - busy_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + busy_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 model: 2.90inv2 full_update_every: 30 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: waveshare_epaper spi_id: spi_id_1 - cs_pin: GPIO23 - dc_pin: GPIO23 - busy_pin: GPIO23 - reset_pin: GPIO23 + cs_pin: + allow_other_uses: true + number: GPIO23 + dc_pin: + allow_other_uses: true + number: GPIO23 + busy_pin: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO23 model: 1.54in-m5coreink-m09 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); @@ -610,15 +673,54 @@ display: partial_updating: false update_interval: 60s - ckv_pin: GPIO1 - sph_pin: GPIO1 - gmod_pin: GPIO1 - gpio0_enable_pin: GPIO1 - oe_pin: GPIO1 - spv_pin: GPIO1 - powerup_pin: GPIO1 - wakeup_pin: GPIO1 - vcom_pin: GPIO1 + display_data_1_pin: + number: 5 + allow_other_uses: true + display_data_2_pin: + number: 18 + allow_other_uses: true + display_data_3_pin: + number: 19 + allow_other_uses: true + display_data_5_pin: + number: 25 + allow_other_uses: true + display_data_4_pin: + number: 23 + allow_other_uses: true + display_data_6_pin: + number: 26 + allow_other_uses: true + display_data_7_pin: + number: 27 + allow_other_uses: true + ckv_pin: + allow_other_uses: true + number: GPIO1 + sph_pin: + allow_other_uses: true + number: GPIO1 + gmod_pin: + allow_other_uses: true + number: GPIO1 + gpio0_enable_pin: + allow_other_uses: true + number: GPIO1 + oe_pin: + allow_other_uses: true + number: GPIO1 + spv_pin: + allow_other_uses: true + number: GPIO1 + powerup_pin: + allow_other_uses: true + number: GPIO1 + wakeup_pin: + allow_other_uses: true + number: GPIO1 + vcom_pin: + allow_other_uses: true + number: GPIO1 number: - platform: tuya @@ -706,18 +808,54 @@ output: id: dac7678_1_ch7 esp32_camera: name: ESP-32 Camera - data_pins: [GPIO17, GPIO35, GPIO34, GPIO5, GPIO39, GPIO18, GPIO36, GPIO19] - vsync_pin: GPIO22 - href_pin: GPIO26 - pixel_clock_pin: GPIO21 + data_pins: + - number: GPIO17 + allow_other_uses: true + - number: GPIO35 + allow_other_uses: true + - + number: GPIO34 + - + number: GPIO5 + allow_other_uses: true + - + number: GPIO39 + - + number: GPIO18 + allow_other_uses: true + - + number: GPIO36 + allow_other_uses: true + - + number: GPIO19 + allow_other_uses: true + vsync_pin: + allow_other_uses: true + number: GPIO22 + href_pin: + allow_other_uses: true + number: GPIO26 + pixel_clock_pin: + allow_other_uses: true + number: GPIO21 external_clock: - pin: GPIO27 + pin: + allow_other_uses: true + number: GPIO27 frequency: 20MHz i2c_pins: - sda: GPIO25 - scl: GPIO23 - reset_pin: GPIO15 - power_down_pin: GPIO1 + sda: + allow_other_uses: true + number: GPIO25 + scl: + allow_other_uses: true + number: GPIO23 + reset_pin: + allow_other_uses: true + number: GPIO15 + power_down_pin: + allow_other_uses: true + number: GPIO1 resolution: 640x480 jpeg_quality: 10 @@ -748,8 +886,12 @@ button: touchscreen: - platform: ektf2232 - interrupt_pin: GPIO36 - rts_pin: GPIO5 + interrupt_pin: + allow_other_uses: true + number: GPIO36 + rts_pin: + allow_other_uses: true + number: GPIO5 display: inkplate_display on_touch: - logger.log: @@ -759,8 +901,11 @@ touchscreen: - platform: xpt2046 id: xpt_touchscreen spi_id: spi_id_2 - cs_pin: 17 - interrupt_pin: 16 + cs_pin: + allow_other_uses: true + number: 17 + interrupt_pin: + number: 16 display: inkplate_display update_interval: 50ms report_interval: 1s @@ -777,7 +922,9 @@ touchscreen: - platform: lilygo_t5_47 id: lilygo_touchscreen - interrupt_pin: GPIO36 + interrupt_pin: + allow_other_uses: true + number: GPIO36 display: inkplate_display on_touch: - logger.log: @@ -789,16 +936,26 @@ touchscreen: i2s_audio: - i2s_lrclk_pin: GPIO26 - i2s_bclk_pin: GPIO27 - i2s_mclk_pin: GPIO25 + i2s_lrclk_pin: + allow_other_uses: true + number: GPIO26 + i2s_bclk_pin: + allow_other_uses: true + number: GPIO27 + i2s_mclk_pin: + allow_other_uses: true + number: GPIO25 media_player: - platform: i2s_audio name: None dac_type: external - i2s_dout_pin: GPIO25 - mute_pin: GPIO14 + i2s_dout_pin: + allow_other_uses: true + number: GPIO25 + mute_pin: + allow_other_uses: true + number: GPIO14 on_state: - media_player.play: - media_player.play_media: http://localhost/media.mp3 @@ -827,12 +984,16 @@ prometheus: microphone: - platform: i2s_audio id: mic_id_adc - adc_pin: GPIO35 + adc_pin: + allow_other_uses: true + number: GPIO35 adc_type: internal - platform: i2s_audio id: mic_id_external - i2s_din_pin: GPIO23 + i2s_din_pin: + allow_other_uses: true + number: GPIO23 adc_type: external pdm: false @@ -840,7 +1001,9 @@ speaker: - platform: i2s_audio id: speaker_id dac_type: external - i2s_dout_pin: GPIO25 + i2s_dout_pin: + allow_other_uses: true + number: GPIO25 mode: mono voice_assistant: diff --git a/tests/test5.yaml b/tests/test5.yaml index 46cedcabd2..bf4247fb92 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -42,17 +42,27 @@ uart: baud_rate: 9600 - id: uart_2 tx_pin: + allow_other_uses: true number: 17 inverted: true - rx_pin: 16 + rx_pin: + allow_other_uses: true + number: 16 baud_rate: 19200 i2c: + sda: + allow_other_uses: true + number: 21 + scl: + number: 22 frequency: 100khz modbus: uart_id: uart_1 - flow_control_pin: 5 + flow_control_pin: + allow_other_uses: true + number: 5 id: mod_bus1 modbus_controller: @@ -214,9 +224,15 @@ binary_sensor: lambda: return x[0] & 1; tlc5947: - data_pin: GPIO12 - clock_pin: GPIO14 - lat_pin: GPIO15 + data_pin: + number: GPIO12 + allow_other_uses: true + clock_pin: + allow_other_uses: true + number: GPIO14 + lat_pin: + allow_other_uses: true + number: GPIO15 gp8403: - id: gp8403_5v @@ -614,7 +630,9 @@ switch: display: - platform: tm1638 id: primarydisplay - stb_pin: 5 #TM1638 STB + stb_pin: + allow_other_uses: true + number: 5 #TM1638 STB clk_pin: 18 #TM1638 CLK dio_pin: 23 #TM1638 DIO update_interval: 5s @@ -659,8 +677,12 @@ text_sensor: sn74hc165: id: sn74hc165_hub - data_pin: GPIO12 - clock_pin: GPIO14 + data_pin: + allow_other_uses: true + number: GPIO12 + clock_pin: + allow_other_uses: true + number: GPIO14 load_pin: GPIO27 clock_inhibit_pin: GPIO26 sr_count: 4 @@ -668,11 +690,17 @@ sn74hc165: matrix_keypad: id: keypad rows: - - pin: 21 + - pin: + allow_other_uses: true + number: 21 - pin: 19 columns: - - pin: 17 - - pin: 16 + - pin: + allow_other_uses: true + number: 17 + - pin: + allow_other_uses: true + number: 16 keys: "1234" has_pulldowns: true @@ -692,7 +720,9 @@ light: chipset: ws2812 - platform: esp32_rmt_led_strip id: led_strip2 - pin: 15 + pin: + allow_other_uses: true + number: 15 num_leds: 60 rmt_channel: 2 rgb_order: RGB diff --git a/tests/test8.yaml b/tests/test8.yaml index cbac2cb833..5e4a41080a 100644 --- a/tests/test8.yaml +++ b/tests/test8.yaml @@ -57,7 +57,9 @@ display: model: ili9342 cs_pin: GPIO5 dc_pin: GPIO4 - reset_pin: GPIO48 + reset_pin: + number: GPIO48 + allow_other_uses: true i2c: scl: GPIO18 @@ -68,7 +70,10 @@ touchscreen: interrupt_pin: number: GPIO3 ignore_strapping_warning: true - reset_pin: GPIO48 + allow_other_uses: false + reset_pin: + number: GPIO48 + allow_other_uses: true binary_sensor: - platform: tt21100