Add swap to climate and change data_count -> count in modbus (#51668)
parent
61079ab7fa
commit
7ad91fdf71
|
@ -187,7 +187,9 @@ BASE_SWITCH_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
CLIMATE_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
CLIMATE_SCHEMA = vol.All(
|
||||||
|
cv.deprecated(CONF_DATA_COUNT, replacement_key=CONF_COUNT),
|
||||||
|
BASE_COMPONENT_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_INPUT_TYPE, default=CALL_TYPE_REGISTER_HOLDING): vol.In(
|
vol.Optional(CONF_INPUT_TYPE, default=CALL_TYPE_REGISTER_HOLDING): vol.In(
|
||||||
[
|
[
|
||||||
|
@ -196,7 +198,7 @@ CLIMATE_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
vol.Required(CONF_TARGET_TEMP): cv.positive_int,
|
vol.Required(CONF_TARGET_TEMP): cv.positive_int,
|
||||||
vol.Optional(CONF_DATA_COUNT, default=2): cv.positive_int,
|
vol.Optional(CONF_COUNT, default=2): cv.positive_int,
|
||||||
vol.Optional(CONF_DATA_TYPE, default=DATA_TYPE_FLOAT): vol.In(
|
vol.Optional(CONF_DATA_TYPE, default=DATA_TYPE_FLOAT): vol.In(
|
||||||
[DATA_TYPE_INT, DATA_TYPE_UINT, DATA_TYPE_FLOAT, DATA_TYPE_CUSTOM]
|
[DATA_TYPE_INT, DATA_TYPE_UINT, DATA_TYPE_FLOAT, DATA_TYPE_CUSTOM]
|
||||||
),
|
),
|
||||||
|
@ -208,7 +210,11 @@ CLIMATE_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
||||||
vol.Optional(CONF_STEP, default=0.5): vol.Coerce(float),
|
vol.Optional(CONF_STEP, default=0.5): vol.Coerce(float),
|
||||||
vol.Optional(CONF_STRUCTURE, default=DEFAULT_STRUCTURE_PREFIX): cv.string,
|
vol.Optional(CONF_STRUCTURE, default=DEFAULT_STRUCTURE_PREFIX): cv.string,
|
||||||
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_SWAP, default=CONF_SWAP_NONE): vol.In(
|
||||||
|
[CONF_SWAP_NONE, CONF_SWAP_BYTE, CONF_SWAP_WORD, CONF_SWAP_WORD_BYTE]
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
COVERS_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
COVERS_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
||||||
|
|
|
@ -11,6 +11,7 @@ from homeassistant.components.climate.const import (
|
||||||
SUPPORT_TARGET_TEMPERATURE,
|
SUPPORT_TARGET_TEMPERATURE,
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
CONF_COUNT,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_OFFSET,
|
CONF_OFFSET,
|
||||||
CONF_STRUCTURE,
|
CONF_STRUCTURE,
|
||||||
|
@ -28,13 +29,16 @@ from .const import (
|
||||||
CALL_TYPE_REGISTER_HOLDING,
|
CALL_TYPE_REGISTER_HOLDING,
|
||||||
CALL_TYPE_WRITE_REGISTERS,
|
CALL_TYPE_WRITE_REGISTERS,
|
||||||
CONF_CLIMATES,
|
CONF_CLIMATES,
|
||||||
CONF_DATA_COUNT,
|
|
||||||
CONF_DATA_TYPE,
|
CONF_DATA_TYPE,
|
||||||
CONF_MAX_TEMP,
|
CONF_MAX_TEMP,
|
||||||
CONF_MIN_TEMP,
|
CONF_MIN_TEMP,
|
||||||
CONF_PRECISION,
|
CONF_PRECISION,
|
||||||
CONF_SCALE,
|
CONF_SCALE,
|
||||||
CONF_STEP,
|
CONF_STEP,
|
||||||
|
CONF_SWAP,
|
||||||
|
CONF_SWAP_BYTE,
|
||||||
|
CONF_SWAP_WORD,
|
||||||
|
CONF_SWAP_WORD_BYTE,
|
||||||
CONF_TARGET_TEMP,
|
CONF_TARGET_TEMP,
|
||||||
DATA_TYPE_CUSTOM,
|
DATA_TYPE_CUSTOM,
|
||||||
DEFAULT_STRUCT_FORMAT,
|
DEFAULT_STRUCT_FORMAT,
|
||||||
|
@ -59,7 +63,7 @@ async def async_setup_platform(
|
||||||
entities = []
|
entities = []
|
||||||
for entity in discovery_info[CONF_CLIMATES]:
|
for entity in discovery_info[CONF_CLIMATES]:
|
||||||
hub: ModbusHub = hass.data[MODBUS_DOMAIN][discovery_info[CONF_NAME]]
|
hub: ModbusHub = hass.data[MODBUS_DOMAIN][discovery_info[CONF_NAME]]
|
||||||
count = entity[CONF_DATA_COUNT]
|
count = entity[CONF_COUNT]
|
||||||
data_type = entity[CONF_DATA_TYPE]
|
data_type = entity[CONF_DATA_TYPE]
|
||||||
name = entity[CONF_NAME]
|
name = entity[CONF_NAME]
|
||||||
structure = entity[CONF_STRUCTURE]
|
structure = entity[CONF_STRUCTURE]
|
||||||
|
@ -110,7 +114,7 @@ class ModbusThermostat(BasePlatform, RestoreEntity, ClimateEntity):
|
||||||
self._current_temperature = None
|
self._current_temperature = None
|
||||||
self._data_type = config[CONF_DATA_TYPE]
|
self._data_type = config[CONF_DATA_TYPE]
|
||||||
self._structure = config[CONF_STRUCTURE]
|
self._structure = config[CONF_STRUCTURE]
|
||||||
self._count = config[CONF_DATA_COUNT]
|
self._count = config[CONF_COUNT]
|
||||||
self._precision = config[CONF_PRECISION]
|
self._precision = config[CONF_PRECISION]
|
||||||
self._scale = config[CONF_SCALE]
|
self._scale = config[CONF_SCALE]
|
||||||
self._offset = config[CONF_OFFSET]
|
self._offset = config[CONF_OFFSET]
|
||||||
|
@ -118,6 +122,7 @@ class ModbusThermostat(BasePlatform, RestoreEntity, ClimateEntity):
|
||||||
self._max_temp = config[CONF_MAX_TEMP]
|
self._max_temp = config[CONF_MAX_TEMP]
|
||||||
self._min_temp = config[CONF_MIN_TEMP]
|
self._min_temp = config[CONF_MIN_TEMP]
|
||||||
self._temp_step = config[CONF_STEP]
|
self._temp_step = config[CONF_STEP]
|
||||||
|
self._swap = config[CONF_SWAP]
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Handle entity which will be added."""
|
"""Handle entity which will be added."""
|
||||||
|
@ -194,6 +199,21 @@ class ModbusThermostat(BasePlatform, RestoreEntity, ClimateEntity):
|
||||||
self._available = result is not None
|
self._available = result is not None
|
||||||
await self.async_update()
|
await self.async_update()
|
||||||
|
|
||||||
|
def _swap_registers(self, registers):
|
||||||
|
"""Do swap as needed."""
|
||||||
|
if self._swap in [CONF_SWAP_BYTE, CONF_SWAP_WORD_BYTE]:
|
||||||
|
# convert [12][34] --> [21][43]
|
||||||
|
for i, register in enumerate(registers):
|
||||||
|
registers[i] = int.from_bytes(
|
||||||
|
register.to_bytes(2, byteorder="little"),
|
||||||
|
byteorder="big",
|
||||||
|
signed=False,
|
||||||
|
)
|
||||||
|
if self._swap in [CONF_SWAP_WORD, CONF_SWAP_WORD_BYTE]:
|
||||||
|
# convert [12][34] ==> [34][12]
|
||||||
|
registers.reverse()
|
||||||
|
return registers
|
||||||
|
|
||||||
async def async_update(self, now=None):
|
async def async_update(self, now=None):
|
||||||
"""Update Target & Current Temperature."""
|
"""Update Target & Current Temperature."""
|
||||||
# remark "now" is a dummy parameter to avoid problems with
|
# remark "now" is a dummy parameter to avoid problems with
|
||||||
|
@ -216,9 +236,8 @@ class ModbusThermostat(BasePlatform, RestoreEntity, ClimateEntity):
|
||||||
self._available = False
|
self._available = False
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
byte_string = b"".join(
|
registers = self._swap_registers(result.registers)
|
||||||
[x.to_bytes(2, byteorder="big") for x in result.registers]
|
byte_string = b"".join([x.to_bytes(2, byteorder="big") for x in registers])
|
||||||
)
|
|
||||||
val = struct.unpack(self._structure, byte_string)
|
val = struct.unpack(self._structure, byte_string)
|
||||||
if len(val) != 1 or not isinstance(val[0], (float, int)):
|
if len(val) != 1 or not isinstance(val[0], (float, int)):
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
|
|
|
@ -3,14 +3,11 @@ import pytest
|
||||||
|
|
||||||
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
|
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
|
||||||
from homeassistant.components.climate.const import HVAC_MODE_AUTO
|
from homeassistant.components.climate.const import HVAC_MODE_AUTO
|
||||||
from homeassistant.components.modbus.const import (
|
from homeassistant.components.modbus.const import CONF_CLIMATES, CONF_TARGET_TEMP
|
||||||
CONF_CLIMATES,
|
|
||||||
CONF_DATA_COUNT,
|
|
||||||
CONF_TARGET_TEMP,
|
|
||||||
)
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_TEMPERATURE,
|
ATTR_TEMPERATURE,
|
||||||
CONF_ADDRESS,
|
CONF_ADDRESS,
|
||||||
|
CONF_COUNT,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_SCAN_INTERVAL,
|
CONF_SCAN_INTERVAL,
|
||||||
CONF_SLAVE,
|
CONF_SLAVE,
|
||||||
|
@ -28,7 +25,7 @@ from tests.common import mock_restore_cache
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
CONF_SCAN_INTERVAL: 20,
|
CONF_SCAN_INTERVAL: 20,
|
||||||
CONF_DATA_COUNT: 2,
|
CONF_COUNT: 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -73,7 +70,7 @@ async def test_temperature_climate(hass, regs, expected):
|
||||||
CONF_SLAVE: 1,
|
CONF_SLAVE: 1,
|
||||||
CONF_TARGET_TEMP: 117,
|
CONF_TARGET_TEMP: 117,
|
||||||
CONF_ADDRESS: 117,
|
CONF_ADDRESS: 117,
|
||||||
CONF_DATA_COUNT: 2,
|
CONF_COUNT: 2,
|
||||||
},
|
},
|
||||||
climate_name,
|
climate_name,
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
|
|
Loading…
Reference in New Issue