mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 02:37:08 +00:00
Use attributes in wilight (#73898)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
parent
15b7564171
commit
9b88b77b66
@ -1,5 +1,9 @@
|
|||||||
"""The WiLight integration."""
|
"""The WiLight integration."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from pywilight.wilight_device import Device as PyWiLightDevice
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
@ -51,61 +55,43 @@ class WiLightDevice(Entity):
|
|||||||
Contains the common logic for WiLight entities.
|
Contains the common logic for WiLight entities.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, api_device, index, item_name):
|
_attr_should_poll = False
|
||||||
|
|
||||||
|
def __init__(self, api_device: PyWiLightDevice, index: str, item_name: str) -> None:
|
||||||
"""Initialize the device."""
|
"""Initialize the device."""
|
||||||
# WiLight specific attributes for every component type
|
# WiLight specific attributes for every component type
|
||||||
self._device_id = api_device.device_id
|
self._device_id = api_device.device_id
|
||||||
self._sw_version = api_device.swversion
|
|
||||||
self._client = api_device.client
|
self._client = api_device.client
|
||||||
self._model = api_device.model
|
|
||||||
self._name = item_name
|
|
||||||
self._index = index
|
self._index = index
|
||||||
self._unique_id = f"{self._device_id}_{self._index}"
|
self._status: dict[str, Any] = {}
|
||||||
self._status = {}
|
|
||||||
|
|
||||||
@property
|
self._attr_name = item_name
|
||||||
def should_poll(self):
|
self._attr_unique_id = f"{self._device_id}_{index}"
|
||||||
"""No polling needed."""
|
self._attr_device_info = DeviceInfo(
|
||||||
return False
|
name=item_name,
|
||||||
|
identifiers={(DOMAIN, self._attr_unique_id)},
|
||||||
@property
|
model=api_device.model,
|
||||||
def name(self):
|
|
||||||
"""Return a name for this WiLight item."""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unique_id(self):
|
|
||||||
"""Return the unique ID for this WiLight item."""
|
|
||||||
return self._unique_id
|
|
||||||
|
|
||||||
@property
|
|
||||||
def device_info(self) -> DeviceInfo:
|
|
||||||
"""Return the device info."""
|
|
||||||
return DeviceInfo(
|
|
||||||
name=self._name,
|
|
||||||
identifiers={(DOMAIN, self._unique_id)},
|
|
||||||
model=self._model,
|
|
||||||
manufacturer="WiLight",
|
manufacturer="WiLight",
|
||||||
sw_version=self._sw_version,
|
sw_version=api_device.swversion,
|
||||||
via_device=(DOMAIN, self._device_id),
|
via_device=(DOMAIN, self._device_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self) -> bool:
|
||||||
"""Return True if entity is available."""
|
"""Return True if entity is available."""
|
||||||
return bool(self._client.is_connected)
|
return bool(self._client.is_connected)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_event_callback(self, states):
|
def handle_event_callback(self, states: dict[str, Any]) -> None:
|
||||||
"""Propagate changes through ha."""
|
"""Propagate changes through ha."""
|
||||||
self._status = states
|
self._status = states
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self) -> None:
|
||||||
"""Synchronize state with api_device."""
|
"""Synchronize state with api_device."""
|
||||||
await self._client.status(self._index)
|
await self._client.status(self._index)
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Register update callback."""
|
"""Register update callback."""
|
||||||
self._client.register_status_callback(self.handle_event_callback, self._index)
|
self._client.register_status_callback(self.handle_event_callback, self._index)
|
||||||
await self._client.status(self._index)
|
await self._client.status(self._index)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
"""Support for WiLight Cover."""
|
"""Support for WiLight Cover."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pywilight.const import (
|
from pywilight.const import (
|
||||||
@ -18,16 +20,18 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import DOMAIN, WiLightDevice
|
from . import DOMAIN, WiLightDevice
|
||||||
|
from .parent_device import WiLightParent
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up WiLight covers from a config entry."""
|
"""Set up WiLight covers from a config entry."""
|
||||||
parent = hass.data[DOMAIN][entry.entry_id]
|
parent: WiLightParent = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
# Handle a discovered WiLight device.
|
# Handle a discovered WiLight device.
|
||||||
entities = []
|
entities = []
|
||||||
|
assert parent.api
|
||||||
for item in parent.api.items:
|
for item in parent.api.items:
|
||||||
if item["type"] != ITEM_COVER:
|
if item["type"] != ITEM_COVER:
|
||||||
continue
|
continue
|
||||||
@ -35,18 +39,17 @@ async def async_setup_entry(
|
|||||||
item_name = item["name"]
|
item_name = item["name"]
|
||||||
if item["sub_type"] != COVER_V1:
|
if item["sub_type"] != COVER_V1:
|
||||||
continue
|
continue
|
||||||
entity = WiLightCover(parent.api, index, item_name)
|
entities.append(WiLightCover(parent.api, index, item_name))
|
||||||
entities.append(entity)
|
|
||||||
|
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
def wilight_to_hass_position(value):
|
def wilight_to_hass_position(value: int) -> int:
|
||||||
"""Convert wilight position 1..255 to hass format 0..100."""
|
"""Convert wilight position 1..255 to hass format 0..100."""
|
||||||
return min(100, round((value * 100) / 255))
|
return min(100, round((value * 100) / 255))
|
||||||
|
|
||||||
|
|
||||||
def hass_to_wilight_position(value):
|
def hass_to_wilight_position(value: int) -> int:
|
||||||
"""Convert hass position 0..100 to wilight 1..255 scale."""
|
"""Convert hass position 0..100 to wilight 1..255 scale."""
|
||||||
return min(255, round((value * 255) / 100))
|
return min(255, round((value * 255) / 100))
|
||||||
|
|
||||||
@ -55,7 +58,7 @@ class WiLightCover(WiLightDevice, CoverEntity):
|
|||||||
"""Representation of a WiLights cover."""
|
"""Representation of a WiLights cover."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_cover_position(self):
|
def current_cover_position(self) -> int | None:
|
||||||
"""Return current position of cover.
|
"""Return current position of cover.
|
||||||
|
|
||||||
None is unknown, 0 is closed, 100 is fully open.
|
None is unknown, 0 is closed, 100 is fully open.
|
||||||
@ -65,21 +68,21 @@ class WiLightCover(WiLightDevice, CoverEntity):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_opening(self):
|
def is_opening(self) -> bool | None:
|
||||||
"""Return if the cover is opening or not."""
|
"""Return if the cover is opening or not."""
|
||||||
if "motor_state" not in self._status:
|
if "motor_state" not in self._status:
|
||||||
return None
|
return None
|
||||||
return self._status["motor_state"] == WL_OPENING
|
return self._status["motor_state"] == WL_OPENING
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closing(self):
|
def is_closing(self) -> bool | None:
|
||||||
"""Return if the cover is closing or not."""
|
"""Return if the cover is closing or not."""
|
||||||
if "motor_state" not in self._status:
|
if "motor_state" not in self._status:
|
||||||
return None
|
return None
|
||||||
return self._status["motor_state"] == WL_CLOSING
|
return self._status["motor_state"] == WL_CLOSING
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self):
|
def is_closed(self) -> bool | None:
|
||||||
"""Return if the cover is closed or not."""
|
"""Return if the cover is closed or not."""
|
||||||
if "motor_state" not in self._status or "position_current" not in self._status:
|
if "motor_state" not in self._status or "position_current" not in self._status:
|
||||||
return None
|
return None
|
||||||
|
@ -13,6 +13,7 @@ from pywilight.const import (
|
|||||||
WL_SPEED_LOW,
|
WL_SPEED_LOW,
|
||||||
WL_SPEED_MEDIUM,
|
WL_SPEED_MEDIUM,
|
||||||
)
|
)
|
||||||
|
from pywilight.wilight_device import Device as PyWiLightDevice
|
||||||
|
|
||||||
from homeassistant.components.fan import DIRECTION_FORWARD, FanEntity, FanEntityFeature
|
from homeassistant.components.fan import DIRECTION_FORWARD, FanEntity, FanEntityFeature
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -24,6 +25,7 @@ from homeassistant.util.percentage import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from . import DOMAIN, WiLightDevice
|
from . import DOMAIN, WiLightDevice
|
||||||
|
from .parent_device import WiLightParent
|
||||||
|
|
||||||
ORDERED_NAMED_FAN_SPEEDS = [WL_SPEED_LOW, WL_SPEED_MEDIUM, WL_SPEED_HIGH]
|
ORDERED_NAMED_FAN_SPEEDS = [WL_SPEED_LOW, WL_SPEED_MEDIUM, WL_SPEED_HIGH]
|
||||||
|
|
||||||
@ -32,10 +34,11 @@ async def async_setup_entry(
|
|||||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up WiLight lights from a config entry."""
|
"""Set up WiLight lights from a config entry."""
|
||||||
parent = hass.data[DOMAIN][entry.entry_id]
|
parent: WiLightParent = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
# Handle a discovered WiLight device.
|
# Handle a discovered WiLight device.
|
||||||
entities = []
|
entities = []
|
||||||
|
assert parent.api
|
||||||
for item in parent.api.items:
|
for item in parent.api.items:
|
||||||
if item["type"] != ITEM_FAN:
|
if item["type"] != ITEM_FAN:
|
||||||
continue
|
continue
|
||||||
@ -43,8 +46,7 @@ async def async_setup_entry(
|
|||||||
item_name = item["name"]
|
item_name = item["name"]
|
||||||
if item["sub_type"] != FAN_V1:
|
if item["sub_type"] != FAN_V1:
|
||||||
continue
|
continue
|
||||||
entity = WiLightFan(parent.api, index, item_name)
|
entities.append(WiLightFan(parent.api, index, item_name))
|
||||||
entities.append(entity)
|
|
||||||
|
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
|
|
||||||
@ -52,19 +54,16 @@ async def async_setup_entry(
|
|||||||
class WiLightFan(WiLightDevice, FanEntity):
|
class WiLightFan(WiLightDevice, FanEntity):
|
||||||
"""Representation of a WiLights fan."""
|
"""Representation of a WiLights fan."""
|
||||||
|
|
||||||
|
_attr_icon = "mdi:fan"
|
||||||
|
_attr_speed_count = len(ORDERED_NAMED_FAN_SPEEDS)
|
||||||
_attr_supported_features = FanEntityFeature.SET_SPEED | FanEntityFeature.DIRECTION
|
_attr_supported_features = FanEntityFeature.SET_SPEED | FanEntityFeature.DIRECTION
|
||||||
|
|
||||||
def __init__(self, api_device, index, item_name):
|
def __init__(self, api_device: PyWiLightDevice, index: str, item_name: str) -> None:
|
||||||
"""Initialize the device."""
|
"""Initialize the device."""
|
||||||
super().__init__(api_device, index, item_name)
|
super().__init__(api_device, index, item_name)
|
||||||
# Initialize the WiLights fan.
|
# Initialize the WiLights fan.
|
||||||
self._direction = WL_DIRECTION_FORWARD
|
self._direction = WL_DIRECTION_FORWARD
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self):
|
|
||||||
"""Return the icon of device based on its type."""
|
|
||||||
return "mdi:fan"
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
"""Return true if device is on."""
|
"""Return true if device is on."""
|
||||||
@ -83,11 +82,6 @@ class WiLightFan(WiLightDevice, FanEntity):
|
|||||||
return None
|
return None
|
||||||
return ordered_list_item_to_percentage(ORDERED_NAMED_FAN_SPEEDS, wl_speed)
|
return ordered_list_item_to_percentage(ORDERED_NAMED_FAN_SPEEDS, wl_speed)
|
||||||
|
|
||||||
@property
|
|
||||||
def speed_count(self) -> int:
|
|
||||||
"""Return the number of speeds the fan supports."""
|
|
||||||
return len(ORDERED_NAMED_FAN_SPEEDS)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_direction(self) -> str:
|
def current_direction(self) -> str:
|
||||||
"""Return the current direction of the fan."""
|
"""Return the current direction of the fan."""
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
"""Support for WiLight lights."""
|
"""Support for WiLight lights."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from pywilight.const import ITEM_LIGHT, LIGHT_COLOR, LIGHT_DIMMER, LIGHT_ON_OFF
|
from pywilight.const import ITEM_LIGHT, LIGHT_COLOR, LIGHT_DIMMER, LIGHT_ON_OFF
|
||||||
|
from pywilight.wilight_device import Device as PyWiLightDevice
|
||||||
|
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
@ -12,25 +17,23 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import DOMAIN, WiLightDevice
|
from . import DOMAIN, WiLightDevice
|
||||||
|
from .parent_device import WiLightParent
|
||||||
|
|
||||||
|
|
||||||
def entities_from_discovered_wilight(hass, api_device):
|
def entities_from_discovered_wilight(api_device: PyWiLightDevice) -> list[LightEntity]:
|
||||||
"""Parse configuration and add WiLight light entities."""
|
"""Parse configuration and add WiLight light entities."""
|
||||||
entities = []
|
entities: list[LightEntity] = []
|
||||||
for item in api_device.items:
|
for item in api_device.items:
|
||||||
if item["type"] != ITEM_LIGHT:
|
if item["type"] != ITEM_LIGHT:
|
||||||
continue
|
continue
|
||||||
index = item["index"]
|
index = item["index"]
|
||||||
item_name = item["name"]
|
item_name = item["name"]
|
||||||
if item["sub_type"] == LIGHT_ON_OFF:
|
if item["sub_type"] == LIGHT_ON_OFF:
|
||||||
entity = WiLightLightOnOff(api_device, index, item_name)
|
entities.append(WiLightLightOnOff(api_device, index, item_name))
|
||||||
elif item["sub_type"] == LIGHT_DIMMER:
|
elif item["sub_type"] == LIGHT_DIMMER:
|
||||||
entity = WiLightLightDimmer(api_device, index, item_name)
|
entities.append(WiLightLightDimmer(api_device, index, item_name))
|
||||||
elif item["sub_type"] == LIGHT_COLOR:
|
elif item["sub_type"] == LIGHT_COLOR:
|
||||||
entity = WiLightLightColor(api_device, index, item_name)
|
entities.append(WiLightLightColor(api_device, index, item_name))
|
||||||
else:
|
|
||||||
continue
|
|
||||||
entities.append(entity)
|
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
@ -39,10 +42,11 @@ async def async_setup_entry(
|
|||||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up WiLight lights from a config entry."""
|
"""Set up WiLight lights from a config entry."""
|
||||||
parent = hass.data[DOMAIN][entry.entry_id]
|
parent: WiLightParent = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
# Handle a discovered WiLight device.
|
# Handle a discovered WiLight device.
|
||||||
entities = entities_from_discovered_wilight(hass, parent.api)
|
assert parent.api
|
||||||
|
entities = entities_from_discovered_wilight(parent.api)
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
@ -53,15 +57,15 @@ class WiLightLightOnOff(WiLightDevice, LightEntity):
|
|||||||
_attr_supported_color_modes = {ColorMode.ONOFF}
|
_attr_supported_color_modes = {ColorMode.ONOFF}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if device is on."""
|
"""Return true if device is on."""
|
||||||
return self._status.get("on")
|
return self._status.get("on")
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
await self._client.turn_on(self._index)
|
await self._client.turn_on(self._index)
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device off."""
|
"""Turn the device off."""
|
||||||
await self._client.turn_off(self._index)
|
await self._client.turn_off(self._index)
|
||||||
|
|
||||||
@ -73,16 +77,16 @@ class WiLightLightDimmer(WiLightDevice, LightEntity):
|
|||||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self):
|
def brightness(self) -> int:
|
||||||
"""Return the brightness of this light between 0..255."""
|
"""Return the brightness of this light between 0..255."""
|
||||||
return int(self._status.get("brightness", 0))
|
return int(self._status.get("brightness", 0))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if device is on."""
|
"""Return true if device is on."""
|
||||||
return self._status.get("on")
|
return self._status.get("on")
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device on,set brightness if needed."""
|
"""Turn the device on,set brightness if needed."""
|
||||||
# Dimmer switches use a range of [0, 255] to control
|
# Dimmer switches use a range of [0, 255] to control
|
||||||
# brightness. Level 255 might mean to set it to previous value
|
# brightness. Level 255 might mean to set it to previous value
|
||||||
@ -92,27 +96,27 @@ class WiLightLightDimmer(WiLightDevice, LightEntity):
|
|||||||
else:
|
else:
|
||||||
await self._client.turn_on(self._index)
|
await self._client.turn_on(self._index)
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device off."""
|
"""Turn the device off."""
|
||||||
await self._client.turn_off(self._index)
|
await self._client.turn_off(self._index)
|
||||||
|
|
||||||
|
|
||||||
def wilight_to_hass_hue(value):
|
def wilight_to_hass_hue(value: int) -> float:
|
||||||
"""Convert wilight hue 1..255 to hass 0..360 scale."""
|
"""Convert wilight hue 1..255 to hass 0..360 scale."""
|
||||||
return min(360, round((value * 360) / 255, 3))
|
return min(360, round((value * 360) / 255, 3))
|
||||||
|
|
||||||
|
|
||||||
def hass_to_wilight_hue(value):
|
def hass_to_wilight_hue(value: float) -> int:
|
||||||
"""Convert hass hue 0..360 to wilight 1..255 scale."""
|
"""Convert hass hue 0..360 to wilight 1..255 scale."""
|
||||||
return min(255, round((value * 255) / 360))
|
return min(255, round((value * 255) / 360))
|
||||||
|
|
||||||
|
|
||||||
def wilight_to_hass_saturation(value):
|
def wilight_to_hass_saturation(value: int) -> float:
|
||||||
"""Convert wilight saturation 1..255 to hass 0..100 scale."""
|
"""Convert wilight saturation 1..255 to hass 0..100 scale."""
|
||||||
return min(100, round((value * 100) / 255, 3))
|
return min(100, round((value * 100) / 255, 3))
|
||||||
|
|
||||||
|
|
||||||
def hass_to_wilight_saturation(value):
|
def hass_to_wilight_saturation(value: float) -> int:
|
||||||
"""Convert hass saturation 0..100 to wilight 1..255 scale."""
|
"""Convert hass saturation 0..100 to wilight 1..255 scale."""
|
||||||
return min(255, round((value * 255) / 100))
|
return min(255, round((value * 255) / 100))
|
||||||
|
|
||||||
@ -124,24 +128,24 @@ class WiLightLightColor(WiLightDevice, LightEntity):
|
|||||||
_attr_supported_color_modes = {ColorMode.HS}
|
_attr_supported_color_modes = {ColorMode.HS}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self):
|
def brightness(self) -> int:
|
||||||
"""Return the brightness of this light between 0..255."""
|
"""Return the brightness of this light between 0..255."""
|
||||||
return int(self._status.get("brightness", 0))
|
return int(self._status.get("brightness", 0))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hs_color(self):
|
def hs_color(self) -> tuple[float, float]:
|
||||||
"""Return the hue and saturation color value [float, float]."""
|
"""Return the hue and saturation color value [float, float]."""
|
||||||
return [
|
return (
|
||||||
wilight_to_hass_hue(int(self._status.get("hue", 0))),
|
wilight_to_hass_hue(int(self._status.get("hue", 0))),
|
||||||
wilight_to_hass_saturation(int(self._status.get("saturation", 0))),
|
wilight_to_hass_saturation(int(self._status.get("saturation", 0))),
|
||||||
]
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if device is on."""
|
"""Return true if device is on."""
|
||||||
return self._status.get("on")
|
return self._status.get("on")
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device on,set brightness if needed."""
|
"""Turn the device on,set brightness if needed."""
|
||||||
# Brightness use a range of [0, 255] to control
|
# Brightness use a range of [0, 255] to control
|
||||||
# Hue use a range of [0, 360] to control
|
# Hue use a range of [0, 360] to control
|
||||||
@ -161,6 +165,6 @@ class WiLightLightColor(WiLightDevice, LightEntity):
|
|||||||
else:
|
else:
|
||||||
await self._client.turn_on(self._index)
|
await self._client.turn_on(self._index)
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device off."""
|
"""Turn the device off."""
|
||||||
await self._client.turn_off(self._index)
|
await self._client.turn_off(self._index)
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
"""The WiLight Device integration."""
|
"""The WiLight Device integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pywilight
|
import pywilight
|
||||||
|
from pywilight.wilight_device import Device as PyWiLightDevice
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_HOST, EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import CONF_HOST, EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -15,23 +19,23 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class WiLightParent:
|
class WiLightParent:
|
||||||
"""Manages a single WiLight Parent Device."""
|
"""Manages a single WiLight Parent Device."""
|
||||||
|
|
||||||
def __init__(self, hass, config_entry):
|
def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
|
||||||
"""Initialize the system."""
|
"""Initialize the system."""
|
||||||
self._host = config_entry.data[CONF_HOST]
|
self._host: str = config_entry.data[CONF_HOST]
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._api = None
|
self._api: PyWiLightDevice | None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def host(self):
|
def host(self) -> str:
|
||||||
"""Return the host of this parent."""
|
"""Return the host of this parent."""
|
||||||
return self._host
|
return self._host
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api(self):
|
def api(self) -> PyWiLightDevice | None:
|
||||||
"""Return the api of this parent."""
|
"""Return the api of this parent."""
|
||||||
return self._api
|
return self._api
|
||||||
|
|
||||||
async def async_setup(self):
|
async def async_setup(self) -> bool:
|
||||||
"""Set up a WiLight Parent Device based on host parameter."""
|
"""Set up a WiLight Parent Device based on host parameter."""
|
||||||
host = self._host
|
host = self._host
|
||||||
hass = self._hass
|
hass = self._hass
|
||||||
@ -42,7 +46,7 @@ class WiLightParent:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def disconnected():
|
def disconnected() -> None:
|
||||||
# Schedule reconnect after connection has been lost.
|
# Schedule reconnect after connection has been lost.
|
||||||
_LOGGER.warning("WiLight %s disconnected", api_device.device_id)
|
_LOGGER.warning("WiLight %s disconnected", api_device.device_id)
|
||||||
async_dispatcher_send(
|
async_dispatcher_send(
|
||||||
@ -50,14 +54,14 @@ class WiLightParent:
|
|||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def reconnected():
|
def reconnected() -> None:
|
||||||
# Schedule reconnect after connection has been lost.
|
# Schedule reconnect after connection has been lost.
|
||||||
_LOGGER.warning("WiLight %s reconnect", api_device.device_id)
|
_LOGGER.warning("WiLight %s reconnect", api_device.device_id)
|
||||||
async_dispatcher_send(
|
async_dispatcher_send(
|
||||||
hass, f"wilight_device_available_{api_device.device_id}", True
|
hass, f"wilight_device_available_{api_device.device_id}", True
|
||||||
)
|
)
|
||||||
|
|
||||||
async def connect(api_device):
|
async def connect(api_device: PyWiLightDevice) -> None:
|
||||||
# Set up connection and hook it into HA for reconnect/shutdown.
|
# Set up connection and hook it into HA for reconnect/shutdown.
|
||||||
_LOGGER.debug("Initiating connection to %s", api_device.device_id)
|
_LOGGER.debug("Initiating connection to %s", api_device.device_id)
|
||||||
|
|
||||||
@ -81,7 +85,7 @@ class WiLightParent:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def async_reset(self):
|
async def async_reset(self) -> None:
|
||||||
"""Reset api."""
|
"""Reset api."""
|
||||||
|
|
||||||
# If the initialization was not wrong.
|
# If the initialization was not wrong.
|
||||||
@ -89,15 +93,13 @@ class WiLightParent:
|
|||||||
self._api.client.stop()
|
self._api.client.stop()
|
||||||
|
|
||||||
|
|
||||||
def create_api_device(host):
|
def create_api_device(host: str) -> PyWiLightDevice:
|
||||||
"""Create an API Device."""
|
"""Create an API Device."""
|
||||||
try:
|
try:
|
||||||
device = pywilight.device_from_host(host)
|
return pywilight.device_from_host(host)
|
||||||
except (
|
except (
|
||||||
requests.exceptions.ConnectionError,
|
requests.exceptions.ConnectionError,
|
||||||
requests.exceptions.Timeout,
|
requests.exceptions.Timeout,
|
||||||
) as err:
|
) as err:
|
||||||
_LOGGER.error("Unable to access WiLight at %s (%s)", host, err)
|
_LOGGER.error("Unable to access WiLight at %s (%s)", host, err)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return device
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user