mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 13:34:54 +01:00
Allow validation of pins based on hub config (#5647)
This commit is contained in:
parent
40c001bdc2
commit
9eea52ea85
8 changed files with 72 additions and 12 deletions
|
@ -64,7 +64,7 @@ PCA6416A_PIN_SCHEMA = cv.All(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pins.PIN_SCHEMA_REGISTRY.register("pca6416a", PCA6416A_PIN_SCHEMA)
|
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PCA6416A, PCA6416A_PIN_SCHEMA)
|
||||||
async def pca6416a_pin_to_code(config):
|
async def pca6416a_pin_to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
parent = await cg.get_variable(config[CONF_PCA6416A])
|
parent = await cg.get_variable(config[CONF_PCA6416A])
|
||||||
|
|
|
@ -92,7 +92,7 @@ PCA9554_PIN_SCHEMA = cv.All(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pins.PIN_SCHEMA_REGISTRY.register("pca9554", PCA9554_PIN_SCHEMA)
|
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PCA9554, PCA9554_PIN_SCHEMA)
|
||||||
async def pca9554_pin_to_code(config):
|
async def pca9554_pin_to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
parent = await cg.get_variable(config[CONF_PCA9554])
|
parent = await cg.get_variable(config[CONF_PCA9554])
|
||||||
|
|
|
@ -65,7 +65,7 @@ PCF8574_PIN_SCHEMA = cv.All(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pins.PIN_SCHEMA_REGISTRY.register("pcf8574", PCF8574_PIN_SCHEMA)
|
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PCF8574, PCF8574_PIN_SCHEMA)
|
||||||
async def pcf8574_pin_to_code(config):
|
async def pcf8574_pin_to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
parent = await cg.get_variable(config[CONF_PCF8574])
|
parent = await cg.get_variable(config[CONF_PCF8574])
|
||||||
|
|
|
@ -77,7 +77,15 @@ SN74HC165_PIN_SCHEMA = cv.All(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pins.PIN_SCHEMA_REGISTRY.register(CONF_SN74HC165, SN74HC165_PIN_SCHEMA)
|
def sn74hc165_pin_final_validate(pin_config, parent_config):
|
||||||
|
max_pins = parent_config[CONF_SR_COUNT] * 8
|
||||||
|
if pin_config[CONF_NUMBER] >= max_pins:
|
||||||
|
raise cv.Invalid(f"Pin number must be less than {max_pins}")
|
||||||
|
|
||||||
|
|
||||||
|
@pins.PIN_SCHEMA_REGISTRY.register(
|
||||||
|
CONF_SN74HC165, SN74HC165_PIN_SCHEMA, sn74hc165_pin_final_validate
|
||||||
|
)
|
||||||
async def sn74hc165_pin_to_code(config):
|
async def sn74hc165_pin_to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_parented(var, config[CONF_SN74HC165])
|
await cg.register_parented(var, config[CONF_SN74HC165])
|
||||||
|
|
|
@ -10,7 +10,7 @@ from contextlib import contextmanager
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from esphome import core, yaml_util, loader
|
from esphome import core, yaml_util, loader, pins
|
||||||
import esphome.core.config as core_config
|
import esphome.core.config as core_config
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ESPHOME,
|
CONF_ESPHOME,
|
||||||
|
@ -645,14 +645,40 @@ class FinalValidateValidationStep(ConfigValidationStep):
|
||||||
# If result already has errors, skip this step
|
# If result already has errors, skip this step
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.comp.final_validate_schema is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
token = fv.full_config.set(result)
|
token = fv.full_config.set(result)
|
||||||
|
|
||||||
conf = result.get_nested_item(self.path)
|
conf = result.get_nested_item(self.path)
|
||||||
with result.catch_error(self.path):
|
with result.catch_error(self.path):
|
||||||
self.comp.final_validate_schema(conf)
|
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)
|
fv.full_config.reset(token)
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ async def gpio_pin_expression(conf):
|
||||||
return None
|
return None
|
||||||
from esphome import pins
|
from esphome import pins
|
||||||
|
|
||||||
for key, (func, _) in pins.PIN_SCHEMA_REGISTRY.items():
|
for key, (func, _, _) in pins.PIN_SCHEMA_REGISTRY.items():
|
||||||
if key in conf:
|
if key in conf:
|
||||||
return await coroutine(func)(conf)
|
return await coroutine(func)(conf)
|
||||||
return await coroutine(pins.PIN_SCHEMA_REGISTRY[CORE.target_platform][0])(conf)
|
return await coroutine(pins.PIN_SCHEMA_REGISTRY[CORE.target_platform][0])(conf)
|
||||||
|
|
|
@ -11,10 +11,10 @@ from esphome.const import (
|
||||||
CONF_PULLUP,
|
CONF_PULLUP,
|
||||||
CONF_IGNORE_STRAPPING_WARNING,
|
CONF_IGNORE_STRAPPING_WARNING,
|
||||||
)
|
)
|
||||||
from esphome.util import SimpleRegistry
|
from esphome.util import PinRegistry
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
|
|
||||||
PIN_SCHEMA_REGISTRY = SimpleRegistry()
|
PIN_SCHEMA_REGISTRY = PinRegistry()
|
||||||
|
|
||||||
|
|
||||||
def _set_mode(value, default_mode):
|
def _set_mode(value, default_mode):
|
||||||
|
|
|
@ -57,6 +57,32 @@ class SimpleRegistry(dict):
|
||||||
return decorator
|
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"):
|
def safe_print(message="", end="\n"):
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue