2019-02-14 15:01:46 +00:00
|
|
|
"""Support for Homekit lights."""
|
2022-02-01 19:30:37 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from typing import Any
|
|
|
|
|
2020-02-24 09:55:33 +00:00
|
|
|
from aiohomekit.model.characteristics import CharacteristicsTypes
|
2022-02-01 19:30:37 +00:00
|
|
|
from aiohomekit.model.services import Service, ServicesTypes
|
2019-08-14 16:14:15 +00:00
|
|
|
|
2018-04-13 17:25:35 +00:00
|
|
|
from homeassistant.components.light import (
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_BRIGHTNESS,
|
|
|
|
ATTR_COLOR_TEMP,
|
|
|
|
ATTR_HS_COLOR,
|
2022-04-20 19:26:15 +00:00
|
|
|
COLOR_MODE_BRIGHTNESS,
|
|
|
|
COLOR_MODE_COLOR_TEMP,
|
|
|
|
COLOR_MODE_HS,
|
|
|
|
COLOR_MODE_ONOFF,
|
2020-04-26 16:49:41 +00:00
|
|
|
LightEntity,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2021-12-28 18:24:40 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
|
|
|
from homeassistant.core import HomeAssistant, callback
|
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
2018-04-13 17:25:35 +00:00
|
|
|
|
2019-03-26 06:49:51 +00:00
|
|
|
from . import KNOWN_DEVICES, HomeKitEntity
|
2019-03-21 05:56:46 +00:00
|
|
|
|
2018-04-13 17:25:35 +00:00
|
|
|
|
2021-12-28 18:24:40 +00:00
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config_entry: ConfigEntry,
|
|
|
|
async_add_entities: AddEntitiesCallback,
|
|
|
|
) -> None:
|
2019-05-13 06:56:05 +00:00
|
|
|
"""Set up Homekit lightbulb."""
|
2019-07-31 19:25:30 +00:00
|
|
|
hkid = config_entry.data["AccessoryPairingID"]
|
2019-05-13 06:56:05 +00:00
|
|
|
conn = hass.data[KNOWN_DEVICES][hkid]
|
|
|
|
|
2020-01-29 21:59:45 +00:00
|
|
|
@callback
|
2022-02-01 19:30:37 +00:00
|
|
|
def async_add_service(service: Service) -> bool:
|
2022-01-31 22:48:16 +00:00
|
|
|
if service.type != ServicesTypes.LIGHTBULB:
|
2019-05-13 06:56:05 +00:00
|
|
|
return False
|
2020-11-16 23:11:39 +00:00
|
|
|
info = {"aid": service.accessory.aid, "iid": service.iid}
|
2019-05-13 06:56:05 +00:00
|
|
|
async_add_entities([HomeKitLight(conn, info)], True)
|
|
|
|
return True
|
|
|
|
|
|
|
|
conn.add_listener(async_add_service)
|
2018-04-13 17:25:35 +00:00
|
|
|
|
|
|
|
|
2020-04-26 16:49:41 +00:00
|
|
|
class HomeKitLight(HomeKitEntity, LightEntity):
|
2018-04-13 17:25:35 +00:00
|
|
|
"""Representation of a Homekit light."""
|
|
|
|
|
2022-02-01 19:30:37 +00:00
|
|
|
def get_characteristic_types(self) -> list[str]:
|
2019-01-28 16:21:20 +00:00
|
|
|
"""Define the homekit characteristics the entity cares about."""
|
|
|
|
return [
|
|
|
|
CharacteristicsTypes.ON,
|
|
|
|
CharacteristicsTypes.BRIGHTNESS,
|
|
|
|
CharacteristicsTypes.COLOR_TEMPERATURE,
|
|
|
|
CharacteristicsTypes.HUE,
|
|
|
|
CharacteristicsTypes.SATURATION,
|
|
|
|
]
|
|
|
|
|
2018-04-13 17:25:35 +00:00
|
|
|
@property
|
2022-02-01 19:30:37 +00:00
|
|
|
def is_on(self) -> bool:
|
2018-04-13 17:25:35 +00:00
|
|
|
"""Return true if device is on."""
|
2020-03-11 11:40:47 +00:00
|
|
|
return self.service.value(CharacteristicsTypes.ON)
|
2018-04-13 17:25:35 +00:00
|
|
|
|
|
|
|
@property
|
2022-02-01 19:30:37 +00:00
|
|
|
def brightness(self) -> int:
|
2018-04-13 17:25:35 +00:00
|
|
|
"""Return the brightness of this light between 0..255."""
|
2020-03-11 11:40:47 +00:00
|
|
|
return self.service.value(CharacteristicsTypes.BRIGHTNESS) * 255 / 100
|
2018-04-13 17:25:35 +00:00
|
|
|
|
|
|
|
@property
|
2022-02-01 19:30:37 +00:00
|
|
|
def hs_color(self) -> tuple[float, float]:
|
2018-04-13 17:25:35 +00:00
|
|
|
"""Return the color property."""
|
2020-03-11 11:40:47 +00:00
|
|
|
return (
|
|
|
|
self.service.value(CharacteristicsTypes.HUE),
|
|
|
|
self.service.value(CharacteristicsTypes.SATURATION),
|
|
|
|
)
|
2018-04-13 17:25:35 +00:00
|
|
|
|
|
|
|
@property
|
2022-02-01 19:30:37 +00:00
|
|
|
def color_temp(self) -> int:
|
2018-04-13 17:25:35 +00:00
|
|
|
"""Return the color temperature."""
|
2020-03-11 11:40:47 +00:00
|
|
|
return self.service.value(CharacteristicsTypes.COLOR_TEMPERATURE)
|
2018-04-13 17:25:35 +00:00
|
|
|
|
|
|
|
@property
|
2022-04-20 19:26:15 +00:00
|
|
|
def color_mode(self) -> str:
|
|
|
|
"""Return the color mode of the light."""
|
|
|
|
# aiohomekit does not keep track of the light's color mode, report
|
|
|
|
# hs for light supporting both hs and ct
|
|
|
|
if self.service.has(CharacteristicsTypes.HUE) or self.service.has(
|
|
|
|
CharacteristicsTypes.SATURATION
|
|
|
|
):
|
|
|
|
return COLOR_MODE_HS
|
|
|
|
|
|
|
|
if self.service.has(CharacteristicsTypes.COLOR_TEMPERATURE):
|
|
|
|
return COLOR_MODE_COLOR_TEMP
|
2020-03-18 15:12:55 +00:00
|
|
|
|
|
|
|
if self.service.has(CharacteristicsTypes.BRIGHTNESS):
|
2022-04-20 19:26:15 +00:00
|
|
|
return COLOR_MODE_BRIGHTNESS
|
|
|
|
|
|
|
|
return COLOR_MODE_ONOFF
|
|
|
|
|
|
|
|
@property
|
|
|
|
def supported_color_modes(self) -> set[str] | None:
|
|
|
|
"""Flag supported color modes."""
|
|
|
|
color_modes = set()
|
|
|
|
|
|
|
|
if self.service.has(CharacteristicsTypes.HUE) or self.service.has(
|
|
|
|
CharacteristicsTypes.SATURATION
|
|
|
|
):
|
|
|
|
color_modes.add(COLOR_MODE_HS)
|
2020-03-18 15:12:55 +00:00
|
|
|
|
|
|
|
if self.service.has(CharacteristicsTypes.COLOR_TEMPERATURE):
|
2022-04-20 19:26:15 +00:00
|
|
|
color_modes.add(COLOR_MODE_COLOR_TEMP)
|
2020-03-18 15:12:55 +00:00
|
|
|
|
2022-04-20 19:26:15 +00:00
|
|
|
if not color_modes and self.service.has(CharacteristicsTypes.BRIGHTNESS):
|
|
|
|
color_modes.add(COLOR_MODE_BRIGHTNESS)
|
2020-03-18 15:12:55 +00:00
|
|
|
|
2022-04-20 19:26:15 +00:00
|
|
|
if not color_modes:
|
|
|
|
color_modes.add(COLOR_MODE_ONOFF)
|
2020-03-18 15:12:55 +00:00
|
|
|
|
2022-04-20 19:26:15 +00:00
|
|
|
return color_modes
|
2018-04-13 17:25:35 +00:00
|
|
|
|
2022-02-01 19:30:37 +00:00
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
2018-04-13 17:25:35 +00:00
|
|
|
"""Turn the specified light on."""
|
|
|
|
hs_color = kwargs.get(ATTR_HS_COLOR)
|
|
|
|
temperature = kwargs.get(ATTR_COLOR_TEMP)
|
|
|
|
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
|
|
|
|
2020-03-11 16:27:20 +00:00
|
|
|
characteristics = {}
|
|
|
|
|
2018-04-13 17:25:35 +00:00
|
|
|
if hs_color is not None:
|
2020-03-11 16:27:20 +00:00
|
|
|
characteristics.update(
|
2019-07-31 19:25:30 +00:00
|
|
|
{
|
2020-03-11 16:27:20 +00:00
|
|
|
CharacteristicsTypes.HUE: hs_color[0],
|
|
|
|
CharacteristicsTypes.SATURATION: hs_color[1],
|
2019-07-31 19:25:30 +00:00
|
|
|
}
|
|
|
|
)
|
2020-03-11 16:27:20 +00:00
|
|
|
|
2018-04-13 17:25:35 +00:00
|
|
|
if brightness is not None:
|
2020-03-11 16:27:20 +00:00
|
|
|
characteristics[CharacteristicsTypes.BRIGHTNESS] = int(
|
|
|
|
brightness * 100 / 255
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2018-04-13 17:25:35 +00:00
|
|
|
|
|
|
|
if temperature is not None:
|
2020-03-11 16:27:20 +00:00
|
|
|
characteristics[CharacteristicsTypes.COLOR_TEMPERATURE] = int(temperature)
|
|
|
|
|
|
|
|
characteristics[CharacteristicsTypes.ON] = True
|
|
|
|
|
|
|
|
await self.async_put_characteristics(characteristics)
|
2018-04-13 17:25:35 +00:00
|
|
|
|
2022-02-01 19:30:37 +00:00
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
2018-04-13 17:25:35 +00:00
|
|
|
"""Turn the specified light off."""
|
2020-03-11 16:27:20 +00:00
|
|
|
await self.async_put_characteristics({CharacteristicsTypes.ON: False})
|