Powerview dataclass (#73746)

Co-authored-by: J. Nick Koston <nick@koston.org>
pull/73768/head
kingy444 2022-06-22 02:12:11 +10:00 committed by GitHub
parent f285b6099a
commit a816348616
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 129 additions and 174 deletions

View File

@ -512,6 +512,7 @@ omit =
homeassistant/components/hunterdouglas_powerview/cover.py homeassistant/components/hunterdouglas_powerview/cover.py
homeassistant/components/hunterdouglas_powerview/diagnostics.py homeassistant/components/hunterdouglas_powerview/diagnostics.py
homeassistant/components/hunterdouglas_powerview/entity.py homeassistant/components/hunterdouglas_powerview/entity.py
homeassistant/components/hunterdouglas_powerview/model.py
homeassistant/components/hunterdouglas_powerview/scene.py homeassistant/components/hunterdouglas_powerview/scene.py
homeassistant/components/hunterdouglas_powerview/sensor.py homeassistant/components/hunterdouglas_powerview/sensor.py
homeassistant/components/hunterdouglas_powerview/shade_data.py homeassistant/components/hunterdouglas_powerview/shade_data.py

View File

@ -19,29 +19,14 @@ import homeassistant.helpers.config_validation as cv
from .const import ( from .const import (
API_PATH_FWVERSION, API_PATH_FWVERSION,
COORDINATOR,
DEFAULT_LEGACY_MAINPROCESSOR, DEFAULT_LEGACY_MAINPROCESSOR,
DEVICE_FIRMWARE,
DEVICE_INFO,
DEVICE_MAC_ADDRESS,
DEVICE_MODEL,
DEVICE_NAME,
DEVICE_REVISION,
DEVICE_SERIAL_NUMBER,
DOMAIN, DOMAIN,
FIRMWARE, FIRMWARE,
FIRMWARE_MAINPROCESSOR, FIRMWARE_MAINPROCESSOR,
FIRMWARE_NAME, FIRMWARE_NAME,
FIRMWARE_REVISION,
HUB_EXCEPTIONS, HUB_EXCEPTIONS,
HUB_NAME, HUB_NAME,
MAC_ADDRESS_IN_USERDATA, MAC_ADDRESS_IN_USERDATA,
PV_API,
PV_HUB_ADDRESS,
PV_ROOM_DATA,
PV_SCENE_DATA,
PV_SHADE_DATA,
PV_SHADES,
ROOM_DATA, ROOM_DATA,
SCENE_DATA, SCENE_DATA,
SERIAL_NUMBER_IN_USERDATA, SERIAL_NUMBER_IN_USERDATA,
@ -49,6 +34,7 @@ from .const import (
USER_DATA, USER_DATA,
) )
from .coordinator import PowerviewShadeUpdateCoordinator from .coordinator import PowerviewShadeUpdateCoordinator
from .model import PowerviewDeviceInfo, PowerviewEntryData
from .shade_data import PowerviewShadeData from .shade_data import PowerviewShadeData
from .util import async_map_data_by_id from .util import async_map_data_by_id
@ -72,8 +58,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
try: try:
async with async_timeout.timeout(10): async with async_timeout.timeout(10):
device_info = await async_get_device_info(pv_request) device_info = await async_get_device_info(pv_request, hub_address)
device_info[PV_HUB_ADDRESS] = hub_address
async with async_timeout.timeout(10): async with async_timeout.timeout(10):
rooms = Rooms(pv_request) rooms = Rooms(pv_request)
@ -102,22 +87,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# populate raw shade data into the coordinator for diagnostics # populate raw shade data into the coordinator for diagnostics
coordinator.data.store_group_data(shade_entries[SHADE_DATA]) coordinator.data.store_group_data(shade_entries[SHADE_DATA])
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { hass.data.setdefault(DOMAIN, {})[entry.entry_id] = PowerviewEntryData(
PV_API: pv_request, api=pv_request,
PV_ROOM_DATA: room_data, room_data=room_data,
PV_SCENE_DATA: scene_data, scene_data=scene_data,
PV_SHADES: shades, shade_data=shade_data,
PV_SHADE_DATA: shade_data, coordinator=coordinator,
COORDINATOR: coordinator, device_info=device_info,
DEVICE_INFO: device_info, )
}
hass.config_entries.async_setup_platforms(entry, PLATFORMS) hass.config_entries.async_setup_platforms(entry, PLATFORMS)
return True return True
async def async_get_device_info(pv_request): async def async_get_device_info(
pv_request: AioRequest, hub_address: str
) -> PowerviewDeviceInfo:
"""Determine device info.""" """Determine device info."""
userdata = UserData(pv_request) userdata = UserData(pv_request)
resources = await userdata.get_resources() resources = await userdata.get_resources()
@ -135,14 +121,14 @@ async def async_get_device_info(pv_request):
else: else:
main_processor_info = DEFAULT_LEGACY_MAINPROCESSOR main_processor_info = DEFAULT_LEGACY_MAINPROCESSOR
return { return PowerviewDeviceInfo(
DEVICE_NAME: base64_to_unicode(userdata_data[HUB_NAME]), name=base64_to_unicode(userdata_data[HUB_NAME]),
DEVICE_MAC_ADDRESS: userdata_data[MAC_ADDRESS_IN_USERDATA], mac_address=userdata_data[MAC_ADDRESS_IN_USERDATA],
DEVICE_SERIAL_NUMBER: userdata_data[SERIAL_NUMBER_IN_USERDATA], serial_number=userdata_data[SERIAL_NUMBER_IN_USERDATA],
DEVICE_REVISION: main_processor_info[FIRMWARE_REVISION], firmware=main_processor_info,
DEVICE_FIRMWARE: main_processor_info, model=main_processor_info[FIRMWARE_NAME],
DEVICE_MODEL: main_processor_info[FIRMWARE_NAME], hub_address=hub_address,
} )
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

View File

@ -13,18 +13,10 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import ( from .const import DOMAIN, ROOM_ID_IN_SHADE, ROOM_NAME_UNICODE
COORDINATOR,
DEVICE_INFO,
DOMAIN,
PV_API,
PV_ROOM_DATA,
PV_SHADE_DATA,
ROOM_ID_IN_SHADE,
ROOM_NAME_UNICODE,
)
from .coordinator import PowerviewShadeUpdateCoordinator from .coordinator import PowerviewShadeUpdateCoordinator
from .entity import ShadeEntity from .entity import ShadeEntity
from .model import PowerviewDeviceInfo, PowerviewEntryData
@dataclass @dataclass
@ -66,25 +58,20 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up the hunter douglas advanced feature buttons.""" """Set up the hunter douglas advanced feature buttons."""
pv_data = hass.data[DOMAIN][entry.entry_id] pv_entry: PowerviewEntryData = hass.data[DOMAIN][entry.entry_id]
room_data: dict[str | int, Any] = pv_data[PV_ROOM_DATA]
shade_data = pv_data[PV_SHADE_DATA]
pv_request = pv_data[PV_API]
coordinator: PowerviewShadeUpdateCoordinator = pv_data[COORDINATOR]
device_info: dict[str, Any] = pv_data[DEVICE_INFO]
entities: list[ButtonEntity] = [] entities: list[ButtonEntity] = []
for raw_shade in shade_data.values(): for raw_shade in pv_entry.shade_data.values():
shade: BaseShade = PvShade(raw_shade, pv_request) shade: BaseShade = PvShade(raw_shade, pv_entry.api)
name_before_refresh = shade.name name_before_refresh = shade.name
room_id = shade.raw_data.get(ROOM_ID_IN_SHADE) room_id = shade.raw_data.get(ROOM_ID_IN_SHADE)
room_name = room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "") room_name = pv_entry.room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "")
for description in BUTTONS: for description in BUTTONS:
entities.append( entities.append(
PowerviewButton( PowerviewButton(
coordinator, pv_entry.coordinator,
device_info, pv_entry.device_info,
room_name, room_name,
shade, shade,
name_before_refresh, name_before_refresh,
@ -101,7 +88,7 @@ class PowerviewButton(ShadeEntity, ButtonEntity):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
name: str, name: str,

View File

@ -14,7 +14,7 @@ from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from . import async_get_device_info from . import async_get_device_info
from .const import DEVICE_NAME, DEVICE_SERIAL_NUMBER, DOMAIN, HUB_EXCEPTIONS from .const import DOMAIN, HUB_EXCEPTIONS
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -35,14 +35,14 @@ async def validate_input(hass: core.HomeAssistant, hub_address: str) -> dict[str
try: try:
async with async_timeout.timeout(10): async with async_timeout.timeout(10):
device_info = await async_get_device_info(pv_request) device_info = await async_get_device_info(pv_request, hub_address)
except HUB_EXCEPTIONS as err: except HUB_EXCEPTIONS as err:
raise CannotConnect from err raise CannotConnect from err
# Return info that you want to store in the config entry. # Return info that you want to store in the config entry.
return { return {
"title": device_info[DEVICE_NAME], "title": device_info.name,
"unique_id": device_info[DEVICE_SERIAL_NUMBER], "unique_id": device_info.serial_number,
} }

View File

@ -27,13 +27,9 @@ FIRMWARE_REVISION = "revision"
FIRMWARE_SUB_REVISION = "subRevision" FIRMWARE_SUB_REVISION = "subRevision"
FIRMWARE_BUILD = "build" FIRMWARE_BUILD = "build"
DEVICE_NAME = "device_name" REDACT_MAC_ADDRESS = "mac_address"
DEVICE_MAC_ADDRESS = "device_mac_address" REDACT_SERIAL_NUMBER = "serial_number"
DEVICE_SERIAL_NUMBER = "device_serial_number" REDACT_HUB_ADDRESS = "hub_address"
DEVICE_REVISION = "device_revision"
DEVICE_INFO = "device_info"
DEVICE_MODEL = "device_model"
DEVICE_FIRMWARE = "device_firmware"
SCENE_NAME = "name" SCENE_NAME = "name"
SCENE_ID = "id" SCENE_ID = "id"
@ -52,15 +48,6 @@ SHADE_BATTERY_LEVEL_MAX = 200
STATE_ATTRIBUTE_ROOM_NAME = "roomName" STATE_ATTRIBUTE_ROOM_NAME = "roomName"
PV_API = "pv_api"
PV_HUB = "pv_hub"
PV_HUB_ADDRESS = "pv_hub_address"
PV_SHADES = "pv_shades"
PV_SCENE_DATA = "pv_scene_data"
PV_SHADE_DATA = "pv_shade_data"
PV_ROOM_DATA = "pv_room_data"
COORDINATOR = "coordinator"
HUB_EXCEPTIONS = ( HUB_EXCEPTIONS = (
ServerDisconnectedError, ServerDisconnectedError,
asyncio.TimeoutError, asyncio.TimeoutError,

View File

@ -38,23 +38,18 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_call_later from homeassistant.helpers.event import async_call_later
from .const import ( from .const import (
COORDINATOR,
DEVICE_INFO,
DEVICE_MODEL,
DOMAIN, DOMAIN,
LEGACY_DEVICE_MODEL, LEGACY_DEVICE_MODEL,
POS_KIND_PRIMARY, POS_KIND_PRIMARY,
POS_KIND_SECONDARY, POS_KIND_SECONDARY,
POS_KIND_VANE, POS_KIND_VANE,
PV_API,
PV_ROOM_DATA,
PV_SHADE_DATA,
ROOM_ID_IN_SHADE, ROOM_ID_IN_SHADE,
ROOM_NAME_UNICODE, ROOM_NAME_UNICODE,
STATE_ATTRIBUTE_ROOM_NAME, STATE_ATTRIBUTE_ROOM_NAME,
) )
from .coordinator import PowerviewShadeUpdateCoordinator from .coordinator import PowerviewShadeUpdateCoordinator
from .entity import ShadeEntity from .entity import ShadeEntity
from .model import PowerviewDeviceInfo, PowerviewEntryData
from .shade_data import PowerviewShadeMove from .shade_data import PowerviewShadeMove
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -83,18 +78,14 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up the hunter douglas shades.""" """Set up the hunter douglas shades."""
pv_data = hass.data[DOMAIN][entry.entry_id] pv_entry: PowerviewEntryData = hass.data[DOMAIN][entry.entry_id]
room_data: dict[str | int, Any] = pv_data[PV_ROOM_DATA] coordinator: PowerviewShadeUpdateCoordinator = pv_entry.coordinator
shade_data = pv_data[PV_SHADE_DATA]
pv_request = pv_data[PV_API]
coordinator: PowerviewShadeUpdateCoordinator = pv_data[COORDINATOR]
device_info: dict[str, Any] = pv_data[DEVICE_INFO]
entities: list[ShadeEntity] = [] entities: list[ShadeEntity] = []
for raw_shade in shade_data.values(): for raw_shade in pv_entry.shade_data.values():
# The shade may be out of sync with the hub # The shade may be out of sync with the hub
# so we force a refresh when we add it if possible # so we force a refresh when we add it if possible
shade: BaseShade = PvShade(raw_shade, pv_request) shade: BaseShade = PvShade(raw_shade, pv_entry.api)
name_before_refresh = shade.name name_before_refresh = shade.name
with suppress(asyncio.TimeoutError): with suppress(asyncio.TimeoutError):
async with async_timeout.timeout(1): async with async_timeout.timeout(1):
@ -108,10 +99,10 @@ async def async_setup_entry(
continue continue
coordinator.data.update_shade_positions(shade.raw_data) coordinator.data.update_shade_positions(shade.raw_data)
room_id = shade.raw_data.get(ROOM_ID_IN_SHADE) room_id = shade.raw_data.get(ROOM_ID_IN_SHADE)
room_name = room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "") room_name = pv_entry.room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "")
entities.extend( entities.extend(
create_powerview_shade_entity( create_powerview_shade_entity(
coordinator, device_info, room_name, shade, name_before_refresh coordinator, pv_entry.device_info, room_name, shade, name_before_refresh
) )
) )
async_add_entities(entities) async_add_entities(entities)
@ -119,7 +110,7 @@ async def async_setup_entry(
def create_powerview_shade_entity( def create_powerview_shade_entity(
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
name_before_refresh: str, name_before_refresh: str,
@ -161,7 +152,7 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
name: str, name: str,
@ -171,7 +162,7 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity):
self._shade: BaseShade = shade self._shade: BaseShade = shade
self._attr_name = self._shade_name self._attr_name = self._shade_name
self._scheduled_transition_update: CALLBACK_TYPE | None = None self._scheduled_transition_update: CALLBACK_TYPE | None = None
if self._device_info[DEVICE_MODEL] != LEGACY_DEVICE_MODEL: if self._device_info.model != LEGACY_DEVICE_MODEL:
self._attr_supported_features |= CoverEntityFeature.STOP self._attr_supported_features |= CoverEntityFeature.STOP
self._forced_resync = None self._forced_resync = None
@ -387,7 +378,7 @@ class PowerViewShade(PowerViewShadeBase):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
name: str, name: str,
@ -418,7 +409,7 @@ class PowerViewShadeTDBUBottom(PowerViewShadeTDBU):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
name: str, name: str,
@ -455,7 +446,7 @@ class PowerViewShadeTDBUTop(PowerViewShadeTDBU):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
name: str, name: str,
@ -514,7 +505,7 @@ class PowerViewShadeWithTilt(PowerViewShade):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
name: str, name: str,
@ -526,7 +517,7 @@ class PowerViewShadeWithTilt(PowerViewShade):
| CoverEntityFeature.CLOSE_TILT | CoverEntityFeature.CLOSE_TILT
| CoverEntityFeature.SET_TILT_POSITION | CoverEntityFeature.SET_TILT_POSITION
) )
if self._device_info[DEVICE_MODEL] != LEGACY_DEVICE_MODEL: if self._device_info.model != LEGACY_DEVICE_MODEL:
self._attr_supported_features |= CoverEntityFeature.STOP_TILT self._attr_supported_features |= CoverEntityFeature.STOP_TILT
@property @property

View File

@ -1,6 +1,8 @@
"""Diagnostics support for Powerview Hunter Douglas.""" """Diagnostics support for Powerview Hunter Douglas."""
from __future__ import annotations from __future__ import annotations
from dataclasses import asdict
import logging
from typing import Any from typing import Any
import attr import attr
@ -12,24 +14,19 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntry from homeassistant.helpers.device_registry import DeviceEntry
from .const import ( from .const import DOMAIN, REDACT_HUB_ADDRESS, REDACT_MAC_ADDRESS, REDACT_SERIAL_NUMBER
COORDINATOR, from .model import PowerviewEntryData
DEVICE_INFO,
DEVICE_MAC_ADDRESS,
DEVICE_SERIAL_NUMBER,
DOMAIN,
PV_HUB_ADDRESS,
)
from .coordinator import PowerviewShadeUpdateCoordinator
REDACT_CONFIG = { REDACT_CONFIG = {
CONF_HOST, CONF_HOST,
DEVICE_MAC_ADDRESS, REDACT_HUB_ADDRESS,
DEVICE_SERIAL_NUMBER, REDACT_MAC_ADDRESS,
PV_HUB_ADDRESS, REDACT_SERIAL_NUMBER,
ATTR_CONFIGURATION_URL, ATTR_CONFIGURATION_URL,
} }
_LOGGER = logging.getLogger(__name__)
async def async_get_config_entry_diagnostics( async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: ConfigEntry hass: HomeAssistant, entry: ConfigEntry
@ -70,10 +67,9 @@ def _async_get_diagnostics(
entry: ConfigEntry, entry: ConfigEntry,
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return diagnostics for a config entry.""" """Return diagnostics for a config entry."""
pv_data = hass.data[DOMAIN][entry.entry_id] pv_entry: PowerviewEntryData = hass.data[DOMAIN][entry.entry_id]
coordinator: PowerviewShadeUpdateCoordinator = pv_data[COORDINATOR] shade_data = pv_entry.coordinator.data.get_all_raw_data()
shade_data = coordinator.data.get_all_raw_data() hub_info = async_redact_data(asdict(pv_entry.device_info), REDACT_CONFIG)
hub_info = async_redact_data(pv_data[DEVICE_INFO], REDACT_CONFIG)
return {"hub_info": hub_info, "shade_data": shade_data} return {"hub_info": hub_info, "shade_data": shade_data}

View File

@ -1,7 +1,5 @@
"""The powerview integration base entity.""" """The powerview integration base entity."""
from typing import Any
from aiopvapi.resources.shade import ATTR_TYPE, BaseShade from aiopvapi.resources.shade import ATTR_TYPE, BaseShade
from homeassistant.const import ATTR_MODEL, ATTR_SW_VERSION from homeassistant.const import ATTR_MODEL, ATTR_SW_VERSION
@ -12,20 +10,15 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import (
ATTR_BATTERY_KIND, ATTR_BATTERY_KIND,
BATTERY_KIND_HARDWIRED, BATTERY_KIND_HARDWIRED,
DEVICE_FIRMWARE,
DEVICE_MAC_ADDRESS,
DEVICE_MODEL,
DEVICE_NAME,
DEVICE_SERIAL_NUMBER,
DOMAIN, DOMAIN,
FIRMWARE, FIRMWARE,
FIRMWARE_BUILD, FIRMWARE_BUILD,
FIRMWARE_REVISION, FIRMWARE_REVISION,
FIRMWARE_SUB_REVISION, FIRMWARE_SUB_REVISION,
MANUFACTURER, MANUFACTURER,
PV_HUB_ADDRESS,
) )
from .coordinator import PowerviewShadeUpdateCoordinator from .coordinator import PowerviewShadeUpdateCoordinator
from .model import PowerviewDeviceInfo
from .shade_data import PowerviewShadeData, PowerviewShadePositions from .shade_data import PowerviewShadeData, PowerviewShadePositions
@ -35,7 +28,7 @@ class HDEntity(CoordinatorEntity[PowerviewShadeUpdateCoordinator]):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
unique_id: str, unique_id: str,
) -> None: ) -> None:
@ -43,7 +36,6 @@ class HDEntity(CoordinatorEntity[PowerviewShadeUpdateCoordinator]):
super().__init__(coordinator) super().__init__(coordinator)
self._room_name = room_name self._room_name = room_name
self._attr_unique_id = unique_id self._attr_unique_id = unique_id
self._hub_address = device_info[PV_HUB_ADDRESS]
self._device_info = device_info self._device_info = device_info
@property @property
@ -54,19 +46,17 @@ class HDEntity(CoordinatorEntity[PowerviewShadeUpdateCoordinator]):
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
"""Return the device_info of the device.""" """Return the device_info of the device."""
firmware = self._device_info[DEVICE_FIRMWARE] firmware = self._device_info.firmware
sw_version = f"{firmware[FIRMWARE_REVISION]}.{firmware[FIRMWARE_SUB_REVISION]}.{firmware[FIRMWARE_BUILD]}" sw_version = f"{firmware[FIRMWARE_REVISION]}.{firmware[FIRMWARE_SUB_REVISION]}.{firmware[FIRMWARE_BUILD]}"
return DeviceInfo( return DeviceInfo(
connections={ connections={(dr.CONNECTION_NETWORK_MAC, self._device_info.mac_address)},
(dr.CONNECTION_NETWORK_MAC, self._device_info[DEVICE_MAC_ADDRESS]) identifiers={(DOMAIN, self._device_info.serial_number)},
},
identifiers={(DOMAIN, self._device_info[DEVICE_SERIAL_NUMBER])},
manufacturer=MANUFACTURER, manufacturer=MANUFACTURER,
model=self._device_info[DEVICE_MODEL], model=self._device_info.model,
name=self._device_info[DEVICE_NAME], name=self._device_info.name,
suggested_area=self._room_name, suggested_area=self._room_name,
sw_version=sw_version, sw_version=sw_version,
configuration_url=f"http://{self._hub_address}/api/shades", configuration_url=f"http://{self._device_info.hub_address}/api/shades",
) )
@ -76,7 +66,7 @@ class ShadeEntity(HDEntity):
def __init__( def __init__(
self, self,
coordinator: PowerviewShadeUpdateCoordinator, coordinator: PowerviewShadeUpdateCoordinator,
device_info: dict[str, Any], device_info: PowerviewDeviceInfo,
room_name: str, room_name: str,
shade: BaseShade, shade: BaseShade,
shade_name: str, shade_name: str,
@ -104,8 +94,8 @@ class ShadeEntity(HDEntity):
suggested_area=self._room_name, suggested_area=self._room_name,
manufacturer=MANUFACTURER, manufacturer=MANUFACTURER,
model=str(self._shade.raw_data[ATTR_TYPE]), model=str(self._shade.raw_data[ATTR_TYPE]),
via_device=(DOMAIN, self._device_info[DEVICE_SERIAL_NUMBER]), via_device=(DOMAIN, self._device_info.serial_number),
configuration_url=f"http://{self._hub_address}/api/shades/{self._shade.id}", configuration_url=f"http://{self._device_info.hub_address}/api/shades/{self._shade.id}",
) )
for shade in self._shade.shade_types: for shade in self._shade.shade_types:

View File

@ -0,0 +1,33 @@
"""Define Hunter Douglas data models."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from aiopvapi.helpers.aiorequest import AioRequest
from .coordinator import PowerviewShadeUpdateCoordinator
@dataclass
class PowerviewEntryData:
"""Define class for main domain information."""
api: AioRequest
room_data: dict[str, Any]
scene_data: dict[str, Any]
shade_data: dict[str, Any]
coordinator: PowerviewShadeUpdateCoordinator
device_info: PowerviewDeviceInfo
@dataclass
class PowerviewDeviceInfo:
"""Define class for device information."""
name: str
mac_address: str
serial_number: str
firmware: dict[str, Any]
model: str
hub_address: str

View File

@ -10,17 +10,9 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import ( from .const import DOMAIN, ROOM_NAME_UNICODE, STATE_ATTRIBUTE_ROOM_NAME
COORDINATOR,
DEVICE_INFO,
DOMAIN,
PV_API,
PV_ROOM_DATA,
PV_SCENE_DATA,
ROOM_NAME_UNICODE,
STATE_ATTRIBUTE_ROOM_NAME,
)
from .entity import HDEntity from .entity import HDEntity
from .model import PowerviewEntryData
async def async_setup_entry( async def async_setup_entry(
@ -28,18 +20,15 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up powerview scene entries.""" """Set up powerview scene entries."""
pv_data = hass.data[DOMAIN][entry.entry_id] pv_entry: PowerviewEntryData = hass.data[DOMAIN][entry.entry_id]
room_data = pv_data[PV_ROOM_DATA]
scene_data = pv_data[PV_SCENE_DATA]
pv_request = pv_data[PV_API]
coordinator = pv_data[COORDINATOR]
device_info = pv_data[DEVICE_INFO]
pvscenes = [] pvscenes = []
for raw_scene in scene_data.values(): for raw_scene in pv_entry.scene_data.values():
scene = PvScene(raw_scene, pv_request) scene = PvScene(raw_scene, pv_entry.api)
room_name = room_data.get(scene.room_id, {}).get(ROOM_NAME_UNICODE, "") room_name = pv_entry.room_data.get(scene.room_id, {}).get(ROOM_NAME_UNICODE, "")
pvscenes.append(PowerViewScene(coordinator, device_info, room_name, scene)) pvscenes.append(
PowerViewScene(pv_entry.coordinator, pv_entry.device_info, room_name, scene)
)
async_add_entities(pvscenes) async_add_entities(pvscenes)

View File

@ -1,5 +1,5 @@
"""Support for hunterdouglass_powerview sensors.""" """Support for hunterdouglass_powerview sensors."""
from aiopvapi.resources.shade import factory as PvShade from aiopvapi.resources.shade import BaseShade, factory as PvShade
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
SensorDeviceClass, SensorDeviceClass,
@ -13,18 +13,14 @@ from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import ( from .const import (
COORDINATOR,
DEVICE_INFO,
DOMAIN, DOMAIN,
PV_API,
PV_ROOM_DATA,
PV_SHADE_DATA,
ROOM_ID_IN_SHADE, ROOM_ID_IN_SHADE,
ROOM_NAME_UNICODE, ROOM_NAME_UNICODE,
SHADE_BATTERY_LEVEL, SHADE_BATTERY_LEVEL,
SHADE_BATTERY_LEVEL_MAX, SHADE_BATTERY_LEVEL_MAX,
) )
from .entity import ShadeEntity from .entity import ShadeEntity
from .model import PowerviewEntryData
async def async_setup_entry( async def async_setup_entry(
@ -32,24 +28,23 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up the hunter douglas shades sensors.""" """Set up the hunter douglas shades sensors."""
pv_data = hass.data[DOMAIN][entry.entry_id] pv_entry: PowerviewEntryData = hass.data[DOMAIN][entry.entry_id]
room_data = pv_data[PV_ROOM_DATA]
shade_data = pv_data[PV_SHADE_DATA]
pv_request = pv_data[PV_API]
coordinator = pv_data[COORDINATOR]
device_info = pv_data[DEVICE_INFO]
entities = [] entities = []
for raw_shade in shade_data.values(): for raw_shade in pv_entry.shade_data.values():
shade = PvShade(raw_shade, pv_request) shade: BaseShade = PvShade(raw_shade, pv_entry.api)
if SHADE_BATTERY_LEVEL not in shade.raw_data: if SHADE_BATTERY_LEVEL not in shade.raw_data:
continue continue
name_before_refresh = shade.name name_before_refresh = shade.name
room_id = shade.raw_data.get(ROOM_ID_IN_SHADE) room_id = shade.raw_data.get(ROOM_ID_IN_SHADE)
room_name = room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "") room_name = pv_entry.room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "")
entities.append( entities.append(
PowerViewShadeBatterySensor( PowerViewShadeBatterySensor(
coordinator, device_info, room_name, shade, name_before_refresh pv_entry.coordinator,
pv_entry.device_info,
room_name,
shade,
name_before_refresh,
) )
) )
async_add_entities(entities) async_add_entities(entities)