|
1 | 1 | """DataUpdateCoordinator for Plugwise USB-Stick.""" |
2 | 2 |
|
| 3 | +import asyncio |
3 | 4 | from datetime import timedelta |
4 | 5 | import logging |
5 | 6 | from typing import Any |
6 | 7 |
|
7 | | -import async_timeout |
8 | | - |
9 | 8 | from homeassistant.core import HomeAssistant |
10 | | -from homeassistant.exceptions import ConfigEntryNotReady |
11 | 9 | from homeassistant.helpers.update_coordinator import ( |
| 10 | + ConfigEntryError, |
12 | 11 | DataUpdateCoordinator, |
13 | 12 | UpdateFailed, |
14 | 13 | ) |
15 | | -from plugwise_usb.api import NodeFeature |
16 | | -from plugwise_usb.exceptions import NodeError, NodeTimeout, StickError |
| 14 | +from plugwise_usb.api import NodeFeature, NodeInfo |
| 15 | +from plugwise_usb.exceptions import NodeError, NodeTimeout, StickError, StickTimeout |
17 | 16 | from plugwise_usb.nodes import PlugwiseNode |
18 | 17 |
|
19 | 18 | _LOGGER = logging.getLogger(__name__) |
@@ -52,32 +51,35 @@ def __init__( |
52 | 51 | always_update=True, |
53 | 52 | ) |
54 | 53 |
|
| 54 | + async def get_node_info(self) -> NodeInfo: |
| 55 | + """Return node information.""" |
| 56 | + node_info: NodeInfo | None = None |
| 57 | + if (node_info := await self.node.node_info_update()) is None: |
| 58 | + raise UpdateFailed(f"Failed to pull node information from Plugwise node: {self.node.mac}") |
| 59 | + if node_info.battery_powered: |
| 60 | + self.always_update = False |
| 61 | + return node_info |
| 62 | + |
55 | 63 | async def async_node_update(self) -> dict[NodeFeature, Any]: |
56 | 64 | """Request status update for Plugwise Node.""" |
| 65 | + states: dict[NodeFeature, Any] = {} |
| 66 | + if not self._initial_update_done: |
| 67 | + _LOGGER.debug("Initial coordinator update for %s", self.node.mac) |
| 68 | + states[NodeFeature.INFO] = await self.get_node_info() |
| 69 | + self._initial_update_done = True |
| 70 | + return states |
| 71 | + |
| 72 | + features = tuple(self.async_contexts()) |
| 73 | + _LOGGER.debug("Coordinator update for %s, context=%s", self.node.mac, features) |
57 | 74 | try: |
58 | | - async with async_timeout.timeout(30): |
59 | | - if not self._initial_update_done: |
60 | | - _LOGGER.debug( |
61 | | - "Initial coordinator update for %s", self.node.mac |
62 | | - ) |
63 | | - self._initial_update_done = await self.node.node_info_update() |
64 | | - states: dict[NodeFeature, Any] = {} |
65 | | - states[NodeFeature.INFO] = self.node.node_info |
66 | | - if self.node.node_info.battery_powered: |
67 | | - self.always_update = False |
68 | | - return states |
69 | | - features = set(self.async_contexts()) |
70 | | - _LOGGER.debug( |
71 | | - "Coordinator update for %s, context=%s", |
72 | | - self.node.mac, |
73 | | - str(features), |
74 | | - ) |
75 | | - return await self.node.get_state(features) |
| 75 | + states = await self.node.get_state(features) |
76 | 76 | except StickError as err: |
77 | | - raise ConfigEntryNotReady from err |
78 | | - except NodeTimeout as err: |
79 | | - raise TimeoutError from err |
| 77 | + raise ConfigEntryError from err |
| 78 | + except (StickTimeout, NodeTimeout) as err: |
| 79 | + raise asyncio.TimeoutError from err |
80 | 80 | except NodeError as err: |
81 | | - raise UpdateFailed( |
82 | | - f"Failed to pull data from Plugwise node: {err}" |
83 | | - ) from err |
| 81 | + raise UpdateFailed from err |
| 82 | + |
| 83 | + if not states[NodeFeature.AVAILABLE]: |
| 84 | + raise UpdateFailed(f"Plugwise node {self.node.mac} is not on-line.") |
| 85 | + return states |
0 commit comments