mirror of https://github.com/home-assistant/core
208 lines
7.1 KiB
Python
208 lines
7.1 KiB
Python
"""Support for Hydrawise sprinkler sensors."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from dataclasses import dataclass
|
|
from datetime import timedelta
|
|
from typing import Any
|
|
|
|
from pydrawise.schema import ControllerWaterUseSummary
|
|
|
|
from homeassistant.components.sensor import (
|
|
SensorDeviceClass,
|
|
SensorEntity,
|
|
SensorEntityDescription,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import UnitOfTime, UnitOfVolume
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
from .const import DOMAIN
|
|
from .coordinator import HydrawiseUpdateCoordinators
|
|
from .entity import HydrawiseEntity
|
|
|
|
|
|
@dataclass(frozen=True, kw_only=True)
|
|
class HydrawiseSensorEntityDescription(SensorEntityDescription):
|
|
"""Describes Hydrawise binary sensor."""
|
|
|
|
value_fn: Callable[[HydrawiseSensor], Any]
|
|
|
|
|
|
def _get_water_use(sensor: HydrawiseSensor) -> ControllerWaterUseSummary:
|
|
return sensor.coordinator.data.daily_water_summary[sensor.controller.id]
|
|
|
|
|
|
WATER_USE_CONTROLLER_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
|
|
HydrawiseSensorEntityDescription(
|
|
key="daily_active_water_time",
|
|
translation_key="daily_active_water_time",
|
|
device_class=SensorDeviceClass.DURATION,
|
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
|
value_fn=lambda sensor: _get_water_use(
|
|
sensor
|
|
).total_active_time.total_seconds(),
|
|
),
|
|
)
|
|
|
|
|
|
WATER_USE_ZONE_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
|
|
HydrawiseSensorEntityDescription(
|
|
key="daily_active_water_time",
|
|
translation_key="daily_active_water_time",
|
|
device_class=SensorDeviceClass.DURATION,
|
|
native_unit_of_measurement=UnitOfTime.SECONDS,
|
|
value_fn=lambda sensor: (
|
|
_get_water_use(sensor)
|
|
.active_time_by_zone_id.get(sensor.zone.id, timedelta())
|
|
.total_seconds()
|
|
),
|
|
),
|
|
)
|
|
|
|
FLOW_CONTROLLER_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
|
|
HydrawiseSensorEntityDescription(
|
|
key="daily_total_water_use",
|
|
translation_key="daily_total_water_use",
|
|
device_class=SensorDeviceClass.VOLUME,
|
|
suggested_display_precision=1,
|
|
value_fn=lambda sensor: _get_water_use(sensor).total_use,
|
|
),
|
|
HydrawiseSensorEntityDescription(
|
|
key="daily_active_water_use",
|
|
translation_key="daily_active_water_use",
|
|
device_class=SensorDeviceClass.VOLUME,
|
|
suggested_display_precision=1,
|
|
value_fn=lambda sensor: _get_water_use(sensor).total_active_use,
|
|
),
|
|
HydrawiseSensorEntityDescription(
|
|
key="daily_inactive_water_use",
|
|
translation_key="daily_inactive_water_use",
|
|
device_class=SensorDeviceClass.VOLUME,
|
|
suggested_display_precision=1,
|
|
value_fn=lambda sensor: _get_water_use(sensor).total_inactive_use,
|
|
),
|
|
)
|
|
|
|
FLOW_ZONE_SENSORS: tuple[SensorEntityDescription, ...] = (
|
|
HydrawiseSensorEntityDescription(
|
|
key="daily_active_water_use",
|
|
translation_key="daily_active_water_use",
|
|
device_class=SensorDeviceClass.VOLUME,
|
|
suggested_display_precision=1,
|
|
value_fn=lambda sensor: float(
|
|
_get_water_use(sensor).active_use_by_zone_id.get(sensor.zone.id, 0.0)
|
|
),
|
|
),
|
|
)
|
|
|
|
ZONE_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
|
|
HydrawiseSensorEntityDescription(
|
|
key="next_cycle",
|
|
translation_key="next_cycle",
|
|
device_class=SensorDeviceClass.TIMESTAMP,
|
|
value_fn=lambda sensor: (
|
|
dt_util.as_utc(sensor.zone.scheduled_runs.next_run.start_time)
|
|
if sensor.zone.scheduled_runs.next_run is not None
|
|
else None
|
|
),
|
|
),
|
|
HydrawiseSensorEntityDescription(
|
|
key="watering_time",
|
|
translation_key="watering_time",
|
|
native_unit_of_measurement=UnitOfTime.MINUTES,
|
|
value_fn=lambda sensor: (
|
|
int(
|
|
sensor.zone.scheduled_runs.current_run.remaining_time.total_seconds()
|
|
/ 60
|
|
)
|
|
if sensor.zone.scheduled_runs.current_run is not None
|
|
else 0
|
|
),
|
|
),
|
|
)
|
|
|
|
FLOW_MEASUREMENT_KEYS = [x.key for x in FLOW_CONTROLLER_SENSORS]
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
config_entry: ConfigEntry,
|
|
async_add_entities: AddEntitiesCallback,
|
|
) -> None:
|
|
"""Set up the Hydrawise sensor platform."""
|
|
coordinators: HydrawiseUpdateCoordinators = hass.data[DOMAIN][config_entry.entry_id]
|
|
entities: list[HydrawiseSensor] = []
|
|
for controller in coordinators.main.data.controllers.values():
|
|
entities.extend(
|
|
HydrawiseSensor(coordinators.water_use, description, controller)
|
|
for description in WATER_USE_CONTROLLER_SENSORS
|
|
)
|
|
entities.extend(
|
|
HydrawiseSensor(
|
|
coordinators.water_use, description, controller, zone_id=zone.id
|
|
)
|
|
for zone in controller.zones
|
|
for description in WATER_USE_ZONE_SENSORS
|
|
)
|
|
entities.extend(
|
|
HydrawiseSensor(coordinators.main, description, controller, zone_id=zone.id)
|
|
for zone in controller.zones
|
|
for description in ZONE_SENSORS
|
|
)
|
|
if (
|
|
coordinators.water_use.data.daily_water_summary[controller.id].total_use
|
|
is not None
|
|
):
|
|
# we have a flow sensor for this controller
|
|
entities.extend(
|
|
HydrawiseSensor(coordinators.water_use, description, controller)
|
|
for description in FLOW_CONTROLLER_SENSORS
|
|
)
|
|
entities.extend(
|
|
HydrawiseSensor(
|
|
coordinators.water_use,
|
|
description,
|
|
controller,
|
|
zone_id=zone.id,
|
|
)
|
|
for zone in controller.zones
|
|
for description in FLOW_ZONE_SENSORS
|
|
)
|
|
async_add_entities(entities)
|
|
|
|
|
|
class HydrawiseSensor(HydrawiseEntity, SensorEntity):
|
|
"""A sensor implementation for Hydrawise device."""
|
|
|
|
entity_description: HydrawiseSensorEntityDescription
|
|
|
|
@property
|
|
def native_unit_of_measurement(self) -> str | None:
|
|
"""Return the unit_of_measurement of the sensor."""
|
|
if self.entity_description.device_class != SensorDeviceClass.VOLUME:
|
|
return self.entity_description.native_unit_of_measurement
|
|
return (
|
|
UnitOfVolume.GALLONS
|
|
if self.coordinator.data.user.units.units_name == "imperial"
|
|
else UnitOfVolume.LITERS
|
|
)
|
|
|
|
@property
|
|
def icon(self) -> str | None:
|
|
"""Icon of the entity based on the value."""
|
|
if (
|
|
self.entity_description.key in FLOW_MEASUREMENT_KEYS
|
|
and self.entity_description.device_class == SensorDeviceClass.VOLUME
|
|
and round(self.state, 2) == 0.0
|
|
):
|
|
return "mdi:water-outline"
|
|
return None
|
|
|
|
def _update_attrs(self) -> None:
|
|
"""Update state attributes."""
|
|
self._attr_native_value = self.entity_description.value_fn(self)
|