Update python-homewizard-energy to 1.5.0 (#85966)

* Update python-homewizard-energy to 1.5.0

* Remove strict typing for now

* Revert "Remove strict typing for now"

This reverts commit ebcd327fdf.

* Adjust typing to resolve upstream changes
This commit is contained in:
Franck Nijhof 2023-01-16 09:23:03 +01:00 committed by GitHub
parent 719f2e650c
commit fa0d653216
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 86 additions and 79 deletions

View file

@ -1,6 +1,4 @@
"""The Homewizard integration."""
import logging
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntry
from homeassistant.const import CONF_IP_ADDRESS
from homeassistant.core import HomeAssistant
@ -9,8 +7,6 @@ from homeassistant.exceptions import ConfigEntryNotReady
from .const import DOMAIN, PLATFORMS
from .coordinator import HWEnergyDeviceUpdateCoordinator as Coordinator
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Homewizard from a config entry."""
@ -19,22 +15,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await coordinator.async_config_entry_first_refresh()
except ConfigEntryNotReady:
await coordinator.api.close()
await coordinator.api.close() # type: ignore[no-untyped-call]
if coordinator.api_disabled:
entry.async_start_reauth(hass)
raise
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
# Abort reauth config flow if active
for progress_flow in hass.config_entries.flow.async_progress_by_handler(DOMAIN):
if progress_flow["context"].get("source") == SOURCE_REAUTH:
if (
"context" in progress_flow
and progress_flow["context"].get("source") == SOURCE_REAUTH
):
hass.config_entries.flow.async_abort(progress_flow["flow_id"])
# Setup entry
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = coordinator
# Finalize
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
@ -43,12 +40,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
_LOGGER.debug("__init__ async_unload_entry")
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
coordinator = hass.data[DOMAIN].pop(entry.entry_id)
await coordinator.api.close()
return unload_ok

View file

@ -251,7 +251,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
raise AbortFlow("unknown_error") from ex
finally:
await energy_api.close()
await energy_api.close() # type: ignore[no-untyped-call]
async def _async_set_and_check_unique_id(self, entry_info: dict[str, Any]) -> None:
"""Validate if entry exists."""

View file

@ -1,8 +1,8 @@
"""Constants for the Homewizard integration."""
from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
from typing import TypedDict
# Set up.
from homewizard_energy.models import Data, Device, State, System
@ -24,10 +24,11 @@ CONF_SERIAL = "serial"
UPDATE_INTERVAL = timedelta(seconds=5)
class DeviceResponseEntry(TypedDict):
@dataclass
class DeviceResponseEntry:
"""Dict describing a single response entry."""
device: Device
data: Data
state: State
system: System
state: State | None
system: System | None = None

View file

@ -39,16 +39,15 @@ class HWEnergyDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceResponseEntry]
# Update all properties
try:
data: DeviceResponseEntry = {
"device": await self.api.device(),
"data": await self.api.data(),
"state": await self.api.state(),
"system": None,
}
data = DeviceResponseEntry(
device=await self.api.device(),
data=await self.api.data(),
state=await self.api.state(),
)
features = await self.api.features()
if features.has_system:
data["system"] = await self.api.system()
data.system = await self.api.system()
except RequestError as ex:
raise UpdateFailed(ex) from ex

View file

@ -22,13 +22,13 @@ async def async_get_config_entry_diagnostics(
coordinator: HWEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
meter_data = {
"device": asdict(coordinator.data["device"]),
"data": asdict(coordinator.data["data"]),
"state": asdict(coordinator.data["state"])
if coordinator.data["state"] is not None
"device": asdict(coordinator.data.device),
"data": asdict(coordinator.data.data),
"state": asdict(coordinator.data.state)
if coordinator.data.state is not None
else None,
"system": asdict(coordinator.data["system"])
if coordinator.data["system"] is not None
"system": asdict(coordinator.data.system)
if coordinator.data.system is not None
else None,
}

View file

@ -1,6 +1,7 @@
"""Base entity for the HomeWizard integration."""
from __future__ import annotations
from homeassistant.const import ATTR_IDENTIFIERS
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
@ -19,7 +20,11 @@ class HomeWizardEntity(CoordinatorEntity[HWEnergyDeviceUpdateCoordinator]):
self._attr_device_info = DeviceInfo(
name=coordinator.entry.title,
manufacturer="HomeWizard",
sw_version=coordinator.data["device"].firmware_version,
model=coordinator.data["device"].product_type,
identifiers={(DOMAIN, coordinator.data["device"].serial)},
sw_version=coordinator.data.device.firmware_version,
model=coordinator.data.device.product_type,
)
if coordinator.data.device.serial is not None:
self._attr_device_info[ATTR_IDENTIFIERS] = {
(DOMAIN, coordinator.data.device.serial)
}

View file

@ -21,7 +21,8 @@ def homewizard_exception_handler(
"""Decorate HomeWizard Energy calls to handle HomeWizardEnergy exceptions.
A decorator that wraps the passed in function, catches HomeWizardEnergy errors,
and reloads the integration when the API was disabled so the reauth flow is triggered.
and reloads the integration when the API was disabled so the reauth flow is
triggered.
"""
async def handler(
@ -29,7 +30,6 @@ def homewizard_exception_handler(
) -> None:
try:
await func(self, *args, **kwargs)
except RequestError as ex:
raise HomeAssistantError from ex
except DisabledError as ex:

View file

@ -4,7 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/homewizard",
"codeowners": ["@DCSBL"],
"dependencies": [],
"requirements": ["python-homewizard-energy==1.4.0"],
"requirements": ["python-homewizard-energy==1.5.0"],
"zeroconf": ["_hwenergy._tcp.local."],
"config_flow": true,
"quality_scale": "platinum",

View file

@ -1,8 +1,6 @@
"""Creates HomeWizard Number entities."""
from __future__ import annotations
from typing import Optional, cast
from homeassistant.components.number import NumberEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE
@ -23,19 +21,17 @@ async def async_setup_entry(
) -> None:
"""Set up numbers for device."""
coordinator: HWEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
if coordinator.data["state"]:
async_add_entities(
[
HWEnergyNumberEntity(coordinator, entry),
]
)
if coordinator.data.state:
async_add_entities([HWEnergyNumberEntity(coordinator, entry)])
class HWEnergyNumberEntity(HomeWizardEntity, NumberEntity):
"""Representation of status light number."""
_attr_entity_category = EntityCategory.CONFIG
_attr_icon = "mdi:lightbulb-on"
_attr_name = "Status light brightness"
_attr_native_unit_of_measurement = PERCENTAGE
def __init__(
self,
@ -45,20 +41,19 @@ class HWEnergyNumberEntity(HomeWizardEntity, NumberEntity):
"""Initialize the control number."""
super().__init__(coordinator)
self._attr_unique_id = f"{entry.unique_id}_status_light_brightness"
self._attr_name = "Status light brightness"
self._attr_native_unit_of_measurement = PERCENTAGE
self._attr_icon = "mdi:lightbulb-on"
@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 * (255 / 100))
await self.coordinator.api.state_set(brightness=int(value * (255 / 100)))
await self.coordinator.async_refresh()
@property
def native_value(self) -> float | None:
"""Return the current value."""
brightness = cast(Optional[float], self.coordinator.data["state"].brightness)
if brightness is None:
if (
self.coordinator.data.state is None
or self.coordinator.data.state.brightness is None
):
return None
return round(brightness * (100 / 255))
return round(self.coordinator.data.state.brightness * (100 / 255))

View file

@ -137,11 +137,13 @@ async def async_setup_entry(
"""Initialize sensors."""
coordinator: HWEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
entities = []
if coordinator.data["data"] is not None:
for description in SENSORS:
if getattr(coordinator.data["data"], description.key) is not None:
entities.append(HWEnergySensor(coordinator, entry, description))
entities: list[HWEnergySensor] = []
if coordinator.data.data is not None:
entities.extend(
HWEnergySensor(coordinator, entry, description)
for description in SENSORS
if getattr(coordinator.data.data, description.key) is not None
)
async_add_entities(entities)
@ -166,11 +168,14 @@ class HWEnergySensor(HomeWizardEntity, SensorEntity):
# Special case for export, not everyone has solarpanels
# The chance that 'export' is non-zero when you have solar panels is nil
if self.data_type in [
if (
self.data_type
in [
"total_power_export_t1_kwh",
"total_power_export_t2_kwh",
]:
if self.native_value == 0:
]
and self.native_value == 0
):
self._attr_entity_registry_enabled_default = False
@property
@ -181,7 +186,7 @@ class HWEnergySensor(HomeWizardEntity, SensorEntity):
@property
def native_value(self) -> StateType:
"""Return state of meter."""
return cast(StateType, getattr(self.data["data"], self.data_type))
return cast(StateType, getattr(self.data.data, self.data_type))
@property
def available(self) -> bool:

View file

@ -25,11 +25,11 @@ async def async_setup_entry(
entities: list[SwitchEntity] = []
if coordinator.data["state"]:
if coordinator.data.state:
entities.append(HWEnergyMainSwitchEntity(coordinator, entry))
entities.append(HWEnergySwitchLockEntity(coordinator, entry))
if coordinator.data["system"]:
if coordinator.data.system:
entities.append(HWEnergyEnableCloudEntity(hass, coordinator, entry))
async_add_entities(entities)
@ -79,12 +79,18 @@ class HWEnergyMainSwitchEntity(HWEnergySwitchEntity):
This switch becomes unavailable when switch_lock is enabled.
"""
return super().available and not self.coordinator.data["state"].switch_lock
return (
super().available
and self.coordinator.data.state is not None
and not self.coordinator.data.state.switch_lock
)
@property
def is_on(self) -> bool:
def is_on(self) -> bool | None:
"""Return true if switch is on."""
return bool(self.coordinator.data["state"].power_on)
if self.coordinator.data.state is None:
return None
return self.coordinator.data.state.power_on
class HWEnergySwitchLockEntity(HWEnergySwitchEntity):
@ -118,9 +124,11 @@ class HWEnergySwitchLockEntity(HWEnergySwitchEntity):
await self.coordinator.async_refresh()
@property
def is_on(self) -> bool:
def is_on(self) -> bool | None:
"""Return true if switch is on."""
return bool(self.coordinator.data["state"].switch_lock)
if self.coordinator.data.state is None:
return None
return self.coordinator.data.state.switch_lock
class HWEnergyEnableCloudEntity(HWEnergySwitchEntity):
@ -164,6 +172,8 @@ class HWEnergyEnableCloudEntity(HWEnergySwitchEntity):
return "mdi:cloud" if self.is_on else "mdi:cloud-off-outline"
@property
def is_on(self) -> bool:
def is_on(self) -> bool | None:
"""Return true if cloud connection is active."""
return bool(self.coordinator.data["system"].cloud_enabled)
if self.coordinator.data.system is None:
return None
return self.coordinator.data.system.cloud_enabled

View file

@ -2039,7 +2039,7 @@ python-gc100==1.0.3a0
python-gitlab==1.6.0
# homeassistant.components.homewizard
python-homewizard-energy==1.4.0
python-homewizard-energy==1.5.0
# homeassistant.components.hp_ilo
python-hpilo==4.3

View file

@ -1444,7 +1444,7 @@ python-forecastio==1.4.0
python-fullykiosk==0.0.12
# homeassistant.components.homewizard
python-homewizard-energy==1.4.0
python-homewizard-energy==1.5.0
# homeassistant.components.izone
python-izone==1.2.9