Fix missing powerview shade data when initial refresh fails (#113033)

This commit is contained in:
J. Nick Koston 2024-03-27 03:38:57 -10:00 committed by GitHub
parent 5316b94705
commit ce022a1793
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 31 additions and 39 deletions

View File

@ -71,7 +71,6 @@ async def async_setup_entry(
entities: list[ShadeEntity] = []
for shade in pv_entry.shade_data.values():
coordinator.data.update_shade_position(shade.id, shade.current_position)
room_name = getattr(pv_entry.room_data.get(shade.room_id), ATTR_NAME, "")
entities.extend(
create_powerview_shade_entity(

View File

@ -41,7 +41,7 @@ def store_velocity(
value: float | None,
) -> None:
"""Store the desired shade velocity in the coordinator."""
coordinator.data.update_shade_velocity(shade_id, ShadePosition(velocity=value))
coordinator.data.update_shade_position(shade_id, ShadePosition(velocity=value))
NUMBERS: Final = (

View File

@ -2,6 +2,7 @@
from __future__ import annotations
from dataclasses import fields
import logging
from typing import Any
@ -12,74 +13,66 @@ from .util import async_map_data_by_id
_LOGGER = logging.getLogger(__name__)
POSITION_FIELDS = fields(ShadePosition)
def copy_position_data(source: ShadePosition, target: ShadePosition) -> ShadePosition:
"""Copy position data from source to target for None values only."""
# the hub will always return a velocity of 0 on initial connect,
# separate definition to store consistent value in HA
# this value is purely driven from HA
for field in POSITION_FIELDS:
if (value := getattr(source, field.name)) is not None:
setattr(target, field.name, value)
class PowerviewShadeData:
"""Coordinate shade data between multiple api calls."""
def __init__(self) -> None:
"""Init the shade data."""
self._group_data_by_id: dict[int, dict[str | int, Any]] = {}
self._shade_data_by_id: dict[int, BaseShade] = {}
self._raw_data_by_id: dict[int, dict[str | int, Any]] = {}
self._shade_group_data_by_id: dict[int, BaseShade] = {}
self.positions: dict[int, ShadePosition] = {}
def get_raw_data(self, shade_id: int) -> dict[str | int, Any]:
"""Get data for the shade."""
return self._group_data_by_id[shade_id]
return self._raw_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
return self._raw_data_by_id
def get_shade(self, shade_id: int) -> BaseShade:
"""Get specific shade from the coordinator."""
return self._shade_data_by_id[shade_id]
return self._shade_group_data_by_id[shade_id]
def get_shade_position(self, shade_id: int) -> ShadePosition:
"""Get positions for a shade."""
if shade_id not in self.positions:
self.positions[shade_id] = ShadePosition()
shade_position = ShadePosition()
# If we have the group data, use it to populate the initial position
if shade := self._shade_group_data_by_id.get(shade_id):
copy_position_data(shade.current_position, shade_position)
self.positions[shade_id] = shade_position
return self.positions[shade_id]
def update_from_group_data(self, shade_id: int) -> None:
"""Process an update from the group data."""
self.update_shade_positions(self._shade_data_by_id[shade_id])
data = self._shade_group_data_by_id[shade_id]
copy_position_data(data.current_position, self.get_shade_position(data.id))
def store_group_data(self, shade_data: PowerviewData) -> None:
"""Store data from the all shades endpoint.
This does not update the shades or positions
This does not update the shades or positions (self.positions)
as the data may be stale. update_from_group_data
with a shade_id will update a specific shade
from the group data.
"""
self._shade_data_by_id = shade_data.processed
self._group_data_by_id = async_map_data_by_id(shade_data.raw)
self._shade_group_data_by_id = shade_data.processed
self._raw_data_by_id = async_map_data_by_id(shade_data.raw)
def update_shade_position(self, shade_id: int, shade_data: ShadePosition) -> None:
def update_shade_position(self, shade_id: int, new_position: ShadePosition) -> None:
"""Update a single shades position."""
if shade_id not in self.positions:
self.positions[shade_id] = ShadePosition()
# ShadePosition will return None if the value is not set
if shade_data.primary is not None:
self.positions[shade_id].primary = shade_data.primary
if shade_data.secondary is not None:
self.positions[shade_id].secondary = shade_data.secondary
if shade_data.tilt is not None:
self.positions[shade_id].tilt = shade_data.tilt
def update_shade_velocity(self, shade_id: int, shade_data: ShadePosition) -> None:
"""Update a single shades velocity."""
if shade_id not in self.positions:
self.positions[shade_id] = ShadePosition()
# the hub will always return a velocity of 0 on initial connect,
# separate definition to store consistent value in HA
# this value is purely driven from HA
if shade_data.velocity is not None:
self.positions[shade_id].velocity = shade_data.velocity
def update_shade_positions(self, data: BaseShade) -> None:
"""Update a shades from data dict."""
_LOGGER.debug("Raw data update: %s", data.raw_data)
self.update_shade_position(data.id, data.current_position)
copy_position_data(new_position, self.get_shade_position(shade_id))