diff --git a/custom_components/versatile_thermostat/presence_manager.py b/custom_components/versatile_thermostat/presence_manager.py index 27d1bae..479622a 100644 --- a/custom_components/versatile_thermostat/presence_manager.py +++ b/custom_components/versatile_thermostat/presence_manager.py @@ -175,6 +175,8 @@ class FeaturePresenceManager(BaseFeatureManager): def presence_state(self) -> str | None: """Return the current presence state STATE_ON or STATE_OFF or STATE_UNAVAILABLE if not configured""" + if not self._is_configured: + return STATE_UNAVAILABLE return self._presence_state @property @@ -185,5 +187,10 @@ class FeaturePresenceManager(BaseFeatureManager): STATE_OFF, ] + @property + def presence_sensor_entity_id(self) -> bool: + """Return true if the presence is configured and presence sensor is OFF""" + return self._presence_sensor_entity_id + def __str__(self): return f"PresenceManager-{self.name}" diff --git a/tests/test_binary_sensors.py b/tests/test_binary_sensors.py index 64852f7..c5a17a7 100644 --- a/tests/test_binary_sensors.py +++ b/tests/test_binary_sensors.py @@ -419,7 +419,7 @@ async def test_presence_binary_sensors( await entity.async_set_preset_mode(PRESET_COMFORT) await entity.async_set_hvac_mode(HVACMode.HEAT) await send_temperature_change_event(entity, 15, now) - assert entity.presence_state is None + assert entity.presence_state is STATE_UNKNOWN await presence_binary_sensor.async_my_climate_changed() assert presence_binary_sensor.state is STATE_OFF diff --git a/tests/test_central_config.py b/tests/test_central_config.py index b74c51b..ef434f1 100644 --- a/tests/test_central_config.py +++ b/tests/test_central_config.py @@ -295,7 +295,10 @@ async def test_full_over_switch_wo_central_config( assert entity._power_sensor_entity_id == "sensor.mock_power_sensor" assert entity._max_power_sensor_entity_id == "sensor.mock_max_power_sensor" - assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor" + assert ( + entity._presence_manager.presence_sensor_entity_id + == "binary_sensor.mock_presence_sensor" + ) entity.remove_thermostat() @@ -409,7 +412,10 @@ async def test_full_over_switch_with_central_config( assert entity._power_sensor_entity_id == "sensor.mock_power_sensor" assert entity._max_power_sensor_entity_id == "sensor.mock_max_power_sensor" - assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor" + assert ( + entity._presence_manager.presence_sensor_entity_id + == "binary_sensor.mock_presence_sensor" + ) entity.remove_thermostat() diff --git a/tests/test_movement.py b/tests/test_movement.py index 6038eea..afb36fd 100644 --- a/tests/test_movement.py +++ b/tests/test_movement.py @@ -76,7 +76,7 @@ async def test_movement_management_time_not_enough( # because no motion is detected yet assert entity.target_temperature == 18 assert entity.motion_state is None - assert entity.presence_state is None + assert entity.presence_state is STATE_UNKNOWN event_timestamp = now - timedelta(minutes=5) await send_temperature_change_event(entity, 18, event_timestamp) @@ -283,7 +283,7 @@ async def test_movement_management_time_enough_and_presence( # because no motion is detected yet assert entity.target_temperature == 18 assert entity.motion_state is None - assert entity.presence_state is None + assert entity.presence_state is STATE_UNKNOWN event_timestamp = now - timedelta(minutes=4) await send_temperature_change_event(entity, 18, event_timestamp) @@ -313,8 +313,7 @@ async def test_movement_management_time_enough_and_presence( # because motion is detected yet -> switch to Boost mode assert entity.target_temperature == 19 assert entity.motion_state == "on" - assert entity.presence_state == "on" - + assert entity.presence_state == STATE_ON assert mock_send_event.call_count == 0 # Change is confirmed. Heater should be started assert mock_heater_on.call_count == 1 @@ -342,7 +341,7 @@ async def test_movement_management_time_enough_and_presence( # because no motion is detected yet assert entity.target_temperature == 18 assert entity.motion_state == "off" - assert entity.presence_state == "on" + assert entity.presence_state == STATE_ON assert mock_send_event.call_count == 0 assert mock_heater_on.call_count == 0 @@ -415,7 +414,7 @@ async def test_movement_management_time_enoughand_not_presence( # because no motion is detected yet and presence is unknown assert entity.target_temperature == 18 assert entity.motion_state is None - assert entity.presence_state is None + assert entity.presence_state is STATE_UNKNOWN event_timestamp = now - timedelta(minutes=4) await send_temperature_change_event(entity, 18, event_timestamp) @@ -445,7 +444,7 @@ async def test_movement_management_time_enoughand_not_presence( # because motion is detected yet -> switch to Boost away mode assert entity.target_temperature == 19.1 assert entity.motion_state == "on" - assert entity.presence_state == "off" + assert entity.presence_state == STATE_OFF assert mock_send_event.call_count == 0 # Change is confirmed. Heater should be started @@ -474,8 +473,7 @@ async def test_movement_management_time_enoughand_not_presence( # because no motion is detected yet assert entity.target_temperature == 18.1 assert entity.motion_state == "off" - assert entity.presence_state == "off" - + assert entity.presence_state == STATE_OFF assert mock_send_event.call_count == 0 # 18.1 starts heating with a low on_percent assert mock_heater_on.call_count == 1 @@ -549,7 +547,7 @@ async def test_movement_management_with_stop_during_condition( # because no motion is detected yet assert entity.target_temperature == 18 assert entity.motion_state is None - assert entity.presence_state is None + assert entity.presence_state is STATE_UNKNOWN event_timestamp = now - timedelta(minutes=6) await send_temperature_change_event(entity, 18, event_timestamp) @@ -583,8 +581,7 @@ async def test_movement_management_with_stop_during_condition( # because motion is detected yet -> switch to Boost mode assert entity.target_temperature == 18 assert entity.motion_state is None - assert entity.presence_state == "off" - + assert entity.presence_state == STATE_OFF # Send a stop detection event_timestamp = now - timedelta(minutes=4) try_condition = await send_motion_change_event( @@ -596,7 +593,7 @@ async def test_movement_management_with_stop_during_condition( assert entity.preset_mode is PRESET_ACTIVITY assert entity.target_temperature == 18 assert entity.motion_state is None - assert entity.presence_state == "off" + assert entity.presence_state == STATE_OFF # Resend a start detection event_timestamp = now - timedelta(minutes=3) @@ -612,13 +609,13 @@ async def test_movement_management_with_stop_during_condition( # still no motion detected assert entity.target_temperature == 18 assert entity.motion_state is None - assert entity.presence_state == "off" + assert entity.presence_state == STATE_OFF await try_condition1(None) # We should have switch this time assert entity.target_temperature == 19 # Boost assert entity.motion_state == "on" # switch to movement on - assert entity.presence_state == "off" # Non change + assert entity.presence_state == STATE_OFF # Non change @pytest.mark.parametrize("expected_lingering_tasks", [True]) diff --git a/tests/test_overclimate_valve.py b/tests/test_overclimate_valve.py index 8dde208..4478654 100644 --- a/tests/test_overclimate_valve.py +++ b/tests/test_overclimate_valve.py @@ -114,7 +114,7 @@ async def test_over_climate_valve_mono(hass: HomeAssistant, skip_hass_states_get assert vtherm._security_state is False assert vtherm._window_state is None assert vtherm._motion_state is None - assert vtherm._presence_state is None + assert vtherm.presence_state is STATE_UNKNOWN assert vtherm.is_device_active is False assert vtherm.valve_open_percent == 0 diff --git a/tests/test_start.py b/tests/test_start.py index b227bb0..bc2d5d4 100644 --- a/tests/test_start.py +++ b/tests/test_start.py @@ -56,7 +56,7 @@ async def test_over_switch_full_start(hass: HomeAssistant, skip_hass_states_is_s assert entity._security_state is False assert entity._window_state is None assert entity._motion_state is None - assert entity._presence_state is None + assert entity.presence_state is STATE_UNKNOWN assert entity._prop_algorithm is not None assert entity.have_valve_regulation is False @@ -115,7 +115,7 @@ async def test_over_climate_full_start(hass: HomeAssistant, skip_hass_states_is_ assert entity._security_state is False assert entity._window_state is None assert entity._motion_state is None - assert entity._presence_state is None + assert entity.presence_state is STATE_UNAVAILABLE assert entity.have_valve_regulation is False # should have been called with EventType.PRESET_EVENT and EventType.HVAC_MODE_EVENT @@ -183,7 +183,7 @@ async def test_over_4switch_full_start(hass: HomeAssistant, skip_hass_states_is_ assert entity._security_state is False assert entity._window_state is None assert entity._motion_state is None - assert entity._presence_state is None + assert entity.presence_state is STATE_UNKNOWN assert entity._prop_algorithm is not None assert entity.nb_underlying_entities == 4 diff --git a/tests/test_switch_ac.py b/tests/test_switch_ac.py index 043f9fa..e87a266 100644 --- a/tests/test_switch_ac.py +++ b/tests/test_switch_ac.py @@ -92,7 +92,7 @@ async def test_over_switch_ac_full_start( assert entity._security_state is False # pylint: disable=protected-access assert entity._window_state is None # pylint: disable=protected-access assert entity._motion_state is None # pylint: disable=protected-access - assert entity._presence_state is None # pylint: disable=protected-access + assert entity.presence_state is STATE_UNKNOWN assert entity._prop_algorithm is not None # pylint: disable=protected-access # should have been called with EventType.PRESET_EVENT and EventType.HVAC_MODE_EVENT @@ -114,7 +114,7 @@ async def test_over_switch_ac_full_start( event_timestamp = now - timedelta(minutes=4) await send_presence_change_event(entity, True, False, event_timestamp) - assert entity._presence_state == STATE_ON # pylint: disable=protected-access + assert entity.presence_state == STATE_ON # pylint: disable=protected-access await entity.async_set_hvac_mode(HVACMode.COOL) assert entity.hvac_mode is HVACMode.COOL @@ -131,7 +131,7 @@ async def test_over_switch_ac_full_start( # Unset the presence event_timestamp = now - timedelta(minutes=3) await send_presence_change_event(entity, False, True, event_timestamp) - assert entity._presence_state == STATE_OFF # pylint: disable=protected-access + assert entity.presence_state == STATE_OFF # pylint: disable=protected-access assert entity.target_temperature == 27 # eco_ac_away # Open a window diff --git a/tests/test_valve.py b/tests/test_valve.py index 70023d4..1a2a3b3 100644 --- a/tests/test_valve.py +++ b/tests/test_valve.py @@ -101,7 +101,7 @@ async def test_over_valve_full_start( assert entity._security_state is False # pylint: disable=protected-access assert entity._window_state is None # pylint: disable=protected-access assert entity._motion_state is None # pylint: disable=protected-access - assert entity._presence_state is None # pylint: disable=protected-access + assert entity.presence_state is STATE_UNKNOWN assert entity._prop_algorithm is not None # pylint: disable=protected-access assert entity.have_valve_regulation is False