mirror of https://github.com/home-assistant/core
129 lines
4.5 KiB
Python
129 lines
4.5 KiB
Python
"""Support for SwitchBee light."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from switchbee.api.central_unit import SwitchBeeDeviceOfflineError, SwitchBeeError
|
|
from switchbee.device import ApiStateCommand, DeviceType, SwitchBeeDimmer
|
|
|
|
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from .const import DOMAIN
|
|
from .coordinator import SwitchBeeCoordinator
|
|
from .entity import SwitchBeeDeviceEntity
|
|
|
|
MAX_BRIGHTNESS = 255
|
|
|
|
|
|
def _hass_brightness_to_switchbee(value: int) -> int:
|
|
"""Convert hass brightness to SwitchBee."""
|
|
sb_brightness = int(100 * value / MAX_BRIGHTNESS)
|
|
# SwitchBee maximum brightness is 99
|
|
return sb_brightness if sb_brightness != 100 else 99
|
|
|
|
|
|
def _switchbee_brightness_to_hass(value: int) -> int:
|
|
"""Convert SwitchBee brightness to hass."""
|
|
if value == 99:
|
|
value = 100
|
|
return round(value * MAX_BRIGHTNESS / 100)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
|
) -> None:
|
|
"""Set up SwitchBee light."""
|
|
coordinator = hass.data[DOMAIN][entry.entry_id]
|
|
async_add_entities(
|
|
SwitchBeeLightEntity(switchbee_device, coordinator)
|
|
for switchbee_device in coordinator.data.values()
|
|
if switchbee_device.type == DeviceType.Dimmer
|
|
)
|
|
|
|
|
|
class SwitchBeeLightEntity(SwitchBeeDeviceEntity[SwitchBeeDimmer], LightEntity):
|
|
"""Representation of a SwitchBee light."""
|
|
|
|
_attr_color_mode = ColorMode.BRIGHTNESS
|
|
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
|
|
|
def __init__(
|
|
self,
|
|
device: SwitchBeeDimmer,
|
|
coordinator: SwitchBeeCoordinator,
|
|
) -> None:
|
|
"""Initialize the SwitchBee light."""
|
|
super().__init__(device, coordinator)
|
|
self._attr_is_on = False
|
|
self._attr_brightness = 0
|
|
|
|
self._update_attrs_from_coordinator()
|
|
|
|
@callback
|
|
def _handle_coordinator_update(self) -> None:
|
|
"""Handle updated data from the coordinator."""
|
|
self._update_attrs_from_coordinator()
|
|
super()._handle_coordinator_update()
|
|
|
|
def _update_attrs_from_coordinator(self) -> None:
|
|
coordinator_device = self._get_coordinator_device()
|
|
brightness = coordinator_device.brightness
|
|
|
|
# module is offline
|
|
if brightness == -1:
|
|
self._check_if_became_offline()
|
|
return
|
|
|
|
self._check_if_became_online()
|
|
|
|
self._attr_is_on = bool(brightness != 0)
|
|
|
|
# 1-99 is the only valid SwitchBee brightness range
|
|
if 0 < brightness < 100:
|
|
self._attr_brightness = _switchbee_brightness_to_hass(brightness)
|
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
"""Async function to set on to light."""
|
|
if ATTR_BRIGHTNESS in kwargs:
|
|
state: int | str = _hass_brightness_to_switchbee(kwargs[ATTR_BRIGHTNESS])
|
|
else:
|
|
state = ApiStateCommand.ON
|
|
if self.brightness:
|
|
state = _hass_brightness_to_switchbee(self.brightness)
|
|
|
|
try:
|
|
await self.coordinator.api.set_state(self._device.id, state)
|
|
except (SwitchBeeError, SwitchBeeDeviceOfflineError) as exp:
|
|
raise HomeAssistantError(
|
|
f"Failed to set {self.name} state {state}, {exp!s}"
|
|
) from exp
|
|
|
|
if not isinstance(state, int):
|
|
# We just turned the light on, still don't know the last brightness
|
|
# known the Central Unit (yet) the brightness will be learned
|
|
# and updated in the next coordinator refresh
|
|
return
|
|
|
|
# update the coordinator data manually we already know the Central Unit
|
|
# brightness data for this light
|
|
self._get_coordinator_device().brightness = state
|
|
self.coordinator.async_set_updated_data(self.coordinator.data)
|
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
"""Turn off SwitchBee light."""
|
|
try:
|
|
await self.coordinator.api.set_state(self._device.id, ApiStateCommand.OFF)
|
|
except (SwitchBeeError, SwitchBeeDeviceOfflineError) as exp:
|
|
raise HomeAssistantError(
|
|
f"Failed to turn off {self._attr_name}, {exp!s}"
|
|
) from exp
|
|
|
|
# update the coordinator manually
|
|
self._get_coordinator_device().brightness = 0
|
|
self.coordinator.async_set_updated_data(self.coordinator.data)
|