Add YoLink MultiOutlet support (#82622)

This commit is contained in:
Matrix 2022-11-29 21:10:38 +08:00 committed by GitHub
parent 412c12b992
commit f0b979556c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 14 deletions

View file

@ -16,6 +16,7 @@ ATTR_DEVICE_ID = "deviceId"
ATTR_DEVICE_DOOR_SENSOR = "DoorSensor"
ATTR_DEVICE_TH_SENSOR = "THSensor"
ATTR_DEVICE_MOTION_SENSOR = "MotionSensor"
ATTR_DEVICE_MULTI_OUTLET = "MultiOutlet"
ATTR_DEVICE_LEAK_SENSOR = "LeakSensor"
ATTR_DEVICE_VIBRATION_SENSOR = "VibrationSensor"
ATTR_DEVICE_OUTLET = "Outlet"

View file

@ -3,6 +3,7 @@ from __future__ import annotations
from abc import abstractmethod
from yolink.client_request import ClientRequest
from yolink.exception import YoLinkAuthFailError, YoLinkClientError
from homeassistant.config_entries import ConfigEntry
@ -70,3 +71,15 @@ class YoLinkEntity(CoordinatorEntity[YoLinkCoordinator]):
except YoLinkClientError as yl_client_err:
self.coordinator.last_update_success = False
raise HomeAssistantError(yl_client_err) from yl_client_err
async def call_device(self, request: ClientRequest) -> None:
"""Call device api."""
try:
# call_device will check result, fail by raise YoLinkClientError
await self.coordinator.device.call_device(request)
except YoLinkAuthFailError as yl_auth_err:
self.config_entry.async_start_reauth(self.hass)
raise HomeAssistantError(yl_auth_err) from yl_auth_err
except YoLinkClientError as yl_client_err:
self.coordinator.last_update_success = False
raise HomeAssistantError(yl_client_err) from yl_client_err

View file

@ -3,7 +3,7 @@
"name": "YoLink",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/yolink",
"requirements": ["yolink-api==0.1.0"],
"requirements": ["yolink-api==0.1.5"],
"dependencies": ["auth", "application_credentials"],
"codeowners": ["@matrixd2"],
"iot_class": "cloud_push"

View file

@ -6,6 +6,7 @@ from dataclasses import dataclass
from typing import Any
from yolink.device import YoLinkDevice
from yolink.outlet_request_builder import OutletRequestBuilder
from homeassistant.components.switch import (
SwitchDeviceClass,
@ -19,6 +20,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import (
ATTR_COORDINATORS,
ATTR_DEVICE_MANIPULATOR,
ATTR_DEVICE_MULTI_OUTLET,
ATTR_DEVICE_OUTLET,
ATTR_DEVICE_SWITCH,
DOMAIN,
@ -32,8 +34,7 @@ class YoLinkSwitchEntityDescription(SwitchEntityDescription):
"""YoLink SwitchEntityDescription."""
exists_fn: Callable[[YoLinkDevice], bool] = lambda _: True
value: Callable[[Any], bool | None] = lambda _: None
state_key: str = "state"
plug_index: int | None = None
DEVICE_TYPES: tuple[YoLinkSwitchEntityDescription, ...] = (
@ -41,26 +42,63 @@ DEVICE_TYPES: tuple[YoLinkSwitchEntityDescription, ...] = (
key="outlet_state",
device_class=SwitchDeviceClass.OUTLET,
name="State",
value=lambda value: value == "open" if value is not None else None,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_OUTLET,
),
YoLinkSwitchEntityDescription(
key="manipulator_state",
name="State",
icon="mdi:pipe",
value=lambda value: value == "open" if value is not None else None,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_MANIPULATOR,
),
YoLinkSwitchEntityDescription(
key="switch_state",
name="State",
device_class=SwitchDeviceClass.SWITCH,
value=lambda value: value == "open" if value is not None else None,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_SWITCH,
),
YoLinkSwitchEntityDescription(
key="multi_outlet_usb_ports",
name="UsbPorts",
device_class=SwitchDeviceClass.OUTLET,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_MULTI_OUTLET,
plug_index=0,
),
YoLinkSwitchEntityDescription(
key="multi_outlet_plug_1",
name="Plug1",
device_class=SwitchDeviceClass.OUTLET,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_MULTI_OUTLET,
plug_index=1,
),
YoLinkSwitchEntityDescription(
key="multi_outlet_plug_2",
name="Plug2",
device_class=SwitchDeviceClass.OUTLET,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_MULTI_OUTLET,
plug_index=2,
),
YoLinkSwitchEntityDescription(
key="multi_outlet_plug_3",
name="Plug3",
device_class=SwitchDeviceClass.OUTLET,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_MULTI_OUTLET,
plug_index=3,
),
YoLinkSwitchEntityDescription(
key="multi_outlet_plug_4",
name="Plug4",
device_class=SwitchDeviceClass.OUTLET,
exists_fn=lambda device: device.device_type == ATTR_DEVICE_MULTI_OUTLET,
plug_index=4,
),
)
DEVICE_TYPE = [ATTR_DEVICE_MANIPULATOR, ATTR_DEVICE_OUTLET, ATTR_DEVICE_SWITCH]
DEVICE_TYPE = [
ATTR_DEVICE_MANIPULATOR,
ATTR_DEVICE_MULTI_OUTLET,
ATTR_DEVICE_OUTLET,
ATTR_DEVICE_SWITCH,
]
async def async_setup_entry(
@ -108,18 +146,30 @@ class YoLinkSwitchEntity(YoLinkEntity, SwitchEntity):
f"{coordinator.device.device_name} ({self.entity_description.name})"
)
def _get_state(
self, state_value: str | list[str] | None, plug_index: int | None
) -> bool | None:
"""Parse state value."""
if isinstance(state_value, list) and plug_index is not None:
return state_value[plug_index] == "open"
return state_value == "open" if state_value is not None else None
@callback
def update_entity_state(self, state: dict[str, Any]) -> None:
def update_entity_state(self, state: dict[str, str | list[str]]) -> None:
"""Update HA Entity State."""
self._attr_is_on = self.entity_description.value(
state.get(self.entity_description.state_key)
self._attr_is_on = self._get_state(
state.get("state"), self.entity_description.plug_index
)
self.async_write_ha_state()
async def call_state_change(self, state: str) -> None:
"""Call setState api to change switch state."""
await self.call_device_api("setState", {"state": state})
self._attr_is_on = self.entity_description.value(state)
await self.call_device(
OutletRequestBuilder.set_state_request(
state, self.entity_description.plug_index
)
)
self._attr_is_on = self._get_state(state, self.entity_description.plug_index)
self.async_write_ha_state()
async def async_turn_on(self, **kwargs: Any) -> None:

View file

@ -2609,7 +2609,7 @@ yeelight==0.7.10
yeelightsunflower==0.0.10
# homeassistant.components.yolink
yolink-api==0.1.0
yolink-api==0.1.5
# homeassistant.components.youless
youless-api==0.16

View file

@ -1816,7 +1816,7 @@ yalexs==1.2.6
yeelight==0.7.10
# homeassistant.components.yolink
yolink-api==0.1.0
yolink-api==0.1.5
# homeassistant.components.youless
youless-api==0.16