Refactor HgiGateway status to use async state model (#537)#541
Open
PWhite-Eng wants to merge 5 commits intoramses-rf:masterfrom
Open
Refactor HgiGateway status to use async state model (#537)#541PWhite-Eng wants to merge 5 commits intoramses-rf:masterfrom
PWhite-Eng wants to merge 5 commits intoramses-rf:masterfrom
Conversation
…ses-rf#537) - Added `GATEWAY_MESSAGE_TIMEOUT` constant (5 minutes) in `const.py`. - Refactored `HgiGateway.is_active` in `base.py` into an async method to evaluate gateway availability based on `_engine._this_msg.dtm`. - Consolidated and expanded tests in `test_base.py` covering DeviceBase heartbeats, BatteryState mock behavior, and HgiGateway message timeouts. - Resolved strict mypy static analysis issues using robust type assertions. Fixes Issue ramses-rf#537.
Contributor
Author
|
@silverailscolo, this PR is stacked ontop of #539, please merge that PR before merging this PR. Please note there is a matching PR for ramses_cc to be released shortly |
|
|
||
| import logging | ||
| from collections.abc import Callable | ||
| from datetime import timedelta |
Collaborator
There was a problem hiding this comment.
Also here: import timedelta as td
silverailscolo
requested changes
Mar 29, 2026
|
|
||
| import logging | ||
| from collections.abc import Callable | ||
| from datetime import timedelta |
| """Return the timeout before the device is considered unavailable. | ||
|
|
||
| :return: The timeout duration before going unavailable. | ||
| :rtype: timedelta |
| # lf._msgs_ot_ctl_polled = {} | ||
|
|
||
| @property | ||
| def heartbeat_timeout(self) -> timedelta: |
| """Return the timeout before the device is considered unavailable. | ||
|
|
||
| :return: The timeout duration. | ||
| :rtype: timedelta |
| _STATE_ATTR = SZ_HEAT_DEMAND | ||
|
|
||
| @property | ||
| def heartbeat_timeout(self) -> timedelta: |
| """Return the timeout before the device is considered unavailable. | ||
|
|
||
| :return: The timeout duration. | ||
| :rtype: timedelta |
| """Return the timeout before the device is considered unavailable. | ||
|
|
||
| :return: The timeout duration. | ||
| :rtype: timedelta |
| which all reside in ramses_rf/device/base.py. | ||
| """ | ||
|
|
||
| from datetime import UTC, datetime, timedelta |
Minimum allowed line rate is |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Problem:
Currently, determining if the Gateway is active relies on synchronous engine querying which bypasses the standard asynchronous state model of the architecture. This technical debt makes state tracking inconsistent and harder to maintain for Home Assistant integrations (Issue #537).
Consequences:
If left unaddressed, the library retains architectural fragmentation by mixing synchronous attribute polling with async state evaluations. This limits the ability to safely track and expose the Gateway's live connection status to downstream consumers (like ramses_cc), potentially leading to stale UI representations or blocking calls.
The Fix:
We encapsulated the gateway state logic within the HgiGateway class itself by adding an asynchronous is_active() method. We also introduced a formal configurable timeout to define exactly when a gateway is considered "inactive".
Technical Implementation:
Note: This PR introduces a breaking change to how gateway status is queried and MUST be merged at the exact same time as the matching PR for ramses_cc.
Testing Performed:
Risks of NOT Implementing:
Failing to adopt this change leaves the gateway state tracking coupled to internal engine attributes, making future architectural shifts difficult and maintaining legacy synchronous blocks in an asynchronous application.
Risks of Implementing:
Consumers of the ramses_rf library (specifically ramses_cc) that currently inspect the gateway engine properties directly or rely on synchronous evaluation will break.
Mitigation Steps:
We have ensured complete backward compatibility for standard devices while explicitly isolating the breaking changes to HgiGateway.is_active(). A corresponding branch and PR for ramses_cc has been developed in tandem to utilize resolve_async_attr to handle this new implementation gracefully.
AI Assistance Disclosure:
This contribution was developed with the assistance of Google Gemini 3.1 Pro for code generation and documentation. No Agentic AI systems were employed; all logic and implementations were reviewed, verified, and manually committed by the author.