mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 10:47:10 +00:00
Replace modbus number_validator by HA standard (#108939)
This commit is contained in:
parent
858fb1fa37
commit
3cc5ffaa4b
@ -136,7 +136,6 @@ from .validators import (
|
|||||||
check_config,
|
check_config,
|
||||||
duplicate_fan_mode_validator,
|
duplicate_fan_mode_validator,
|
||||||
nan_validator,
|
nan_validator,
|
||||||
number_validator,
|
|
||||||
register_int_list_validator,
|
register_int_list_validator,
|
||||||
struct_validator,
|
struct_validator,
|
||||||
)
|
)
|
||||||
@ -187,8 +186,8 @@ BASE_STRUCT_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
vol.Optional(CONF_STRUCTURE): cv.string,
|
vol.Optional(CONF_STRUCTURE): cv.string,
|
||||||
vol.Optional(CONF_SCALE, default=1): number_validator,
|
vol.Optional(CONF_SCALE, default=1): cv.positive_float,
|
||||||
vol.Optional(CONF_OFFSET, default=0): number_validator,
|
vol.Optional(CONF_OFFSET, default=0): vol.Coerce(float),
|
||||||
vol.Optional(CONF_PRECISION): cv.positive_int,
|
vol.Optional(CONF_PRECISION): cv.positive_int,
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_SWAP,
|
CONF_SWAP,
|
||||||
@ -242,8 +241,8 @@ CLIMATE_SCHEMA = vol.All(
|
|||||||
{
|
{
|
||||||
vol.Required(CONF_TARGET_TEMP): cv.positive_int,
|
vol.Required(CONF_TARGET_TEMP): cv.positive_int,
|
||||||
vol.Optional(CONF_TARGET_TEMP_WRITE_REGISTERS, default=False): cv.boolean,
|
vol.Optional(CONF_TARGET_TEMP_WRITE_REGISTERS, default=False): cv.boolean,
|
||||||
vol.Optional(CONF_MAX_TEMP, default=35): number_validator,
|
vol.Optional(CONF_MAX_TEMP, default=35): cv.positive_float,
|
||||||
vol.Optional(CONF_MIN_TEMP, default=5): number_validator,
|
vol.Optional(CONF_MIN_TEMP, default=5): cv.positive_float,
|
||||||
vol.Optional(CONF_STEP, default=0.5): vol.Coerce(float),
|
vol.Optional(CONF_STEP, default=0.5): vol.Coerce(float),
|
||||||
vol.Optional(CONF_TEMPERATURE_UNIT, default=DEFAULT_TEMP_UNIT): cv.string,
|
vol.Optional(CONF_TEMPERATURE_UNIT, default=DEFAULT_TEMP_UNIT): cv.string,
|
||||||
vol.Optional(CONF_HVAC_ONOFF_REGISTER): cv.positive_int,
|
vol.Optional(CONF_HVAC_ONOFF_REGISTER): cv.positive_int,
|
||||||
@ -343,10 +342,10 @@ SENSOR_SCHEMA = vol.All(
|
|||||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||||
vol.Exclusive(CONF_VIRTUAL_COUNT, "vir_sen_count"): cv.positive_int,
|
vol.Exclusive(CONF_VIRTUAL_COUNT, "vir_sen_count"): cv.positive_int,
|
||||||
vol.Exclusive(CONF_SLAVE_COUNT, "vir_sen_count"): cv.positive_int,
|
vol.Exclusive(CONF_SLAVE_COUNT, "vir_sen_count"): cv.positive_int,
|
||||||
vol.Optional(CONF_MIN_VALUE): number_validator,
|
vol.Optional(CONF_MIN_VALUE): cv.positive_float,
|
||||||
vol.Optional(CONF_MAX_VALUE): number_validator,
|
vol.Optional(CONF_MAX_VALUE): cv.positive_float,
|
||||||
vol.Optional(CONF_NAN_VALUE): nan_validator,
|
vol.Optional(CONF_NAN_VALUE): nan_validator,
|
||||||
vol.Optional(CONF_ZERO_SUPPRESS): number_validator,
|
vol.Optional(CONF_ZERO_SUPPRESS): cv.positive_float,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -182,12 +182,25 @@ class BaseStructPlatform(BasePlatform, RestoreEntity):
|
|||||||
self._data_type = config[CONF_DATA_TYPE]
|
self._data_type = config[CONF_DATA_TYPE]
|
||||||
self._structure: str = config[CONF_STRUCTURE]
|
self._structure: str = config[CONF_STRUCTURE]
|
||||||
self._scale = config[CONF_SCALE]
|
self._scale = config[CONF_SCALE]
|
||||||
self._precision = config.get(CONF_PRECISION, 2 if self._scale < 1 else 0)
|
self._precision = config.get(CONF_PRECISION, 2)
|
||||||
self._offset = config[CONF_OFFSET]
|
self._offset = config[CONF_OFFSET]
|
||||||
self._slave_count = config.get(CONF_SLAVE_COUNT, None) or config.get(
|
self._slave_count = config.get(CONF_SLAVE_COUNT, None) or config.get(
|
||||||
CONF_VIRTUAL_COUNT, 0
|
CONF_VIRTUAL_COUNT, 0
|
||||||
)
|
)
|
||||||
self._slave_size = self._count = config[CONF_COUNT]
|
self._slave_size = self._count = config[CONF_COUNT]
|
||||||
|
self._value_is_int: bool = self._data_type in (
|
||||||
|
DataType.INT16,
|
||||||
|
DataType.INT32,
|
||||||
|
DataType.INT64,
|
||||||
|
DataType.UINT16,
|
||||||
|
DataType.UINT32,
|
||||||
|
DataType.UINT64,
|
||||||
|
)
|
||||||
|
if self._value_is_int:
|
||||||
|
if self._min_value:
|
||||||
|
self._min_value = round(self._min_value)
|
||||||
|
if self._max_value:
|
||||||
|
self._max_value = round(self._max_value)
|
||||||
|
|
||||||
def _swap_registers(self, registers: list[int], slave_count: int) -> list[int]:
|
def _swap_registers(self, registers: list[int], slave_count: int) -> list[int]:
|
||||||
"""Do swap as needed."""
|
"""Do swap as needed."""
|
||||||
@ -227,7 +240,7 @@ class BaseStructPlatform(BasePlatform, RestoreEntity):
|
|||||||
return str(self._max_value)
|
return str(self._max_value)
|
||||||
if self._zero_suppress is not None and abs(val) <= self._zero_suppress:
|
if self._zero_suppress is not None and abs(val) <= self._zero_suppress:
|
||||||
return "0"
|
return "0"
|
||||||
if self._precision == 0:
|
if self._precision == 0 or self._value_is_int:
|
||||||
return str(int(round(val, 0)))
|
return str(int(round(val, 0)))
|
||||||
return f"{float(val):.{self._precision}f}"
|
return f"{float(val):.{self._precision}f}"
|
||||||
|
|
||||||
|
@ -125,7 +125,10 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreSensor, SensorEntity):
|
|||||||
if self._coordinator:
|
if self._coordinator:
|
||||||
if result:
|
if result:
|
||||||
result_array = list(
|
result_array = list(
|
||||||
map(float if self._precision else int, result.split(","))
|
map(
|
||||||
|
float if not self._value_is_int else int,
|
||||||
|
result.split(","),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
self._attr_native_value = result_array[0]
|
self._attr_native_value = result_array[0]
|
||||||
self._coordinator.async_set_updated_data(result_array)
|
self._coordinator.async_set_updated_data(result_array)
|
||||||
|
@ -172,23 +172,6 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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:
|
|
||||||
return int(value)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
return float(value)
|
|
||||||
except (TypeError, ValueError) as err:
|
|
||||||
raise vol.Invalid(f"invalid number {value}") from err
|
|
||||||
|
|
||||||
|
|
||||||
def nan_validator(value: Any) -> int:
|
def nan_validator(value: Any) -> int:
|
||||||
"""Convert nan string to number (can be hex string or int)."""
|
"""Convert nan string to number (can be hex string or int)."""
|
||||||
if isinstance(value, int):
|
if isinstance(value, int):
|
||||||
|
@ -83,7 +83,6 @@ from homeassistant.components.modbus.validators import (
|
|||||||
duplicate_fan_mode_validator,
|
duplicate_fan_mode_validator,
|
||||||
duplicate_modbus_validator,
|
duplicate_modbus_validator,
|
||||||
nan_validator,
|
nan_validator,
|
||||||
number_validator,
|
|
||||||
register_int_list_validator,
|
register_int_list_validator,
|
||||||
struct_validator,
|
struct_validator,
|
||||||
)
|
)
|
||||||
@ -157,28 +156,6 @@ async def test_register_int_list_validator() -> None:
|
|||||||
register_int_list_validator(["aq"])
|
register_int_list_validator(["aq"])
|
||||||
|
|
||||||
|
|
||||||
async def test_number_validator() -> None:
|
|
||||||
"""Test number validator."""
|
|
||||||
|
|
||||||
for value, value_type in (
|
|
||||||
(15, int),
|
|
||||||
(15.1, float),
|
|
||||||
("15", int),
|
|
||||||
("15.1", float),
|
|
||||||
(-15, int),
|
|
||||||
(-15.1, float),
|
|
||||||
("-15", int),
|
|
||||||
("-15.1", float),
|
|
||||||
):
|
|
||||||
assert isinstance(number_validator(value), value_type)
|
|
||||||
|
|
||||||
try:
|
|
||||||
number_validator("x15.1")
|
|
||||||
except vol.Invalid:
|
|
||||||
return
|
|
||||||
pytest.fail("Number_validator not throwing exception")
|
|
||||||
|
|
||||||
|
|
||||||
async def test_nan_validator() -> None:
|
async def test_nan_validator() -> None:
|
||||||
"""Test number validator."""
|
"""Test number validator."""
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[7],
|
[7],
|
||||||
False,
|
False,
|
||||||
"34.0000",
|
"34",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -379,7 +379,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[9],
|
[9],
|
||||||
False,
|
False,
|
||||||
"18.5",
|
"18",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -390,7 +390,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[1],
|
[1],
|
||||||
False,
|
False,
|
||||||
"2.40",
|
"2",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -401,7 +401,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[2],
|
[2],
|
||||||
False,
|
False,
|
||||||
"-8.3",
|
"-8",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -445,7 +445,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[0x89AB, 0xCDEF, 0x0123, 0x4567],
|
[0x89AB, 0xCDEF, 0x0123, 0x4567],
|
||||||
False,
|
False,
|
||||||
"9920249030613615975",
|
"9920249030613616640",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -456,7 +456,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[0x0123, 0x4567, 0x89AB, 0xCDEF],
|
[0x0123, 0x4567, 0x89AB, 0xCDEF],
|
||||||
False,
|
False,
|
||||||
"163971058432973793",
|
"163971058432973792",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -676,7 +676,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[0x00AB, 0xCDEF],
|
[0x00AB, 0xCDEF],
|
||||||
False,
|
False,
|
||||||
"112593.75",
|
"112594",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -686,7 +686,7 @@ async def test_config_wrong_struct_sensor(
|
|||||||
},
|
},
|
||||||
[0x00AB, 0xCDEF],
|
[0x00AB, 0xCDEF],
|
||||||
False,
|
False,
|
||||||
"112593.75",
|
"112594",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -727,7 +727,7 @@ async def test_all_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None:
|
|||||||
int.from_bytes(struct.pack(">f", float("nan"))[2:4]),
|
int.from_bytes(struct.pack(">f", float("nan"))[2:4]),
|
||||||
],
|
],
|
||||||
False,
|
False,
|
||||||
["34899771392", "0"],
|
["34899771392.0", "0.0"],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -742,7 +742,7 @@ async def test_all_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None:
|
|||||||
int.from_bytes(struct.pack(">f", float("nan"))[2:4]),
|
int.from_bytes(struct.pack(">f", float("nan"))[2:4]),
|
||||||
],
|
],
|
||||||
False,
|
False,
|
||||||
["34899771392", "0"],
|
["34899771392.0", "0.0"],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -937,7 +937,7 @@ async def test_virtual_sensor(
|
|||||||
},
|
},
|
||||||
[0x0102, 0x0304, 0x0506, 0x0708],
|
[0x0102, 0x0304, 0x0506, 0x0708],
|
||||||
False,
|
False,
|
||||||
[str(0x0708050603040102)],
|
[str(0x0708050603040100)],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -970,7 +970,7 @@ async def test_virtual_sensor(
|
|||||||
},
|
},
|
||||||
[0x0102, 0x0304, 0x0506, 0x0708, 0x0901, 0x0902, 0x0903, 0x0904],
|
[0x0102, 0x0304, 0x0506, 0x0708, 0x0901, 0x0902, 0x0903, 0x0904],
|
||||||
False,
|
False,
|
||||||
[str(0x0708050603040102), str(0x0904090309020901)],
|
[str(0x0708050603040100), str(0x0904090309020900)],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -1035,10 +1035,10 @@ async def test_virtual_sensor(
|
|||||||
],
|
],
|
||||||
False,
|
False,
|
||||||
[
|
[
|
||||||
str(0x0604060306020601),
|
str(0x0604060306020600),
|
||||||
str(0x0704070307020701),
|
str(0x0704070307020700),
|
||||||
str(0x0804080308020801),
|
str(0x0804080308020800),
|
||||||
str(0x0904090309020901),
|
str(0x0904090309020900),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1202,7 +1202,7 @@ async def test_unpack_ok(hass: HomeAssistant, mock_do_cycle, expected) -> None:
|
|||||||
0x0000,
|
0x0000,
|
||||||
0x000A,
|
0x000A,
|
||||||
],
|
],
|
||||||
"0,10",
|
"0,10.00",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user