Skip to content

Commit

Permalink
Don't update failed frames.
Browse files Browse the repository at this point in the history
Requests, that are failed during async_setup, should not ever be sent via versioning.

Related to denpamusic/homeassistant-plum-ecomax#26
  • Loading branch information
denpamusic committed Apr 27, 2023
1 parent 87fbb5f commit fcb6b7f
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 23 deletions.
1 change: 1 addition & 0 deletions pyplumio/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ATTR_CONNECTED: Final = "connected"
ATTR_CURRENT_TEMP: Final = "current_temp"
ATTR_DEVICE_INDEX: Final = "device_index"
ATTR_FRAME_ERRORS: Final = "frame_errors"
ATTR_INDEX: Final = "index"
ATTR_LOADED: Final = "loaded"
ATTR_OFFSET: Final = "offset"
Expand Down
37 changes: 19 additions & 18 deletions pyplumio/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import ClassVar

from pyplumio import util
from pyplumio.const import ATTR_LOADED, DeviceType, FrameType
from pyplumio.const import ATTR_FRAME_ERRORS, ATTR_LOADED, DeviceType, FrameType
from pyplumio.exceptions import ParameterNotFoundError, UnknownDeviceError
from pyplumio.frames import DataFrameDescription, Frame, Request, get_frame_handler
from pyplumio.helpers.event_manager import EventManager
Expand Down Expand Up @@ -99,22 +99,23 @@ def handle_frame(self, frame: Frame) -> None:

async def async_setup(self) -> bool:
"""Setup addressable device object."""
try:
await asyncio.gather(
*{
self.create_task(
self.request(description.provides, description.frame_type)
)
for description in self._frame_types
},
return_exceptions=False,
)
await self.dispatch(ATTR_LOADED, True)
return True
except ValueError as e:
_LOGGER.error("Request failed: %s", e)
await self.dispatch(ATTR_LOADED, False)
return False
results = await asyncio.gather(
*{
self.create_task(
self.request(description.provides, description.frame_type)
)
for description in self._frame_types
},
return_exceptions=True,
)

errors = [
result.args[1] for result in results if isinstance(result, ValueError)
]

await self.dispatch(ATTR_FRAME_ERRORS, errors)
await self.dispatch(ATTR_LOADED, True)
return True

async def request(
self,
Expand All @@ -136,7 +137,7 @@ async def request(
except asyncio.TimeoutError:
retries -= 1

raise ValueError(f'could not request "{name}" with "{frame_type.name}"')
raise ValueError(f'could not request "{name}"', frame_type)


class SubDevice(Device):
Expand Down
11 changes: 9 additions & 2 deletions pyplumio/devices/ecomax.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import ClassVar, Final

from pyplumio.const import (
ATTR_FRAME_ERRORS,
ATTR_PASSWORD,
ATTR_SENSORS,
ATTR_STATE,
Expand Down Expand Up @@ -147,11 +148,17 @@ def _has_frame_version(self, frame_type: FrameType | int, version: int) -> bool:
and self._frame_versions[frame_type] == version
)

def _frame_is_supported(self, frame_type: FrameType | int) -> bool:
"""Check if frame is supported by the device."""
return frame_type not in self.data.get(ATTR_FRAME_ERRORS, [])

async def _update_frame_versions(self, versions: dict[int, int]) -> None:
"""Check versions and fetch outdated frames."""
for frame_type, version in versions.items():
if is_known_frame_type(frame_type) and not self._has_frame_version(
frame_type, version
if (
is_known_frame_type(frame_type)
and self._frame_is_supported(frame_type)
and not self._has_frame_version(frame_type, version)
):
# We don't have this frame or it's version has changed.
request = factory(get_frame_handler(frame_type), recipient=self.address)
Expand Down
17 changes: 14 additions & 3 deletions tests/test_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from pyplumio.const import (
ATTR_DEVICE_INDEX,
ATTR_FRAME_ERRORS,
ATTR_INDEX,
ATTR_LOADED,
ATTR_OFFSET,
Expand Down Expand Up @@ -117,6 +118,7 @@ async def test_async_setup() -> None:
await ecomax.wait_until_done()

assert await ecomax.get(ATTR_LOADED)
assert not ecomax.data[ATTR_FRAME_ERRORS]
assert mock_request.await_count == len(DATA_FRAME_TYPES)


Expand All @@ -126,13 +128,22 @@ async def test_async_setup_error(caplog) -> None:

with patch("pyplumio.devices.ecomax.EcoMAX.wait_for"), patch(
"pyplumio.devices.ecomax.EcoMAX.request",
side_effect=(ValueError("test"), True, True, True, True, True, True, True),
side_effect=(
ValueError("test", FrameType.REQUEST_ALERTS),
True,
True,
True,
True,
True,
True,
True,
),
) as mock_request:
await ecomax.async_setup()
await ecomax.wait_until_done()

assert "Request failed" in caplog.text
assert not await ecomax.get(ATTR_LOADED)
assert await ecomax.get(ATTR_LOADED)
assert ecomax.data[ATTR_FRAME_ERRORS][0] == FrameType.REQUEST_ALERTS
assert mock_request.await_count == len(DATA_FRAME_TYPES)


Expand Down

0 comments on commit fcb6b7f

Please sign in to comment.