parent
f285b6099a
commit
a816348616
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue