diff --git a/homeassistant/components/switchbot/__init__.py b/homeassistant/components/switchbot/__init__.py index 5d4f29b9dfe..445920ad276 100644 --- a/homeassistant/components/switchbot/__init__.py +++ b/homeassistant/components/switchbot/__init__.py @@ -50,6 +50,11 @@ PLATFORMS_BY_TYPE = { Platform.LOCK, Platform.SENSOR, ], + SupportedModels.BLIND_TILT.value: [ + Platform.COVER, + Platform.BINARY_SENSOR, + Platform.SENSOR, + ], } CLASS_BY_DEVICE = { SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight, @@ -60,6 +65,7 @@ CLASS_BY_DEVICE = { SupportedModels.LIGHT_STRIP.value: switchbot.SwitchbotLightStrip, SupportedModels.HUMIDIFIER.value: switchbot.SwitchbotHumidifier, SupportedModels.LOCK.value: switchbot.SwitchbotLock, + SupportedModels.BLIND_TILT.value: switchbot.SwitchbotBlindTilt, } diff --git a/homeassistant/components/switchbot/const.py b/homeassistant/components/switchbot/const.py index 3d606d93169..a21bd859efc 100644 --- a/homeassistant/components/switchbot/const.py +++ b/homeassistant/components/switchbot/const.py @@ -25,6 +25,7 @@ class SupportedModels(StrEnum): MOTION = "motion" HUMIDIFIER = "humidifier" LOCK = "lock" + BLIND_TILT = "blind_tilt" CONNECTABLE_SUPPORTED_MODEL_TYPES = { @@ -36,6 +37,7 @@ CONNECTABLE_SUPPORTED_MODEL_TYPES = { SwitchbotModel.CEILING_LIGHT: SupportedModels.CEILING_LIGHT, SwitchbotModel.HUMIDIFIER: SupportedModels.HUMIDIFIER, SwitchbotModel.LOCK: SupportedModels.LOCK, + SwitchbotModel.BLIND_TILT: SupportedModels.BLIND_TILT, } NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = { diff --git a/homeassistant/components/switchbot/cover.py b/homeassistant/components/switchbot/cover.py index 7450653e9a9..495ce0468a0 100644 --- a/homeassistant/components/switchbot/cover.py +++ b/homeassistant/components/switchbot/cover.py @@ -8,7 +8,9 @@ import switchbot from homeassistant.components.cover import ( ATTR_CURRENT_POSITION, + ATTR_CURRENT_TILT_POSITION, ATTR_POSITION, + ATTR_TILT_POSITION, CoverDeviceClass, CoverEntity, CoverEntityFeature, @@ -32,7 +34,10 @@ async def async_setup_entry( ) -> None: """Set up Switchbot curtain based on a config entry.""" coordinator: SwitchbotDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] - async_add_entities([SwitchBotCurtainEntity(coordinator)]) + if isinstance(coordinator.device, switchbot.SwitchbotBlindTilt): + async_add_entities([SwitchBotBlindTiltEntity(coordinator)]) + else: + async_add_entities([SwitchBotCurtainEntity(coordinator)]) class SwitchBotCurtainEntity(SwitchbotEntity, CoverEntity, RestoreEntity): @@ -102,3 +107,80 @@ class SwitchBotCurtainEntity(SwitchbotEntity, CoverEntity, RestoreEntity): self._attr_is_closed = self.parsed_data["position"] <= 20 self._attr_is_opening = self.parsed_data["inMotion"] self.async_write_ha_state() + + +class SwitchBotBlindTiltEntity(SwitchbotEntity, CoverEntity, RestoreEntity): + """Representation of a Switchbot.""" + + _device: switchbot.SwitchbotBlindTilt + _attr_device_class = CoverDeviceClass.BLIND + _attr_supported_features = ( + CoverEntityFeature.OPEN_TILT + | CoverEntityFeature.CLOSE_TILT + | CoverEntityFeature.STOP_TILT + | CoverEntityFeature.SET_TILT_POSITION + ) + CLOSED_UP_THRESHOLD = 80 + CLOSED_DOWN_THRESHOLD = 20 + + def __init__(self, coordinator: SwitchbotDataUpdateCoordinator) -> None: + """Initialize the Switchbot.""" + super().__init__(coordinator) + self._attr_is_closed = None + + async def async_added_to_hass(self) -> None: + """Run when entity about to be added.""" + await super().async_added_to_hass() + last_state = await self.async_get_last_state() + if not last_state or ATTR_CURRENT_TILT_POSITION not in last_state.attributes: + return + + self._attr_current_cover_tilt_position = last_state.attributes.get( + ATTR_CURRENT_TILT_POSITION + ) + self._last_run_success = last_state.attributes.get("last_run_success") + if (_tilt := self._attr_current_cover_position) is not None: + self._attr_is_closed = (_tilt < self.CLOSED_DOWN_THRESHOLD) or ( + _tilt > self.CLOSED_UP_THRESHOLD + ) + + async def async_open_cover_tilt(self, **kwargs: Any) -> None: + """Open the tilt.""" + + _LOGGER.debug("Switchbot to open blind tilt %s", self._address) + self._last_run_success = bool(await self._device.open()) + self.async_write_ha_state() + + async def async_close_cover_tilt(self, **kwargs: Any) -> None: + """Close the tilt.""" + + _LOGGER.debug("Switchbot to close the blind tilt %s", self._address) + self._last_run_success = bool(await self._device.close()) + self.async_write_ha_state() + + async def async_stop_cover_tilt(self, **kwargs: Any) -> None: + """Stop the moving of this device.""" + + _LOGGER.debug("Switchbot to stop %s", self._address) + self._last_run_success = bool(await self._device.stop()) + self.async_write_ha_state() + + async def async_set_cover_tilt_position(self, **kwargs: Any) -> None: + """Move the cover tilt to a specific position.""" + position = kwargs.get(ATTR_TILT_POSITION) + + _LOGGER.debug("Switchbot to move at %d %s", position, self._address) + self._last_run_success = bool(await self._device.set_position(position)) + self.async_write_ha_state() + + @callback + def _handle_coordinator_update(self) -> None: + """Handle updated data from the coordinator.""" + _tilt = self.parsed_data["tilt"] + self._attr_current_cover_tilt_position = _tilt + self._attr_is_closed = (_tilt < self.CLOSED_DOWN_THRESHOLD) or ( + _tilt > self.CLOSED_UP_THRESHOLD + ) + self._attr_is_opening = self.parsed_data["motionDirection"]["opening"] + self._attr_is_closing = self.parsed_data["motionDirection"]["closing"] + self.async_write_ha_state() diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index 29531a75a20..16d4e1cccdf 100644 --- a/homeassistant/components/switchbot/manifest.json +++ b/homeassistant/components/switchbot/manifest.json @@ -40,5 +40,5 @@ "documentation": "https://www.home-assistant.io/integrations/switchbot", "iot_class": "local_push", "loggers": ["switchbot"], - "requirements": ["PySwitchbot==0.36.4"] + "requirements": ["PySwitchbot==0.37.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index bc84932ea50..dfb3f44d4a3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -40,7 +40,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.36.4 +PySwitchbot==0.37.1 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5dcae6f00d4..4b23916067f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -36,7 +36,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.36.4 +PySwitchbot==0.37.1 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1