Skip to content

Commit

Permalink
Add device info to Hydrawise (home-assistant#100828)
Browse files Browse the repository at this point in the history
* Add device info to Hydrawise

* Apply suggestions from code review

Co-authored-by: Joost Lekkerkerker <[email protected]>

* Remove _attr_has_entity_name

---------

Co-authored-by: Joost Lekkerkerker <[email protected]>
  • Loading branch information
dknowles2 and joostlek authored Sep 26, 2023
1 parent 7b1b189 commit 8ba6fd7
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 9 deletions.
6 changes: 4 additions & 2 deletions homeassistant/components/hydrawise/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Support for Hydrawise cloud."""


from pydrawise.legacy import LegacyHydrawise
from pydrawise import legacy
from requests.exceptions import ConnectTimeout, HTTPError
import voluptuous as vol

Expand Down Expand Up @@ -54,7 +54,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
"""Set up Hydrawise from a config entry."""
access_token = config_entry.data[CONF_API_KEY]
try:
hydrawise = await hass.async_add_executor_job(LegacyHydrawise, access_token)
hydrawise = await hass.async_add_executor_job(
legacy.LegacyHydrawise, access_token
)
except (ConnectTimeout, HTTPError) as ex:
LOGGER.error("Unable to connect to Hydrawise cloud service: %s", str(ex))
raise ConfigEntryNotReady(
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/hydrawise/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ async def async_setup_entry(
data=hydrawise.current_controller,
coordinator=coordinator,
description=BINARY_SENSOR_STATUS,
device_id_key="controller_id",
)
]

Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/hydrawise/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
DOMAIN = "hydrawise"
DEFAULT_WATERING_TIME = 15

MANUFACTURER = "Hydrawise"

SCAN_INTERVAL = timedelta(seconds=120)

SIGNAL_UPDATE_HYDRAWISE = "hydrawise_update"
16 changes: 10 additions & 6 deletions homeassistant/components/hydrawise/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

from typing import Any

from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN, MANUFACTURER
from .coordinator import HydrawiseDataUpdateCoordinator


Expand All @@ -20,14 +22,16 @@ def __init__(
data: dict[str, Any],
coordinator: HydrawiseDataUpdateCoordinator,
description: EntityDescription,
device_id_key: str = "relay_id",
) -> None:
"""Initialize the Hydrawise entity."""
super().__init__(coordinator=coordinator)
self.data = data
self.entity_description = description
self._attr_name = f"{self.data['name']} {description.name}"

@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes."""
return {"identifier": self.data.get("relay")}
self._device_id = str(data.get(device_id_key))
self._attr_unique_id = f"{self._device_id}_{description.key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._device_id)},
name=data["name"],
manufacturer=MANUFACTURER,
)
91 changes: 90 additions & 1 deletion tests/components/hydrawise/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
"""Common fixtures for the Hydrawise tests."""

from collections.abc import Generator
from unittest.mock import AsyncMock, patch
from typing import Any
from unittest.mock import AsyncMock, Mock, patch

import pytest

from homeassistant.components.hydrawise.const import DOMAIN
from homeassistant.const import CONF_API_KEY
from homeassistant.core import HomeAssistant

from tests.common import MockConfigEntry


@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock, None, None]:
Expand All @@ -13,3 +20,85 @@ def mock_setup_entry() -> Generator[AsyncMock, None, None]:
"homeassistant.components.hydrawise.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry


@pytest.fixture
def mock_pydrawise(
mock_controller: dict[str, Any],
mock_zones: list[dict[str, Any]],
) -> Generator[Mock, None, None]:
"""Mock LegacyHydrawise."""
with patch("pydrawise.legacy.LegacyHydrawise", autospec=True) as mock_pydrawise:
mock_pydrawise.return_value.controller_info = {"controllers": [mock_controller]}
mock_pydrawise.return_value.current_controller = mock_controller
mock_pydrawise.return_value.controller_status = {"relays": mock_zones}
mock_pydrawise.return_value.relays = mock_zones
yield mock_pydrawise.return_value


@pytest.fixture
def mock_controller() -> dict[str, Any]:
"""Mock Hydrawise controller."""
return {
"name": "Home Controller",
"last_contact": 1693292420,
"serial_number": "0310b36090",
"controller_id": 52496,
"status": "Unknown",
}


@pytest.fixture
def mock_zones() -> list[dict[str, Any]]:
"""Mock Hydrawise zones."""
return [
{
"name": "Zone One",
"period": 259200,
"relay": 1,
"relay_id": 5965394,
"run": 1800,
"stop": 1,
"time": 330597,
"timestr": "Sat",
"type": 1,
},
{
"name": "Zone Two",
"period": 259200,
"relay": 2,
"relay_id": 5965395,
"run": 1788,
"stop": 1,
"time": 1,
"timestr": "Now",
"type": 106,
},
]


@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Mock ConfigEntry."""
return MockConfigEntry(
title="Hydrawise",
domain=DOMAIN,
data={
CONF_API_KEY: "abc123",
},
unique_id="hydrawise-customerid",
)


@pytest.fixture
async def mock_added_config_entry(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_pydrawise: Mock,
) -> MockConfigEntry:
"""Mock ConfigEntry that's been added to HA."""
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert DOMAIN in hass.config_entries.async_domains()
return mock_config_entry
36 changes: 36 additions & 0 deletions tests/components/hydrawise/test_device.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Tests for Hydrawise devices."""

from unittest.mock import Mock

from homeassistant.components.hydrawise.const import DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr


def test_zones_in_device_registry(
hass: HomeAssistant, mock_added_config_entry: ConfigEntry, mock_pydrawise: Mock
) -> None:
"""Test that devices are added to the device registry."""
device_registry = dr.async_get(hass)

device1 = device_registry.async_get_device(identifiers={(DOMAIN, "5965394")})
assert device1 is not None
assert device1.name == "Zone One"
assert device1.manufacturer == "Hydrawise"

device2 = device_registry.async_get_device(identifiers={(DOMAIN, "5965395")})
assert device2 is not None
assert device2.name == "Zone Two"
assert device2.manufacturer == "Hydrawise"


def test_controller_in_device_registry(
hass: HomeAssistant, mock_added_config_entry: ConfigEntry, mock_pydrawise: Mock
) -> None:
"""Test that devices are added to the device registry."""
device_registry = dr.async_get(hass)
device = device_registry.async_get_device(identifiers={(DOMAIN, "52496")})
assert device is not None
assert device.name == "Home Controller"
assert device.manufacturer == "Hydrawise"

0 comments on commit 8ba6fd7

Please sign in to comment.