Add yolink finger support (#96944)

This commit is contained in:
Matrix 2023-07-25 14:30:16 +08:00 committed by GitHub
parent 945fffebcc
commit 3bbbd8642f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 61 additions and 14 deletions

View file

@ -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:

View file

@ -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 {}

View file

@ -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."""

View file

@ -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"]
}

View file

@ -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",

View file

@ -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()

View file

@ -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

View file

@ -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