Compare commits

..

1 Commits

Author SHA1 Message Date
Jean-Marc Collin
d4a719a660 Issue #903 - Modify "follow underlying changes" behavior - Transform 'Auto' hvac_mode to 'Heating' 2025-02-10 17:30:05 +00:00
5 changed files with 40 additions and 25 deletions

View File

@@ -130,10 +130,10 @@ class FeatureWindowManager(BaseFeatureManager):
async def start_listening(self):
"""Start listening the underlying entity"""
#Try to get last window bypass state
# Try to get last window bypass state
old_state = await self._vtherm.async_get_last_state()
self._is_window_bypass = True if old_state and old_state.attributes and old_state.attributes.get("is_window_bypass") == True else False
self._is_window_bypass = True if old_state and old_state.attributes and old_state.attributes.get("is_window_bypass") is True else False
if self._is_configured:
self.stop_listening()
if self._window_sensor_entity_id:
@@ -453,7 +453,7 @@ class FeatureWindowManager(BaseFeatureManager):
"""Set the window bypass flag
Return True if state have been changed"""
self._is_window_bypass = window_bypass
if self._window_state == STATE_ON:
if not self._is_window_bypass:
_LOGGER.info(

View File

@@ -14,6 +14,6 @@
"quality_scale": "silver",
"requirements": [],
"ssdp": [],
"version": "7.2.2",
"version": "7.2.1",
"zeroconf": []
}

View File

@@ -625,6 +625,10 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
changes = False
new_hvac_mode = new_state.state
# Issue #903 - patch AUTO mode
if new_hvac_mode == HVACMode.AUTO:
new_hvac_mode = HVACMode.HEAT if not self.ac_mode else HVACMode.COOL
old_state = event.data.get("old_state")
# Issue #829 - refresh underlying command if it comes back to life

View File

@@ -1158,8 +1158,7 @@ class UnderlyingValveRegulation(UnderlyingValve):
if self.have_closing_degree_entity:
await self._send_value_to_number(
self._closing_degree_entity_id,
# Patch to fix the hvac_action always Idle issue (issue #902)
closing_degree := max(self._max_opening_degree - 1 - self._percent_open, 0),
closing_degree := self._max_opening_degree - self._percent_open,
)
# send offset_calibration to the difference between target temp and local temp

View File

@@ -139,7 +139,7 @@ async def test_over_climate_valve_mono(hass: HomeAssistant, skip_hass_states_get
mock_service_call.assert_has_calls(
[
call(domain='number', service='set_value', service_data={'value': 0}, target={'entity_id': 'number.mock_opening_degree'}),
call(domain='number', service='set_value', service_data={'value': 99}, target={'entity_id': 'number.mock_closing_degree'}),
call(domain='number', service='set_value', service_data={'value': 100}, target={'entity_id': 'number.mock_closing_degree'}),
call("climate","set_temperature",{
"entity_id": "climate.mock_climate",
"temperature": 15, # temp-min
@@ -188,7 +188,7 @@ async def test_over_climate_valve_mono(hass: HomeAssistant, skip_hass_states_get
[
call('climate', 'set_temperature', {'entity_id': 'climate.mock_climate', 'temperature': 19.0}),
call(domain='number', service='set_value', service_data={'value': 40}, target={'entity_id': 'number.mock_opening_degree'}),
call(domain='number', service='set_value', service_data={'value': 59}, target={'entity_id': 'number.mock_closing_degree'}),
call(domain='number', service='set_value', service_data={'value': 60}, target={'entity_id': 'number.mock_closing_degree'}),
# 3 = 18 (room) - 15 (current of underlying) + 0 (current offset)
call(domain='number', service='set_value', service_data={'value': 3.0}, target={'entity_id': 'number.mock_offset_calibration'})
]
@@ -234,7 +234,7 @@ async def test_over_climate_valve_mono(hass: HomeAssistant, skip_hass_states_get
mock_service_call.assert_has_calls(
[
call(domain='number', service='set_value', service_data={'value': 13}, target={'entity_id': 'number.mock_opening_degree'}),
call(domain='number', service='set_value', service_data={'value': 86}, target={'entity_id': 'number.mock_closing_degree'}),
call(domain='number', service='set_value', service_data={'value': 87}, target={'entity_id': 'number.mock_closing_degree'}),
# 6 = 18 (room) - 15 (current of underlying) + 3 (current offset)
call(domain='number', service='set_value', service_data={'value': 6.899999999999999}, target={'entity_id': 'number.mock_offset_calibration'})
]
@@ -280,7 +280,7 @@ async def test_over_climate_valve_mono(hass: HomeAssistant, skip_hass_states_get
mock_service_call.assert_has_calls(
[
call(domain='number', service='set_value', service_data={'value': 0}, target={'entity_id': 'number.mock_opening_degree'}),
call(domain='number', service='set_value', service_data={'value': 99}, target={'entity_id': 'number.mock_closing_degree'}),
call(domain='number', service='set_value', service_data={'value': 100}, target={'entity_id': 'number.mock_closing_degree'}),
# 6 = 18 (room) - 15 (current of underlying) + 3 (current offset)
call(domain='number', service='set_value', service_data={'value': 9.0}, target={'entity_id': 'number.mock_offset_calibration'})
]
@@ -365,13 +365,25 @@ async def test_over_climate_valve_multi_presence(
mock_get_state_side_effect = SideEffects(
{
# Valve 1 is open
"number.mock_opening_degree1": State("number.mock_opening_degree1", "10", {"min": 0, "max": 100}),
"number.mock_closing_degree1": State("number.mock_closing_degree1", "89", {"min": 0, "max": 100}),
"number.mock_offset_calibration1": State("number.mock_offset_calibration1", "0", {"min": -12, "max": 12}),
"number.mock_opening_degree1": State(
"number.mock_opening_degree1", "10", {"min": 0, "max": 100}
),
"number.mock_closing_degree1": State(
"number.mock_closing_degree1", "90", {"min": 0, "max": 100}
),
"number.mock_offset_calibration1": State(
"number.mock_offset_calibration1", "0", {"min": -12, "max": 12}
),
# Valve 2 is closed
"number.mock_opening_degree2": State("number.mock_opening_degree2", "0", {"min": 0, "max": 100}),
"number.mock_closing_degree2": State("number.mock_closing_degree2", "99", {"min": 0, "max": 100}),
"number.mock_offset_calibration2": State("number.mock_offset_calibration2", "10", {"min": -12, "max": 12}),
"number.mock_opening_degree2": State(
"number.mock_opening_degree2", "0", {"min": 0, "max": 100}
),
"number.mock_closing_degree2": State(
"number.mock_closing_degree2", "100", {"min": 0, "max": 100}
),
"number.mock_offset_calibration2": State(
"number.mock_offset_calibration2", "10", {"min": -12, "max": 12}
),
},
State("unknown.entity_id", "unknown"),
)
@@ -431,10 +443,10 @@ async def test_over_climate_valve_multi_presence(
call('climate', 'set_temperature', {'entity_id': 'climate.mock_climate1', 'temperature': 19.0}),
call('climate', 'set_temperature', {'entity_id': 'climate.mock_climate2', 'temperature': 19.0}),
call(domain='number', service='set_value', service_data={'value': 40}, target={'entity_id': 'number.mock_opening_degree1'}),
call(domain='number', service='set_value', service_data={'value': 59}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 60}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 3.0}, target={'entity_id': 'number.mock_offset_calibration1'}),
call(domain='number', service='set_value', service_data={'value': 40}, target={'entity_id': 'number.mock_opening_degree2'}),
call(domain='number', service='set_value', service_data={'value': 59}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 60}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 12}, target={'entity_id': 'number.mock_offset_calibration2'})
]
)
@@ -462,10 +474,10 @@ async def test_over_climate_valve_multi_presence(
call('climate', 'set_temperature', {'entity_id': 'climate.mock_climate1', 'temperature': 17.2}),
call('climate', 'set_temperature', {'entity_id': 'climate.mock_climate2', 'temperature': 17.2}),
call(domain='number', service='set_value', service_data={'value': 0}, target={'entity_id': 'number.mock_opening_degree1'}),
call(domain='number', service='set_value', service_data={'value': 99}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 100}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 3.0}, target={'entity_id': 'number.mock_offset_calibration1'}),
call(domain='number', service='set_value', service_data={'value': 0}, target={'entity_id': 'number.mock_opening_degree2'}),
call(domain='number', service='set_value', service_data={'value': 99}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 100}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 12}, target={'entity_id': 'number.mock_offset_calibration2'})
]
)
@@ -616,10 +628,10 @@ async def test_over_climate_valve_multi_min_opening_degrees(
mock_service_call.assert_has_calls([
# min is 60
call(domain='number', service='set_value', service_data={'value': 68}, target={'entity_id': 'number.mock_opening_degree1'}),
call(domain='number', service='set_value', service_data={'value': 31}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 32}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 3.0}, target={'entity_id': 'number.mock_offset_calibration1'}),
call(domain='number', service='set_value', service_data={'value': 76}, target={'entity_id': 'number.mock_opening_degree2'}),
call(domain='number', service='set_value', service_data={'value': 23}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 24}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 12}, target={'entity_id': 'number.mock_offset_calibration2'})
]
)
@@ -645,10 +657,10 @@ async def test_over_climate_valve_multi_min_opening_degrees(
assert mock_service_call.call_count == 6
mock_service_call.assert_has_calls([
call(domain='number', service='set_value', service_data={'value': 0}, target={'entity_id': 'number.mock_opening_degree1'}),
call(domain='number', service='set_value', service_data={'value': 99}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 100}, target={'entity_id': 'number.mock_closing_degree1'}),
call(domain='number', service='set_value', service_data={'value': 7.0}, target={'entity_id': 'number.mock_offset_calibration1'}),
call(domain='number', service='set_value', service_data={'value': 0}, target={'entity_id': 'number.mock_opening_degree2'}),
call(domain='number', service='set_value', service_data={'value': 99}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 100}, target={'entity_id': 'number.mock_closing_degree2'}),
call(domain='number', service='set_value', service_data={'value': 12}, target={'entity_id': 'number.mock_offset_calibration2'})
]
)