Release 7.2.0- Heating is inverted on over_switch with inverted commands ? (#891)

* Release 7.2.0- Heating is inverted on `over_switch` with inverted commands ?
Fixes #889

* Release

---------

Co-authored-by: Jean-Marc Collin <jean-marc.collin-extern@renault.com>
This commit is contained in:
Jean-Marc Collin
2025-02-08 11:56:24 +01:00
committed by GitHub
parent 87064882a3
commit c20e641ac1
5 changed files with 48 additions and 18 deletions

View File

@@ -191,6 +191,9 @@ input_boolean:
fake_valve_sonoff_trvzb2: fake_valve_sonoff_trvzb2:
name: Valve Sonoff TRVZB2 name: Valve Sonoff TRVZB2
icon: mdi:valve icon: mdi:valve
fake_inversed_heater:
name: Inversed Heater
icon: mdi:radiator-off
climate: climate:
- platform: generic_thermostat - platform: generic_thermostat
@@ -314,6 +317,21 @@ switch:
option: comfort-2 option: comfort-2
target: target:
entity_id: select.seche_serviettes_sdb_rdc_cable_outlet_mode entity_id: select.seche_serviettes_sdb_rdc_cable_outlet_mode
- platform: template
switches:
fake_inversed_switch:
friendly_name: "A fake inversed switch"
value_template: "{{ is_state('input_boolean.fake_inversed_heater', 'on') }}"
turn_on:
action: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.fake_inversed_heater
turn_off:
action: input_boolean.turn_off
data: {}
target:
entity_id: input_boolean.fake_inversed_heater
frontend: frontend:
extra_module_url: extra_module_url:

View File

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

View File

@@ -281,8 +281,8 @@ class UnderlyingSwitch(UnderlyingEntity):
# not self.is_inversed and real_state # not self.is_inversed and real_state
# ) # )
is_on = self._hass.states.is_state(self._entity_id, self._on_command.get("state")) is_on = self._hass.states.is_state(self._entity_id, self._on_command.get("state"))
if self.is_inversed: # if self.is_inversed:
return not is_on # return not is_on
return is_on return is_on

View File

@@ -18,6 +18,12 @@ logging.getLogger().setLevel(logging.DEBUG)
async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state): async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
"""Test the Window auto management""" """Test the Window auto management"""
temps = {
"eco": 17,
"comfort": 18,
"boost": 21,
}
entry = MockConfigEntry( entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
title="TheOverSwitchMockName", title="TheOverSwitchMockName",
@@ -30,14 +36,11 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
CONF_CYCLE_MIN: 5, CONF_CYCLE_MIN: 5,
CONF_TEMP_MIN: 15, CONF_TEMP_MIN: 15,
CONF_TEMP_MAX: 30, CONF_TEMP_MAX: 30,
"eco_temp": 17,
"comfort_temp": 18,
"boost_temp": 21,
CONF_USE_WINDOW_FEATURE: False, CONF_USE_WINDOW_FEATURE: False,
CONF_USE_MOTION_FEATURE: False, CONF_USE_MOTION_FEATURE: False,
CONF_USE_POWER_FEATURE: False, CONF_USE_POWER_FEATURE: False,
CONF_USE_PRESENCE_FEATURE: False, CONF_USE_PRESENCE_FEATURE: False,
CONF_HEATER: "switch.mock_switch", CONF_UNDERLYING_LIST: ["switch.mock_switch"],
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI, CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
CONF_TPI_COEF_INT: 0.3, CONF_TPI_COEF_INT: 0.3,
CONF_TPI_COEF_EXT: 0.01, CONF_TPI_COEF_EXT: 0.01,
@@ -51,14 +54,12 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
}, },
) )
with patch( # 0. Create the entity
"homeassistant.core.ServiceRegistry.async_call"
) as mock_service_call, patch( with patch("homeassistant.core.ServiceRegistry.async_call") as mock_service_call, patch(
"homeassistant.core.StateMachine.is_state", return_value=True # switch is On "homeassistant.core.StateMachine.is_state", return_value=False # switch is On so is_state(switch, 'off') is False
): ):
entity: ThermostatOverSwitch = await create_thermostat( entity: ThermostatOverSwitch = await create_thermostat(hass, entry, "climate.theoverswitchmockname", temps)
hass, entry, "climate.theoverswitchmockname"
)
assert entity assert entity
assert entity.is_inversed assert entity.is_inversed
@@ -78,12 +79,10 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
assert mock_service_call.call_count == 0 assert mock_service_call.call_count == 0
# 1. Make the temperature down to activate the switch # 1. Make the temperature down to activate the switch
with patch( with patch("custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"), patch(
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
), patch(
"homeassistant.core.ServiceRegistry.async_call" "homeassistant.core.ServiceRegistry.async_call"
) as mock_service_call, patch( ) as mock_service_call, patch(
"homeassistant.core.StateMachine.is_state", return_value=True # switch is Off "homeassistant.core.StateMachine.is_state", return_value=True # switch is Off so is_state(switch, 'off') is True
): ):
event_timestamp = now - timedelta(minutes=4) event_timestamp = now - timedelta(minutes=4)
await send_temperature_change_event(entity, 19, event_timestamp) await send_temperature_change_event(entity, 19, event_timestamp)

View File

@@ -71,6 +71,19 @@ from .commons import *
HVACMode.HEAT, HVACMode.HEAT,
True, True,
), ),
# Inversed switch without command personnalisations
(
True,
None,
None,
"turn_off",
{"entity_id": "switch.test"},
STATE_OFF,
"turn_on",
{"entity_id": "switch.test"},
STATE_ON,
True,
),
# Error cases invalid command # Error cases invalid command
( (
False, False,