Bump py-aosmith to 1.0.6 (#107409)

pull/107053/head^2
Brandon Rothweiler 2024-01-06 17:01:11 -05:00 committed by GitHub
parent 4ea8c174f5
commit 3f2170bd06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 197 additions and 315 deletions

View File

@ -37,16 +37,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await status_coordinator.async_config_entry_first_refresh()
device_registry = dr.async_get(hass)
for junction_id, status_data in status_coordinator.data.items():
for junction_id, aosmith_device in status_coordinator.data.items():
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, junction_id)},
manufacturer="A. O. Smith",
name=status_data.get("name"),
model=status_data.get("model"),
serial_number=status_data.get("serial"),
suggested_area=status_data.get("install", {}).get("location"),
sw_version=status_data.get("data", {}).get("firmwareVersion"),
name=aosmith_device.name,
model=aosmith_device.model,
serial_number=aosmith_device.serial,
suggested_area=aosmith_device.install_location,
sw_version=aosmith_device.status.firmware_version,
)
energy_coordinator = AOSmithEnergyCoordinator(

View File

@ -4,11 +4,6 @@ from datetime import timedelta
DOMAIN = "aosmith"
AOSMITH_MODE_ELECTRIC = "ELECTRIC"
AOSMITH_MODE_HEAT_PUMP = "HEAT_PUMP"
AOSMITH_MODE_HYBRID = "HYBRID"
AOSMITH_MODE_VACATION = "VACATION"
# Update interval to be used for normal background updates.
REGULAR_INTERVAL = timedelta(seconds=30)
@ -17,9 +12,3 @@ FAST_INTERVAL = timedelta(seconds=1)
# Update interval to be used for energy usage data.
ENERGY_USAGE_INTERVAL = timedelta(minutes=10)
HOT_WATER_STATUS_MAP = {
"LOW": "low",
"MEDIUM": "medium",
"HIGH": "high",
}

View File

@ -1,12 +1,12 @@
"""The data update coordinator for the A. O. Smith integration."""
import logging
from typing import Any
from py_aosmith import (
AOSmithAPIClient,
AOSmithInvalidCredentialsException,
AOSmithUnknownException,
)
from py_aosmith.models import Device as AOSmithDevice
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed
@ -17,7 +17,7 @@ from .const import DOMAIN, ENERGY_USAGE_INTERVAL, FAST_INTERVAL, REGULAR_INTERVA
_LOGGER = logging.getLogger(__name__)
class AOSmithStatusCoordinator(DataUpdateCoordinator[dict[str, dict[str, Any]]]):
class AOSmithStatusCoordinator(DataUpdateCoordinator[dict[str, AOSmithDevice]]):
"""Coordinator for device status, updating with a frequent interval."""
def __init__(self, hass: HomeAssistant, client: AOSmithAPIClient) -> None:
@ -25,7 +25,7 @@ class AOSmithStatusCoordinator(DataUpdateCoordinator[dict[str, dict[str, Any]]])
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=REGULAR_INTERVAL)
self.client = client
async def _async_update_data(self) -> dict[str, dict[str, Any]]:
async def _async_update_data(self) -> dict[str, AOSmithDevice]:
"""Fetch latest data from the device status endpoint."""
try:
devices = await self.client.get_devices()
@ -34,12 +34,9 @@ class AOSmithStatusCoordinator(DataUpdateCoordinator[dict[str, dict[str, Any]]])
except AOSmithUnknownException as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
mode_pending = any(
device.get("data", {}).get("modePending") for device in devices
)
mode_pending = any(device.status.mode_change_pending for device in devices)
setpoint_pending = any(
device.get("data", {}).get("temperatureSetpointPending")
for device in devices
device.status.temperature_setpoint_pending for device in devices
)
if mode_pending or setpoint_pending:
@ -47,7 +44,7 @@ class AOSmithStatusCoordinator(DataUpdateCoordinator[dict[str, dict[str, Any]]])
else:
self.update_interval = REGULAR_INTERVAL
return {device.get("junctionId"): device for device in devices}
return {device.junction_id: device for device in devices}
class AOSmithEnergyCoordinator(DataUpdateCoordinator[dict[str, float]]):
@ -78,6 +75,6 @@ class AOSmithEnergyCoordinator(DataUpdateCoordinator[dict[str, float]]):
except AOSmithUnknownException as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
energy_usage_by_junction_id[junction_id] = energy_usage.get("lifetimeKwh")
energy_usage_by_junction_id[junction_id] = energy_usage.lifetime_kwh
return energy_usage_by_junction_id

View File

@ -2,6 +2,7 @@
from typing import TypeVar
from py_aosmith import AOSmithAPIClient
from py_aosmith.models import Device as AOSmithDevice
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
@ -37,26 +38,20 @@ class AOSmithStatusEntity(AOSmithEntity[AOSmithStatusCoordinator]):
"""Base entity for entities that use data from the status coordinator."""
@property
def device(self):
"""Shortcut to get the device status from the coordinator data."""
return self.coordinator.data.get(self.junction_id)
@property
def device_data(self):
"""Shortcut to get the device data within the device status."""
device = self.device
return None if device is None else device.get("data", {})
def device(self) -> AOSmithDevice:
"""Shortcut to get the device from the coordinator data."""
return self.coordinator.data[self.junction_id]
@property
def available(self) -> bool:
"""Return True if entity is available."""
return super().available and self.device_data.get("isOnline") is True
return super().available and self.device.status.is_online
class AOSmithEnergyEntity(AOSmithEntity[AOSmithEnergyCoordinator]):
"""Base entity for entities that use data from the energy coordinator."""
@property
def energy_usage(self) -> float | None:
def energy_usage(self) -> float:
"""Shortcut to get the energy usage from the coordinator data."""
return self.coordinator.data.get(self.junction_id)
return self.coordinator.data[self.junction_id]

View File

@ -5,5 +5,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/aosmith",
"iot_class": "cloud_polling",
"requirements": ["py-aosmith==1.0.4"]
"requirements": ["py-aosmith==1.0.6"]
}

View File

@ -2,7 +2,8 @@
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from py_aosmith.models import Device as AOSmithDevice, HotWaterStatus
from homeassistant.components.sensor import (
SensorDeviceClass,
@ -16,7 +17,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AOSmithData
from .const import DOMAIN, HOT_WATER_STATUS_MAP
from .const import DOMAIN
from .coordinator import AOSmithEnergyCoordinator, AOSmithStatusCoordinator
from .entity import AOSmithEnergyEntity, AOSmithStatusEntity
@ -25,7 +26,7 @@ from .entity import AOSmithEnergyEntity, AOSmithStatusEntity
class AOSmithStatusSensorEntityDescription(SensorEntityDescription):
"""Entity description class for sensors using data from the status coordinator."""
value_fn: Callable[[dict[str, Any]], str | int | None]
value_fn: Callable[[AOSmithDevice], str | int | None]
STATUS_ENTITY_DESCRIPTIONS: tuple[AOSmithStatusSensorEntityDescription, ...] = (
@ -36,11 +37,17 @@ STATUS_ENTITY_DESCRIPTIONS: tuple[AOSmithStatusSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.ENUM,
options=["low", "medium", "high"],
value_fn=lambda device: HOT_WATER_STATUS_MAP.get(
device.get("data", {}).get("hotWaterStatus")
device.status.hot_water_status
),
),
)
HOT_WATER_STATUS_MAP: dict[HotWaterStatus, str] = {
HotWaterStatus.LOW: "low",
HotWaterStatus.MEDIUM: "medium",
HotWaterStatus.HIGH: "high",
}
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback

View File

@ -2,6 +2,8 @@
from typing import Any
from py_aosmith.models import OperationMode as AOSmithOperationMode
from homeassistant.components.water_heater import (
STATE_ECO,
STATE_ELECTRIC,
@ -16,31 +18,25 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AOSmithData
from .const import (
AOSMITH_MODE_ELECTRIC,
AOSMITH_MODE_HEAT_PUMP,
AOSMITH_MODE_HYBRID,
AOSMITH_MODE_VACATION,
DOMAIN,
)
from .const import DOMAIN
from .coordinator import AOSmithStatusCoordinator
from .entity import AOSmithStatusEntity
MODE_HA_TO_AOSMITH = {
STATE_OFF: AOSMITH_MODE_VACATION,
STATE_ECO: AOSMITH_MODE_HYBRID,
STATE_ELECTRIC: AOSMITH_MODE_ELECTRIC,
STATE_HEAT_PUMP: AOSMITH_MODE_HEAT_PUMP,
STATE_ECO: AOSmithOperationMode.HYBRID,
STATE_ELECTRIC: AOSmithOperationMode.ELECTRIC,
STATE_HEAT_PUMP: AOSmithOperationMode.HEAT_PUMP,
STATE_OFF: AOSmithOperationMode.VACATION,
}
MODE_AOSMITH_TO_HA = {
AOSMITH_MODE_ELECTRIC: STATE_ELECTRIC,
AOSMITH_MODE_HEAT_PUMP: STATE_HEAT_PUMP,
AOSMITH_MODE_HYBRID: STATE_ECO,
AOSMITH_MODE_VACATION: STATE_OFF,
AOSmithOperationMode.ELECTRIC: STATE_ELECTRIC,
AOSmithOperationMode.HEAT_PUMP: STATE_HEAT_PUMP,
AOSmithOperationMode.HYBRID: STATE_ECO,
AOSmithOperationMode.VACATION: STATE_OFF,
}
# Operation mode to use when exiting away mode
DEFAULT_OPERATION_MODE = AOSMITH_MODE_HYBRID
DEFAULT_OPERATION_MODE = AOSmithOperationMode.HYBRID
DEFAULT_SUPPORT_FLAGS = (
WaterHeaterEntityFeature.TARGET_TEMPERATURE
@ -79,23 +75,22 @@ class AOSmithWaterHeaterEntity(AOSmithStatusEntity, WaterHeaterEntity):
@property
def operation_list(self) -> list[str]:
"""Return the list of supported operation modes."""
op_modes = []
for mode_dict in self.device_data.get("modes", []):
mode_name = mode_dict.get("mode")
ha_mode = MODE_AOSMITH_TO_HA.get(mode_name)
ha_modes = []
for supported_mode in self.device.supported_modes:
ha_mode = MODE_AOSMITH_TO_HA.get(supported_mode.mode)
# Filtering out STATE_OFF since it is handled by away mode
if ha_mode is not None and ha_mode != STATE_OFF:
op_modes.append(ha_mode)
ha_modes.append(ha_mode)
return op_modes
return ha_modes
@property
def supported_features(self) -> WaterHeaterEntityFeature:
"""Return the list of supported features."""
supports_vacation_mode = any(
mode_dict.get("mode") == AOSMITH_MODE_VACATION
for mode_dict in self.device_data.get("modes", [])
supported_mode.mode == AOSmithOperationMode.VACATION
for supported_mode in self.device.supported_modes
)
if supports_vacation_mode:
@ -106,22 +101,22 @@ class AOSmithWaterHeaterEntity(AOSmithStatusEntity, WaterHeaterEntity):
@property
def target_temperature(self) -> float | None:
"""Return the temperature we try to reach."""
return self.device_data.get("temperatureSetpoint")
return self.device.status.temperature_setpoint
@property
def max_temp(self) -> float:
"""Return the maximum temperature."""
return self.device_data.get("temperatureSetpointMaximum")
return self.device.status.temperature_setpoint_maximum
@property
def current_operation(self) -> str:
"""Return the current operation mode."""
return MODE_AOSMITH_TO_HA.get(self.device_data.get("mode"), STATE_OFF)
return MODE_AOSMITH_TO_HA.get(self.device.status.current_mode, STATE_OFF)
@property
def is_away_mode_on(self):
"""Return True if away mode is on."""
return self.device_data.get("mode") == AOSMITH_MODE_VACATION
return self.device.status.current_mode == AOSmithOperationMode.VACATION
async def async_set_operation_mode(self, operation_mode: str) -> None:
"""Set new target operation mode."""
@ -129,18 +124,19 @@ class AOSmithWaterHeaterEntity(AOSmithStatusEntity, WaterHeaterEntity):
if aosmith_mode is not None:
await self.client.update_mode(self.junction_id, aosmith_mode)
await self.coordinator.async_request_refresh()
await self.coordinator.async_request_refresh()
async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
temperature = kwargs.get("temperature")
await self.client.update_setpoint(self.junction_id, temperature)
if temperature is not None:
await self.client.update_setpoint(self.junction_id, temperature)
await self.coordinator.async_request_refresh()
await self.coordinator.async_request_refresh()
async def async_turn_away_mode_on(self) -> None:
"""Turn away mode on."""
await self.client.update_mode(self.junction_id, AOSMITH_MODE_VACATION)
await self.client.update_mode(self.junction_id, AOSmithOperationMode.VACATION)
await self.coordinator.async_request_refresh()

View File

@ -1554,7 +1554,7 @@ pushover_complete==1.1.1
pvo==2.1.1
# homeassistant.components.aosmith
py-aosmith==1.0.4
py-aosmith==1.0.6
# homeassistant.components.canary
py-canary==0.5.3

View File

@ -1201,7 +1201,7 @@ pushover_complete==1.1.1
pvo==2.1.1
# homeassistant.components.aosmith
py-aosmith==1.0.4
py-aosmith==1.0.6
# homeassistant.components.canary
py-canary==0.5.3

View File

@ -3,6 +3,16 @@ from collections.abc import Generator
from unittest.mock import AsyncMock, MagicMock, patch
from py_aosmith import AOSmithAPIClient
from py_aosmith.models import (
Device,
DeviceStatus,
DeviceType,
EnergyUseData,
EnergyUseHistoryEntry,
HotWaterStatus,
OperationMode,
SupportedOperationModeInfo,
)
import pytest
from homeassistant.components.aosmith.const import DOMAIN
@ -10,11 +20,7 @@ from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.core import HomeAssistant
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
from tests.common import (
MockConfigEntry,
load_json_array_fixture,
load_json_object_fixture,
)
from tests.common import MockConfigEntry, load_json_object_fixture
FIXTURE_USER_INPUT = {
CONF_EMAIL: "testemail@example.com",
@ -22,6 +28,80 @@ FIXTURE_USER_INPUT = {
}
def build_device_fixture(
mode_pending: bool, setpoint_pending: bool, has_vacation_mode: bool
):
"""Build a fixture for a device."""
supported_modes: list[SupportedOperationModeInfo] = [
SupportedOperationModeInfo(
mode=OperationMode.HYBRID,
original_name="HYBRID",
has_day_selection=False,
),
SupportedOperationModeInfo(
mode=OperationMode.HEAT_PUMP,
original_name="HEAT_PUMP",
has_day_selection=False,
),
SupportedOperationModeInfo(
mode=OperationMode.ELECTRIC,
original_name="ELECTRIC",
has_day_selection=True,
),
]
if has_vacation_mode:
supported_modes.append(
SupportedOperationModeInfo(
mode=OperationMode.VACATION,
original_name="VACATION",
has_day_selection=True,
)
)
return Device(
brand="aosmith",
model="HPTS-50 200 202172000",
device_type=DeviceType.NEXT_GEN_HEAT_PUMP,
dsn="dsn",
junction_id="junctionId",
name="My water heater",
serial="serial",
install_location="Basement",
supported_modes=supported_modes,
status=DeviceStatus(
firmware_version="2.14",
is_online=True,
current_mode=OperationMode.HEAT_PUMP,
mode_change_pending=mode_pending,
temperature_setpoint=130,
temperature_setpoint_pending=setpoint_pending,
temperature_setpoint_previous=130,
temperature_setpoint_maximum=130,
hot_water_status=HotWaterStatus.LOW,
),
)
ENERGY_USE_FIXTURE = EnergyUseData(
lifetime_kwh=132.825,
history=[
EnergyUseHistoryEntry(
date="2023-10-30T04:00:00.000Z",
energy_use_kwh=2.01,
),
EnergyUseHistoryEntry(
date="2023-10-31T04:00:00.000Z",
energy_use_kwh=1.542,
),
EnergyUseHistoryEntry(
date="2023-11-01T04:00:00.000Z",
energy_use_kwh=1.908,
),
],
)
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Return the default mocked config entry."""
@ -42,25 +122,44 @@ def mock_setup_entry() -> Generator[AsyncMock, None, None]:
@pytest.fixture
def get_devices_fixture() -> str:
"""Return the name of the fixture to use for get_devices."""
return "get_devices"
def get_devices_fixture_mode_pending() -> bool:
"""Return whether to set mode_pending in the get_devices fixture."""
return False
@pytest.fixture
async def mock_client(get_devices_fixture: str) -> Generator[MagicMock, None, None]:
def get_devices_fixture_setpoint_pending() -> bool:
"""Return whether to set setpoint_pending in the get_devices fixture."""
return False
@pytest.fixture
def get_devices_fixture_has_vacation_mode() -> bool:
"""Return whether to include vacation mode in the get_devices fixture."""
return True
@pytest.fixture
async def mock_client(
get_devices_fixture_mode_pending: bool,
get_devices_fixture_setpoint_pending: bool,
get_devices_fixture_has_vacation_mode: bool,
) -> Generator[MagicMock, None, None]:
"""Return a mocked client."""
get_devices_fixture = load_json_array_fixture(f"{get_devices_fixture}.json", DOMAIN)
get_energy_use_fixture = load_json_object_fixture(
"get_energy_use_data.json", DOMAIN
)
get_devices_fixture = [
build_device_fixture(
get_devices_fixture_mode_pending,
get_devices_fixture_setpoint_pending,
get_devices_fixture_has_vacation_mode,
)
]
get_all_device_info_fixture = load_json_object_fixture(
"get_all_device_info.json", DOMAIN
)
client_mock = MagicMock(AOSmithAPIClient)
client_mock.get_devices = AsyncMock(return_value=get_devices_fixture)
client_mock.get_energy_use_data = AsyncMock(return_value=get_energy_use_fixture)
client_mock.get_energy_use_data = AsyncMock(return_value=ENERGY_USE_FIXTURE)
client_mock.get_all_device_info = AsyncMock(
return_value=get_all_device_info_fixture
)

View File

@ -1,46 +0,0 @@
[
{
"brand": "aosmith",
"model": "HPTS-50 200 202172000",
"deviceType": "NEXT_GEN_HEAT_PUMP",
"dsn": "dsn",
"junctionId": "junctionId",
"name": "My water heater",
"serial": "serial",
"install": {
"location": "Basement"
},
"data": {
"__typename": "NextGenHeatPump",
"temperatureSetpoint": 130,
"temperatureSetpointPending": false,
"temperatureSetpointPrevious": 130,
"temperatureSetpointMaximum": 130,
"modes": [
{
"mode": "HYBRID",
"controls": null
},
{
"mode": "HEAT_PUMP",
"controls": null
},
{
"mode": "ELECTRIC",
"controls": "SELECT_DAYS"
},
{
"mode": "VACATION",
"controls": "SELECT_DAYS"
}
],
"isOnline": true,
"firmwareVersion": "2.14",
"hotWaterStatus": "LOW",
"mode": "HEAT_PUMP",
"modePending": false,
"vacationModeRemainingDays": 0,
"electricModeRemainingDays": 0
}
}
]

View File

@ -1,46 +0,0 @@
[
{
"brand": "aosmith",
"model": "HPTS-50 200 202172000",
"deviceType": "NEXT_GEN_HEAT_PUMP",
"dsn": "dsn",
"junctionId": "junctionId",
"name": "My water heater",
"serial": "serial",
"install": {
"location": "Basement"
},
"data": {
"__typename": "NextGenHeatPump",
"temperatureSetpoint": 130,
"temperatureSetpointPending": false,
"temperatureSetpointPrevious": 130,
"temperatureSetpointMaximum": 130,
"modes": [
{
"mode": "HYBRID",
"controls": null
},
{
"mode": "HEAT_PUMP",
"controls": null
},
{
"mode": "ELECTRIC",
"controls": "SELECT_DAYS"
},
{
"mode": "VACATION",
"controls": "SELECT_DAYS"
}
],
"isOnline": true,
"firmwareVersion": "2.14",
"hotWaterStatus": "LOW",
"mode": "HEAT_PUMP",
"modePending": true,
"vacationModeRemainingDays": 0,
"electricModeRemainingDays": 0
}
}
]

View File

@ -1,42 +0,0 @@
[
{
"brand": "aosmith",
"model": "HPTS-50 200 202172000",
"deviceType": "NEXT_GEN_HEAT_PUMP",
"dsn": "dsn",
"junctionId": "junctionId",
"name": "My water heater",
"serial": "serial",
"install": {
"location": "Basement"
},
"data": {
"__typename": "NextGenHeatPump",
"temperatureSetpoint": 130,
"temperatureSetpointPending": false,
"temperatureSetpointPrevious": 130,
"temperatureSetpointMaximum": 130,
"modes": [
{
"mode": "HYBRID",
"controls": null
},
{
"mode": "HEAT_PUMP",
"controls": null
},
{
"mode": "ELECTRIC",
"controls": "SELECT_DAYS"
}
],
"isOnline": true,
"firmwareVersion": "2.14",
"hotWaterStatus": "LOW",
"mode": "HEAT_PUMP",
"modePending": false,
"vacationModeRemainingDays": 0,
"electricModeRemainingDays": 0
}
}
]

View File

@ -1,46 +0,0 @@
[
{
"brand": "aosmith",
"model": "HPTS-50 200 202172000",
"deviceType": "NEXT_GEN_HEAT_PUMP",
"dsn": "dsn",
"junctionId": "junctionId",
"name": "My water heater",
"serial": "serial",
"install": {
"location": "Basement"
},
"data": {
"__typename": "NextGenHeatPump",
"temperatureSetpoint": 130,
"temperatureSetpointPending": true,
"temperatureSetpointPrevious": 130,
"temperatureSetpointMaximum": 130,
"modes": [
{
"mode": "HYBRID",
"controls": null
},
{
"mode": "HEAT_PUMP",
"controls": null
},
{
"mode": "ELECTRIC",
"controls": "SELECT_DAYS"
},
{
"mode": "VACATION",
"controls": "SELECT_DAYS"
}
],
"isOnline": true,
"firmwareVersion": "2.14",
"hotWaterStatus": "LOW",
"mode": "HEAT_PUMP",
"modePending": false,
"vacationModeRemainingDays": 0,
"electricModeRemainingDays": 0
}
}
]

View File

@ -1,19 +0,0 @@
{
"average": 2.7552000000000003,
"graphData": [
{
"date": "2023-10-30T04:00:00.000Z",
"kwh": 2.01
},
{
"date": "2023-10-31T04:00:00.000Z",
"kwh": 1.542
},
{
"date": "2023-11-01T04:00:00.000Z",
"kwh": 1.908
}
],
"lifetimeKwh": 132.825,
"startDate": "Oct 30"
}

View File

@ -15,11 +15,9 @@ from homeassistant.components.aosmith.const import (
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_json_array_fixture,
)
from .conftest import build_device_fixture
from tests.common import MockConfigEntry, async_fire_time_changed
async def test_config_entry_setup(init_integration: MockConfigEntry) -> None:
@ -52,7 +50,7 @@ async def test_config_entry_not_ready_get_energy_use_data_error(
"""Test the config entry not ready when get_energy_use_data fails."""
mock_config_entry.add_to_hass(hass)
get_devices_fixture = load_json_array_fixture("get_devices.json", DOMAIN)
get_devices_fixture = [build_device_fixture(False, False, True)]
with patch(
"homeassistant.components.aosmith.config_flow.AOSmithAPIClient.get_devices",
@ -68,12 +66,17 @@ async def test_config_entry_not_ready_get_energy_use_data_error(
@pytest.mark.parametrize(
("get_devices_fixture", "time_to_wait", "expected_call_count"),
(
"get_devices_fixture_mode_pending",
"get_devices_fixture_setpoint_pending",
"time_to_wait",
"expected_call_count",
),
[
("get_devices", REGULAR_INTERVAL, 1),
("get_devices", FAST_INTERVAL, 0),
("get_devices_mode_pending", FAST_INTERVAL, 1),
("get_devices_setpoint_pending", FAST_INTERVAL, 1),
(False, False, REGULAR_INTERVAL, 1),
(False, False, FAST_INTERVAL, 0),
(True, False, FAST_INTERVAL, 1),
(False, True, FAST_INTERVAL, 1),
],
)
async def test_update(

View File

@ -2,15 +2,10 @@
from unittest.mock import MagicMock
from py_aosmith.models import OperationMode
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.aosmith.const import (
AOSMITH_MODE_ELECTRIC,
AOSMITH_MODE_HEAT_PUMP,
AOSMITH_MODE_HYBRID,
AOSMITH_MODE_VACATION,
)
from homeassistant.components.water_heater import (
ATTR_AWAY_MODE,
ATTR_OPERATION_MODE,
@ -59,8 +54,8 @@ async def test_state(
@pytest.mark.parametrize(
("get_devices_fixture"),
["get_devices_no_vacation_mode"],
("get_devices_fixture_has_vacation_mode"),
[False],
)
async def test_state_away_mode_unsupported(
hass: HomeAssistant, init_integration: MockConfigEntry
@ -77,9 +72,9 @@ async def test_state_away_mode_unsupported(
@pytest.mark.parametrize(
("hass_mode", "aosmith_mode"),
[
(STATE_HEAT_PUMP, AOSMITH_MODE_HEAT_PUMP),
(STATE_ECO, AOSMITH_MODE_HYBRID),
(STATE_ELECTRIC, AOSMITH_MODE_ELECTRIC),
(STATE_HEAT_PUMP, OperationMode.HEAT_PUMP),
(STATE_ECO, OperationMode.HYBRID),
(STATE_ELECTRIC, OperationMode.ELECTRIC),
],
)
async def test_set_operation_mode(
@ -122,8 +117,8 @@ async def test_set_temperature(
@pytest.mark.parametrize(
("hass_away_mode", "aosmith_mode"),
[
(True, AOSMITH_MODE_VACATION),
(False, AOSMITH_MODE_HYBRID),
(True, OperationMode.VACATION),
(False, OperationMode.HYBRID),
],
)
async def test_away_mode(