From 02459e68132b255b0b8a069e88ff022d1eae3ee2 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Sun, 8 Aug 2021 23:23:21 +0200 Subject: [PATCH] Convert last properties in modbus to _attr_variable (#53919) --- .../components/modbus/base_platform.py | 71 +++++++++---------- .../components/modbus/binary_sensor.py | 11 +-- homeassistant/components/modbus/climate.py | 3 +- homeassistant/components/modbus/cover.py | 25 +++---- homeassistant/components/modbus/fan.py | 8 +++ homeassistant/components/modbus/sensor.py | 9 +-- 6 files changed, 53 insertions(+), 74 deletions(-) diff --git a/homeassistant/components/modbus/base_platform.py b/homeassistant/components/modbus/base_platform.py index f767201496c..c580e6167ca 100644 --- a/homeassistant/components/modbus/base_platform.py +++ b/homeassistant/components/modbus/base_platform.py @@ -21,7 +21,7 @@ from homeassistant.const import ( CONF_STRUCTURE, STATE_ON, ) -from homeassistant.helpers.entity import Entity +from homeassistant.helpers.entity import Entity, ToggleEntity from homeassistant.helpers.event import async_call_later, async_track_time_interval from homeassistant.helpers.restore_state import RestoreEntity @@ -124,48 +124,46 @@ class BaseStructPlatform(BasePlatform, RestoreEntity): registers = self._swap_registers(registers) byte_string = b"".join([x.to_bytes(2, byteorder="big") for x in registers]) if self._data_type == DATA_TYPE_STRING: - self._value = byte_string.decode() - else: - val = struct.unpack(self._structure, byte_string) + return byte_string.decode() - # Issue: https://github.com/home-assistant/core/issues/41944 - # If unpack() returns a tuple greater than 1, don't try to process the value. - # Instead, return the values of unpack(...) separated by commas. - if len(val) > 1: - # Apply scale and precision to floats and ints - v_result = [] - for entry in val: - v_temp = self._scale * entry + self._offset - - # We could convert int to float, and the code would still work; however - # we lose some precision, and unit tests will fail. Therefore, we do - # the conversion only when it's absolutely necessary. - if isinstance(v_temp, int) and self._precision == 0: - v_result.append(str(v_temp)) - else: - v_result.append(f"{float(v_temp):.{self._precision}f}") - self._value = ",".join(map(str, v_result)) - else: - # Apply scale and precision to floats and ints - val = self._scale * val[0] + self._offset + val = struct.unpack(self._structure, byte_string) + # Issue: https://github.com/home-assistant/core/issues/41944 + # If unpack() returns a tuple greater than 1, don't try to process the value. + # Instead, return the values of unpack(...) separated by commas. + if len(val) > 1: + # Apply scale and precision to floats and ints + v_result = [] + for entry in val: + v_temp = self._scale * entry + self._offset # We could convert int to float, and the code would still work; however # we lose some precision, and unit tests will fail. Therefore, we do # the conversion only when it's absolutely necessary. - if isinstance(val, int) and self._precision == 0: - self._value = str(val) + if isinstance(v_temp, int) and self._precision == 0: + v_result.append(str(v_temp)) else: - self._value = f"{float(val):.{self._precision}f}" + v_result.append(f"{float(v_temp):.{self._precision}f}") + return ",".join(map(str, v_result)) + + # Apply scale and precision to floats and ints + val = self._scale * val[0] + self._offset + + # We could convert int to float, and the code would still work; however + # we lose some precision, and unit tests will fail. Therefore, we do + # the conversion only when it's absolutely necessary. + if isinstance(val, int) and self._precision == 0: + return str(val) + return f"{float(val):.{self._precision}f}" -class BaseSwitch(BasePlatform, RestoreEntity): +class BaseSwitch(BasePlatform, ToggleEntity, RestoreEntity): """Base class representing a Modbus switch.""" def __init__(self, hub: ModbusHub, config: dict) -> None: """Initialize the switch.""" config[CONF_INPUT_TYPE] = "" super().__init__(hub, config) - self._is_on = None + self._attr_is_on = False convert = { CALL_TYPE_REGISTER_HOLDING: ( CALL_TYPE_REGISTER_HOLDING, @@ -202,12 +200,7 @@ class BaseSwitch(BasePlatform, RestoreEntity): await self.async_base_added_to_hass() state = await self.async_get_last_state() if state: - self._is_on = state.state == STATE_ON - - @property - def is_on(self): - """Return true if switch is on.""" - return self._is_on + self._attr_is_on = state.state == STATE_ON async def async_turn(self, command): """Evaluate switch result.""" @@ -221,7 +214,7 @@ class BaseSwitch(BasePlatform, RestoreEntity): self._attr_available = True if not self._verify_active: - self._is_on = command == self.command_on + self._attr_is_on = command == self.command_on self.async_write_ha_state() return @@ -258,13 +251,13 @@ class BaseSwitch(BasePlatform, RestoreEntity): self._attr_available = True if self._verify_type == CALL_TYPE_COIL: - self._is_on = bool(result.bits[0] & 1) + self._attr_is_on = bool(result.bits[0] & 1) else: value = int(result.registers[0]) if value == self._state_on: - self._is_on = True + self._attr_is_on = True elif value == self._state_off: - self._is_on = False + self._attr_is_on = False elif value is not None: _LOGGER.error( "Unexpected response from modbus device slave %s register %s, got 0x%2x", diff --git a/homeassistant/components/modbus/binary_sensor.py b/homeassistant/components/modbus/binary_sensor.py index a54630379b8..08ebfc72880 100644 --- a/homeassistant/components/modbus/binary_sensor.py +++ b/homeassistant/components/modbus/binary_sensor.py @@ -43,14 +43,7 @@ class ModbusBinarySensor(BasePlatform, RestoreEntity, BinarySensorEntity): await self.async_base_added_to_hass() state = await self.async_get_last_state() if state: - self._value = state.state == STATE_ON - else: - self._value = None - - @property - def is_on(self): - """Return the state of the sensor.""" - return self._value + self._attr_is_on = state.state == STATE_ON async def async_update(self, now=None): """Update the state of the sensor.""" @@ -68,6 +61,6 @@ class ModbusBinarySensor(BasePlatform, RestoreEntity, BinarySensorEntity): self.async_write_ha_state() return - self._value = result.bits[0] & 1 + self._attr_is_on = result.bits[0] & 1 self._attr_available = True self.async_write_ha_state() diff --git a/homeassistant/components/modbus/climate.py b/homeassistant/components/modbus/climate.py index 692d3c9a058..831f3c979cc 100644 --- a/homeassistant/components/modbus/climate.py +++ b/homeassistant/components/modbus/climate.py @@ -165,8 +165,7 @@ class ModbusThermostat(BaseStructPlatform, RestoreEntity, ClimateEntity): self._attr_available = False return -1 - self.unpack_structure_result(result.registers) - + self._value = self.unpack_structure_result(result.registers) self._attr_available = True if self._value is None: diff --git a/homeassistant/components/modbus/cover.py b/homeassistant/components/modbus/cover.py index e55fe6d92eb..64165412d27 100644 --- a/homeassistant/components/modbus/cover.py +++ b/homeassistant/components/modbus/cover.py @@ -109,22 +109,13 @@ class ModbusCover(BasePlatform, CoverEntity, RestoreEntity): STATE_UNAVAILABLE: None, STATE_UNKNOWN: None, } - self._value = convert[state.state] + self._set_attr_state(convert[state.state]) - @property - def is_opening(self): - """Return if the cover is opening or not.""" - return self._value == self._state_opening - - @property - def is_closing(self): - """Return if the cover is closing or not.""" - return self._value == self._state_closing - - @property - def is_closed(self): - """Return if the cover is closed or not.""" - return self._value == self._state_closed + def _set_attr_state(self, value): + """Convert received value to HA state.""" + self._attr_is_opening = value == self._state_opening + self._attr_is_closing = value == self._state_closing + self._attr_is_closed = value == self._state_closed async def async_open_cover(self, **kwargs: Any) -> None: """Open cover.""" @@ -160,7 +151,7 @@ class ModbusCover(BasePlatform, CoverEntity, RestoreEntity): return None self._attr_available = True if self._input_type == CALL_TYPE_COIL: - self._value = bool(result.bits[0] & 1) + self._set_attr_state(bool(result.bits[0] & 1)) else: - self._value = int(result.registers[0]) + self._set_attr_state(int(result.registers[0])) self.async_write_ha_state() diff --git a/homeassistant/components/modbus/fan.py b/homeassistant/components/modbus/fan.py index 435d331bbc4..cf5c9762db8 100644 --- a/homeassistant/components/modbus/fan.py +++ b/homeassistant/components/modbus/fan.py @@ -43,3 +43,11 @@ class ModbusFan(BaseSwitch, FanEntity): ) -> None: """Set fan on.""" await self.async_turn(self.command_on) + + @property + def is_on(self): + """Return true if fan is on. + + This is needed due to the ongoing conversion of fan. + """ + return self._attr_is_on diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py index 7bb7e1cd049..fee3f53667d 100644 --- a/homeassistant/components/modbus/sensor.py +++ b/homeassistant/components/modbus/sensor.py @@ -54,12 +54,7 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreEntity, SensorEntity): await self.async_base_added_to_hass() state = await self.async_get_last_state() if state: - self._value = state.state - - @property - def state(self): - """Return the state of the sensor.""" - return self._value + self._attr_state = state.state async def async_update(self, now=None): """Update the state of the sensor.""" @@ -73,6 +68,6 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreEntity, SensorEntity): self.async_write_ha_state() return - self.unpack_structure_result(result.registers) + self._attr_state = self.unpack_structure_result(result.registers) self._attr_available = True self.async_write_ha_state()