Adjust HomeWizard to use updated python-homewizard-energy library (#135046)

This commit is contained in:
Duco Sebel 2025-01-10 13:19:55 +01:00 committed by GitHub
parent 1f0eda8e47
commit f31f6d7ed0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 723 additions and 787 deletions

View File

@ -19,7 +19,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Identify button."""
if entry.runtime_data.supports_identify():
if entry.runtime_data.data.device.supports_identify():
async_add_entities([HomeWizardIdentifyButton(entry.runtime_data)])

View File

@ -8,7 +8,7 @@ from typing import Any, NamedTuple
from homewizard_energy import HomeWizardEnergyV1
from homewizard_energy.errors import DisabledError, RequestError, UnsupportedError
from homewizard_energy.v1.models import Device
from homewizard_energy.models import Device
import voluptuous as vol
from homeassistant.components import onboarding, zeroconf
@ -206,6 +206,7 @@ class HomeWizardConfigFlow(ConfigFlow, domain=DOMAIN):
if user_input:
try:
device_info = await self._async_try_connect(user_input[CONF_IP_ADDRESS])
except RecoverableError as ex:
_LOGGER.error(ex)
errors = {"base": ex.error_code}

View File

@ -2,12 +2,9 @@
from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
import logging
from homewizard_energy.v1.models import Data, Device, State, System
from homeassistant.const import Platform
DOMAIN = "homewizard"
@ -23,13 +20,3 @@ CONF_PRODUCT_TYPE = "product_type"
CONF_SERIAL = "serial"
UPDATE_INTERVAL = timedelta(seconds=5)
@dataclass
class DeviceResponseEntry:
"""Dict describing a single response entry."""
device: Device
data: Data
state: State | None = None
system: System | None = None

View File

@ -4,10 +4,9 @@ from __future__ import annotations
import logging
from homewizard_energy import HomeWizardEnergyV1
from homewizard_energy.errors import DisabledError, RequestError, UnsupportedError
from homewizard_energy.v1.const import SUPPORTS_IDENTIFY, SUPPORTS_STATE
from homewizard_energy.v1.models import Device
from homewizard_energy import HomeWizardEnergy, HomeWizardEnergyV1
from homewizard_energy.errors import DisabledError, RequestError
from homewizard_energy.models import CombinedModels as DeviceResponseEntry
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_IP_ADDRESS
@ -15,7 +14,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN, UPDATE_INTERVAL, DeviceResponseEntry
from .const import DOMAIN, UPDATE_INTERVAL
_LOGGER = logging.getLogger(__name__)
@ -23,11 +22,9 @@ _LOGGER = logging.getLogger(__name__)
class HWEnergyDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceResponseEntry]):
"""Gather data for the energy device."""
api: HomeWizardEnergyV1
api: HomeWizardEnergy
api_disabled: bool = False
_unsupported_error: bool = False
config_entry: ConfigEntry
def __init__(
@ -44,26 +41,7 @@ class HWEnergyDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceResponseEntry]
async def _async_update_data(self) -> DeviceResponseEntry:
"""Fetch all device and sensor data from api."""
try:
data = DeviceResponseEntry(
device=await self.api.device(),
data=await self.api.data(),
)
try:
if self.supports_state(data.device):
data.state = await self.api.state()
data.system = await self.api.system()
except UnsupportedError as ex:
# Old firmware, ignore
if not self._unsupported_error:
self._unsupported_error = True
_LOGGER.warning(
"%s is running an outdated firmware version (%s). Contact HomeWizard support to update your device",
self.config_entry.title,
ex,
)
data = await self.api.combined()
except RequestError as ex:
raise UpdateFailed(
@ -89,18 +67,3 @@ class HWEnergyDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceResponseEntry]
self.data = data
return data
def supports_state(self, device: Device | None = None) -> bool:
"""Return True if the device supports state."""
if device is None:
device = self.data.device
return device.product_type in SUPPORTS_STATE
def supports_identify(self, device: Device | None = None) -> bool:
"""Return True if the device supports identify."""
if device is None:
device = self.data.device
return device.product_type in SUPPORTS_IDENTIFY

View File

@ -13,11 +13,12 @@ from . import HomeWizardConfigEntry
TO_REDACT = {
CONF_IP_ADDRESS,
"serial",
"wifi_ssid",
"unique_meter_id",
"unique_id",
"gas_unique_id",
"id",
"serial",
"unique_id",
"unique_meter_id",
"wifi_ssid",
}
@ -27,23 +28,10 @@ async def async_get_config_entry_diagnostics(
"""Return diagnostics for a config entry."""
data = entry.runtime_data.data
state: dict[str, Any] | None = None
if data.state:
state = asdict(data.state)
system: dict[str, Any] | None = None
if data.system:
system = asdict(data.system)
return async_redact_data(
{
"entry": async_redact_data(entry.data, TO_REDACT),
"data": {
"device": asdict(data.device),
"data": asdict(data.data),
"state": state,
"system": system,
},
"data": asdict(data),
},
TO_REDACT,
)

View File

@ -22,9 +22,7 @@ class HomeWizardEntity(CoordinatorEntity[HWEnergyDeviceUpdateCoordinator]):
manufacturer="HomeWizard",
sw_version=coordinator.data.device.firmware_version,
model_id=coordinator.data.device.product_type,
model=coordinator.data.device.product.name
if coordinator.data.device.product
else None,
model=coordinator.data.device.model_name,
)
if (serial_number := coordinator.data.device.serial) is not None:

View File

@ -12,6 +12,6 @@
"iot_class": "local_polling",
"loggers": ["homewizard_energy"],
"quality_scale": "platinum",
"requirements": ["python-homewizard-energy==v7.0.1"],
"requirements": ["python-homewizard-energy==v8.0.0"],
"zeroconf": ["_hwenergy._tcp.local."]
}

View File

@ -6,7 +6,6 @@ from homeassistant.components.number import NumberEntity
from homeassistant.const import PERCENTAGE, EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.color import brightness_to_value, value_to_brightness
from . import HomeWizardConfigEntry
from .coordinator import HWEnergyDeviceUpdateCoordinator
@ -22,7 +21,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up numbers for device."""
if entry.runtime_data.supports_state():
if entry.runtime_data.data.device.supports_state():
async_add_entities([HWEnergyNumberEntity(entry.runtime_data)])
@ -46,22 +45,21 @@ class HWEnergyNumberEntity(HomeWizardEntity, NumberEntity):
@homewizard_exception_handler
async def async_set_native_value(self, value: float) -> None:
"""Set a new value."""
await self.coordinator.api.state_set(
brightness=value_to_brightness((0, 100), value)
)
await self.coordinator.api.system(status_led_brightness_pct=int(value))
await self.coordinator.async_refresh()
@property
def available(self) -> bool:
"""Return if entity is available."""
return super().available and self.coordinator.data.state is not None
return super().available and self.coordinator.data.system is not None
@property
def native_value(self) -> float | None:
"""Return the current value."""
if (
not self.coordinator.data.state
or (brightness := self.coordinator.data.state.brightness) is None
not self.coordinator.data.system
or (brightness := self.coordinator.data.system.status_led_brightness_pct)
is None
):
return None
return round(brightness_to_value((0, 100), brightness))
return round(brightness)

View File

@ -6,7 +6,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from typing import Final
from homewizard_energy.v1.models import Data, ExternalDevice
from homewizard_energy.models import ExternalDevice, Measurement
from homeassistant.components.sensor import (
DEVICE_CLASS_UNITS,
@ -46,9 +46,9 @@ PARALLEL_UPDATES = 1
class HomeWizardSensorEntityDescription(SensorEntityDescription):
"""Class describing HomeWizard sensor entities."""
enabled_fn: Callable[[Data], bool] = lambda data: True
has_fn: Callable[[Data], bool]
value_fn: Callable[[Data], StateType]
enabled_fn: Callable[[Measurement], bool] = lambda x: True
has_fn: Callable[[Measurement], bool]
value_fn: Callable[[Measurement], StateType]
@dataclass(frozen=True, kw_only=True)
@ -69,8 +69,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
key="smr_version",
translation_key="dsmr_version",
entity_category=EntityCategory.DIAGNOSTIC,
has_fn=lambda data: data.smr_version is not None,
value_fn=lambda data: data.smr_version,
has_fn=lambda data: data.protocol_version is not None,
value_fn=lambda data: data.protocol_version,
),
HomeWizardSensorEntityDescription(
key="meter_model",
@ -83,8 +83,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
key="unique_meter_id",
translation_key="unique_meter_id",
entity_category=EntityCategory.DIAGNOSTIC,
has_fn=lambda data: data.unique_meter_id is not None,
value_fn=lambda data: data.unique_meter_id,
has_fn=lambda data: data.unique_id is not None,
value_fn=lambda data: data.unique_id,
),
HomeWizardSensorEntityDescription(
key="wifi_ssid",
@ -96,10 +96,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
HomeWizardSensorEntityDescription(
key="active_tariff",
translation_key="active_tariff",
has_fn=lambda data: data.active_tariff is not None,
value_fn=lambda data: (
None if data.active_tariff is None else str(data.active_tariff)
),
has_fn=lambda data: data.tariff is not None,
value_fn=lambda data: None if data.tariff is None else str(data.tariff),
device_class=SensorDeviceClass.ENUM,
options=["1", "2", "3", "4"],
),
@ -119,8 +117,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_import_kwh is not None,
value_fn=lambda data: data.total_energy_import_kwh,
has_fn=lambda data: data.energy_import_kwh is not None,
value_fn=lambda data: data.energy_import_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_import_t1_kwh",
@ -131,10 +129,10 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: (
# SKT/SDM230/630 provides both total and tariff 1: duplicate.
data.total_energy_import_t1_kwh is not None
and data.total_energy_export_t2_kwh is not None
data.energy_import_t1_kwh is not None
and data.energy_export_t2_kwh is not None
),
value_fn=lambda data: data.total_energy_import_t1_kwh,
value_fn=lambda data: data.energy_import_t1_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_import_t2_kwh",
@ -143,8 +141,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_import_t2_kwh is not None,
value_fn=lambda data: data.total_energy_import_t2_kwh,
has_fn=lambda data: data.energy_import_t2_kwh is not None,
value_fn=lambda data: data.energy_import_t2_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_import_t3_kwh",
@ -153,8 +151,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_import_t3_kwh is not None,
value_fn=lambda data: data.total_energy_import_t3_kwh,
has_fn=lambda data: data.energy_import_t3_kwh is not None,
value_fn=lambda data: data.energy_import_t3_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_import_t4_kwh",
@ -163,8 +161,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_import_t4_kwh is not None,
value_fn=lambda data: data.total_energy_import_t4_kwh,
has_fn=lambda data: data.energy_import_t4_kwh is not None,
value_fn=lambda data: data.energy_import_t4_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_export_kwh",
@ -172,9 +170,9 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_export_kwh is not None,
enabled_fn=lambda data: data.total_energy_export_kwh != 0,
value_fn=lambda data: data.total_energy_export_kwh,
has_fn=lambda data: data.energy_export_kwh is not None,
enabled_fn=lambda data: data.energy_export_kwh != 0,
value_fn=lambda data: data.energy_export_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_export_t1_kwh",
@ -185,11 +183,11 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: (
# SKT/SDM230/630 provides both total and tariff 1: duplicate.
data.total_energy_export_t1_kwh is not None
and data.total_energy_export_t2_kwh is not None
data.energy_export_t1_kwh is not None
and data.energy_export_t2_kwh is not None
),
enabled_fn=lambda data: data.total_energy_export_t1_kwh != 0,
value_fn=lambda data: data.total_energy_export_t1_kwh,
enabled_fn=lambda data: data.energy_export_t1_kwh != 0,
value_fn=lambda data: data.energy_export_t1_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_export_t2_kwh",
@ -198,9 +196,9 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_export_t2_kwh is not None,
enabled_fn=lambda data: data.total_energy_export_t2_kwh != 0,
value_fn=lambda data: data.total_energy_export_t2_kwh,
has_fn=lambda data: data.energy_export_t2_kwh is not None,
enabled_fn=lambda data: data.energy_export_t2_kwh != 0,
value_fn=lambda data: data.energy_export_t2_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_export_t3_kwh",
@ -209,9 +207,9 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_export_t3_kwh is not None,
enabled_fn=lambda data: data.total_energy_export_t3_kwh != 0,
value_fn=lambda data: data.total_energy_export_t3_kwh,
has_fn=lambda data: data.energy_export_t3_kwh is not None,
enabled_fn=lambda data: data.energy_export_t3_kwh != 0,
value_fn=lambda data: data.energy_export_t3_kwh,
),
HomeWizardSensorEntityDescription(
key="total_power_export_t4_kwh",
@ -220,9 +218,9 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
has_fn=lambda data: data.total_energy_export_t4_kwh is not None,
enabled_fn=lambda data: data.total_energy_export_t4_kwh != 0,
value_fn=lambda data: data.total_energy_export_t4_kwh,
has_fn=lambda data: data.energy_export_t4_kwh is not None,
enabled_fn=lambda data: data.energy_export_t4_kwh != 0,
value_fn=lambda data: data.energy_export_t4_kwh,
),
HomeWizardSensorEntityDescription(
key="active_power_w",
@ -230,8 +228,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
has_fn=lambda data: data.active_power_w is not None,
value_fn=lambda data: data.active_power_w,
has_fn=lambda data: data.power_w is not None,
value_fn=lambda data: data.power_w,
),
HomeWizardSensorEntityDescription(
key="active_power_l1_w",
@ -241,8 +239,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
has_fn=lambda data: data.active_power_l1_w is not None,
value_fn=lambda data: data.active_power_l1_w,
has_fn=lambda data: data.power_l1_w is not None,
value_fn=lambda data: data.power_l1_w,
),
HomeWizardSensorEntityDescription(
key="active_power_l2_w",
@ -252,8 +250,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
has_fn=lambda data: data.active_power_l2_w is not None,
value_fn=lambda data: data.active_power_l2_w,
has_fn=lambda data: data.power_l2_w is not None,
value_fn=lambda data: data.power_l2_w,
),
HomeWizardSensorEntityDescription(
key="active_power_l3_w",
@ -263,8 +261,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
has_fn=lambda data: data.active_power_l3_w is not None,
value_fn=lambda data: data.active_power_l3_w,
has_fn=lambda data: data.power_l3_w is not None,
value_fn=lambda data: data.power_l3_w,
),
HomeWizardSensorEntityDescription(
key="active_voltage_v",
@ -272,8 +270,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_voltage_v is not None,
value_fn=lambda data: data.active_voltage_v,
has_fn=lambda data: data.voltage_v is not None,
value_fn=lambda data: data.voltage_v,
),
HomeWizardSensorEntityDescription(
key="active_voltage_l1_v",
@ -283,8 +281,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_voltage_l1_v is not None,
value_fn=lambda data: data.active_voltage_l1_v,
has_fn=lambda data: data.voltage_l1_v is not None,
value_fn=lambda data: data.voltage_l1_v,
),
HomeWizardSensorEntityDescription(
key="active_voltage_l2_v",
@ -294,8 +292,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_voltage_l2_v is not None,
value_fn=lambda data: data.active_voltage_l2_v,
has_fn=lambda data: data.voltage_l2_v is not None,
value_fn=lambda data: data.voltage_l2_v,
),
HomeWizardSensorEntityDescription(
key="active_voltage_l3_v",
@ -305,8 +303,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_voltage_l3_v is not None,
value_fn=lambda data: data.active_voltage_l3_v,
has_fn=lambda data: data.voltage_l3_v is not None,
value_fn=lambda data: data.voltage_l3_v,
),
HomeWizardSensorEntityDescription(
key="active_current_a",
@ -314,8 +312,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_current_a is not None,
value_fn=lambda data: data.active_current_a,
has_fn=lambda data: data.current_a is not None,
value_fn=lambda data: data.current_a,
),
HomeWizardSensorEntityDescription(
key="active_current_l1_a",
@ -325,8 +323,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_current_l1_a is not None,
value_fn=lambda data: data.active_current_l1_a,
has_fn=lambda data: data.current_l1_a is not None,
value_fn=lambda data: data.current_l1_a,
),
HomeWizardSensorEntityDescription(
key="active_current_l2_a",
@ -336,8 +334,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_current_l2_a is not None,
value_fn=lambda data: data.active_current_l2_a,
has_fn=lambda data: data.current_l2_a is not None,
value_fn=lambda data: data.current_l2_a,
),
HomeWizardSensorEntityDescription(
key="active_current_l3_a",
@ -347,8 +345,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_current_l3_a is not None,
value_fn=lambda data: data.active_current_l3_a,
has_fn=lambda data: data.current_l3_a is not None,
value_fn=lambda data: data.current_l3_a,
),
HomeWizardSensorEntityDescription(
key="active_frequency_hz",
@ -356,8 +354,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.FREQUENCY,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_frequency_hz is not None,
value_fn=lambda data: data.active_frequency_hz,
has_fn=lambda data: data.frequency_hz is not None,
value_fn=lambda data: data.frequency_hz,
),
HomeWizardSensorEntityDescription(
key="active_apparent_power_va",
@ -365,8 +363,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.APPARENT_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_apparent_power_va is not None,
value_fn=lambda data: data.active_apparent_power_va,
has_fn=lambda data: data.apparent_power_va is not None,
value_fn=lambda data: data.apparent_power_va,
),
HomeWizardSensorEntityDescription(
key="active_apparent_power_l1_va",
@ -376,8 +374,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.APPARENT_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_apparent_power_l1_va is not None,
value_fn=lambda data: data.active_apparent_power_l1_va,
has_fn=lambda data: data.apparent_power_l1_va is not None,
value_fn=lambda data: data.apparent_power_l1_va,
),
HomeWizardSensorEntityDescription(
key="active_apparent_power_l2_va",
@ -387,8 +385,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.APPARENT_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_apparent_power_l2_va is not None,
value_fn=lambda data: data.active_apparent_power_l2_va,
has_fn=lambda data: data.apparent_power_l2_va is not None,
value_fn=lambda data: data.apparent_power_l2_va,
),
HomeWizardSensorEntityDescription(
key="active_apparent_power_l3_va",
@ -398,8 +396,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.APPARENT_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_apparent_power_l3_va is not None,
value_fn=lambda data: data.active_apparent_power_l3_va,
has_fn=lambda data: data.apparent_power_l3_va is not None,
value_fn=lambda data: data.apparent_power_l3_va,
),
HomeWizardSensorEntityDescription(
key="active_reactive_power_var",
@ -407,8 +405,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.REACTIVE_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_reactive_power_var is not None,
value_fn=lambda data: data.active_reactive_power_var,
has_fn=lambda data: data.reactive_power_var is not None,
value_fn=lambda data: data.reactive_power_var,
),
HomeWizardSensorEntityDescription(
key="active_reactive_power_l1_var",
@ -418,8 +416,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.REACTIVE_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_reactive_power_l1_var is not None,
value_fn=lambda data: data.active_reactive_power_l1_var,
has_fn=lambda data: data.reactive_power_l1_var is not None,
value_fn=lambda data: data.reactive_power_l1_var,
),
HomeWizardSensorEntityDescription(
key="active_reactive_power_l2_var",
@ -429,8 +427,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.REACTIVE_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_reactive_power_l2_var is not None,
value_fn=lambda data: data.active_reactive_power_l2_var,
has_fn=lambda data: data.reactive_power_l2_var is not None,
value_fn=lambda data: data.reactive_power_l2_var,
),
HomeWizardSensorEntityDescription(
key="active_reactive_power_l3_var",
@ -440,8 +438,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.REACTIVE_POWER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_reactive_power_l3_var is not None,
value_fn=lambda data: data.active_reactive_power_l3_var,
has_fn=lambda data: data.reactive_power_l3_var is not None,
value_fn=lambda data: data.reactive_power_l3_var,
),
HomeWizardSensorEntityDescription(
key="active_power_factor",
@ -449,8 +447,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_power_factor is not None,
value_fn=lambda data: to_percentage(data.active_power_factor),
has_fn=lambda data: data.power_factor is not None,
value_fn=lambda data: to_percentage(data.power_factor),
),
HomeWizardSensorEntityDescription(
key="active_power_factor_l1",
@ -460,8 +458,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_power_factor_l1 is not None,
value_fn=lambda data: to_percentage(data.active_power_factor_l1),
has_fn=lambda data: data.power_factor_l1 is not None,
value_fn=lambda data: to_percentage(data.power_factor_l1),
),
HomeWizardSensorEntityDescription(
key="active_power_factor_l2",
@ -471,8 +469,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_power_factor_l2 is not None,
value_fn=lambda data: to_percentage(data.active_power_factor_l2),
has_fn=lambda data: data.power_factor_l2 is not None,
value_fn=lambda data: to_percentage(data.power_factor_l2),
),
HomeWizardSensorEntityDescription(
key="active_power_factor_l3",
@ -482,8 +480,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
has_fn=lambda data: data.active_power_factor_l3 is not None,
value_fn=lambda data: to_percentage(data.active_power_factor_l3),
has_fn=lambda data: data.power_factor_l3 is not None,
value_fn=lambda data: to_percentage(data.power_factor_l3),
),
HomeWizardSensorEntityDescription(
key="voltage_sag_l1_count",
@ -552,8 +550,8 @@ SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = (
translation_key="active_power_average_w",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
has_fn=lambda data: data.active_power_average_w is not None,
value_fn=lambda data: data.active_power_average_w,
has_fn=lambda data: data.average_power_15m_w is not None,
value_fn=lambda data: data.average_power_15m_w,
),
HomeWizardSensorEntityDescription(
key="monthly_power_peak_w",
@ -624,19 +622,21 @@ async def async_setup_entry(
) -> None:
"""Initialize sensors."""
data = entry.runtime_data.data.data
measurement = entry.runtime_data.data.measurement
# Initialize default sensors
entities: list = [
HomeWizardSensorEntity(entry.runtime_data, description)
for description in SENSORS
if description.has_fn(data)
if description.has_fn(measurement)
]
# Initialize external devices
if data.external_devices is not None:
for unique_id, device in data.external_devices.items():
if description := EXTERNAL_SENSORS.get(device.meter_type):
if measurement.external_devices is not None:
for unique_id, device in measurement.external_devices.items():
if device.type is not None and (
description := EXTERNAL_SENSORS.get(device.type)
):
# Add external device
entities.append(
HomeWizardExternalSensorEntity(
@ -661,13 +661,13 @@ class HomeWizardSensorEntity(HomeWizardEntity, SensorEntity):
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.config_entry.unique_id}_{description.key}"
if not description.enabled_fn(self.coordinator.data.data):
if not description.enabled_fn(self.coordinator.data.measurement):
self._attr_entity_registry_enabled_default = False
@property
def native_value(self) -> StateType:
"""Return the sensor value."""
return self.entity_description.value_fn(self.coordinator.data.data)
return self.entity_description.value_fn(self.coordinator.data.measurement)
@property
def available(self) -> bool:
@ -712,8 +712,8 @@ class HomeWizardExternalSensorEntity(HomeWizardEntity, SensorEntity):
def device(self) -> ExternalDevice | None:
"""Return ExternalDevice object."""
return (
self.coordinator.data.data.external_devices[self._device_id]
if self.coordinator.data.data.external_devices is not None
self.coordinator.data.measurement.external_devices[self._device_id]
if self.coordinator.data.measurement.external_devices is not None
else None
)

View File

@ -6,7 +6,8 @@ from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any
from homewizard_energy import HomeWizardEnergyV1
from homewizard_energy import HomeWizardEnergy
from homewizard_energy.models import CombinedModels as DeviceResponseEntry
from homeassistant.components.switch import (
SwitchDeviceClass,
@ -18,7 +19,6 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import HomeWizardConfigEntry
from .const import DeviceResponseEntry
from .coordinator import HWEnergyDeviceUpdateCoordinator
from .entity import HomeWizardEntity
from .helpers import homewizard_exception_handler
@ -31,9 +31,9 @@ class HomeWizardSwitchEntityDescription(SwitchEntityDescription):
"""Class describing HomeWizard switch entities."""
available_fn: Callable[[DeviceResponseEntry], bool]
create_fn: Callable[[HWEnergyDeviceUpdateCoordinator], bool]
create_fn: Callable[[DeviceResponseEntry], bool]
is_on_fn: Callable[[DeviceResponseEntry], bool | None]
set_fn: Callable[[HomeWizardEnergyV1, bool], Awaitable[Any]]
set_fn: Callable[[HomeWizardEnergy, bool], Awaitable[Any]]
SWITCHES = [
@ -41,28 +41,28 @@ SWITCHES = [
key="power_on",
name=None,
device_class=SwitchDeviceClass.OUTLET,
create_fn=lambda coordinator: coordinator.supports_state(),
available_fn=lambda data: data.state is not None and not data.state.switch_lock,
is_on_fn=lambda data: data.state.power_on if data.state else None,
set_fn=lambda api, active: api.state_set(power_on=active),
create_fn=lambda x: x.device.supports_state(),
available_fn=lambda x: x.state is not None and not x.state.switch_lock,
is_on_fn=lambda x: x.state.power_on if x.state else None,
set_fn=lambda api, active: api.state(power_on=active),
),
HomeWizardSwitchEntityDescription(
key="switch_lock",
translation_key="switch_lock",
entity_category=EntityCategory.CONFIG,
create_fn=lambda coordinator: coordinator.supports_state(),
available_fn=lambda data: data.state is not None,
is_on_fn=lambda data: data.state.switch_lock if data.state else None,
set_fn=lambda api, active: api.state_set(switch_lock=active),
create_fn=lambda x: x.device.supports_state(),
available_fn=lambda x: x.state is not None,
is_on_fn=lambda x: x.state.switch_lock if x.state else None,
set_fn=lambda api, active: api.state(switch_lock=active),
),
HomeWizardSwitchEntityDescription(
key="cloud_connection",
translation_key="cloud_connection",
entity_category=EntityCategory.CONFIG,
create_fn=lambda _: True,
available_fn=lambda data: data.system is not None,
is_on_fn=lambda data: data.system.cloud_enabled if data.system else None,
set_fn=lambda api, active: api.system_set(cloud_enabled=active),
available_fn=lambda x: x.system is not None,
is_on_fn=lambda x: x.system.cloud_enabled if x.system else None,
set_fn=lambda api, active: api.system(cloud_enabled=active),
),
]
@ -76,7 +76,7 @@ async def async_setup_entry(
async_add_entities(
HomeWizardSwitchEntity(entry.runtime_data, description)
for description in SWITCHES
if description.create_fn(entry.runtime_data)
if description.create_fn(entry.runtime_data.data)
)

2
requirements_all.txt generated
View File

@ -2381,7 +2381,7 @@ python-gitlab==1.6.0
python-homeassistant-analytics==0.8.1
# homeassistant.components.homewizard
python-homewizard-energy==v7.0.1
python-homewizard-energy==v8.0.0
# homeassistant.components.hp_ilo
python-hpilo==4.4.3

View File

@ -1923,7 +1923,7 @@ python-fullykiosk==0.0.14
python-homeassistant-analytics==0.8.1
# homeassistant.components.homewizard
python-homewizard-energy==v7.0.1
python-homewizard-energy==v8.0.0
# homeassistant.components.izone
python-izone==1.2.9

View File

@ -3,8 +3,7 @@
from collections.abc import Generator
from unittest.mock import AsyncMock, MagicMock, patch
from homewizard_energy.errors import NotFoundError
from homewizard_energy.v1.models import Data, Device, State, System
from homewizard_energy.models import CombinedModels, Device, Measurement, State, System
import pytest
from homeassistant.components.homewizard.const import DOMAIN
@ -37,26 +36,31 @@ def mock_homewizardenergy(
):
client = homewizard.return_value
client.device.return_value = Device.from_dict(
load_json_object_fixture(f"{device_fixture}/device.json", DOMAIN)
)
client.data.return_value = Data.from_dict(
load_json_object_fixture(f"{device_fixture}/data.json", DOMAIN)
client.combined.return_value = CombinedModels(
device=Device.from_dict(
load_json_object_fixture(f"{device_fixture}/device.json", DOMAIN)
),
measurement=Measurement.from_dict(
load_json_object_fixture(f"{device_fixture}/data.json", DOMAIN)
),
state=(
State.from_dict(
load_json_object_fixture(f"{device_fixture}/state.json", DOMAIN)
)
if get_fixture_path(f"{device_fixture}/state.json", DOMAIN).exists()
else None
),
system=(
System.from_dict(
load_json_object_fixture(f"{device_fixture}/system.json", DOMAIN)
)
if get_fixture_path(f"{device_fixture}/system.json", DOMAIN).exists()
else None
),
)
if get_fixture_path(f"{device_fixture}/state.json", DOMAIN).exists():
client.state.return_value = State.from_dict(
load_json_object_fixture(f"{device_fixture}/state.json", DOMAIN)
)
else:
client.state.side_effect = NotFoundError
if get_fixture_path(f"{device_fixture}/system.json", DOMAIN).exists():
client.system.return_value = System.from_dict(
load_json_object_fixture(f"{device_fixture}/system.json", DOMAIN)
)
else:
client.system.side_effect = NotFoundError
# device() call is used during configuration flow
client.device.return_value = client.combined.return_value.device
yield client

File diff suppressed because it is too large Load Diff

View File

@ -431,7 +431,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '50',
'state': '50.0',
})
# ---
# name: test_sensors[HWE-KWH1-entity_ids7][sensor.device_power:device-registry]
@ -1124,7 +1124,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-KWH3-entity_ids8][sensor.device_apparent_power_phase_2:device-registry]
@ -1472,7 +1472,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-KWH3-entity_ids8][sensor.device_current_phase_2:device-registry]
@ -2084,7 +2084,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '100',
'state': '100.0',
})
# ---
# name: test_sensors[HWE-KWH3-entity_ids8][sensor.device_power_factor_phase_2:device-registry]
@ -2702,7 +2702,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-KWH3-entity_ids8][sensor.device_reactive_power_phase_2:device-registry]
@ -3476,7 +3476,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '-4',
'state': '-4.0',
})
# ---
# name: test_sensors[HWE-P1-entity_ids0][sensor.device_current_phase_2:device-registry]
@ -3563,7 +3563,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2',
'state': '2.0',
})
# ---
# name: test_sensors[HWE-P1-entity_ids0][sensor.device_current_phase_3:device-registry]
@ -3650,7 +3650,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-P1-entity_ids0][sensor.device_dsmr_version:device-registry]
@ -4689,7 +4689,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '50',
'state': '50.0',
})
# ---
# name: test_sensors[HWE-P1-entity_ids0][sensor.device_long_power_failures_detected:device-registry]
@ -4945,7 +4945,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '-123',
'state': '-123.0',
})
# ---
# name: test_sensors[HWE-P1-entity_ids0][sensor.device_power_failures_detected:device-registry]
@ -5117,7 +5117,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '-123',
'state': '-123.0',
})
# ---
# name: test_sensors[HWE-P1-entity_ids0][sensor.device_power_phase_2:device-registry]
@ -5207,7 +5207,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '456',
'state': '456.0',
})
# ---
# name: test_sensors[HWE-P1-entity_ids0][sensor.device_power_phase_3:device-registry]
@ -7236,7 +7236,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '-4',
'state': '-4.0',
})
# ---
# name: test_sensors[HWE-P1-invalid-EAN-entity_ids9][sensor.device_current_phase_2:device-registry]
@ -7323,7 +7323,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2',
'state': '2.0',
})
# ---
# name: test_sensors[HWE-P1-invalid-EAN-entity_ids9][sensor.device_current_phase_3:device-registry]
@ -7410,7 +7410,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-P1-invalid-EAN-entity_ids9][sensor.device_dsmr_version:device-registry]
@ -8449,7 +8449,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '50',
'state': '50.0',
})
# ---
# name: test_sensors[HWE-P1-invalid-EAN-entity_ids9][sensor.device_long_power_failures_detected:device-registry]
@ -8705,7 +8705,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '-123',
'state': '-123.0',
})
# ---
# name: test_sensors[HWE-P1-invalid-EAN-entity_ids9][sensor.device_power_failures_detected:device-registry]
@ -8877,7 +8877,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '-123',
'state': '-123.0',
})
# ---
# name: test_sensors[HWE-P1-invalid-EAN-entity_ids9][sensor.device_power_phase_2:device-registry]
@ -8967,7 +8967,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '456',
'state': '456.0',
})
# ---
# name: test_sensors[HWE-P1-invalid-EAN-entity_ids9][sensor.device_power_phase_3:device-registry]
@ -10909,7 +10909,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-P1-zero-values-entity_ids1][sensor.device_current_phase_1:device-registry]
@ -10996,7 +10996,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-P1-zero-values-entity_ids1][sensor.device_current_phase_2:device-registry]
@ -11083,7 +11083,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-P1-zero-values-entity_ids1][sensor.device_current_phase_3:device-registry]
@ -11170,7 +11170,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-P1-zero-values-entity_ids1][sensor.device_energy_export:device-registry]
@ -12127,7 +12127,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-P1-zero-values-entity_ids1][sensor.device_long_power_failures_detected:device-registry]
@ -13664,7 +13664,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-SKT-11-entity_ids2][sensor.device_energy_import:device-registry]
@ -15316,7 +15316,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[HWE-WTR-entity_ids4][sensor.device_wi_fi_ssid:device-registry]
@ -15919,7 +15919,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '50',
'state': '50.0',
})
# ---
# name: test_sensors[SDM230-entity_ids5][sensor.device_power:device-registry]
@ -16612,7 +16612,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[SDM630-entity_ids6][sensor.device_apparent_power_phase_2:device-registry]
@ -16960,7 +16960,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[SDM630-entity_ids6][sensor.device_current_phase_2:device-registry]
@ -17572,7 +17572,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '100',
'state': '100.0',
})
# ---
# name: test_sensors[SDM630-entity_ids6][sensor.device_power_factor_phase_2:device-registry]
@ -18190,7 +18190,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
'state': '0.0',
})
# ---
# name: test_sensors[SDM630-entity_ids6][sensor.device_reactive_power_phase_2:device-registry]

View File

@ -1,5 +1,5 @@
# serializer version: 1
# name: test_switch_entities[HWE-KWH1-switch.device_cloud_connection-system_set-cloud_enabled]
# name: test_switch_entities[HWE-KWH1-switch.device_cloud_connection-system-cloud_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Cloud connection',
@ -12,7 +12,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[HWE-KWH1-switch.device_cloud_connection-system_set-cloud_enabled].1
# name: test_switch_entities[HWE-KWH1-switch.device_cloud_connection-system-cloud_enabled].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -45,7 +45,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-KWH1-switch.device_cloud_connection-system_set-cloud_enabled].2
# name: test_switch_entities[HWE-KWH1-switch.device_cloud_connection-system-cloud_enabled].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -81,7 +81,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-KWH3-switch.device_cloud_connection-system_set-cloud_enabled]
# name: test_switch_entities[HWE-KWH3-switch.device_cloud_connection-system-cloud_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Cloud connection',
@ -94,7 +94,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[HWE-KWH3-switch.device_cloud_connection-system_set-cloud_enabled].1
# name: test_switch_entities[HWE-KWH3-switch.device_cloud_connection-system-cloud_enabled].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -127,7 +127,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-KWH3-switch.device_cloud_connection-system_set-cloud_enabled].2
# name: test_switch_entities[HWE-KWH3-switch.device_cloud_connection-system-cloud_enabled].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -163,7 +163,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device-state_set-power_on]
# name: test_switch_entities[HWE-SKT-11-switch.device-state-power_on]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'outlet',
@ -177,7 +177,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device-state_set-power_on].1
# name: test_switch_entities[HWE-SKT-11-switch.device-state-power_on].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -210,7 +210,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device-state_set-power_on].2
# name: test_switch_entities[HWE-SKT-11-switch.device-state-power_on].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -246,7 +246,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device_cloud_connection-system_set-cloud_enabled]
# name: test_switch_entities[HWE-SKT-11-switch.device_cloud_connection-system-cloud_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Cloud connection',
@ -259,7 +259,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device_cloud_connection-system_set-cloud_enabled].1
# name: test_switch_entities[HWE-SKT-11-switch.device_cloud_connection-system-cloud_enabled].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -292,7 +292,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device_cloud_connection-system_set-cloud_enabled].2
# name: test_switch_entities[HWE-SKT-11-switch.device_cloud_connection-system-cloud_enabled].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -328,7 +328,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device_switch_lock-state_set-switch_lock]
# name: test_switch_entities[HWE-SKT-11-switch.device_switch_lock-state-switch_lock]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Switch lock',
@ -341,7 +341,7 @@
'state': 'off',
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device_switch_lock-state_set-switch_lock].1
# name: test_switch_entities[HWE-SKT-11-switch.device_switch_lock-state-switch_lock].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -374,7 +374,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-SKT-11-switch.device_switch_lock-state_set-switch_lock].2
# name: test_switch_entities[HWE-SKT-11-switch.device_switch_lock-state-switch_lock].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -410,7 +410,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device-state_set-power_on]
# name: test_switch_entities[HWE-SKT-21-switch.device-state-power_on]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'outlet',
@ -424,7 +424,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device-state_set-power_on].1
# name: test_switch_entities[HWE-SKT-21-switch.device-state-power_on].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -457,7 +457,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device-state_set-power_on].2
# name: test_switch_entities[HWE-SKT-21-switch.device-state-power_on].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -493,7 +493,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device_cloud_connection-system_set-cloud_enabled]
# name: test_switch_entities[HWE-SKT-21-switch.device_cloud_connection-system-cloud_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Cloud connection',
@ -506,7 +506,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device_cloud_connection-system_set-cloud_enabled].1
# name: test_switch_entities[HWE-SKT-21-switch.device_cloud_connection-system-cloud_enabled].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -539,7 +539,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device_cloud_connection-system_set-cloud_enabled].2
# name: test_switch_entities[HWE-SKT-21-switch.device_cloud_connection-system-cloud_enabled].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -575,7 +575,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device_switch_lock-state_set-switch_lock]
# name: test_switch_entities[HWE-SKT-21-switch.device_switch_lock-state-switch_lock]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Switch lock',
@ -588,7 +588,7 @@
'state': 'off',
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device_switch_lock-state_set-switch_lock].1
# name: test_switch_entities[HWE-SKT-21-switch.device_switch_lock-state-switch_lock].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -621,7 +621,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-SKT-21-switch.device_switch_lock-state_set-switch_lock].2
# name: test_switch_entities[HWE-SKT-21-switch.device_switch_lock-state-switch_lock].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -657,7 +657,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[HWE-WTR-switch.device_cloud_connection-system_set-cloud_enabled]
# name: test_switch_entities[HWE-WTR-switch.device_cloud_connection-system-cloud_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Cloud connection',
@ -670,7 +670,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[HWE-WTR-switch.device_cloud_connection-system_set-cloud_enabled].1
# name: test_switch_entities[HWE-WTR-switch.device_cloud_connection-system-cloud_enabled].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -703,7 +703,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[HWE-WTR-switch.device_cloud_connection-system_set-cloud_enabled].2
# name: test_switch_entities[HWE-WTR-switch.device_cloud_connection-system-cloud_enabled].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -739,7 +739,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[SDM230-switch.device_cloud_connection-system_set-cloud_enabled]
# name: test_switch_entities[SDM230-switch.device_cloud_connection-system-cloud_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Cloud connection',
@ -752,7 +752,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[SDM230-switch.device_cloud_connection-system_set-cloud_enabled].1
# name: test_switch_entities[SDM230-switch.device_cloud_connection-system-cloud_enabled].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -785,7 +785,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[SDM230-switch.device_cloud_connection-system_set-cloud_enabled].2
# name: test_switch_entities[SDM230-switch.device_cloud_connection-system-cloud_enabled].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@ -821,7 +821,7 @@
'via_device_id': None,
})
# ---
# name: test_switch_entities[SDM630-switch.device_cloud_connection-system_set-cloud_enabled]
# name: test_switch_entities[SDM630-switch.device_cloud_connection-system-cloud_enabled]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Device Cloud connection',
@ -834,7 +834,7 @@
'state': 'on',
})
# ---
# name: test_switch_entities[SDM630-switch.device_cloud_connection-system_set-cloud_enabled].1
# name: test_switch_entities[SDM630-switch.device_cloud_connection-system-cloud_enabled].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -867,7 +867,7 @@
'unit_of_measurement': None,
})
# ---
# name: test_switch_entities[SDM630-switch.device_cloud_connection-system_set-cloud_enabled].2
# name: test_switch_entities[SDM630-switch.device_cloud_connection-system-cloud_enabled].2
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,

View File

@ -25,7 +25,7 @@ async def test_load_unload(
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.LOADED
assert len(mock_homewizardenergy.device.mock_calls) == 1
assert len(mock_homewizardenergy.combined.mock_calls) == 1
await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
@ -39,7 +39,7 @@ async def test_load_failed_host_unavailable(
mock_homewizardenergy: MagicMock,
) -> None:
"""Test setup handles unreachable host."""
mock_homewizardenergy.device.side_effect = TimeoutError()
mock_homewizardenergy.combined.side_effect = TimeoutError()
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
@ -53,7 +53,7 @@ async def test_load_detect_api_disabled(
mock_homewizardenergy: MagicMock,
) -> None:
"""Test setup detects disabled API."""
mock_homewizardenergy.device.side_effect = DisabledError()
mock_homewizardenergy.combined.side_effect = DisabledError()
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
@ -115,7 +115,7 @@ async def test_disablederror_reloads_integration(
assert len(flows) == 0
# Simulate DisabledError and wait for next update
mock_homewizardenergy.device.side_effect = DisabledError()
mock_homewizardenergy.combined.side_effect = DisabledError()
freezer.tick(timedelta(seconds=5))
async_fire_time_changed(hass)

View File

@ -3,6 +3,7 @@
from unittest.mock import MagicMock
from homewizard_energy.errors import DisabledError, RequestError
from homewizard_energy.models import CombinedModels, Measurement, State, System
import pytest
from syrupy.assertion import SnapshotAssertion
@ -44,7 +45,9 @@ async def test_number_entities(
# Test unknown handling
assert state.state == "100"
mock_homewizardenergy.state.return_value.brightness = None
mock_homewizardenergy.combined.return_value = CombinedModels(
device=None, measurement=Measurement(), system=System(), state=State()
)
async_fire_time_changed(hass, dt_util.utcnow() + UPDATE_INTERVAL)
await hass.async_block_till_done()
@ -53,7 +56,7 @@ async def test_number_entities(
assert state.state == STATE_UNKNOWN
# Test service methods
assert len(mock_homewizardenergy.state_set.mock_calls) == 0
assert len(mock_homewizardenergy.state.mock_calls) == 0
await hass.services.async_call(
number.DOMAIN,
SERVICE_SET_VALUE,
@ -64,10 +67,10 @@ async def test_number_entities(
blocking=True,
)
assert len(mock_homewizardenergy.state_set.mock_calls) == 1
mock_homewizardenergy.state_set.assert_called_with(brightness=129)
assert len(mock_homewizardenergy.system.mock_calls) == 1
mock_homewizardenergy.system.assert_called_with(status_led_brightness_pct=50)
mock_homewizardenergy.state_set.side_effect = RequestError
mock_homewizardenergy.system.side_effect = RequestError
with pytest.raises(
HomeAssistantError,
match=r"^An error occurred while communicating with HomeWizard device$",
@ -82,7 +85,7 @@ async def test_number_entities(
blocking=True,
)
mock_homewizardenergy.state_set.side_effect = DisabledError
mock_homewizardenergy.system.side_effect = DisabledError
with pytest.raises(
HomeAssistantError,
match=r"^The local API is disabled$",

View File

@ -3,7 +3,6 @@
from unittest.mock import MagicMock
from homewizard_energy.errors import RequestError
from homewizard_energy.v1.models import Data
import pytest
from syrupy.assertion import SnapshotAssertion
@ -456,7 +455,7 @@ async def test_sensors_unreachable(
assert (state := hass.states.get("sensor.device_energy_import_tariff_1"))
assert state.state == "10830.511"
mock_homewizardenergy.data.side_effect = exception
mock_homewizardenergy.combined.side_effect = exception
async_fire_time_changed(hass, dt_util.utcnow() + UPDATE_INTERVAL)
await hass.async_block_till_done()
@ -464,15 +463,17 @@ async def test_sensors_unreachable(
assert state.state == STATE_UNAVAILABLE
@pytest.mark.parametrize("exception", [RequestError])
async def test_external_sensors_unreachable(
hass: HomeAssistant,
mock_homewizardenergy: MagicMock,
exception: Exception,
) -> None:
"""Test external device sensor handles API unreachable."""
assert (state := hass.states.get("sensor.gas_meter_gas"))
assert state.state == "111.111"
mock_homewizardenergy.data.return_value = Data.from_dict({})
mock_homewizardenergy.combined.side_effect = exception
async_fire_time_changed(hass, dt_util.utcnow() + UPDATE_INTERVAL)
await hass.async_block_till_done()

View File

@ -86,17 +86,17 @@ async def test_entities_not_created_for_device(
@pytest.mark.parametrize(
("device_fixture", "entity_id", "method", "parameter"),
[
("HWE-SKT-11", "switch.device", "state_set", "power_on"),
("HWE-SKT-11", "switch.device_switch_lock", "state_set", "switch_lock"),
("HWE-SKT-11", "switch.device_cloud_connection", "system_set", "cloud_enabled"),
("HWE-SKT-21", "switch.device", "state_set", "power_on"),
("HWE-SKT-21", "switch.device_switch_lock", "state_set", "switch_lock"),
("HWE-SKT-21", "switch.device_cloud_connection", "system_set", "cloud_enabled"),
("HWE-WTR", "switch.device_cloud_connection", "system_set", "cloud_enabled"),
("SDM230", "switch.device_cloud_connection", "system_set", "cloud_enabled"),
("SDM630", "switch.device_cloud_connection", "system_set", "cloud_enabled"),
("HWE-KWH1", "switch.device_cloud_connection", "system_set", "cloud_enabled"),
("HWE-KWH3", "switch.device_cloud_connection", "system_set", "cloud_enabled"),
("HWE-SKT-11", "switch.device", "state", "power_on"),
("HWE-SKT-11", "switch.device_switch_lock", "state", "switch_lock"),
("HWE-SKT-11", "switch.device_cloud_connection", "system", "cloud_enabled"),
("HWE-SKT-21", "switch.device", "state", "power_on"),
("HWE-SKT-21", "switch.device_switch_lock", "state", "switch_lock"),
("HWE-SKT-21", "switch.device_cloud_connection", "system", "cloud_enabled"),
("HWE-WTR", "switch.device_cloud_connection", "system", "cloud_enabled"),
("SDM230", "switch.device_cloud_connection", "system", "cloud_enabled"),
("SDM630", "switch.device_cloud_connection", "system", "cloud_enabled"),
("HWE-KWH1", "switch.device_cloud_connection", "system", "cloud_enabled"),
("HWE-KWH3", "switch.device_cloud_connection", "system", "cloud_enabled"),
],
)
async def test_switch_entities(
@ -200,9 +200,9 @@ async def test_switch_entities(
@pytest.mark.parametrize(
("entity_id", "method"),
[
("switch.device", "state"),
("switch.device_switch_lock", "state"),
("switch.device_cloud_connection", "system"),
("switch.device", "combined"),
("switch.device_switch_lock", "combined"),
("switch.device_cloud_connection", "combined"),
],
)
async def test_switch_unreachable(