Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Switchbot Blind Tilt #86591

Merged
merged 10 commits into from
Feb 17, 2023
6 changes: 6 additions & 0 deletions homeassistant/components/switchbot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
Platform.LOCK,
Platform.SENSOR,
],
SupportedModels.BLIND_TILT.value: [
Platform.COVER,
Platform.BINARY_SENSOR,
Platform.SENSOR,
],
}
CLASS_BY_DEVICE = {
SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight,
Expand All @@ -60,6 +65,7 @@
SupportedModels.LIGHT_STRIP.value: switchbot.SwitchbotLightStrip,
SupportedModels.HUMIDIFIER.value: switchbot.SwitchbotHumidifier,
SupportedModels.LOCK.value: switchbot.SwitchbotLock,
SupportedModels.BLIND_TILT.value: switchbot.SwitchbotBlindTilt,
}


Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/switchbot/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class SupportedModels(StrEnum):
MOTION = "motion"
HUMIDIFIER = "humidifier"
LOCK = "lock"
BLIND_TILT = "blind_tilt"


CONNECTABLE_SUPPORTED_MODEL_TYPES = {
Expand All @@ -36,6 +37,7 @@ class SupportedModels(StrEnum):
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 = {
Expand Down
84 changes: 83 additions & 1 deletion homeassistant/components/switchbot/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

from homeassistant.components.cover import (
ATTR_CURRENT_POSITION,
ATTR_CURRENT_TILT_POSITION,
ATTR_POSITION,
ATTR_TILT_POSITION,
CoverDeviceClass,
CoverEntity,
CoverEntityFeature,
Expand All @@ -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):
Expand Down Expand Up @@ -102,3 +107,80 @@ def _handle_coordinator_update(self) -> None:
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()
2 changes: 1 addition & 1 deletion homeassistant/components/switchbot/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"domain": "switchbot",
"name": "SwitchBot",
"documentation": "https://www.home-assistant.io/integrations/switchbot",
"requirements": ["PySwitchbot==0.36.4"],
"requirements": ["PySwitchbot==0.37.1"],
"config_flow": true,
"dependencies": ["bluetooth_adapters"],
"codeowners": [
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down