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:
Thomas Kistler 2024-05-07 12:26:10 -07:00 committed by GitHub
parent a3248ccff9
commit 14fcf7be8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 1307 additions and 149 deletions

View File

@ -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)

View File

@ -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,
)

View File

@ -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()

View File

@ -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"
}
}
}
}

View File

@ -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)

View File

@ -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"
},

View File

@ -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)

View File

@ -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."""

View 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',
})
# ---

View 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',
})
# ---

View 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',
})
# ---

View File

@ -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(

View File

@ -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"

View File

@ -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(