Add YoLink Water Meter Support (#114148)
* Add YS-5006/5007/5008 Water Meter Support * Add YoLink Water Meter Support * Update .coveragerc * fix as suggestion
This commit is contained in:
parent
54a69a2687
commit
63b4fd09c1
6 changed files with 142 additions and 0 deletions
|
@ -1687,6 +1687,7 @@ omit =
|
|||
homeassistant/components/yolink/services.py
|
||||
homeassistant/components/yolink/siren.py
|
||||
homeassistant/components/yolink/switch.py
|
||||
homeassistant/components/yolink/valve.py
|
||||
homeassistant/components/youless/__init__.py
|
||||
homeassistant/components/youless/sensor.py
|
||||
homeassistant/components/zabbix/*
|
||||
|
|
|
@ -46,6 +46,7 @@ PLATFORMS = [
|
|||
Platform.SENSOR,
|
||||
Platform.SIREN,
|
||||
Platform.SWITCH,
|
||||
Platform.VALVE,
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -14,3 +14,5 @@ ATTR_REPEAT = "repeat"
|
|||
ATTR_TONE = "tone"
|
||||
YOLINK_EVENT = f"{DOMAIN}_event"
|
||||
YOLINK_OFFLINE_TIME = 32400
|
||||
|
||||
DEV_MODEL_WATER_METER_YS5007 = "YS5007"
|
||||
|
|
|
@ -24,6 +24,7 @@ from yolink.const import (
|
|||
ATTR_DEVICE_THERMOSTAT,
|
||||
ATTR_DEVICE_VIBRATION_SENSOR,
|
||||
ATTR_DEVICE_WATER_DEPTH_SENSOR,
|
||||
ATTR_DEVICE_WATER_METER_CONTROLLER,
|
||||
ATTR_GARAGE_DOOR_CONTROLLER,
|
||||
)
|
||||
from yolink.device import YoLinkDevice
|
||||
|
@ -41,6 +42,7 @@ from homeassistant.const import (
|
|||
EntityCategory,
|
||||
UnitOfLength,
|
||||
UnitOfTemperature,
|
||||
UnitOfVolume,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
@ -76,6 +78,7 @@ SENSOR_DEVICE_TYPE = [
|
|||
ATTR_DEVICE_THERMOSTAT,
|
||||
ATTR_DEVICE_VIBRATION_SENSOR,
|
||||
ATTR_DEVICE_WATER_DEPTH_SENSOR,
|
||||
ATTR_DEVICE_WATER_METER_CONTROLLER,
|
||||
ATTR_DEVICE_LOCK,
|
||||
ATTR_DEVICE_MANIPULATOR,
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
|
@ -96,6 +99,7 @@ BATTERY_POWER_SENSOR = [
|
|||
ATTR_DEVICE_MANIPULATOR,
|
||||
ATTR_DEVICE_CO_SMOKE_SENSOR,
|
||||
ATTR_DEVICE_WATER_DEPTH_SENSOR,
|
||||
ATTR_DEVICE_WATER_METER_CONTROLLER,
|
||||
]
|
||||
|
||||
MCU_DEV_TEMPERATURE_SENSOR = [
|
||||
|
@ -202,6 +206,17 @@ SENSOR_TYPES: tuple[YoLinkSensorEntityDescription, ...] = (
|
|||
native_unit_of_measurement=UnitOfLength.METERS,
|
||||
exists_fn=lambda device: device.device_type in ATTR_DEVICE_WATER_DEPTH_SENSOR,
|
||||
),
|
||||
YoLinkSensorEntityDescription(
|
||||
key="meter_reading",
|
||||
translation_key="water_meter_reading",
|
||||
device_class=SensorDeviceClass.WATER,
|
||||
icon="mdi:gauge",
|
||||
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
should_update_entity=lambda value: value is not None,
|
||||
exists_fn=lambda device: device.device_type
|
||||
in ATTR_DEVICE_WATER_METER_CONTROLLER,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -73,12 +73,20 @@
|
|||
"enabled": "[%key:common::state::enabled%]",
|
||||
"disabled": "[%key:common::state::disabled%]"
|
||||
}
|
||||
},
|
||||
"water_meter_reading": {
|
||||
"name": "Water meter reading"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"config_volume": {
|
||||
"name": "Volume"
|
||||
}
|
||||
},
|
||||
"valve": {
|
||||
"meter_valve_state": {
|
||||
"name": "Valve state"
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
|
|
115
homeassistant/components/yolink/valve.py
Normal file
115
homeassistant/components/yolink/valve.py
Normal file
|
@ -0,0 +1,115 @@
|
|||
"""YoLink Valve."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from yolink.client_request import ClientRequest
|
||||
from yolink.const import ATTR_DEVICE_WATER_METER_CONTROLLER
|
||||
from yolink.device import YoLinkDevice
|
||||
|
||||
from homeassistant.components.valve import (
|
||||
ValveDeviceClass,
|
||||
ValveEntity,
|
||||
ValveEntityDescription,
|
||||
ValveEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DEV_MODEL_WATER_METER_YS5007, DOMAIN
|
||||
from .coordinator import YoLinkCoordinator
|
||||
from .entity import YoLinkEntity
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class YoLinkValveEntityDescription(ValveEntityDescription):
|
||||
"""YoLink ValveEntityDescription."""
|
||||
|
||||
exists_fn: Callable[[YoLinkDevice], bool] = lambda _: True
|
||||
value: Callable = lambda state: state
|
||||
|
||||
|
||||
DEVICE_TYPES: tuple[YoLinkValveEntityDescription, ...] = (
|
||||
YoLinkValveEntityDescription(
|
||||
key="valve_state",
|
||||
translation_key="meter_valve_state",
|
||||
device_class=ValveDeviceClass.WATER,
|
||||
value=lambda value: value == "closed" if value is not None else None,
|
||||
exists_fn=lambda device: device.device_type
|
||||
== ATTR_DEVICE_WATER_METER_CONTROLLER
|
||||
and not device.device_model_name.startswith(DEV_MODEL_WATER_METER_YS5007),
|
||||
),
|
||||
)
|
||||
|
||||
DEVICE_TYPE = [ATTR_DEVICE_WATER_METER_CONTROLLER]
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up YoLink valve from a config entry."""
|
||||
device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
|
||||
valve_device_coordinators = [
|
||||
device_coordinator
|
||||
for device_coordinator in device_coordinators.values()
|
||||
if device_coordinator.device.device_type in DEVICE_TYPE
|
||||
]
|
||||
async_add_entities(
|
||||
YoLinkValveEntity(config_entry, valve_device_coordinator, description)
|
||||
for valve_device_coordinator in valve_device_coordinators
|
||||
for description in DEVICE_TYPES
|
||||
if description.exists_fn(valve_device_coordinator.device)
|
||||
)
|
||||
|
||||
|
||||
class YoLinkValveEntity(YoLinkEntity, ValveEntity):
|
||||
"""YoLink Valve Entity."""
|
||||
|
||||
entity_description: YoLinkValveEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config_entry: ConfigEntry,
|
||||
coordinator: YoLinkCoordinator,
|
||||
description: YoLinkValveEntityDescription,
|
||||
) -> None:
|
||||
"""Init YoLink valve."""
|
||||
super().__init__(config_entry, coordinator)
|
||||
self._attr_supported_features = (
|
||||
ValveEntityFeature.OPEN | ValveEntityFeature.CLOSE
|
||||
)
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = (
|
||||
f"{coordinator.device.device_id} {self.entity_description.key}"
|
||||
)
|
||||
|
||||
@callback
|
||||
def update_entity_state(self, state: dict[str, str | list[str]]) -> None:
|
||||
"""Update HA Entity State."""
|
||||
if (
|
||||
attr_val := self.entity_description.value(
|
||||
state.get(self.entity_description.key)
|
||||
)
|
||||
) is None:
|
||||
return
|
||||
self._attr_is_closed = attr_val
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def _async_invoke_device(self, state: str) -> None:
|
||||
"""Call setState api to change valve state."""
|
||||
await self.call_device(ClientRequest("setState", {"valve": state}))
|
||||
self._attr_is_closed = state == "close"
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_open_valve(self) -> None:
|
||||
"""Open the valve."""
|
||||
await self._async_invoke_device("open")
|
||||
|
||||
async def async_close_valve(self) -> None:
|
||||
"""Close valve."""
|
||||
await self._async_invoke_device("close")
|
Loading…
Add table
Reference in a new issue