diff --git a/homeassistant/components/modbus/binary_sensor.py b/homeassistant/components/modbus/binary_sensor.py index cd336ba4f73..979888d0a19 100644 --- a/homeassistant/components/modbus/binary_sensor.py +++ b/homeassistant/components/modbus/binary_sensor.py @@ -129,7 +129,7 @@ class ModbusBinarySensor(BinarySensorEntity): async def async_added_to_hass(self): """Handle entity which will be added.""" async_track_time_interval( - self.hass, lambda arg: self._update(), self._scan_interval + self.hass, lambda arg: self.update(), self._scan_interval ) @property @@ -162,7 +162,7 @@ class ModbusBinarySensor(BinarySensorEntity): """Return True if entity is available.""" return self._available - def _update(self): + def update(self): """Update the state of the sensor.""" if self._input_type == CALL_TYPE_COIL: result = self._hub.read_coils(self._slave, self._address, 1) diff --git a/homeassistant/components/modbus/climate.py b/homeassistant/components/modbus/climate.py index 7d326407c3b..d98cda3ed43 100644 --- a/homeassistant/components/modbus/climate.py +++ b/homeassistant/components/modbus/climate.py @@ -133,7 +133,7 @@ class ModbusThermostat(ClimateEntity): async def async_added_to_hass(self): """Handle entity which will be added.""" async_track_time_interval( - self.hass, lambda arg: self._update(), self._scan_interval + self.hass, lambda arg: self.update(), self._scan_interval ) @property @@ -214,14 +214,14 @@ class ModbusThermostat(ClimateEntity): self._target_temperature_register, register_value, ) - self._update() + self.update() @property def available(self) -> bool: """Return True if entity is available.""" return self._available - def _update(self): + def update(self): """Update Target & Current Temperature.""" self._target_temperature = self._read_register( CALL_TYPE_REGISTER_HOLDING, self._target_temperature_register diff --git a/homeassistant/components/modbus/cover.py b/homeassistant/components/modbus/cover.py index a0deba9d732..7d9bf9e2e45 100644 --- a/homeassistant/components/modbus/cover.py +++ b/homeassistant/components/modbus/cover.py @@ -107,7 +107,7 @@ class ModbusCover(CoverEntity, RestoreEntity): self._value = state.state async_track_time_interval( - self.hass, lambda arg: self._update(), self._scan_interval + self.hass, lambda arg: self.update(), self._scan_interval ) @property @@ -161,7 +161,7 @@ class ModbusCover(CoverEntity, RestoreEntity): else: self._write_register(self._state_open) - self._update() + self.update() def close_cover(self, **kwargs: Any) -> None: """Close cover.""" @@ -170,9 +170,9 @@ class ModbusCover(CoverEntity, RestoreEntity): else: self._write_register(self._state_closed) - self._update() + self.update() - def _update(self): + def update(self): """Update the state of the cover.""" if self._coil is not None and self._status_register is None: self._value = self._read_coil() diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py index 81b54cb62e1..c1a33c41f6d 100644 --- a/homeassistant/components/modbus/sensor.py +++ b/homeassistant/components/modbus/sensor.py @@ -229,7 +229,7 @@ class ModbusRegisterSensor(RestoreEntity, SensorEntity): self._value = state.state async_track_time_interval( - self.hass, lambda arg: self._update(), self._scan_interval + self.hass, lambda arg: self.update(), self._scan_interval ) @property @@ -282,7 +282,7 @@ class ModbusRegisterSensor(RestoreEntity, SensorEntity): registers.reverse() return registers - def _update(self): + def update(self): """Update the state of the sensor.""" if self._register_type == CALL_TYPE_REGISTER_INPUT: result = self._hub.read_input_registers( diff --git a/homeassistant/components/modbus/switch.py b/homeassistant/components/modbus/switch.py index 3a74b5d14e1..6fff8c1d373 100644 --- a/homeassistant/components/modbus/switch.py +++ b/homeassistant/components/modbus/switch.py @@ -99,7 +99,7 @@ class ModbusSwitch(SwitchEntity, RestoreEntity): if self._verify_active: async_track_time_interval( - self.hass, lambda arg: self._update(), self._scan_interval + self.hass, lambda arg: self.update(), self._scan_interval ) @property @@ -132,7 +132,7 @@ class ModbusSwitch(SwitchEntity, RestoreEntity): else: self._available = True if self._verify_active: - self._update() + self.update() else: self._is_on = True self.schedule_update_ha_state() @@ -146,12 +146,12 @@ class ModbusSwitch(SwitchEntity, RestoreEntity): else: self._available = True if self._verify_active: - self._update() + self.update() else: self._is_on = False self.schedule_update_ha_state() - def _update(self): + def update(self): """Update the entity state.""" if not self._verify_active: return diff --git a/tests/components/modbus/conftest.py b/tests/components/modbus/conftest.py index de30e690bba..d3ae1286ef1 100644 --- a/tests/components/modbus/conftest.py +++ b/tests/components/modbus/conftest.py @@ -201,3 +201,21 @@ async def base_config_test( config_modbus=config_modbus, expect_init_to_fail=expect_init_to_fail, ) + + +async def prepare_service_update(hass, config): + """Run test for service write_coil.""" + + config_modbus = { + DOMAIN: { + CONF_NAME: DEFAULT_HUB, + CONF_TYPE: "tcp", + CONF_HOST: "modbusTest", + CONF_PORT: 5001, + **config, + }, + } + assert await async_setup_component(hass, DOMAIN, config_modbus) + await hass.async_block_till_done() + assert await async_setup_component(hass, "homeassistant", {}) + await hass.async_block_till_done() diff --git a/tests/components/modbus/test_modbus_binary_sensor.py b/tests/components/modbus/test_modbus_binary_sensor.py index 4ce423b2f16..27821c170e1 100644 --- a/tests/components/modbus/test_modbus_binary_sensor.py +++ b/tests/components/modbus/test_modbus_binary_sensor.py @@ -19,7 +19,7 @@ from homeassistant.const import ( STATE_UNAVAILABLE, ) -from .conftest import base_config_test, base_test +from .conftest import ReadResult, base_config_test, base_test, prepare_service_update @pytest.mark.parametrize("do_discovery", [False, True]) @@ -99,3 +99,34 @@ async def test_all_binary_sensor(hass, do_type, regs, expected): scan_interval=5, ) assert state == expected + + +async def test_service_binary_sensor_update(hass, mock_pymodbus): + """Run test for service homeassistant.update_entity.""" + + entity_id = "binary_sensor.test" + config = { + CONF_BINARY_SENSORS: [ + { + CONF_NAME: "test", + CONF_ADDRESS: 1234, + CONF_INPUT_TYPE: CALL_TYPE_COIL, + } + ] + } + mock_pymodbus.read_coils.return_value = ReadResult([0x00]) + await prepare_service_update( + hass, + config, + ) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + await hass.async_block_till_done() + assert hass.states.get(entity_id).state == STATE_OFF + + mock_pymodbus.read_coils.return_value = ReadResult([0x01]) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == STATE_ON diff --git a/tests/components/modbus/test_modbus_climate.py b/tests/components/modbus/test_modbus_climate.py index f932817b12e..1e14b255ba5 100644 --- a/tests/components/modbus/test_modbus_climate.py +++ b/tests/components/modbus/test_modbus_climate.py @@ -10,7 +10,7 @@ from homeassistant.components.modbus.const import ( ) from homeassistant.const import CONF_NAME, CONF_SCAN_INTERVAL, CONF_SLAVE -from .conftest import base_config_test, base_test +from .conftest import ReadResult, base_config_test, base_test, prepare_service_update @pytest.mark.parametrize( @@ -76,3 +76,28 @@ async def test_temperature_climate(hass, regs, expected): scan_interval=5, ) assert state == expected + + +async def test_service_climate_update(hass, mock_pymodbus): + """Run test for service homeassistant.update_entity.""" + + entity_id = "climate.test" + config = { + CONF_CLIMATES: [ + { + CONF_NAME: "test", + CONF_TARGET_TEMP: 117, + CONF_CURRENT_TEMP: 117, + CONF_SLAVE: 10, + } + ] + } + mock_pymodbus.read_input_registers.return_value = ReadResult([0x00]) + await prepare_service_update( + hass, + config, + ) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == "auto" diff --git a/tests/components/modbus/test_modbus_cover.py b/tests/components/modbus/test_modbus_cover.py index 957f4b28c75..09d23ebf8bd 100644 --- a/tests/components/modbus/test_modbus_cover.py +++ b/tests/components/modbus/test_modbus_cover.py @@ -4,7 +4,12 @@ import logging import pytest from homeassistant.components.cover import DOMAIN as COVER_DOMAIN -from homeassistant.components.modbus.const import CALL_TYPE_COIL, CONF_REGISTER +from homeassistant.components.modbus.const import ( + CALL_TYPE_COIL, + CALL_TYPE_REGISTER_HOLDING, + CONF_REGISTER, + CONF_STATUS_REGISTER_TYPE, +) from homeassistant.const import ( CONF_COVERS, CONF_NAME, @@ -14,7 +19,7 @@ from homeassistant.const import ( STATE_OPEN, ) -from .conftest import base_config_test, base_test +from .conftest import ReadResult, base_config_test, base_test, prepare_service_update @pytest.mark.parametrize( @@ -168,3 +173,32 @@ async def test_unsupported_config_cover(hass, read_type, caplog): assert len(caplog.records) == 1 assert caplog.records[0].levelname == "WARNING" + + +async def test_service_cover_update(hass, mock_pymodbus): + """Run test for service homeassistant.update_entity.""" + + entity_id = "cover.test" + config = { + CONF_COVERS: [ + { + CONF_NAME: "test", + CONF_REGISTER: 1234, + CONF_STATUS_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, + } + ] + } + mock_pymodbus.read_holding_registers.return_value = ReadResult([0x00]) + await prepare_service_update( + hass, + config, + ) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == STATE_CLOSED + mock_pymodbus.read_holding_registers.return_value = ReadResult([0x01]) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == STATE_OPEN diff --git a/tests/components/modbus/test_modbus_sensor.py b/tests/components/modbus/test_modbus_sensor.py index b8ab10953c8..c83eab0b3d6 100644 --- a/tests/components/modbus/test_modbus_sensor.py +++ b/tests/components/modbus/test_modbus_sensor.py @@ -40,7 +40,7 @@ from homeassistant.const import ( ) from homeassistant.core import State -from .conftest import base_config_test, base_test +from .conftest import ReadResult, base_config_test, base_test, prepare_service_update @pytest.mark.parametrize( @@ -621,3 +621,32 @@ async def test_swap_sensor_wrong_config(hass, caplog, swap_type): expect_init_to_fail=True, ) assert caplog.messages[-1].startswith("Error in sensor " + sensor_name + " swap") + + +async def test_service_sensor_update(hass, mock_pymodbus): + """Run test for service homeassistant.update_entity.""" + + entity_id = "sensor.test" + config = { + CONF_SENSORS: [ + { + CONF_NAME: "test", + CONF_ADDRESS: 1234, + CONF_INPUT_TYPE: CALL_TYPE_REGISTER_INPUT, + } + ] + } + mock_pymodbus.read_input_registers.return_value = ReadResult([27]) + await prepare_service_update( + hass, + config, + ) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == "27" + mock_pymodbus.read_input_registers.return_value = ReadResult([32]) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == "32" diff --git a/tests/components/modbus/test_modbus_switch.py b/tests/components/modbus/test_modbus_switch.py index bc96127cbd6..f247bb4b148 100644 --- a/tests/components/modbus/test_modbus_switch.py +++ b/tests/components/modbus/test_modbus_switch.py @@ -25,7 +25,7 @@ from homeassistant.const import ( STATE_ON, ) -from .conftest import base_config_test, base_test +from .conftest import ReadResult, base_config_test, base_test, prepare_service_update @pytest.mark.parametrize( @@ -220,3 +220,33 @@ async def test_register_state_switch(hass, regs, expected): scan_interval=5, ) assert state == expected + + +async def test_service_switch_update(hass, mock_pymodbus): + """Run test for service homeassistant.update_entity.""" + + entity_id = "switch.test" + config = { + CONF_SWITCHES: [ + { + CONF_NAME: "test", + CONF_ADDRESS: 1234, + CONF_WRITE_TYPE: CALL_TYPE_COIL, + CONF_VERIFY: {}, + } + ] + } + mock_pymodbus.read_coils.return_value = ReadResult([0x01]) + await prepare_service_update( + hass, + config, + ) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == STATE_ON + mock_pymodbus.read_coils.return_value = ReadResult([0x00]) + await hass.services.async_call( + "homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True + ) + assert hass.states.get(entity_id).state == STATE_OFF