Move modbus schema validators to validators.py (#51121)
This commit is contained in:
parent
47f016b340
commit
5afd16ef5d
3 changed files with 84 additions and 71 deletions
|
@ -1,10 +1,19 @@
|
|||
"""Validate Modbus configuration."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import struct
|
||||
from typing import Any
|
||||
|
||||
from voluptuous import Invalid
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_COUNT, CONF_NAME, CONF_STRUCTURE
|
||||
from homeassistant.const import (
|
||||
CONF_COUNT,
|
||||
CONF_NAME,
|
||||
CONF_SCAN_INTERVAL,
|
||||
CONF_STRUCTURE,
|
||||
CONF_TIMEOUT,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
CONF_DATA_TYPE,
|
||||
|
@ -15,7 +24,10 @@ from .const import (
|
|||
CONF_SWAP_WORD,
|
||||
DATA_TYPE_CUSTOM,
|
||||
DATA_TYPE_STRING,
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
DEFAULT_STRUCT_FORMAT,
|
||||
MINIMUM_SCAN_INTERVAL,
|
||||
PLATFORMS,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -32,14 +44,14 @@ def sensor_schema_validator(config):
|
|||
f">{DEFAULT_STRUCT_FORMAT[config[CONF_DATA_TYPE]][config[CONF_COUNT]]}"
|
||||
)
|
||||
except KeyError:
|
||||
raise Invalid(
|
||||
raise vol.Invalid(
|
||||
f"Unable to detect data type for {config[CONF_NAME]} sensor, try a custom type"
|
||||
) from KeyError
|
||||
else:
|
||||
structure = config.get(CONF_STRUCTURE)
|
||||
|
||||
if not structure:
|
||||
raise Invalid(
|
||||
raise vol.Invalid(
|
||||
f"Error in sensor {config[CONF_NAME]}. The `{CONF_STRUCTURE}` field can not be empty "
|
||||
f"if the parameter `{CONF_DATA_TYPE}` is set to the `{DATA_TYPE_CUSTOM}`"
|
||||
)
|
||||
|
@ -47,13 +59,13 @@ def sensor_schema_validator(config):
|
|||
try:
|
||||
size = struct.calcsize(structure)
|
||||
except struct.error as err:
|
||||
raise Invalid(
|
||||
raise vol.Invalid(
|
||||
f"Error in sensor {config[CONF_NAME]} structure: {str(err)}"
|
||||
) from err
|
||||
|
||||
bytecount = config[CONF_COUNT] * 2
|
||||
if bytecount != size:
|
||||
raise Invalid(
|
||||
raise vol.Invalid(
|
||||
f"Structure request {size} bytes, "
|
||||
f"but {config[CONF_COUNT]} registers have a size of {bytecount} bytes"
|
||||
)
|
||||
|
@ -73,7 +85,7 @@ def sensor_schema_validator(config):
|
|||
else: # CONF_SWAP_WORD_BYTE, CONF_SWAP_WORD
|
||||
regs_needed = 2
|
||||
if config[CONF_COUNT] < regs_needed or (config[CONF_COUNT] % regs_needed) != 0:
|
||||
raise Invalid(
|
||||
raise vol.Invalid(
|
||||
f"Error in sensor {config[CONF_NAME]} swap({swap_type}) "
|
||||
f"not possible due to the registers "
|
||||
f"count: {config[CONF_COUNT]}, needed: {regs_needed}"
|
||||
|
@ -84,3 +96,56 @@ def sensor_schema_validator(config):
|
|||
CONF_STRUCTURE: structure,
|
||||
CONF_SWAP: swap_type,
|
||||
}
|
||||
|
||||
|
||||
def number_validator(value: Any) -> int | float:
|
||||
"""Coerce a value to number without losing precision."""
|
||||
if isinstance(value, int):
|
||||
return value
|
||||
if isinstance(value, float):
|
||||
return value
|
||||
|
||||
try:
|
||||
value = int(value)
|
||||
return value
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
try:
|
||||
value = float(value)
|
||||
return value
|
||||
except (TypeError, ValueError) as err:
|
||||
raise vol.Invalid(f"invalid number {value}") from err
|
||||
|
||||
|
||||
def scan_interval_validator(config: dict) -> dict:
|
||||
"""Control scan_interval."""
|
||||
for hub in config:
|
||||
minimum_scan_interval = DEFAULT_SCAN_INTERVAL
|
||||
for component, conf_key in PLATFORMS:
|
||||
if conf_key not in hub:
|
||||
continue
|
||||
|
||||
for entry in hub[conf_key]:
|
||||
scan_interval = entry.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||
if scan_interval < MINIMUM_SCAN_INTERVAL:
|
||||
if scan_interval == 0:
|
||||
continue
|
||||
_LOGGER.warning(
|
||||
"%s %s scan_interval(%d) is adjusted to minimum(%d)",
|
||||
component,
|
||||
entry.get(CONF_NAME),
|
||||
scan_interval,
|
||||
MINIMUM_SCAN_INTERVAL,
|
||||
)
|
||||
scan_interval = MINIMUM_SCAN_INTERVAL
|
||||
entry[CONF_SCAN_INTERVAL] = scan_interval
|
||||
minimum_scan_interval = min(scan_interval, minimum_scan_interval)
|
||||
if CONF_TIMEOUT in hub and hub[CONF_TIMEOUT] > minimum_scan_interval - 1:
|
||||
_LOGGER.warning(
|
||||
"Modbus %s timeout(%d) is adjusted(%d) due to scan_interval",
|
||||
hub.get(CONF_NAME, ""),
|
||||
hub[CONF_TIMEOUT],
|
||||
minimum_scan_interval - 1,
|
||||
)
|
||||
hub[CONF_TIMEOUT] = minimum_scan_interval - 1
|
||||
return config
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue