mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Separate the yolink garage door device from the door sensor (#84561)
* Separate the garage door device from the door sensor * Bump yolink api to 0.2.1 * fix suggest * fix typos * Bump yolink-api to 0.2.6 * Bump version to 0.2.7 and fix rename effects * change aiohttp min version to 3.8.1
This commit is contained in:
parent
4dba9c09fc
commit
d6e817aa62
@ -2,14 +2,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
import async_timeout
|
||||
from yolink.client import YoLinkClient
|
||||
from yolink.device import YoLinkDevice
|
||||
from yolink.exception import YoLinkAuthFailError, YoLinkClientError
|
||||
from yolink.model import BRDP
|
||||
from yolink.mqtt_client import MqttClient
|
||||
from yolink.home_manager import YoLinkHome
|
||||
from yolink.message_listener import MessageListener
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform
|
||||
@ -18,7 +19,7 @@ from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
from homeassistant.helpers import aiohttp_client, config_entry_oauth2_flow
|
||||
|
||||
from . import api
|
||||
from .const import ATTR_CLIENT, ATTR_COORDINATORS, ATTR_DEVICE, ATTR_MQTT_CLIENT, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
|
||||
SCAN_INTERVAL = timedelta(minutes=5)
|
||||
@ -36,6 +37,35 @@ PLATFORMS = [
|
||||
]
|
||||
|
||||
|
||||
class YoLinkHomeMessageListener(MessageListener):
|
||||
"""YoLink home message listener."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
"""Init YoLink home message listener."""
|
||||
self._hass = hass
|
||||
self._entry = entry
|
||||
|
||||
def on_message(self, device: YoLinkDevice, msg_data: dict[str, Any]) -> None:
|
||||
"""On YoLink home message received."""
|
||||
entry_data = self._hass.data[DOMAIN].get(self._entry.entry_id)
|
||||
if not entry_data:
|
||||
return
|
||||
device_coordinators = entry_data.device_coordinators
|
||||
if not device_coordinators:
|
||||
return
|
||||
device_coordiantor = device_coordinators.get(device.device_id)
|
||||
if device_coordiantor is not None:
|
||||
device_coordiantor.async_set_updated_data(msg_data)
|
||||
|
||||
|
||||
@dataclass
|
||||
class YoLinkHomeStore:
|
||||
"""YoLink home store."""
|
||||
|
||||
home_instance: YoLinkHome
|
||||
device_coordinators: dict[str, YoLinkCoordinator]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up yolink from a config entry."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
@ -50,58 +80,19 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
auth_mgr = api.ConfigEntryAuth(
|
||||
hass, aiohttp_client.async_get_clientsession(hass), session
|
||||
)
|
||||
|
||||
yolink_http_client = YoLinkClient(auth_mgr)
|
||||
yolink_mqtt_client = MqttClient(auth_mgr)
|
||||
|
||||
def on_message_callback(message: tuple[str, BRDP]) -> None:
|
||||
data = message[1]
|
||||
device_id = message[0]
|
||||
if data.event is None:
|
||||
return
|
||||
event_param = data.event.split(".")
|
||||
event_type = event_param[len(event_param) - 1]
|
||||
if event_type not in (
|
||||
"Report",
|
||||
"Alert",
|
||||
"StatusChange",
|
||||
"getState",
|
||||
):
|
||||
return
|
||||
resolved_state = data.data
|
||||
if resolved_state is None:
|
||||
return
|
||||
entry_data = hass.data[DOMAIN].get(entry.entry_id)
|
||||
if entry_data is None:
|
||||
return
|
||||
device_coordinators = entry_data.get(ATTR_COORDINATORS)
|
||||
if device_coordinators is None:
|
||||
return
|
||||
device_coordinator = device_coordinators.get(device_id)
|
||||
if device_coordinator is None:
|
||||
return
|
||||
device_coordinator.async_set_updated_data(resolved_state)
|
||||
|
||||
yolink_home = YoLinkHome()
|
||||
try:
|
||||
async with async_timeout.timeout(10):
|
||||
device_response = await yolink_http_client.get_auth_devices()
|
||||
home_info = await yolink_http_client.get_general_info()
|
||||
await yolink_mqtt_client.init_home_connection(
|
||||
home_info.data["id"], on_message_callback
|
||||
await yolink_home.async_setup(
|
||||
auth_mgr, YoLinkHomeMessageListener(hass, entry)
|
||||
)
|
||||
except YoLinkAuthFailError as yl_auth_err:
|
||||
raise ConfigEntryAuthFailed from yl_auth_err
|
||||
except (YoLinkClientError, asyncio.TimeoutError) as err:
|
||||
raise ConfigEntryNotReady from err
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = {
|
||||
ATTR_CLIENT: yolink_http_client,
|
||||
ATTR_MQTT_CLIENT: yolink_mqtt_client,
|
||||
}
|
||||
auth_devices = device_response.data[ATTR_DEVICE]
|
||||
device_coordinators = {}
|
||||
for device_info in auth_devices:
|
||||
device = YoLinkDevice(device_info, yolink_http_client)
|
||||
for device in yolink_home.get_devices():
|
||||
device_coordinator = YoLinkCoordinator(hass, device)
|
||||
try:
|
||||
await device_coordinator.async_config_entry_first_refresh()
|
||||
@ -109,15 +100,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
# Not failure by fetching device state
|
||||
device_coordinator.data = {}
|
||||
device_coordinators[device.device_id] = device_coordinator
|
||||
hass.data[DOMAIN][entry.entry_id][ATTR_COORDINATORS] = device_coordinators
|
||||
hass.data[DOMAIN][entry.entry_id] = YoLinkHomeStore(
|
||||
yolink_home, device_coordinators
|
||||
)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
async def shutdown_subscription(event) -> None:
|
||||
"""Shutdown mqtt message subscription."""
|
||||
await yolink_mqtt_client.shutdown_home_subscription()
|
||||
async def async_yolink_unload(event) -> None:
|
||||
"""Unload yolink."""
|
||||
await yolink_home.async_unload()
|
||||
|
||||
entry.async_on_unload(
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, shutdown_subscription)
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_yolink_unload)
|
||||
)
|
||||
|
||||
return True
|
||||
@ -126,8 +119,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
|
||||
await hass.data[DOMAIN][entry.entry_id][
|
||||
ATTR_MQTT_CLIENT
|
||||
].shutdown_home_subscription()
|
||||
await hass.data[DOMAIN][entry.entry_id].home_instance.async_unload()
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
return unload_ok
|
||||
|
@ -5,6 +5,13 @@ from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from yolink.const import (
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_MOTION_SENSOR,
|
||||
ATTR_DEVICE_VIBRATION_SENSOR,
|
||||
)
|
||||
from yolink.device import YoLinkDevice
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
@ -16,15 +23,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import (
|
||||
ATTR_COORDINATORS,
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_MOTION_SENSOR,
|
||||
ATTR_DEVICE_VIBRATION_SENSOR,
|
||||
DOMAIN,
|
||||
)
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -47,13 +46,6 @@ SENSOR_DEVICE_TYPE = [
|
||||
]
|
||||
|
||||
|
||||
def is_door_sensor(device: YoLinkDevice) -> bool:
|
||||
"""Check Door Sensor type."""
|
||||
return device.device_type == ATTR_DEVICE_DOOR_SENSOR and (
|
||||
device.parent_id is None or device.parent_id == "null"
|
||||
)
|
||||
|
||||
|
||||
SENSOR_TYPES: tuple[YoLinkBinarySensorEntityDescription, ...] = (
|
||||
YoLinkBinarySensorEntityDescription(
|
||||
key="door_state",
|
||||
@ -61,7 +53,7 @@ SENSOR_TYPES: tuple[YoLinkBinarySensorEntityDescription, ...] = (
|
||||
device_class=BinarySensorDeviceClass.DOOR,
|
||||
name="State",
|
||||
value=lambda value: value == "open" if value is not None else None,
|
||||
exists_fn=is_door_sensor,
|
||||
exists_fn=lambda device: device.device_type == ATTR_DEVICE_DOOR_SENSOR,
|
||||
),
|
||||
YoLinkBinarySensorEntityDescription(
|
||||
key="motion_state",
|
||||
@ -108,7 +100,7 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink Sensor from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
binary_sensor_device_coordinators = [
|
||||
device_coordinator
|
||||
for device_coordinator in device_coordinators.values()
|
||||
|
@ -3,6 +3,9 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from yolink.const import ATTR_DEVICE_THERMOSTAT
|
||||
from yolink.thermostat_request_builder import ThermostatRequestBuilder, ThermostatState
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ATTR_TARGET_TEMP_HIGH,
|
||||
ATTR_TARGET_TEMP_LOW,
|
||||
@ -20,7 +23,7 @@ from homeassistant.const import UnitOfTemperature
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import ATTR_COORDINATORS, ATTR_DEVICE_THERMOSTAT, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -46,7 +49,7 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink Thermostat from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
entities = [
|
||||
YoLinkClimateEntity(config_entry, device_coordinator)
|
||||
for device_coordinator in device_coordinators.values()
|
||||
@ -107,12 +110,18 @@ class YoLinkClimateEntity(YoLinkEntity, ClimateEntity):
|
||||
"""Set new target hvac mode."""
|
||||
if (hvac_mode_id := HA_MODEL_2_YOLINK.get(hvac_mode)) is None:
|
||||
raise ValueError(f"Received an invalid hvac mode: {hvac_mode}")
|
||||
await self.call_device_api("setState", {"mode": hvac_mode_id})
|
||||
await self.call_device(
|
||||
ThermostatRequestBuilder.set_state_request(
|
||||
ThermostatState(mode=hvac_mode_id)
|
||||
)
|
||||
)
|
||||
await self.coordinator.async_refresh()
|
||||
|
||||
async def async_set_fan_mode(self, fan_mode: str) -> None:
|
||||
"""Set fan mode."""
|
||||
await self.call_device_api("setState", {"fan": fan_mode})
|
||||
await self.call_device(
|
||||
ThermostatRequestBuilder.set_state_request(ThermostatState(fan=fan_mode))
|
||||
)
|
||||
self._attr_fan_mode = fan_mode
|
||||
self.async_write_ha_state()
|
||||
|
||||
@ -121,16 +130,24 @@ class YoLinkClimateEntity(YoLinkEntity, ClimateEntity):
|
||||
target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
|
||||
target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
|
||||
if target_temp_low is not None:
|
||||
await self.call_device_api("setState", {"lowTemp": target_temp_low})
|
||||
await self.call_device(
|
||||
ThermostatRequestBuilder.set_state_request(
|
||||
ThermostatState(lowTemp=target_temp_low)
|
||||
)
|
||||
)
|
||||
self._attr_target_temperature_low = target_temp_low
|
||||
if target_temp_high is not None:
|
||||
await self.call_device_api("setState", {"highTemp": target_temp_high})
|
||||
await self.call_device(
|
||||
ThermostatRequestBuilder.set_state_request(
|
||||
ThermostatState(highTemp=target_temp_high)
|
||||
)
|
||||
)
|
||||
self._attr_target_temperature_high = target_temp_high
|
||||
await self.coordinator.async_refresh()
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Set preset mode."""
|
||||
eco_params = "on" if preset_mode == PRESET_ECO else "off"
|
||||
await self.call_device_api("setECO", {"mode": eco_params})
|
||||
await self.call_device(ThermostatRequestBuilder.set_eco_request(eco_params))
|
||||
self._attr_preset_mode = PRESET_ECO if eco_params == "on" else PRESET_NONE
|
||||
self.async_write_ha_state()
|
||||
|
@ -2,28 +2,8 @@
|
||||
|
||||
DOMAIN = "yolink"
|
||||
MANUFACTURER = "YoLink"
|
||||
HOME_ID = "homeId"
|
||||
HOME_SUBSCRIPTION = "home_subscription"
|
||||
ATTR_PLATFORM_SENSOR = "sensor"
|
||||
ATTR_COORDINATORS = "coordinators"
|
||||
ATTR_DEVICE = "devices"
|
||||
ATTR_DEVICE_TYPE = "type"
|
||||
ATTR_DEVICE_NAME = "name"
|
||||
ATTR_DEVICE_STATE = "state"
|
||||
ATTR_CLIENT = "client"
|
||||
ATTR_MQTT_CLIENT = "mqtt_client"
|
||||
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"
|
||||
ATTR_DEVICE_SIREN = "Siren"
|
||||
ATTR_DEVICE_LOCK = "Lock"
|
||||
ATTR_DEVICE_MANIPULATOR = "Manipulator"
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR = "COSmokeSensor"
|
||||
ATTR_DEVICE_SWITCH = "Switch"
|
||||
ATTR_DEVICE_THERMOSTAT = "Thermostat"
|
||||
ATTR_DEVICE_DIMMER = "Dimmer"
|
||||
|
@ -35,7 +35,7 @@ class YoLinkCoordinator(DataUpdateCoordinator[dict]):
|
||||
"""Fetch device state."""
|
||||
try:
|
||||
async with async_timeout.timeout(10):
|
||||
device_state_resp = await self.device.fetch_state_with_api()
|
||||
device_state_resp = await self.device.fetch_state()
|
||||
except YoLinkAuthFailError as yl_auth_err:
|
||||
raise ConfigEntryAuthFailed from yl_auth_err
|
||||
except YoLinkClientError as yl_client_err:
|
||||
|
@ -3,6 +3,9 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from yolink.client_request import ClientRequest
|
||||
from yolink.const import ATTR_GARAGE_DOOR_CONTROLLER
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
CoverDeviceClass,
|
||||
CoverEntity,
|
||||
@ -12,7 +15,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import ATTR_COORDINATORS, ATTR_DEVICE_DOOR_SENSOR, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -23,13 +26,11 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink garage door from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
entities = [
|
||||
YoLinkCoverEntity(config_entry, device_coordinator)
|
||||
for device_coordinator in device_coordinators.values()
|
||||
if device_coordinator.device.device_type == ATTR_DEVICE_DOOR_SENSOR
|
||||
and device_coordinator.device.parent_id is not None
|
||||
and device_coordinator.device.parent_id != "null"
|
||||
if device_coordinator.device.device_type == ATTR_GARAGE_DOOR_CONTROLLER
|
||||
]
|
||||
async_add_entities(entities)
|
||||
|
||||
@ -54,33 +55,21 @@ class YoLinkCoverEntity(YoLinkEntity, CoverEntity):
|
||||
@callback
|
||||
def update_entity_state(self, state: dict[str, Any]) -> None:
|
||||
"""Update HA Entity State."""
|
||||
self._attr_is_closed = state.get("state") == "closed"
|
||||
if (state_val := state.get("state")) is None:
|
||||
return
|
||||
self._attr_is_closed = state_val == "closed"
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def toggle_garage_state(self, state: str) -> None:
|
||||
async def toggle_garage_state(self) -> None:
|
||||
"""Toggle Garage door state."""
|
||||
# make sure current state is correct
|
||||
await self.coordinator.async_refresh()
|
||||
if state == "open" and self.is_closed is False:
|
||||
return
|
||||
if state == "close" and self.is_closed is True:
|
||||
return
|
||||
# get paired controller
|
||||
door_controller_coordinator = self.hass.data[DOMAIN][
|
||||
self.config_entry.entry_id
|
||||
][ATTR_COORDINATORS].get(self.coordinator.device.parent_id)
|
||||
if door_controller_coordinator is None:
|
||||
raise ValueError(
|
||||
"This device has not been paired with a garage door controller"
|
||||
)
|
||||
# call controller api open/close garage door
|
||||
await door_controller_coordinator.device.call_device_http_api("toggle", None)
|
||||
await self.coordinator.async_refresh()
|
||||
# garage door state will not be changed by device call
|
||||
# it depends on paired device state, such as door sensor or contact sensor
|
||||
await self.call_device(ClientRequest("toggle", {}))
|
||||
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Open garage door."""
|
||||
await self.toggle_garage_state("open")
|
||||
"""Toggle garage door."""
|
||||
await self.toggle_garage_state()
|
||||
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Close garage door."""
|
||||
await self.toggle_garage_state("close")
|
||||
"""Toggle garage door."""
|
||||
await self.toggle_garage_state()
|
||||
|
@ -60,18 +60,6 @@ class YoLinkEntity(CoordinatorEntity[YoLinkCoordinator]):
|
||||
def update_entity_state(self, state: dict) -> None:
|
||||
"""Parse and update entity state, should be overridden."""
|
||||
|
||||
async def call_device_api(self, command: str, params: dict) -> None:
|
||||
"""Call device Api."""
|
||||
try:
|
||||
# call_device_http_api will check result, fail by raise YoLinkClientError
|
||||
await self.coordinator.device.call_device_http_api(command, params)
|
||||
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
|
||||
|
||||
async def call_device(self, request: ClientRequest) -> None:
|
||||
"""Call device api."""
|
||||
try:
|
||||
@ -81,5 +69,4 @@ class YoLinkEntity(CoordinatorEntity[YoLinkCoordinator]):
|
||||
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,12 +3,15 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from yolink.client_request import ClientRequest
|
||||
from yolink.const import ATTR_DEVICE_DIMMER
|
||||
|
||||
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import ATTR_COORDINATORS, ATTR_DEVICE_DIMMER, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -19,7 +22,7 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink Dimmer from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
entities = [
|
||||
YoLinkDimmerEntity(config_entry, device_coordinator)
|
||||
for device_coordinator in device_coordinators.values()
|
||||
@ -61,7 +64,7 @@ class YoLinkDimmerEntity(YoLinkEntity, LightEntity):
|
||||
if brightness is not None:
|
||||
self._attr_brightness = brightness
|
||||
params["brightness"] = round(brightness / 255, 2) * 100
|
||||
await self.call_device_api("setState", params)
|
||||
await self.call_device(ClientRequest("setState", params))
|
||||
self._attr_is_on = state == "open"
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -3,12 +3,15 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from yolink.client_request import ClientRequest
|
||||
from yolink.const import ATTR_DEVICE_LOCK
|
||||
|
||||
from homeassistant.components.lock import LockEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import ATTR_COORDINATORS, ATTR_DEVICE_LOCK, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -19,7 +22,7 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink lock from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
entities = [
|
||||
YoLinkLockEntity(config_entry, device_coordinator)
|
||||
for device_coordinator in device_coordinators.values()
|
||||
@ -52,7 +55,7 @@ class YoLinkLockEntity(YoLinkEntity, LockEntity):
|
||||
|
||||
async def call_lock_state_change(self, state: str) -> None:
|
||||
"""Call setState api to change lock state."""
|
||||
await self.call_device_api("setState", {"state": state})
|
||||
await self.call_device(ClientRequest("setState", {"state": state}))
|
||||
self._attr_is_locked = state == "lock"
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "YoLink",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/yolink",
|
||||
"requirements": ["yolink-api==0.1.5"],
|
||||
"requirements": ["yolink-api==0.2.8"],
|
||||
"dependencies": ["auth", "application_credentials"],
|
||||
"codeowners": ["@matrixd2"],
|
||||
"iot_class": "cloud_push"
|
||||
|
@ -4,6 +4,23 @@ from __future__ import annotations
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from yolink.const import (
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
ATTR_DEVICE_DIMMER,
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_LOCK,
|
||||
ATTR_DEVICE_MANIPULATOR,
|
||||
ATTR_DEVICE_MOTION_SENSOR,
|
||||
ATTR_DEVICE_MULTI_OUTLET,
|
||||
ATTR_DEVICE_OUTLET,
|
||||
ATTR_DEVICE_SIREN,
|
||||
ATTR_DEVICE_SWITCH,
|
||||
ATTR_DEVICE_TH_SENSOR,
|
||||
ATTR_DEVICE_THERMOSTAT,
|
||||
ATTR_DEVICE_VIBRATION_SENSOR,
|
||||
ATTR_GARAGE_DOOR_CONTROLLER,
|
||||
)
|
||||
from yolink.device import YoLinkDevice
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
@ -23,18 +40,7 @@ from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import percentage
|
||||
|
||||
from .const import (
|
||||
ATTR_COORDINATORS,
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_LOCK,
|
||||
ATTR_DEVICE_MANIPULATOR,
|
||||
ATTR_DEVICE_MOTION_SENSOR,
|
||||
ATTR_DEVICE_TH_SENSOR,
|
||||
ATTR_DEVICE_VIBRATION_SENSOR,
|
||||
DOMAIN,
|
||||
)
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -57,14 +63,21 @@ class YoLinkSensorEntityDescription(
|
||||
|
||||
|
||||
SENSOR_DEVICE_TYPE = [
|
||||
ATTR_DEVICE_DIMMER,
|
||||
ATTR_DEVICE_DOOR_SENSOR,
|
||||
ATTR_DEVICE_LEAK_SENSOR,
|
||||
ATTR_DEVICE_MOTION_SENSOR,
|
||||
ATTR_DEVICE_MULTI_OUTLET,
|
||||
ATTR_DEVICE_OUTLET,
|
||||
ATTR_DEVICE_SIREN,
|
||||
ATTR_DEVICE_SWITCH,
|
||||
ATTR_DEVICE_TH_SENSOR,
|
||||
ATTR_DEVICE_THERMOSTAT,
|
||||
ATTR_DEVICE_VIBRATION_SENSOR,
|
||||
ATTR_DEVICE_LOCK,
|
||||
ATTR_DEVICE_MANIPULATOR,
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
ATTR_GARAGE_DOOR_CONTROLLER,
|
||||
]
|
||||
|
||||
BATTERY_POWER_SENSOR = [
|
||||
@ -150,7 +163,7 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink Sensor from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
sensor_device_coordinators = [
|
||||
device_coordinator
|
||||
for device_coordinator in device_coordinators.values()
|
||||
|
@ -5,6 +5,8 @@ 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_SIREN
|
||||
from yolink.device import YoLinkDevice
|
||||
|
||||
from homeassistant.components.siren import (
|
||||
@ -16,7 +18,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import ATTR_COORDINATORS, ATTR_DEVICE_SIREN, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -47,7 +49,7 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink siren from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
siren_device_coordinators = [
|
||||
device_coordinator
|
||||
for device_coordinator in device_coordinators.values()
|
||||
@ -99,7 +101,7 @@ class YoLinkSirenEntity(YoLinkEntity, SirenEntity):
|
||||
|
||||
async def call_state_change(self, state: bool) -> None:
|
||||
"""Call setState api to change siren state."""
|
||||
await self.call_device_api("setState", {"state": {"alarm": state}})
|
||||
await self.call_device(ClientRequest("setState", {"state": {"alarm": state}}))
|
||||
self._attr_is_on = self.entity_description.value("alert" if state else "normal")
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -5,6 +5,12 @@ from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from yolink.const import (
|
||||
ATTR_DEVICE_MANIPULATOR,
|
||||
ATTR_DEVICE_MULTI_OUTLET,
|
||||
ATTR_DEVICE_OUTLET,
|
||||
ATTR_DEVICE_SWITCH,
|
||||
)
|
||||
from yolink.device import YoLinkDevice
|
||||
from yolink.outlet_request_builder import OutletRequestBuilder
|
||||
|
||||
@ -17,14 +23,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
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,
|
||||
)
|
||||
from .const import DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
@ -107,7 +106,7 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink switch from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id][ATTR_COORDINATORS]
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
switch_device_coordinators = [
|
||||
device_coordinator
|
||||
for device_coordinator in device_coordinators.values()
|
||||
|
@ -2672,7 +2672,7 @@ yeelight==0.7.10
|
||||
yeelightsunflower==0.0.10
|
||||
|
||||
# homeassistant.components.yolink
|
||||
yolink-api==0.1.5
|
||||
yolink-api==0.2.8
|
||||
|
||||
# homeassistant.components.youless
|
||||
youless-api==0.16
|
||||
|
@ -1891,7 +1891,7 @@ yalexs_ble==1.12.8
|
||||
yeelight==0.7.10
|
||||
|
||||
# homeassistant.components.yolink
|
||||
yolink-api==0.1.5
|
||||
yolink-api==0.2.8
|
||||
|
||||
# homeassistant.components.youless
|
||||
youless-api==0.16
|
||||
|
Loading…
x
Reference in New Issue
Block a user