Add YoLink MultiOutlet support (#82622)
This commit is contained in:
parent
412c12b992
commit
f0b979556c
6 changed files with 78 additions and 14 deletions
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue