Update modbus validate table to be 3 state, to simplify the code (#104514)
This commit is contained in:
parent
6e5dfa0e9b
commit
be889c89c1
2 changed files with 56 additions and 33 deletions
|
@ -52,6 +52,12 @@ ENTRY = namedtuple(
|
||||||
"validate_parm",
|
"validate_parm",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
ILLEGAL = "I"
|
||||||
|
OPTIONAL = "O"
|
||||||
|
DEMANDED = "D"
|
||||||
|
|
||||||
PARM_IS_LEGAL = namedtuple(
|
PARM_IS_LEGAL = namedtuple(
|
||||||
"PARM_IS_LEGAL",
|
"PARM_IS_LEGAL",
|
||||||
[
|
[
|
||||||
|
@ -62,28 +68,40 @@ PARM_IS_LEGAL = namedtuple(
|
||||||
"swap_word",
|
"swap_word",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
# PARM_IS_LEGAL defines if the keywords:
|
|
||||||
# count:
|
|
||||||
# structure:
|
|
||||||
# swap: byte
|
|
||||||
# swap: word
|
|
||||||
# swap: word_byte (identical to swap: word)
|
|
||||||
# are legal to use.
|
|
||||||
# These keywords are only legal with some datatype: ...
|
|
||||||
# As expressed in DEFAULT_STRUCT_FORMAT
|
|
||||||
|
|
||||||
DEFAULT_STRUCT_FORMAT = {
|
DEFAULT_STRUCT_FORMAT = {
|
||||||
DataType.INT16: ENTRY("h", 1, PARM_IS_LEGAL(False, False, True, True, False)),
|
DataType.INT16: ENTRY(
|
||||||
DataType.UINT16: ENTRY("H", 1, PARM_IS_LEGAL(False, False, True, True, False)),
|
"h", 1, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, ILLEGAL)
|
||||||
DataType.FLOAT16: ENTRY("e", 1, PARM_IS_LEGAL(False, False, True, True, False)),
|
),
|
||||||
DataType.INT32: ENTRY("i", 2, PARM_IS_LEGAL(False, False, True, True, True)),
|
DataType.UINT16: ENTRY(
|
||||||
DataType.UINT32: ENTRY("I", 2, PARM_IS_LEGAL(False, False, True, True, True)),
|
"H", 1, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, ILLEGAL)
|
||||||
DataType.FLOAT32: ENTRY("f", 2, PARM_IS_LEGAL(False, False, True, True, True)),
|
),
|
||||||
DataType.INT64: ENTRY("q", 4, PARM_IS_LEGAL(False, False, True, True, True)),
|
DataType.FLOAT16: ENTRY(
|
||||||
DataType.UINT64: ENTRY("Q", 4, PARM_IS_LEGAL(False, False, True, True, True)),
|
"e", 1, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, ILLEGAL)
|
||||||
DataType.FLOAT64: ENTRY("d", 4, PARM_IS_LEGAL(False, False, True, True, True)),
|
),
|
||||||
DataType.STRING: ENTRY("s", -1, PARM_IS_LEGAL(True, False, False, True, False)),
|
DataType.INT32: ENTRY(
|
||||||
DataType.CUSTOM: ENTRY("?", 0, PARM_IS_LEGAL(True, True, False, False, False)),
|
"i", 2, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, OPTIONAL)
|
||||||
|
),
|
||||||
|
DataType.UINT32: ENTRY(
|
||||||
|
"I", 2, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, OPTIONAL)
|
||||||
|
),
|
||||||
|
DataType.FLOAT32: ENTRY(
|
||||||
|
"f", 2, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, OPTIONAL)
|
||||||
|
),
|
||||||
|
DataType.INT64: ENTRY(
|
||||||
|
"q", 4, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, OPTIONAL)
|
||||||
|
),
|
||||||
|
DataType.UINT64: ENTRY(
|
||||||
|
"Q", 4, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, OPTIONAL)
|
||||||
|
),
|
||||||
|
DataType.FLOAT64: ENTRY(
|
||||||
|
"d", 4, PARM_IS_LEGAL(ILLEGAL, ILLEGAL, OPTIONAL, OPTIONAL, OPTIONAL)
|
||||||
|
),
|
||||||
|
DataType.STRING: ENTRY(
|
||||||
|
"s", 0, PARM_IS_LEGAL(DEMANDED, ILLEGAL, ILLEGAL, OPTIONAL, ILLEGAL)
|
||||||
|
),
|
||||||
|
DataType.CUSTOM: ENTRY(
|
||||||
|
"?", 0, PARM_IS_LEGAL(DEMANDED, DEMANDED, ILLEGAL, ILLEGAL, ILLEGAL)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,32 +114,37 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]:
|
||||||
data_type = config[CONF_DATA_TYPE] = DataType.INT16
|
data_type = config[CONF_DATA_TYPE] = DataType.INT16
|
||||||
count = config.get(CONF_COUNT, None)
|
count = config.get(CONF_COUNT, None)
|
||||||
structure = config.get(CONF_STRUCTURE, None)
|
structure = config.get(CONF_STRUCTURE, None)
|
||||||
slave_count = config.get(CONF_SLAVE_COUNT, config.get(CONF_VIRTUAL_COUNT, 0))
|
slave_count = config.get(CONF_SLAVE_COUNT, config.get(CONF_VIRTUAL_COUNT))
|
||||||
swap_type = config.get(CONF_SWAP, CONF_SWAP_NONE)
|
swap_type = config.get(CONF_SWAP, CONF_SWAP_NONE)
|
||||||
validator = DEFAULT_STRUCT_FORMAT[data_type].validate_parm
|
validator = DEFAULT_STRUCT_FORMAT[data_type].validate_parm
|
||||||
for entry in (
|
for entry in (
|
||||||
(count, validator.count, CONF_COUNT),
|
(count, validator.count, CONF_COUNT),
|
||||||
(structure, validator.structure, CONF_STRUCTURE),
|
(structure, validator.structure, CONF_STRUCTURE),
|
||||||
|
(
|
||||||
|
slave_count,
|
||||||
|
validator.slave_count,
|
||||||
|
f"{CONF_VIRTUAL_COUNT} / {CONF_SLAVE_COUNT}",
|
||||||
|
),
|
||||||
):
|
):
|
||||||
if bool(entry[0]) != entry[1]:
|
if entry[0] is None:
|
||||||
error = "cannot be combined" if not entry[1] else "missing, demanded"
|
if entry[1] == DEMANDED:
|
||||||
|
error = f"{name}: `{entry[2]}:` missing, demanded with `{CONF_DATA_TYPE}: {data_type}`"
|
||||||
|
raise vol.Invalid(error)
|
||||||
|
elif entry[1] == ILLEGAL:
|
||||||
error = (
|
error = (
|
||||||
f"{name}: `{entry[2]}:` {error} with `{CONF_DATA_TYPE}: {data_type}`"
|
f"{name}: `{entry[2]}:` illegal with `{CONF_DATA_TYPE}: {data_type}`"
|
||||||
)
|
)
|
||||||
raise vol.Invalid(error)
|
raise vol.Invalid(error)
|
||||||
|
|
||||||
if slave_count and not validator.slave_count:
|
|
||||||
error = f"{name}: `{CONF_VIRTUAL_COUNT} / {CONF_SLAVE_COUNT}:` cannot be combined with `{CONF_DATA_TYPE}: {data_type}`"
|
|
||||||
raise vol.Invalid(error)
|
|
||||||
if swap_type != CONF_SWAP_NONE:
|
if swap_type != CONF_SWAP_NONE:
|
||||||
swap_type_validator = {
|
swap_type_validator = {
|
||||||
CONF_SWAP_NONE: False,
|
CONF_SWAP_NONE: validator.swap_byte,
|
||||||
CONF_SWAP_BYTE: validator.swap_byte,
|
CONF_SWAP_BYTE: validator.swap_byte,
|
||||||
CONF_SWAP_WORD: validator.swap_word,
|
CONF_SWAP_WORD: validator.swap_word,
|
||||||
CONF_SWAP_WORD_BYTE: validator.swap_word,
|
CONF_SWAP_WORD_BYTE: validator.swap_word,
|
||||||
}[swap_type]
|
}[swap_type]
|
||||||
if not swap_type_validator:
|
if swap_type_validator == ILLEGAL:
|
||||||
error = f"{name}: `{CONF_SWAP}:{swap_type}` cannot be combined with `{CONF_DATA_TYPE}: {data_type}`"
|
error = f"{name}: `{CONF_SWAP}:{swap_type}` illegal with `{CONF_DATA_TYPE}: {data_type}`"
|
||||||
raise vol.Invalid(error)
|
raise vol.Invalid(error)
|
||||||
if config[CONF_DATA_TYPE] == DataType.CUSTOM:
|
if config[CONF_DATA_TYPE] == DataType.CUSTOM:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -247,7 +247,7 @@ async def test_config_sensor(hass: HomeAssistant, mock_modbus) -> None:
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
f"{TEST_ENTITY_NAME}: `{CONF_STRUCTURE}:` missing, demanded with `{CONF_DATA_TYPE}: {DataType.CUSTOM}`",
|
f"{TEST_ENTITY_NAME}: Size of structure is 0 bytes but `{CONF_COUNT}: 4` is 8 bytes",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
@ -276,7 +276,7 @@ async def test_config_sensor(hass: HomeAssistant, mock_modbus) -> None:
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
f"{TEST_ENTITY_NAME}: `{CONF_SWAP}:{CONF_SWAP_WORD}` cannot be combined with `{CONF_DATA_TYPE}: {DataType.CUSTOM}`",
|
f"{TEST_ENTITY_NAME}: `{CONF_SWAP}:{CONF_SWAP_WORD}` illegal with `{CONF_DATA_TYPE}: {DataType.CUSTOM}`",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue