diff --git a/homeassistant/components/modbus/climate.py b/homeassistant/components/modbus/climate.py index b3d6c78387d..f8e7dca245a 100644 --- a/homeassistant/components/modbus/climate.py +++ b/homeassistant/components/modbus/climate.py @@ -490,6 +490,11 @@ class ModbusThermostat(BaseStructPlatform, RestoreEntity, ClimateEntity): if hvac_mode == value: self._attr_hvac_mode = mode break + else: + # since there are no hvac_mode_register, this + # integration should not touch the attr. + # However it lacks in the climate component. + self._attr_hvac_mode = HVACMode.AUTO # Read the HVAC action register if defined if self._hvac_action_register is not None: diff --git a/tests/components/modbus/test_climate.py b/tests/components/modbus/test_climate.py index 38f2aa3337f..f661dd2083c 100644 --- a/tests/components/modbus/test_climate.py +++ b/tests/components/modbus/test_climate.py @@ -794,6 +794,140 @@ async def test_hvac_onoff_coil_update( assert state.state == result +@pytest.mark.parametrize( + ( + "do_config", + "result_before", + "coil_value_before", + "result_after", + "coil_value_after", + ), + [ + ( + { + CONF_CLIMATES: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_TARGET_TEMP: 120, + CONF_ADDRESS: 117, + CONF_SLAVE: 10, + CONF_SCAN_INTERVAL: 0, + CONF_HVAC_ONOFF_COIL: 11, + }, + ] + }, + HVACMode.OFF, + [0x00], + HVACMode.AUTO, + [0x01], + ), + ], +) +async def test_hvac_onoff_coil_transition_update( + hass: HomeAssistant, + mock_modbus_ha, + result_before, + coil_value_before, + result_after, + coil_value_after, +) -> None: + """Test climate update based on On/Off coil values without hvacmode register.""" + mock_modbus_ha.read_coils.return_value = ReadResult(coil_value_before) + + await hass.services.async_call( + HOMEASSISTANT_DOMAIN, + SERVICE_UPDATE_ENTITY, + {ATTR_ENTITY_ID: ENTITY_ID}, + blocking=True, + ) + await hass.async_block_till_done() + + state = hass.states.get(ENTITY_ID) + assert state.state == result_before + + mock_modbus_ha.read_coils.return_value = ReadResult(coil_value_after) + + await hass.services.async_call( + HOMEASSISTANT_DOMAIN, + SERVICE_UPDATE_ENTITY, + {ATTR_ENTITY_ID: ENTITY_ID}, + blocking=True, + ) + await hass.async_block_till_done() + + state = hass.states.get(ENTITY_ID) + assert state.state == result_after + + +@pytest.mark.parametrize( + ( + "do_config", + "result_before", + "register_value_before", + "result_after", + "register_value_after", + ), + [ + ( + { + CONF_CLIMATES: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_TARGET_TEMP: 120, + CONF_ADDRESS: 117, + CONF_SLAVE: 10, + CONF_SCAN_INTERVAL: 0, + CONF_HVAC_ONOFF_REGISTER: 11, + }, + ] + }, + HVACMode.OFF, + [0x00], + HVACMode.AUTO, + [0x01], + ), + ], +) +async def test_hvac_onoff_register_transition_update( + hass: HomeAssistant, + mock_modbus_ha, + result_before, + register_value_before, + result_after, + register_value_after, +) -> None: + """Test climate update based on On/Off register values without hvacmode register.""" + mock_modbus_ha.read_holding_registers.return_value = ReadResult( + register_value_before + ) + + await hass.services.async_call( + HOMEASSISTANT_DOMAIN, + SERVICE_UPDATE_ENTITY, + {ATTR_ENTITY_ID: ENTITY_ID}, + blocking=True, + ) + await hass.async_block_till_done() + + state = hass.states.get(ENTITY_ID) + assert state.state == result_before + + mock_modbus_ha.read_holding_registers.return_value = ReadResult( + register_value_after + ) + + await hass.services.async_call( + HOMEASSISTANT_DOMAIN, + SERVICE_UPDATE_ENTITY, + {ATTR_ENTITY_ID: ENTITY_ID}, + blocking=True, + ) + await hass.async_block_till_done() + + state = hass.states.get(ENTITY_ID) + assert state.state == result_after + + @pytest.mark.parametrize( ("do_config", "result", "register_words"), [