Add yolink finger support (#96944)
This commit is contained in:
parent
945fffebcc
commit
3bbbd8642f
8 changed files with 61 additions and 14 deletions
|
@ -121,8 +121,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
raise ConfigEntryNotReady from err
|
||||
|
||||
device_coordinators = {}
|
||||
|
||||
# revese mapping
|
||||
device_pairing_mapping = {}
|
||||
for device in yolink_home.get_devices():
|
||||
device_coordinator = YoLinkCoordinator(hass, device)
|
||||
if (parent_id := device.get_paired_device_id()) is not None:
|
||||
device_pairing_mapping[parent_id] = device.device_id
|
||||
|
||||
for device in yolink_home.get_devices():
|
||||
paried_device: YoLinkDevice | None = None
|
||||
if (
|
||||
paried_device_id := device_pairing_mapping.get(device.device_id)
|
||||
) is not None:
|
||||
paried_device = yolink_home.get_device(paried_device_id)
|
||||
device_coordinator = YoLinkCoordinator(hass, device, paried_device)
|
||||
try:
|
||||
await device_coordinator.async_config_entry_first_refresh()
|
||||
except ConfigEntryNotReady:
|
||||
|
|
|
@ -20,7 +20,12 @@ _LOGGER = logging.getLogger(__name__)
|
|||
class YoLinkCoordinator(DataUpdateCoordinator[dict]):
|
||||
"""YoLink DataUpdateCoordinator."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, device: YoLinkDevice) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
device: YoLinkDevice,
|
||||
paired_device: YoLinkDevice | None = None,
|
||||
) -> None:
|
||||
"""Init YoLink DataUpdateCoordinator.
|
||||
|
||||
fetch state every 30 minutes base on yolink device heartbeat interval
|
||||
|
@ -31,16 +36,30 @@ class YoLinkCoordinator(DataUpdateCoordinator[dict]):
|
|||
hass, _LOGGER, name=DOMAIN, update_interval=timedelta(minutes=30)
|
||||
)
|
||||
self.device = device
|
||||
self.paired_device = paired_device
|
||||
|
||||
async def _async_update_data(self) -> dict:
|
||||
"""Fetch device state."""
|
||||
try:
|
||||
async with async_timeout.timeout(10):
|
||||
device_state_resp = await self.device.fetch_state()
|
||||
device_state = device_state_resp.data.get(ATTR_DEVICE_STATE)
|
||||
if self.paired_device is not None and device_state is not None:
|
||||
paried_device_state_resp = await self.paired_device.fetch_state()
|
||||
paried_device_state = paried_device_state_resp.data.get(
|
||||
ATTR_DEVICE_STATE
|
||||
)
|
||||
if (
|
||||
paried_device_state is not None
|
||||
and ATTR_DEVICE_STATE in paried_device_state
|
||||
):
|
||||
device_state[ATTR_DEVICE_STATE] = paried_device_state[
|
||||
ATTR_DEVICE_STATE
|
||||
]
|
||||
except YoLinkAuthFailError as yl_auth_err:
|
||||
raise ConfigEntryAuthFailed from yl_auth_err
|
||||
except YoLinkClientError as yl_client_err:
|
||||
raise UpdateFailed from yl_client_err
|
||||
if ATTR_DEVICE_STATE in device_state_resp.data:
|
||||
return device_state_resp.data[ATTR_DEVICE_STATE]
|
||||
if device_state is not None:
|
||||
return device_state
|
||||
return {}
|
||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||
from typing import Any
|
||||
|
||||
from yolink.client_request import ClientRequest
|
||||
from yolink.const import ATTR_GARAGE_DOOR_CONTROLLER
|
||||
from yolink.const import ATTR_DEVICE_FINGER, ATTR_GARAGE_DOOR_CONTROLLER
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
CoverDeviceClass,
|
||||
|
@ -30,7 +30,8 @@ async def async_setup_entry(
|
|||
entities = [
|
||||
YoLinkCoverEntity(config_entry, device_coordinator)
|
||||
for device_coordinator in device_coordinators.values()
|
||||
if device_coordinator.device.device_type == ATTR_GARAGE_DOOR_CONTROLLER
|
||||
if device_coordinator.device.device_type
|
||||
in [ATTR_GARAGE_DOOR_CONTROLLER, ATTR_DEVICE_FINGER]
|
||||
]
|
||||
async_add_entities(entities)
|
||||
|
||||
|
@ -58,8 +59,12 @@ class YoLinkCoverEntity(YoLinkEntity, CoverEntity):
|
|||
"""Update HA Entity State."""
|
||||
if (state_val := state.get("state")) is None:
|
||||
return
|
||||
self._attr_is_closed = state_val == "closed"
|
||||
self.async_write_ha_state()
|
||||
if self.coordinator.paired_device is None:
|
||||
self._attr_is_closed = None
|
||||
self.async_write_ha_state()
|
||||
elif state_val in ["open", "closed"]:
|
||||
self._attr_is_closed = state_val == "closed"
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def toggle_garage_state(self) -> None:
|
||||
"""Toggle Garage door state."""
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
"dependencies": ["auth", "application_credentials"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/yolink",
|
||||
"iot_class": "cloud_push",
|
||||
"requirements": ["yolink-api==0.2.9"]
|
||||
"requirements": ["yolink-api==0.3.0"]
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ from yolink.const import (
|
|||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
ATTR_DEVICE_DIMMER,
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_FINGER,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_LOCK,
|
||||
ATTR_DEVICE_MANIPULATOR,
|
||||
|
@ -67,6 +68,7 @@ class YoLinkSensorEntityDescription(
|
|||
SENSOR_DEVICE_TYPE = [
|
||||
ATTR_DEVICE_DIMMER,
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_FINGER,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_MOTION_SENSOR,
|
||||
ATTR_DEVICE_MULTI_OUTLET,
|
||||
|
@ -86,6 +88,7 @@ SENSOR_DEVICE_TYPE = [
|
|||
|
||||
BATTERY_POWER_SENSOR = [
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_FINGER,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_MOTION_SENSOR,
|
||||
ATTR_DEVICE_POWER_FAILURE_ALARM,
|
||||
|
@ -129,6 +132,7 @@ SENSOR_TYPES: tuple[YoLinkSensorEntityDescription, ...] = (
|
|||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=cvt_battery,
|
||||
exists_fn=lambda device: device.device_type in BATTERY_POWER_SENSOR,
|
||||
should_update_entity=lambda value: value is not None,
|
||||
),
|
||||
YoLinkSensorEntityDescription(
|
||||
key="humidity",
|
||||
|
|
|
@ -5,6 +5,7 @@ from collections.abc import Callable
|
|||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from yolink.client_request import ClientRequest
|
||||
from yolink.const import (
|
||||
ATTR_DEVICE_MANIPULATOR,
|
||||
ATTR_DEVICE_MULTI_OUTLET,
|
||||
|
@ -160,11 +161,17 @@ class YoLinkSwitchEntity(YoLinkEntity, SwitchEntity):
|
|||
|
||||
async def call_state_change(self, state: str) -> None:
|
||||
"""Call setState api to change switch state."""
|
||||
await self.call_device(
|
||||
OutletRequestBuilder.set_state_request(
|
||||
client_request: ClientRequest = None
|
||||
if self.coordinator.device.device_type in [
|
||||
ATTR_DEVICE_OUTLET,
|
||||
ATTR_DEVICE_MULTI_OUTLET,
|
||||
]:
|
||||
client_request = OutletRequestBuilder.set_state_request(
|
||||
state, self.entity_description.plug_index
|
||||
)
|
||||
)
|
||||
else:
|
||||
client_request = ClientRequest("setState", {"state": state})
|
||||
await self.call_device(client_request)
|
||||
self._attr_is_on = self._get_state(state, self.entity_description.plug_index)
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
|
|
@ -2723,7 +2723,7 @@ yeelight==0.7.12
|
|||
yeelightsunflower==0.0.10
|
||||
|
||||
# homeassistant.components.yolink
|
||||
yolink-api==0.2.9
|
||||
yolink-api==0.3.0
|
||||
|
||||
# homeassistant.components.youless
|
||||
youless-api==1.0.1
|
||||
|
|
|
@ -1999,7 +1999,7 @@ yalexs==1.5.1
|
|||
yeelight==0.7.12
|
||||
|
||||
# homeassistant.components.yolink
|
||||
yolink-api==0.2.9
|
||||
yolink-api==0.3.0
|
||||
|
||||
# homeassistant.components.youless
|
||||
youless-api==1.0.1
|
||||
|
|
Loading…
Add table
Reference in a new issue