mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Add flow and rain sensor support to Hydrawise (#116303)
* Add flow and rain sensor support to Hydrawise * Address comments * Cleanup * Review comments * Address review comments * Added tests * Add icon translations * Add snapshot tests * Clean up binary sensor * Mypy cleanup * Another mypy error * Reviewer feedback * Clear next_cycle sensor when the value is unknown * Reviewer feedback * Reviewer feedback * Remove assert * Restructure switches, sensors, and binary sensors * Reviewer feedback * Reviewer feedback
This commit is contained in:
parent
a3248ccff9
commit
14fcf7be8e
@ -2,6 +2,9 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
@ -15,22 +18,40 @@ from .const import DOMAIN
|
||||
from .coordinator import HydrawiseDataUpdateCoordinator
|
||||
from .entity import HydrawiseEntity
|
||||
|
||||
BINARY_SENSOR_STATUS = BinarySensorEntityDescription(
|
||||
key="status",
|
||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||
)
|
||||
|
||||
BINARY_SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = (
|
||||
BinarySensorEntityDescription(
|
||||
key="is_watering",
|
||||
translation_key="watering",
|
||||
device_class=BinarySensorDeviceClass.MOISTURE,
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class HydrawiseBinarySensorEntityDescription(BinarySensorEntityDescription):
|
||||
"""Describes Hydrawise binary sensor."""
|
||||
|
||||
value_fn: Callable[[HydrawiseBinarySensor], bool | None]
|
||||
|
||||
|
||||
CONTROLLER_BINARY_SENSORS: tuple[HydrawiseBinarySensorEntityDescription, ...] = (
|
||||
HydrawiseBinarySensorEntityDescription(
|
||||
key="status",
|
||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||
value_fn=lambda status_sensor: status_sensor.coordinator.last_update_success,
|
||||
),
|
||||
)
|
||||
|
||||
BINARY_SENSOR_KEYS: list[str] = [
|
||||
desc.key for desc in (BINARY_SENSOR_STATUS, *BINARY_SENSOR_TYPES)
|
||||
]
|
||||
RAIN_SENSOR_BINARY_SENSOR: tuple[HydrawiseBinarySensorEntityDescription, ...] = (
|
||||
HydrawiseBinarySensorEntityDescription(
|
||||
key="rain_sensor",
|
||||
translation_key="rain_sensor",
|
||||
device_class=BinarySensorDeviceClass.MOISTURE,
|
||||
value_fn=lambda rain_sensor: rain_sensor.sensor.status.active,
|
||||
),
|
||||
)
|
||||
|
||||
ZONE_BINARY_SENSORS: tuple[HydrawiseBinarySensorEntityDescription, ...] = (
|
||||
HydrawiseBinarySensorEntityDescription(
|
||||
key="is_watering",
|
||||
translation_key="watering",
|
||||
device_class=BinarySensorDeviceClass.RUNNING,
|
||||
value_fn=lambda watering_sensor: watering_sensor.zone.scheduled_runs.current_run
|
||||
is not None,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -42,15 +63,27 @@ async def async_setup_entry(
|
||||
coordinator: HydrawiseDataUpdateCoordinator = hass.data[DOMAIN][
|
||||
config_entry.entry_id
|
||||
]
|
||||
entities = []
|
||||
entities: list[HydrawiseBinarySensor] = []
|
||||
for controller in coordinator.data.controllers.values():
|
||||
entities.append(
|
||||
HydrawiseBinarySensor(coordinator, BINARY_SENSOR_STATUS, controller)
|
||||
entities.extend(
|
||||
HydrawiseBinarySensor(coordinator, description, controller)
|
||||
for description in CONTROLLER_BINARY_SENSORS
|
||||
)
|
||||
entities.extend(
|
||||
HydrawiseBinarySensor(coordinator, description, controller, zone)
|
||||
HydrawiseBinarySensor(
|
||||
coordinator,
|
||||
description,
|
||||
controller,
|
||||
sensor_id=sensor.id,
|
||||
)
|
||||
for sensor in controller.sensors
|
||||
for description in RAIN_SENSOR_BINARY_SENSOR
|
||||
if "rain sensor" in sensor.model.name.lower()
|
||||
)
|
||||
entities.extend(
|
||||
HydrawiseBinarySensor(coordinator, description, controller, zone_id=zone.id)
|
||||
for zone in controller.zones
|
||||
for description in BINARY_SENSOR_TYPES
|
||||
for description in ZONE_BINARY_SENSORS
|
||||
)
|
||||
async_add_entities(entities)
|
||||
|
||||
@ -58,10 +91,8 @@ async def async_setup_entry(
|
||||
class HydrawiseBinarySensor(HydrawiseEntity, BinarySensorEntity):
|
||||
"""A sensor implementation for Hydrawise device."""
|
||||
|
||||
entity_description: HydrawiseBinarySensorEntityDescription
|
||||
|
||||
def _update_attrs(self) -> None:
|
||||
"""Update state attributes."""
|
||||
if self.entity_description.key == "status":
|
||||
self._attr_is_on = self.coordinator.last_update_success
|
||||
elif self.entity_description.key == "is_watering":
|
||||
assert self.zone is not None
|
||||
self._attr_is_on = self.zone.scheduled_runs.current_run is not None
|
||||
self._attr_is_on = self.entity_description.value_fn(self)
|
||||
|
@ -5,11 +5,12 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
|
||||
from pydrawise import HydrawiseBase
|
||||
from pydrawise.schema import Controller, User, Zone
|
||||
from pydrawise import Hydrawise
|
||||
from pydrawise.schema import Controller, ControllerWaterUseSummary, Sensor, User, Zone
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
from homeassistant.util.dt import now
|
||||
|
||||
from .const import DOMAIN, LOGGER
|
||||
|
||||
@ -21,15 +22,17 @@ class HydrawiseData:
|
||||
user: User
|
||||
controllers: dict[int, Controller]
|
||||
zones: dict[int, Zone]
|
||||
sensors: dict[int, Sensor]
|
||||
daily_water_use: dict[int, ControllerWaterUseSummary]
|
||||
|
||||
|
||||
class HydrawiseDataUpdateCoordinator(DataUpdateCoordinator[HydrawiseData]):
|
||||
"""The Hydrawise Data Update Coordinator."""
|
||||
|
||||
api: HydrawiseBase
|
||||
api: Hydrawise
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, api: HydrawiseBase, scan_interval: timedelta
|
||||
self, hass: HomeAssistant, api: Hydrawise, scan_interval: timedelta
|
||||
) -> None:
|
||||
"""Initialize HydrawiseDataUpdateCoordinator."""
|
||||
super().__init__(hass, LOGGER, name=DOMAIN, update_interval=scan_interval)
|
||||
@ -40,8 +43,30 @@ class HydrawiseDataUpdateCoordinator(DataUpdateCoordinator[HydrawiseData]):
|
||||
user = await self.api.get_user()
|
||||
controllers = {}
|
||||
zones = {}
|
||||
sensors = {}
|
||||
daily_water_use: dict[int, ControllerWaterUseSummary] = {}
|
||||
for controller in user.controllers:
|
||||
controllers[controller.id] = controller
|
||||
for zone in controller.zones:
|
||||
zones[zone.id] = zone
|
||||
return HydrawiseData(user=user, controllers=controllers, zones=zones)
|
||||
for sensor in controller.sensors:
|
||||
sensors[sensor.id] = sensor
|
||||
if any(
|
||||
"flow meter" in sensor.model.name.lower()
|
||||
for sensor in controller.sensors
|
||||
):
|
||||
daily_water_use[controller.id] = await self.api.get_water_use_summary(
|
||||
controller,
|
||||
now().replace(hour=0, minute=0, second=0, microsecond=0),
|
||||
now(),
|
||||
)
|
||||
else:
|
||||
daily_water_use[controller.id] = ControllerWaterUseSummary()
|
||||
|
||||
return HydrawiseData(
|
||||
user=user,
|
||||
controllers=controllers,
|
||||
zones=zones,
|
||||
sensors=sensors,
|
||||
daily_water_use=daily_water_use,
|
||||
)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydrawise.schema import Controller, Zone
|
||||
from pydrawise.schema import Controller, Sensor, Zone
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
@ -24,24 +24,42 @@ class HydrawiseEntity(CoordinatorEntity[HydrawiseDataUpdateCoordinator]):
|
||||
coordinator: HydrawiseDataUpdateCoordinator,
|
||||
description: EntityDescription,
|
||||
controller: Controller,
|
||||
zone: Zone | None = None,
|
||||
*,
|
||||
zone_id: int | None = None,
|
||||
sensor_id: int | None = None,
|
||||
) -> None:
|
||||
"""Initialize the Hydrawise entity."""
|
||||
super().__init__(coordinator=coordinator)
|
||||
self.entity_description = description
|
||||
self.controller = controller
|
||||
self.zone = zone
|
||||
self._device_id = str(controller.id if zone is None else zone.id)
|
||||
self.zone_id = zone_id
|
||||
self.sensor_id = sensor_id
|
||||
self._device_id = str(zone_id) if zone_id is not None else str(controller.id)
|
||||
self._attr_unique_id = f"{self._device_id}_{description.key}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, self._device_id)},
|
||||
name=controller.name if zone is None else zone.name,
|
||||
name=self.zone.name if zone_id is not None else controller.name,
|
||||
model="Zone"
|
||||
if zone_id is not None
|
||||
else controller.hardware.model.description,
|
||||
manufacturer=MANUFACTURER,
|
||||
)
|
||||
if zone is not None:
|
||||
if zone_id is not None or sensor_id is not None:
|
||||
self._attr_device_info["via_device"] = (DOMAIN, str(controller.id))
|
||||
self._update_attrs()
|
||||
|
||||
@property
|
||||
def zone(self) -> Zone:
|
||||
"""Return the entity zone."""
|
||||
assert self.zone_id is not None # needed for mypy
|
||||
return self.coordinator.data.zones[self.zone_id]
|
||||
|
||||
@property
|
||||
def sensor(self) -> Sensor:
|
||||
"""Return the entity sensor."""
|
||||
assert self.sensor_id is not None # needed for mypy
|
||||
return self.coordinator.data.sensors[self.sensor_id]
|
||||
|
||||
def _update_attrs(self) -> None:
|
||||
"""Update state attributes."""
|
||||
return # pragma: no cover
|
||||
@ -50,7 +68,5 @@ class HydrawiseEntity(CoordinatorEntity[HydrawiseDataUpdateCoordinator]):
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Get the latest data and updates the state."""
|
||||
self.controller = self.coordinator.data.controllers[self.controller.id]
|
||||
if self.zone:
|
||||
self.zone = self.coordinator.data.zones[self.zone.id]
|
||||
self._update_attrs()
|
||||
super()._handle_coordinator_update()
|
||||
|
@ -1,8 +1,29 @@
|
||||
{
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"daily_active_water_use": {
|
||||
"default": "mdi:water"
|
||||
},
|
||||
"daily_inactive_water_use": {
|
||||
"default": "mdi:water"
|
||||
},
|
||||
"daily_total_water_use": {
|
||||
"default": "mdi:water"
|
||||
},
|
||||
"next_cycle": {
|
||||
"default": "mdi:clock-outline"
|
||||
},
|
||||
"watering_time": {
|
||||
"default": "mdi:water-pump"
|
||||
"default": "mdi:timer-outline"
|
||||
}
|
||||
},
|
||||
"binary_sensor": {
|
||||
"rain_sensor": {
|
||||
"default": "mdi:weather-sunny",
|
||||
"state": {
|
||||
"off": "mdi:weather-sunny",
|
||||
"on": "mdi:weather-pouring"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
|
||||
from pydrawise.schema import Zone
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
@ -12,7 +13,7 @@ from homeassistant.components.sensor import (
|
||||
SensorEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import UnitOfTime
|
||||
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
|
||||
@ -21,22 +22,104 @@ from .const import DOMAIN
|
||||
from .coordinator import HydrawiseDataUpdateCoordinator
|
||||
from .entity import HydrawiseEntity
|
||||
|
||||
SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
||||
SensorEntityDescription(
|
||||
key="next_cycle",
|
||||
translation_key="next_cycle",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class HydrawiseSensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes Hydrawise binary sensor."""
|
||||
|
||||
value_fn: Callable[[HydrawiseSensor], Any]
|
||||
|
||||
|
||||
def _get_zone_watering_time(sensor: HydrawiseSensor) -> int:
|
||||
if (current_run := sensor.zone.scheduled_runs.current_run) is not None:
|
||||
return int(current_run.remaining_time.total_seconds() / 60)
|
||||
return 0
|
||||
|
||||
|
||||
def _get_zone_next_cycle(sensor: HydrawiseSensor) -> datetime | None:
|
||||
if (next_run := sensor.zone.scheduled_runs.next_run) is not None:
|
||||
return dt_util.as_utc(next_run.start_time)
|
||||
return None
|
||||
|
||||
|
||||
def _get_zone_daily_active_water_use(sensor: HydrawiseSensor) -> float:
|
||||
"""Get active water use for the zone."""
|
||||
daily_water_summary = sensor.coordinator.data.daily_water_use[sensor.controller.id]
|
||||
return float(daily_water_summary.active_use_by_zone_id.get(sensor.zone.id, 0.0))
|
||||
|
||||
|
||||
def _get_controller_daily_active_water_use(sensor: HydrawiseSensor) -> float:
|
||||
"""Get active water use for the controller."""
|
||||
daily_water_summary = sensor.coordinator.data.daily_water_use[sensor.controller.id]
|
||||
return daily_water_summary.total_active_use
|
||||
|
||||
|
||||
def _get_controller_daily_inactive_water_use(sensor: HydrawiseSensor) -> float | None:
|
||||
"""Get inactive water use for the controller."""
|
||||
daily_water_summary = sensor.coordinator.data.daily_water_use[sensor.controller.id]
|
||||
return daily_water_summary.total_inactive_use
|
||||
|
||||
|
||||
def _get_controller_daily_total_water_use(sensor: HydrawiseSensor) -> float | None:
|
||||
"""Get inactive water use for the controller."""
|
||||
daily_water_summary = sensor.coordinator.data.daily_water_use[sensor.controller.id]
|
||||
return daily_water_summary.total_use
|
||||
|
||||
|
||||
FLOW_CONTROLLER_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
|
||||
HydrawiseSensorEntityDescription(
|
||||
key="daily_total_water_use",
|
||||
translation_key="daily_total_water_use",
|
||||
device_class=SensorDeviceClass.VOLUME,
|
||||
native_unit_of_measurement=UnitOfVolume.GALLONS,
|
||||
suggested_display_precision=1,
|
||||
value_fn=_get_controller_daily_total_water_use,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="watering_time",
|
||||
translation_key="watering_time",
|
||||
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||
HydrawiseSensorEntityDescription(
|
||||
key="daily_active_water_use",
|
||||
translation_key="daily_active_water_use",
|
||||
device_class=SensorDeviceClass.VOLUME,
|
||||
native_unit_of_measurement=UnitOfVolume.GALLONS,
|
||||
suggested_display_precision=1,
|
||||
value_fn=_get_controller_daily_active_water_use,
|
||||
),
|
||||
HydrawiseSensorEntityDescription(
|
||||
key="daily_inactive_water_use",
|
||||
translation_key="daily_inactive_water_use",
|
||||
device_class=SensorDeviceClass.VOLUME,
|
||||
native_unit_of_measurement=UnitOfVolume.GALLONS,
|
||||
suggested_display_precision=1,
|
||||
value_fn=_get_controller_daily_inactive_water_use,
|
||||
),
|
||||
)
|
||||
|
||||
SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
|
||||
TWO_YEAR_SECONDS = 60 * 60 * 24 * 365 * 2
|
||||
WATERING_TIME_ICON = "mdi:water-pump"
|
||||
FLOW_ZONE_SENSORS: tuple[SensorEntityDescription, ...] = (
|
||||
HydrawiseSensorEntityDescription(
|
||||
key="daily_active_water_use",
|
||||
translation_key="daily_active_water_use",
|
||||
device_class=SensorDeviceClass.VOLUME,
|
||||
native_unit_of_measurement=UnitOfVolume.GALLONS,
|
||||
suggested_display_precision=1,
|
||||
value_fn=_get_zone_daily_active_water_use,
|
||||
),
|
||||
)
|
||||
|
||||
ZONE_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
|
||||
HydrawiseSensorEntityDescription(
|
||||
key="next_cycle",
|
||||
translation_key="next_cycle",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
value_fn=_get_zone_next_cycle,
|
||||
),
|
||||
HydrawiseSensorEntityDescription(
|
||||
key="watering_time",
|
||||
translation_key="watering_time",
|
||||
native_unit_of_measurement=UnitOfTime.MINUTES,
|
||||
value_fn=_get_zone_watering_time,
|
||||
),
|
||||
)
|
||||
|
||||
FLOW_MEASUREMENT_KEYS = [x.key for x in FLOW_CONTROLLER_SENSORS]
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -48,30 +131,50 @@ async def async_setup_entry(
|
||||
coordinator: HydrawiseDataUpdateCoordinator = hass.data[DOMAIN][
|
||||
config_entry.entry_id
|
||||
]
|
||||
async_add_entities(
|
||||
HydrawiseSensor(coordinator, description, controller, zone)
|
||||
for controller in coordinator.data.controllers.values()
|
||||
for zone in controller.zones
|
||||
for description in SENSOR_TYPES
|
||||
)
|
||||
entities: list[HydrawiseSensor] = []
|
||||
for controller in coordinator.data.controllers.values():
|
||||
entities.extend(
|
||||
HydrawiseSensor(coordinator, description, controller, zone_id=zone.id)
|
||||
for zone in controller.zones
|
||||
for description in ZONE_SENSORS
|
||||
)
|
||||
entities.extend(
|
||||
HydrawiseSensor(coordinator, description, controller, sensor_id=sensor.id)
|
||||
for sensor in controller.sensors
|
||||
for description in FLOW_CONTROLLER_SENSORS
|
||||
if "flow meter" in sensor.model.name.lower()
|
||||
)
|
||||
entities.extend(
|
||||
HydrawiseSensor(
|
||||
coordinator,
|
||||
description,
|
||||
controller,
|
||||
zone_id=zone.id,
|
||||
sensor_id=sensor.id,
|
||||
)
|
||||
for zone in controller.zones
|
||||
for sensor in controller.sensors
|
||||
for description in FLOW_ZONE_SENSORS
|
||||
if "flow meter" in sensor.model.name.lower()
|
||||
)
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class HydrawiseSensor(HydrawiseEntity, SensorEntity):
|
||||
"""A sensor implementation for Hydrawise device."""
|
||||
|
||||
zone: Zone
|
||||
entity_description: HydrawiseSensorEntityDescription
|
||||
|
||||
@property
|
||||
def icon(self) -> str | None:
|
||||
"""Icon of the entity based on the value."""
|
||||
if (
|
||||
self.entity_description.key in FLOW_MEASUREMENT_KEYS
|
||||
and round(self.state, 2) == 0.0
|
||||
):
|
||||
return "mdi:water-outline"
|
||||
return None
|
||||
|
||||
def _update_attrs(self) -> None:
|
||||
"""Update state attributes."""
|
||||
if self.entity_description.key == "watering_time":
|
||||
if (current_run := self.zone.scheduled_runs.current_run) is not None:
|
||||
self._attr_native_value = int(
|
||||
current_run.remaining_time.total_seconds() / 60
|
||||
)
|
||||
else:
|
||||
self._attr_native_value = 0
|
||||
elif self.entity_description.key == "next_cycle":
|
||||
if (next_run := self.zone.scheduled_runs.next_run) is not None:
|
||||
self._attr_native_value = dt_util.as_utc(next_run.start_time)
|
||||
else:
|
||||
self._attr_native_value = datetime.max.replace(tzinfo=dt_util.UTC)
|
||||
self._attr_native_value = self.entity_description.value_fn(self)
|
||||
|
@ -24,9 +24,21 @@
|
||||
"binary_sensor": {
|
||||
"watering": {
|
||||
"name": "Watering"
|
||||
},
|
||||
"rain_sensor": {
|
||||
"name": "Rain sensor"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"daily_total_water_use": {
|
||||
"name": "Daily total water use"
|
||||
},
|
||||
"daily_active_water_use": {
|
||||
"name": "Daily active water use"
|
||||
},
|
||||
"daily_inactive_water_use": {
|
||||
"name": "Daily inactive water use"
|
||||
},
|
||||
"next_cycle": {
|
||||
"name": "Next cycle"
|
||||
},
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Coroutine
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
from pydrawise.schema import Zone
|
||||
from pydrawise import Hydrawise, Zone
|
||||
|
||||
from homeassistant.components.switch import (
|
||||
SwitchDeviceClass,
|
||||
@ -21,16 +23,37 @@ from .const import DEFAULT_WATERING_TIME, DOMAIN
|
||||
from .coordinator import HydrawiseDataUpdateCoordinator
|
||||
from .entity import HydrawiseEntity
|
||||
|
||||
SWITCH_TYPES: tuple[SwitchEntityDescription, ...] = (
|
||||
SwitchEntityDescription(
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class HydrawiseSwitchEntityDescription(SwitchEntityDescription):
|
||||
"""Describes Hydrawise binary sensor."""
|
||||
|
||||
turn_on_fn: Callable[[Hydrawise, Zone], Coroutine[Any, Any, None]]
|
||||
turn_off_fn: Callable[[Hydrawise, Zone], Coroutine[Any, Any, None]]
|
||||
value_fn: Callable[[Zone], bool]
|
||||
|
||||
|
||||
SWITCH_TYPES: tuple[HydrawiseSwitchEntityDescription, ...] = (
|
||||
HydrawiseSwitchEntityDescription(
|
||||
key="auto_watering",
|
||||
translation_key="auto_watering",
|
||||
device_class=SwitchDeviceClass.SWITCH,
|
||||
value_fn=lambda zone: zone.status.suspended_until is None,
|
||||
turn_on_fn=lambda api, zone: api.resume_zone(zone),
|
||||
turn_off_fn=lambda api, zone: api.suspend_zone(
|
||||
zone, dt_util.now() + timedelta(days=365)
|
||||
),
|
||||
),
|
||||
SwitchEntityDescription(
|
||||
HydrawiseSwitchEntityDescription(
|
||||
key="manual_watering",
|
||||
translation_key="manual_watering",
|
||||
device_class=SwitchDeviceClass.SWITCH,
|
||||
value_fn=lambda zone: zone.scheduled_runs.current_run is not None,
|
||||
turn_on_fn=lambda api, zone: api.start_zone(
|
||||
zone,
|
||||
custom_run_duration=int(DEFAULT_WATERING_TIME.total_seconds()),
|
||||
),
|
||||
turn_off_fn=lambda api, zone: api.stop_zone(zone),
|
||||
),
|
||||
)
|
||||
|
||||
@ -47,7 +70,7 @@ async def async_setup_entry(
|
||||
config_entry.entry_id
|
||||
]
|
||||
async_add_entities(
|
||||
HydrawiseSwitch(coordinator, description, controller, zone)
|
||||
HydrawiseSwitch(coordinator, description, controller, zone_id=zone.id)
|
||||
for controller in coordinator.data.controllers.values()
|
||||
for zone in controller.zones
|
||||
for description in SWITCH_TYPES
|
||||
@ -57,34 +80,21 @@ async def async_setup_entry(
|
||||
class HydrawiseSwitch(HydrawiseEntity, SwitchEntity):
|
||||
"""A switch implementation for Hydrawise device."""
|
||||
|
||||
entity_description: HydrawiseSwitchEntityDescription
|
||||
zone: Zone
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the device on."""
|
||||
if self.entity_description.key == "manual_watering":
|
||||
await self.coordinator.api.start_zone(
|
||||
self.zone,
|
||||
custom_run_duration=int(DEFAULT_WATERING_TIME.total_seconds()),
|
||||
)
|
||||
elif self.entity_description.key == "auto_watering":
|
||||
await self.coordinator.api.resume_zone(self.zone)
|
||||
await self.entity_description.turn_on_fn(self.coordinator.api, self.zone)
|
||||
self._attr_is_on = True
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the device off."""
|
||||
if self.entity_description.key == "manual_watering":
|
||||
await self.coordinator.api.stop_zone(self.zone)
|
||||
elif self.entity_description.key == "auto_watering":
|
||||
await self.coordinator.api.suspend_zone(
|
||||
self.zone, dt_util.now() + timedelta(days=365)
|
||||
)
|
||||
await self.entity_description.turn_off_fn(self.coordinator.api, self.zone)
|
||||
self._attr_is_on = False
|
||||
self.async_write_ha_state()
|
||||
|
||||
def _update_attrs(self) -> None:
|
||||
"""Update state attributes."""
|
||||
if self.entity_description.key == "manual_watering":
|
||||
self._attr_is_on = self.zone.scheduled_runs.current_run is not None
|
||||
elif self.entity_description.key == "auto_watering":
|
||||
self._attr_is_on = self.zone.status.suspended_until is None
|
||||
self._attr_is_on = self.entity_description.value_fn(self.zone)
|
||||
|
@ -7,8 +7,14 @@ from unittest.mock import AsyncMock, patch
|
||||
from pydrawise.schema import (
|
||||
Controller,
|
||||
ControllerHardware,
|
||||
ControllerWaterUseSummary,
|
||||
CustomSensorTypeEnum,
|
||||
LocalizedValueType,
|
||||
ScheduledZoneRun,
|
||||
ScheduledZoneRuns,
|
||||
Sensor,
|
||||
SensorModel,
|
||||
SensorStatus,
|
||||
User,
|
||||
Zone,
|
||||
)
|
||||
@ -53,12 +59,18 @@ def mock_pydrawise(
|
||||
user: User,
|
||||
controller: Controller,
|
||||
zones: list[Zone],
|
||||
sensors: list[Sensor],
|
||||
controller_water_use_summary: ControllerWaterUseSummary,
|
||||
) -> Generator[AsyncMock, None, None]:
|
||||
"""Mock Hydrawise."""
|
||||
with patch("pydrawise.client.Hydrawise", autospec=True) as mock_pydrawise:
|
||||
user.controllers = [controller]
|
||||
controller.zones = zones
|
||||
controller.sensors = sensors
|
||||
mock_pydrawise.return_value.get_user.return_value = user
|
||||
mock_pydrawise.return_value.get_water_use_summary.return_value = (
|
||||
controller_water_use_summary
|
||||
)
|
||||
yield mock_pydrawise.return_value
|
||||
|
||||
|
||||
@ -86,9 +98,50 @@ def controller() -> Controller:
|
||||
),
|
||||
last_contact_time=datetime.fromtimestamp(1693292420),
|
||||
online=True,
|
||||
sensors=[],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sensors() -> list[Sensor]:
|
||||
"""Hydrawise sensor fixtures."""
|
||||
return [
|
||||
Sensor(
|
||||
id=337844,
|
||||
name="Rain sensor ",
|
||||
model=SensorModel(
|
||||
id=3318,
|
||||
name="Rain Sensor (normally closed wire)",
|
||||
active=True,
|
||||
off_level=1,
|
||||
off_timer=0,
|
||||
divisor=0.0,
|
||||
flow_rate=0.0,
|
||||
sensor_type=CustomSensorTypeEnum.LEVEL_CLOSED,
|
||||
),
|
||||
status=SensorStatus(water_flow=None, active=False),
|
||||
),
|
||||
Sensor(
|
||||
id=337845,
|
||||
name="Flow meter",
|
||||
model=SensorModel(
|
||||
id=3324,
|
||||
name="1, 1½ or 2 inch NPT Flow Meter",
|
||||
active=True,
|
||||
off_level=0,
|
||||
off_timer=0,
|
||||
divisor=0.52834,
|
||||
flow_rate=3.7854,
|
||||
sensor_type=CustomSensorTypeEnum.FLOW,
|
||||
),
|
||||
status=SensorStatus(
|
||||
water_flow=LocalizedValueType(value=577.0044752010709, unit="gal"),
|
||||
active=None,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def zones() -> list[Zone]:
|
||||
"""Hydrawise zone fixtures."""
|
||||
@ -123,6 +176,18 @@ def zones() -> list[Zone]:
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def controller_water_use_summary() -> ControllerWaterUseSummary:
|
||||
"""Mock water use summary for the controller."""
|
||||
return ControllerWaterUseSummary(
|
||||
total_use=345.6,
|
||||
total_active_use=332.6,
|
||||
total_inactive_use=13.0,
|
||||
active_use_by_zone_id={5965394: 120.1, 5965395: 0.0},
|
||||
unit="gal",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry_legacy() -> MockConfigEntry:
|
||||
"""Mock ConfigEntry."""
|
||||
|
193
tests/components/hydrawise/snapshots/test_binary_sensor.ambr
Normal file
193
tests/components/hydrawise/snapshots/test_binary_sensor.ambr
Normal file
@ -0,0 +1,193 @@
|
||||
# serializer version: 1
|
||||
# name: test_all_binary_sensors[binary_sensor.home_controller_connectivity-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.home_controller_connectivity',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.CONNECTIVITY: 'connectivity'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Connectivity',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '52496_status',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_binary_sensors[binary_sensor.home_controller_connectivity-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'connectivity',
|
||||
'friendly_name': 'Home Controller Connectivity',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.home_controller_connectivity',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_binary_sensors[binary_sensor.home_controller_rain_sensor-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.home_controller_rain_sensor',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.MOISTURE: 'moisture'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Rain sensor',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'rain_sensor',
|
||||
'unique_id': '52496_rain_sensor',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_binary_sensors[binary_sensor.home_controller_rain_sensor-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'moisture',
|
||||
'friendly_name': 'Home Controller Rain sensor',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.home_controller_rain_sensor',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_binary_sensors[binary_sensor.zone_one_watering-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.zone_one_watering',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.RUNNING: 'running'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Watering',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'watering',
|
||||
'unique_id': '5965394_is_watering',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_binary_sensors[binary_sensor.zone_one_watering-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'running',
|
||||
'friendly_name': 'Zone One Watering',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.zone_one_watering',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_binary_sensors[binary_sensor.zone_two_watering-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.zone_two_watering',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.RUNNING: 'running'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Watering',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'watering',
|
||||
'unique_id': '5965395_is_watering',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_binary_sensors[binary_sensor.zone_two_watering-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'running',
|
||||
'friendly_name': 'Zone Two Watering',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.zone_two_watering',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
469
tests/components/hydrawise/snapshots/test_sensor.ambr
Normal file
469
tests/components/hydrawise/snapshots/test_sensor.ambr
Normal file
@ -0,0 +1,469 @@
|
||||
# serializer version: 1
|
||||
# name: test_all_sensors[sensor.home_controller_daily_active_water_use-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.home_controller_daily_active_water_use',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLUME: 'volume'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Daily active water use',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'daily_active_water_use',
|
||||
'unique_id': '52496_daily_active_water_use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.home_controller_daily_active_water_use-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'volume',
|
||||
'friendly_name': 'Home Controller Daily active water use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_controller_daily_active_water_use',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '1259.0279593584',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.home_controller_daily_inactive_water_use-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.home_controller_daily_inactive_water_use',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLUME: 'volume'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Daily inactive water use',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'daily_inactive_water_use',
|
||||
'unique_id': '52496_daily_inactive_water_use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.home_controller_daily_inactive_water_use-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'volume',
|
||||
'friendly_name': 'Home Controller Daily inactive water use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_controller_daily_inactive_water_use',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '49.210353192',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.home_controller_daily_total_water_use-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.home_controller_daily_total_water_use',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLUME: 'volume'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Daily total water use',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'daily_total_water_use',
|
||||
'unique_id': '52496_daily_total_water_use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.home_controller_daily_total_water_use-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'volume',
|
||||
'friendly_name': 'Home Controller Daily total water use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.home_controller_daily_total_water_use',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '1308.2383125504',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_one_daily_active_water_use-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.zone_one_daily_active_water_use',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLUME: 'volume'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Daily active water use',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'daily_active_water_use',
|
||||
'unique_id': '5965394_daily_active_water_use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_one_daily_active_water_use-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'volume',
|
||||
'friendly_name': 'Zone One Daily active water use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.zone_one_daily_active_water_use',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '454.6279552584',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_one_next_cycle-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.zone_one_next_cycle',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Next cycle',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'next_cycle',
|
||||
'unique_id': '5965394_next_cycle',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_one_next_cycle-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'Zone One Next cycle',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.zone_one_next_cycle',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2023-10-04T19:49:57+00:00',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_one_watering_time-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.zone_one_watering_time',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Watering time',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'watering_time',
|
||||
'unique_id': '5965394_watering_time',
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_one_watering_time-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'friendly_name': 'Zone One Watering time',
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.zone_one_watering_time',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '0',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_two_daily_active_water_use-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.zone_two_daily_active_water_use',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.VOLUME: 'volume'>,
|
||||
'original_icon': 'mdi:water-outline',
|
||||
'original_name': 'Daily active water use',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'daily_active_water_use',
|
||||
'unique_id': '5965395_daily_active_water_use',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_two_daily_active_water_use-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'volume',
|
||||
'friendly_name': 'Zone Two Daily active water use',
|
||||
'icon': 'mdi:water-outline',
|
||||
'unit_of_measurement': <UnitOfVolume.LITERS: 'L'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.zone_two_daily_active_water_use',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '0.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_two_next_cycle-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.zone_two_next_cycle',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Next cycle',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'next_cycle',
|
||||
'unique_id': '5965395_next_cycle',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_two_next_cycle-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'Zone Two Next cycle',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.zone_two_next_cycle',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_two_watering_time-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.zone_two_watering_time',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Watering time',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'watering_time',
|
||||
'unique_id': '5965395_watering_time',
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_sensors[sensor.zone_two_watering_time-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'friendly_name': 'Zone Two Watering time',
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.zone_two_watering_time',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '29',
|
||||
})
|
||||
# ---
|
193
tests/components/hydrawise/snapshots/test_switch.ambr
Normal file
193
tests/components/hydrawise/snapshots/test_switch.ambr
Normal file
@ -0,0 +1,193 @@
|
||||
# serializer version: 1
|
||||
# name: test_all_switches[switch.zone_one_automatic_watering-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': None,
|
||||
'entity_id': 'switch.zone_one_automatic_watering',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Automatic watering',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'auto_watering',
|
||||
'unique_id': '5965394_auto_watering',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_switches[switch.zone_one_automatic_watering-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'switch',
|
||||
'friendly_name': 'Zone One Automatic watering',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.zone_one_automatic_watering',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_switches[switch.zone_one_manual_watering-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': None,
|
||||
'entity_id': 'switch.zone_one_manual_watering',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Manual watering',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'manual_watering',
|
||||
'unique_id': '5965394_manual_watering',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_switches[switch.zone_one_manual_watering-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'switch',
|
||||
'friendly_name': 'Zone One Manual watering',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.zone_one_manual_watering',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_switches[switch.zone_two_automatic_watering-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': None,
|
||||
'entity_id': 'switch.zone_two_automatic_watering',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Automatic watering',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'auto_watering',
|
||||
'unique_id': '5965395_auto_watering',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_switches[switch.zone_two_automatic_watering-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'switch',
|
||||
'friendly_name': 'Zone Two Automatic watering',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.zone_two_automatic_watering',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_switches[switch.zone_two_manual_watering-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': None,
|
||||
'entity_id': 'switch.zone_two_manual_watering',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Manual watering',
|
||||
'platform': 'hydrawise',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'manual_watering',
|
||||
'unique_id': '5965395_manual_watering',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_switches[switch.zone_two_manual_watering-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by hydrawise.com',
|
||||
'device_class': 'switch',
|
||||
'friendly_name': 'Zone Two Manual watering',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.zone_two_manual_watering',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
@ -1,34 +1,34 @@
|
||||
"""Test Hydrawise binary_sensor."""
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from aiohttp import ClientError
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.hydrawise.const import SCAN_INTERVAL
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||
|
||||
|
||||
async def test_states(
|
||||
async def test_all_binary_sensors(
|
||||
hass: HomeAssistant,
|
||||
mock_added_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
mock_add_config_entry: Callable[[], Awaitable[MockConfigEntry]],
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test binary_sensor states."""
|
||||
connectivity = hass.states.get("binary_sensor.home_controller_connectivity")
|
||||
assert connectivity is not None
|
||||
assert connectivity.state == "on"
|
||||
|
||||
watering1 = hass.states.get("binary_sensor.zone_one_watering")
|
||||
assert watering1 is not None
|
||||
assert watering1.state == "off"
|
||||
|
||||
watering2 = hass.states.get("binary_sensor.zone_two_watering")
|
||||
assert watering2 is not None
|
||||
assert watering2.state == "on"
|
||||
"""Test that all binary sensors are working."""
|
||||
with patch(
|
||||
"homeassistant.components.hydrawise.PLATFORMS",
|
||||
[Platform.BINARY_SENSOR],
|
||||
):
|
||||
config_entry = await mock_add_config_entry()
|
||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_update_data_fails(
|
||||
|
@ -1,34 +1,33 @@
|
||||
"""Test Hydrawise sensor."""
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from pydrawise.schema import Zone
|
||||
from pydrawise.schema import Controller, Zone
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2023-10-01 00:00:00+00:00")
|
||||
async def test_states(
|
||||
async def test_all_sensors(
|
||||
hass: HomeAssistant,
|
||||
mock_added_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
mock_add_config_entry: Callable[[], Awaitable[MockConfigEntry]],
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test sensor states."""
|
||||
watering_time1 = hass.states.get("sensor.zone_one_watering_time")
|
||||
assert watering_time1 is not None
|
||||
assert watering_time1.state == "0"
|
||||
|
||||
watering_time2 = hass.states.get("sensor.zone_two_watering_time")
|
||||
assert watering_time2 is not None
|
||||
assert watering_time2.state == "29"
|
||||
|
||||
next_cycle = hass.states.get("sensor.zone_one_next_cycle")
|
||||
assert next_cycle is not None
|
||||
assert next_cycle.state == "2023-10-04T19:49:57+00:00"
|
||||
"""Test that all sensors are working."""
|
||||
with patch(
|
||||
"homeassistant.components.hydrawise.PLATFORMS",
|
||||
[Platform.SENSOR],
|
||||
):
|
||||
config_entry = await mock_add_config_entry()
|
||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2023-10-01 00:00:00+00:00")
|
||||
@ -43,4 +42,24 @@ async def test_suspended_state(
|
||||
|
||||
next_cycle = hass.states.get("sensor.zone_one_next_cycle")
|
||||
assert next_cycle is not None
|
||||
assert next_cycle.state == "9999-12-31T23:59:59+00:00"
|
||||
assert next_cycle.state == "unknown"
|
||||
|
||||
|
||||
async def test_no_sensor_and_water_state2(
|
||||
hass: HomeAssistant,
|
||||
controller: Controller,
|
||||
mock_add_config_entry: Callable[[], Awaitable[MockConfigEntry]],
|
||||
) -> None:
|
||||
"""Test rain sensor, flow sensor, and water use in the absence of flow and rain sensors."""
|
||||
controller.sensors = []
|
||||
await mock_add_config_entry()
|
||||
|
||||
assert hass.states.get("sensor.zone_one_daily_active_water_use") is None
|
||||
assert hass.states.get("sensor.zone_two_daily_active_water_use") is None
|
||||
assert hass.states.get("sensor.home_controller_daily_active_water_use") is None
|
||||
assert hass.states.get("sensor.home_controller_daily_inactive_water_use") is None
|
||||
assert hass.states.get("binary_sensor.home_controller_rain_sensor") is None
|
||||
|
||||
sensor = hass.states.get("binary_sensor.home_controller_connectivity")
|
||||
assert sensor is not None
|
||||
assert sensor.state == "on"
|
||||
|
@ -1,40 +1,41 @@
|
||||
"""Test Hydrawise switch."""
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from pydrawise.schema import Zone
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.hydrawise.const import DEFAULT_WATERING_TIME
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
async def test_states(
|
||||
async def test_all_switches(
|
||||
hass: HomeAssistant,
|
||||
mock_added_config_entry: MockConfigEntry,
|
||||
mock_add_config_entry: Callable[[], Awaitable[MockConfigEntry]],
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test switch states."""
|
||||
watering1 = hass.states.get("switch.zone_one_manual_watering")
|
||||
assert watering1 is not None
|
||||
assert watering1.state == "off"
|
||||
|
||||
watering2 = hass.states.get("switch.zone_two_manual_watering")
|
||||
assert watering2 is not None
|
||||
assert watering2.state == "on"
|
||||
|
||||
auto_watering1 = hass.states.get("switch.zone_one_automatic_watering")
|
||||
assert auto_watering1 is not None
|
||||
assert auto_watering1.state == "on"
|
||||
|
||||
auto_watering2 = hass.states.get("switch.zone_two_automatic_watering")
|
||||
assert auto_watering2 is not None
|
||||
assert auto_watering2.state == "on"
|
||||
"""Test that all switches are working."""
|
||||
with patch(
|
||||
"homeassistant.components.hydrawise.PLATFORMS",
|
||||
[Platform.SWITCH],
|
||||
):
|
||||
config_entry = await mock_add_config_entry()
|
||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_manual_watering_services(
|
||||
|
Loading…
x
Reference in New Issue
Block a user