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:
parent
719f2e650c
commit
fa0d653216
13 changed files with 86 additions and 79 deletions
|
@ -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
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue