Add Hunter Douglas Powerview Diagnostics (#72918)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
kingy444 2022-06-05 13:42:21 +10:00 committed by GitHub
parent a502a8798f
commit 395d58840c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 118 additions and 3 deletions

View File

@ -506,6 +506,7 @@ omit =
homeassistant/components/hue/light.py homeassistant/components/hue/light.py
homeassistant/components/hunterdouglas_powerview/__init__.py homeassistant/components/hunterdouglas_powerview/__init__.py
homeassistant/components/hunterdouglas_powerview/coordinator.py homeassistant/components/hunterdouglas_powerview/coordinator.py
homeassistant/components/hunterdouglas_powerview/diagnostics.py
homeassistant/components/hunterdouglas_powerview/cover.py homeassistant/components/hunterdouglas_powerview/cover.py
homeassistant/components/hunterdouglas_powerview/entity.py homeassistant/components/hunterdouglas_powerview/entity.py
homeassistant/components/hunterdouglas_powerview/scene.py homeassistant/components/hunterdouglas_powerview/scene.py

View File

@ -87,9 +87,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async with async_timeout.timeout(10): async with async_timeout.timeout(10):
shades = Shades(pv_request) shades = Shades(pv_request)
shade_data = async_map_data_by_id( shade_entries = await shades.get_resources()
(await shades.get_resources())[SHADE_DATA] shade_data = async_map_data_by_id(shade_entries[SHADE_DATA])
)
except HUB_EXCEPTIONS as err: except HUB_EXCEPTIONS as err:
raise ConfigEntryNotReady( raise ConfigEntryNotReady(
f"Connection error to PowerView hub: {hub_address}: {err}" f"Connection error to PowerView hub: {hub_address}: {err}"
@ -99,6 +99,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
coordinator = PowerviewShadeUpdateCoordinator(hass, shades, hub_address) coordinator = PowerviewShadeUpdateCoordinator(hass, shades, hub_address)
coordinator.async_set_updated_data(PowerviewShadeData()) coordinator.async_set_updated_data(PowerviewShadeData())
# populate raw shade data into the coordinator for diagnostics
coordinator.data.store_group_data(shade_entries[SHADE_DATA])
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
PV_API: pv_request, PV_API: pv_request,

View File

@ -0,0 +1,108 @@
"""Diagnostics support for Powerview Hunter Douglas."""
from __future__ import annotations
from typing import Any
import attr
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntry
from .const import (
COORDINATOR,
DEVICE_INFO,
DEVICE_MAC_ADDRESS,
DEVICE_SERIAL_NUMBER,
DOMAIN,
PV_HUB_ADDRESS,
)
from .coordinator import PowerviewShadeUpdateCoordinator
REDACT_CONFIG = {
CONF_HOST,
DEVICE_MAC_ADDRESS,
DEVICE_SERIAL_NUMBER,
PV_HUB_ADDRESS,
"configuration_url",
}
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: ConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
data = _async_get_diagnostics(hass, entry)
device_registry = dr.async_get(hass)
data.update(
device_info=[
_async_device_as_dict(hass, device)
for device in dr.async_entries_for_config_entry(
device_registry, entry.entry_id
)
],
)
return data
async def async_get_device_diagnostics(
hass: HomeAssistant, entry: ConfigEntry, device: DeviceEntry
) -> dict[str, Any]:
"""Return diagnostics for a device entry."""
data = _async_get_diagnostics(hass, entry)
data["device_info"] = _async_device_as_dict(hass, device)
# try to match on name to restrict to shade if we can
# otherwise just return all shade data
# shade name is unique in powerview
shade_data = data["shade_data"]
for shade in shade_data:
if shade_data[shade]["name_unicode"] == device.name:
data["shade_data"] = shade_data[shade]
return data
@callback
def _async_get_diagnostics(
hass: HomeAssistant,
entry: ConfigEntry,
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
pv_data = hass.data[DOMAIN][entry.entry_id]
coordinator: PowerviewShadeUpdateCoordinator = pv_data[COORDINATOR]
shade_data = coordinator.data.get_all_raw_data()
hub_info = async_redact_data(pv_data[DEVICE_INFO], REDACT_CONFIG)
return {"hub_info": hub_info, "shade_data": shade_data}
@callback
def _async_device_as_dict(hass: HomeAssistant, device: DeviceEntry) -> dict[str, Any]:
"""Represent a Powerview device as a dictionary."""
# Gather information how this device is represented in Home Assistant
entity_registry = er.async_get(hass)
data = async_redact_data(attr.asdict(device), REDACT_CONFIG)
data["entities"] = []
entities: list[dict[str, Any]] = data["entities"]
entries = er.async_entries_for_device(
entity_registry,
device_id=device.id,
include_disabled_entities=True,
)
for entity_entry in entries:
state = hass.states.get(entity_entry.entity_id)
state_dict = None
if state:
state_dict = dict(state.as_dict())
state_dict.pop("context", None)
entity = attr.asdict(entity_entry)
entity["state"] = state_dict
entities.append(entity)
return data

View File

@ -59,6 +59,10 @@ class PowerviewShadeData:
"""Get data for the shade.""" """Get data for the shade."""
return self._group_data_by_id[shade_id] return self._group_data_by_id[shade_id]
def get_all_raw_data(self) -> dict[int, dict[str | int, Any]]:
"""Get data for all shades."""
return self._group_data_by_id
def get_shade_positions(self, shade_id: int) -> PowerviewShadePositions: def get_shade_positions(self, shade_id: int) -> PowerviewShadePositions:
"""Get positions for a shade.""" """Get positions for a shade."""
if shade_id not in self.positions: if shade_id not in self.positions: