diff --git a/homeassistant/components/sensibo/binary_sensor.py b/homeassistant/components/sensibo/binary_sensor.py index 2e1d449fc1d..ed280aab4fe 100644 --- a/homeassistant/components/sensibo/binary_sensor.py +++ b/homeassistant/components/sensibo/binary_sensor.py @@ -99,13 +99,6 @@ DEVICE_SENSOR_TYPES: tuple[SensiboDeviceBinarySensorEntityDescription, ...] = ( ) PURE_SENSOR_TYPES: tuple[SensiboDeviceBinarySensorEntityDescription, ...] = ( - SensiboDeviceBinarySensorEntityDescription( - key="pure_boost_enabled", - device_class=BinarySensorDeviceClass.RUNNING, - name="Pure Boost Enabled", - icon="mdi:wind-power-outline", - value_fn=lambda data: data.pure_boost_enabled, - ), SensiboDeviceBinarySensorEntityDescription( key="pure_ac_integration", entity_category=EntityCategory.DIAGNOSTIC, diff --git a/homeassistant/components/sensibo/climate.py b/homeassistant/components/sensibo/climate.py index 6a1084f733c..b4af38ab69c 100644 --- a/homeassistant/components/sensibo/climate.py +++ b/homeassistant/components/sensibo/climate.py @@ -107,21 +107,14 @@ async def async_setup_entry( platform.async_register_entity_service( SERVICE_ENABLE_PURE_BOOST, { - vol.Inclusive(ATTR_AC_INTEGRATION, "settings"): bool, - vol.Inclusive(ATTR_GEO_INTEGRATION, "settings"): bool, - vol.Inclusive(ATTR_INDOOR_INTEGRATION, "settings"): bool, - vol.Inclusive(ATTR_OUTDOOR_INTEGRATION, "settings"): bool, - vol.Inclusive(ATTR_SENSITIVITY, "settings"): vol.In( - ["Normal", "Sensitive"] - ), + vol.Required(ATTR_AC_INTEGRATION): bool, + vol.Required(ATTR_GEO_INTEGRATION): bool, + vol.Required(ATTR_INDOOR_INTEGRATION): bool, + vol.Required(ATTR_OUTDOOR_INTEGRATION): bool, + vol.Required(ATTR_SENSITIVITY): vol.In(["Normal", "Sensitive"]), }, "async_enable_pure_boost", ) - platform.async_register_entity_service( - SERVICE_DISABLE_PURE_BOOST, - {}, - "async_disable_pure_boost", - ) class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity): @@ -353,9 +346,3 @@ class SensiboClimate(SensiboDeviceBaseEntity, ClimateEntity): await self.async_send_command("set_pure_boost", params) await self.coordinator.async_refresh() - - async def async_disable_pure_boost(self) -> None: - """Disable Pure Boost Configuration.""" - - await self.async_send_command("set_pure_boost", {"enabled": False}) - await self.coordinator.async_refresh() diff --git a/homeassistant/components/sensibo/services.yaml b/homeassistant/components/sensibo/services.yaml index 6eb5c065789..9ce13b70eaa 100644 --- a/homeassistant/components/sensibo/services.yaml +++ b/homeassistant/components/sensibo/services.yaml @@ -45,45 +45,38 @@ enable_pure_boost: ac_integration: name: AC Integration description: Integrate with Air Conditioner. - required: false + required: true example: true selector: boolean: geo_integration: name: Geo Integration description: Integrate with Presence. - required: false + required: true example: true selector: boolean: indoor_integration: name: Indoor Air Quality description: Integrate with checking indoor air quality. - required: false + required: true example: true selector: boolean: outdoor_integration: name: Outdoor Air Quality description: Integrate with checking outdoor air quality. - required: false + required: true example: true selector: boolean: sensitivity: name: Sensitivity description: Set the sensitivity for Pure Boost. - required: false + required: true example: "Normal" selector: select: options: - "Normal" - "Sensitive" -disable_pure_boost: - name: Disable Pure Boost - description: Disable Pure Boost. - target: - entity: - integration: sensibo - domain: climate diff --git a/homeassistant/components/sensibo/switch.py b/homeassistant/components/sensibo/switch.py index 3b9915d0a89..d9cf9417504 100644 --- a/homeassistant/components/sensibo/switch.py +++ b/homeassistant/components/sensibo/switch.py @@ -29,7 +29,7 @@ class DeviceBaseEntityDescriptionMixin: """Mixin for required Sensibo base description keys.""" value_fn: Callable[[SensiboDevice], bool | None] - extra_fn: Callable[[SensiboDevice], dict[str, str | bool | None]] + extra_fn: Callable[[SensiboDevice], dict[str, str | bool | None]] | None command_on: str command_off: str remote_key: str @@ -56,6 +56,19 @@ DEVICE_SWITCH_TYPES: tuple[SensiboDeviceSwitchEntityDescription, ...] = ( ), ) +PURE_SWITCH_TYPES: tuple[SensiboDeviceSwitchEntityDescription, ...] = ( + SensiboDeviceSwitchEntityDescription( + key="pure_boost_switch", + device_class=SwitchDeviceClass.SWITCH, + name="Pure Boost", + value_fn=lambda data: data.pure_boost_enabled, + extra_fn=None, + command_on="set_pure_boost", + command_off="set_pure_boost", + remote_key="pure_boost_enabled", + ), +) + def build_params(command: str, device_data: SensiboDevice) -> dict[str, Any] | None: """Build params for turning on switch.""" @@ -66,6 +79,16 @@ def build_params(command: str, device_data: SensiboDevice) -> dict[str, Any] | N "acState": {**device_data.ac_states, "on": new_state}, } return params + if command == "set_pure_boost": + new_state = bool(device_data.pure_boost_enabled is False) + params = {"enabled": new_state} + if device_data.pure_measure_integration is None: + params["sensitivity"] = "N" + params["measurementsIntegration"] = True + params["acIntegration"] = False + params["geoIntegration"] = False + params["primeIntegration"] = False + return params return None @@ -84,6 +107,12 @@ async def async_setup_entry( for device_id, device_data in coordinator.data.parsed.items() if device_data.model != "pure" ) + entities.extend( + SensiboDeviceSwitch(coordinator, device_id, description) + for description in PURE_SWITCH_TYPES + for device_id, device_data in coordinator.data.parsed.items() + if device_data.model == "pure" + ) async_add_entities(entities) @@ -130,7 +159,10 @@ class SensiboDeviceSwitch(SensiboDeviceBaseEntity, SwitchEntity): async def async_turn_off(self, **kwargs: Any) -> None: """Turn the entity off.""" - result = await self.async_send_command(self.entity_description.command_off) + params = build_params(self.entity_description.command_on, self.device_data) + result = await self.async_send_command( + self.entity_description.command_off, params + ) if result["status"] == "success": setattr(self.device_data, self.entity_description.remote_key, False) @@ -141,6 +173,8 @@ class SensiboDeviceSwitch(SensiboDeviceBaseEntity, SwitchEntity): ) @property - def extra_state_attributes(self) -> Mapping[str, Any]: + def extra_state_attributes(self) -> Mapping[str, Any] | None: """Return additional attributes.""" - return self.entity_description.extra_fn(self.device_data) + if self.entity_description.extra_fn: + return self.entity_description.extra_fn(self.device_data) + return None diff --git a/tests/components/sensibo/test_binary_sensor.py b/tests/components/sensibo/test_binary_sensor.py index efa6c5bdb2a..093cfe7e472 100644 --- a/tests/components/sensibo/test_binary_sensor.py +++ b/tests/components/sensibo/test_binary_sensor.py @@ -27,20 +27,18 @@ async def test_binary_sensor( state2 = hass.states.get("binary_sensor.hallway_motion_sensor_main_sensor") state3 = hass.states.get("binary_sensor.hallway_motion_sensor_motion") state4 = hass.states.get("binary_sensor.hallway_room_occupied") - state5 = hass.states.get("binary_sensor.kitchen_pure_boost_enabled") - state6 = hass.states.get( + state5 = hass.states.get( "binary_sensor.kitchen_pure_boost_linked_with_indoor_air_quality" ) - state7 = hass.states.get( + state6 = hass.states.get( "binary_sensor.kitchen_pure_boost_linked_with_outdoor_air_quality" ) assert state1.state == "on" assert state2.state == "on" assert state3.state == "on" assert state4.state == "on" - assert state5.state == "off" - assert state6.state == "on" - assert state7.state == "off" + assert state5.state == "on" + assert state6.state == "off" monkeypatch.setattr( get_data.parsed["ABC999111"].motion_sensors["AABBCC"], "alive", False diff --git a/tests/components/sensibo/test_climate.py b/tests/components/sensibo/test_climate.py index ea7f6eb16fe..e7a3c465f76 100644 --- a/tests/components/sensibo/test_climate.py +++ b/tests/components/sensibo/test_climate.py @@ -28,7 +28,6 @@ from homeassistant.components.sensibo.climate import ( ATTR_OUTDOOR_INTEGRATION, ATTR_SENSITIVITY, SERVICE_ASSUME_STATE, - SERVICE_DISABLE_PURE_BOOST, SERVICE_ENABLE_PURE_BOOST, SERVICE_ENABLE_TIMER, _find_valid_target_temp, @@ -809,7 +808,7 @@ async def test_climate_pure_boost( await hass.async_block_till_done() state_climate = hass.states.get("climate.kitchen") - state2 = hass.states.get("binary_sensor.kitchen_pure_boost_enabled") + state2 = hass.states.get("switch.kitchen_pure_boost") assert state2.state == "off" with patch( @@ -878,7 +877,7 @@ async def test_climate_pure_boost( ) await hass.async_block_till_done() - state1 = hass.states.get("binary_sensor.kitchen_pure_boost_enabled") + state1 = hass.states.get("switch.kitchen_pure_boost") state2 = hass.states.get( "binary_sensor.kitchen_pure_boost_linked_with_indoor_air_quality" ) @@ -890,49 +889,3 @@ async def test_climate_pure_boost( assert state2.state == "on" assert state3.state == "on" assert state4.state == "s" - - with patch( - "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data", - return_value=get_data, - ), patch( - "homeassistant.components.sensibo.coordinator.SensiboClient.async_set_pureboost", - return_value={ - "status": "success", - "result": { - "enabled": False, - "sensitivity": "S", - "measurements_integration": True, - "ac_integration": False, - "geo_integration": False, - "prime_integration": True, - }, - }, - ) as mock_set_pureboost: - await hass.services.async_call( - DOMAIN, - SERVICE_DISABLE_PURE_BOOST, - { - ATTR_ENTITY_ID: state_climate.entity_id, - }, - blocking=True, - ) - await hass.async_block_till_done() - mock_set_pureboost.assert_called_once() - - monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_boost_enabled", False) - monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_sensitivity", "s") - - with patch( - "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data", - return_value=get_data, - ): - async_fire_time_changed( - hass, - dt.utcnow() + timedelta(minutes=5), - ) - await hass.async_block_till_done() - - state1 = hass.states.get("binary_sensor.kitchen_pure_boost_enabled") - state4 = hass.states.get("sensor.kitchen_pure_sensitivity") - assert state1.state == "off" - assert state4.state == "s" diff --git a/tests/components/sensibo/test_switch.py b/tests/components/sensibo/test_switch.py index 49efca4103e..2a24751d70b 100644 --- a/tests/components/sensibo/test_switch.py +++ b/tests/components/sensibo/test_switch.py @@ -25,7 +25,7 @@ from homeassistant.util import dt from tests.common import async_fire_time_changed -async def test_switch( +async def test_switch_timer( hass: HomeAssistant, load_int: ConfigEntry, monkeypatch: MonkeyPatch, @@ -105,6 +105,81 @@ async def test_switch( assert state1.state == STATE_OFF +async def test_switch_pure_boost( + hass: HomeAssistant, + load_int: ConfigEntry, + monkeypatch: MonkeyPatch, + get_data: SensiboData, +) -> None: + """Test the Sensibo switch.""" + + state1 = hass.states.get("switch.kitchen_pure_boost") + assert state1.state == STATE_OFF + + with patch( + "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data", + return_value=get_data, + ), patch( + "homeassistant.components.sensibo.util.SensiboClient.async_set_pureboost", + return_value={"status": "success"}, + ): + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_ON, + { + ATTR_ENTITY_ID: state1.entity_id, + }, + blocking=True, + ) + await hass.async_block_till_done() + + monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_boost_enabled", True) + + with patch( + "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data", + return_value=get_data, + ): + async_fire_time_changed( + hass, + dt.utcnow() + timedelta(minutes=5), + ) + await hass.async_block_till_done() + state1 = hass.states.get("switch.kitchen_pure_boost") + assert state1.state == STATE_ON + + with patch( + "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data", + return_value=get_data, + ), patch( + "homeassistant.components.sensibo.util.SensiboClient.async_set_pureboost", + return_value={"status": "success"}, + ): + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_OFF, + { + ATTR_ENTITY_ID: state1.entity_id, + }, + blocking=True, + ) + await hass.async_block_till_done() + + monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_boost_enabled", False) + + with patch( + "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data", + return_value=get_data, + ): + async_fire_time_changed( + hass, + dt.utcnow() + timedelta(minutes=5), + ) + await hass.async_block_till_done() + + state1 = hass.states.get("switch.kitchen_pure_boost") + assert state1.state == STATE_OFF + + async def test_switch_command_failure( hass: HomeAssistant, load_int: ConfigEntry, @@ -162,4 +237,14 @@ async def test_build_params( "minutesFromNow": 60, "acState": {**get_data.parsed["ABC999111"].ac_states, "on": False}, } + + monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_measure_integration", None) + assert build_params("set_pure_boost", get_data.parsed["AAZZAAZZ"]) == { + "enabled": True, + "sensitivity": "N", + "measurementsIntegration": True, + "acIntegration": False, + "geoIntegration": False, + "primeIntegration": False, + } assert build_params("incorrect_command", get_data.parsed["ABC999111"]) is None