Skip to content

fix: stop sensor value flip when device is offline#770

Open
michikrug wants to merge 1 commit into
tolwi:mainfrom
michikrug:fix-resets
Open

fix: stop sensor value flip when device is offline#770
michikrug wants to merge 1 commit into
tolwi:mainfrom
michikrug:fix-resets

Conversation

@michikrug
Copy link
Copy Markdown

@michikrug michikrug commented Apr 22, 2026

Problem

Two related regressions introduced in v1.5.0 affect devices connected via the public API (e.g. PowerStream) that have no MQTT heartbeat:

1. Sensor values flipping between real values and zero every 30–60 seconds while offline

The _handle_coordinator_update reset logic fired on every coordinator tick while is_offline. Meanwhile, quota_all() continues polling the EcoFlow REST API on a scheduled interval — and the API returns cached data regardless of actual device status. Each quota response bumped changed=True for one tick, temporarily restoring real sensor values, before the next tick reset them back to zero. This caused continuous flipping for the entire offline period.

2. Device stuck permanently offline once it passed through the ASSUME_OFFLINE window

The DeviceStatusCoordinator polls /device/list to recover online status, but only when wants_status_poll is True — which was exclusively the case for ASSUME_OFFLINE. If the coordinator tick missed the ASSUME_OFFLINE window and the tracker decayed to full OFFLINE, wants_status_poll returned False, the poll was permanently skipped, and the device could not recover without a full HA restart.

Root cause context

The v1.5.0 changes were a deliberate fix for a v1.4.1 bug where /device/quota/all returning cached data for offline devices caused online=True to be set unconditionally, meaning devices never showed as offline. The is_auto=False flag on quota PreparedData was the correct fix for that — but the recovery and reset mechanisms did not account for public-API-only devices that have no MQTT activity.

Fix

devices/status_tracker.py — extend wants_status_poll to include OFFLINE:

@property
def wants_status_poll(self) -> bool:
    return not self.is_online  # ASSUME_OFFLINE and OFFLINE both need a poll

The StatusCoordinator interval is already set to assume_offline_sec (default 5 min), so this adds at most one /device/list call per interval with no meaningful API overhead. Maximum recovery time after a device comes back online: ~5 minutes.

entities/__init__.py — fire the offline reset once, suppress cached quota data while offline, and restore immediately on recovery.

Key behaviours:

  • Reset fires once on the first OFFLINE tick, then the entity is frozen at the default value
  • Subsequent ticks while offline — including changed=True ticks from cached quota data — are ignored entirely
  • On the first tick after the device comes back online, params are restored immediately without waiting for the next quota poll

Behaviour summary

Scenario Before (v1.5.0) After this fix
Sensors while offline Flip between real values and 0 every ~30–60s Reset to 0 once, stable for entire offline period
Device offline past ASSUME_OFFLINE window Stuck offline permanently Recovered within ~5 min of coming back online
Device comes back online Values restored on next quota poll (sensors may show 0 in the gap) Values restored on first coordinator tick after status poll

@michikrug michikrug marked this pull request as ready for review April 23, 2026 07:24
@michikrug
Copy link
Copy Markdown
Author

Tested this now for >24h without issues

@tolwi
Copy link
Copy Markdown
Owner

tolwi commented Apr 24, 2026

but the recovery and reset mechanisms did not account for public-API-only devices that have no MQTT activity. - if there is no MQTT activity, then why do we need to bring this device back online?

@michikrug
Copy link
Copy Markdown
Author

michikrug commented Apr 25, 2026

if there is no MQTT activity, then why do we need to bring this device back online?

Unsure if I understood you right...

When the device is offline at startup, /device/list calls on_explicit_status(False) which sets _explicit_offline = True. Status returns OFFLINE directly, wants_status_poll returns False, and the coordinator never polls again. The device cannot recover without a restart of the integration.

Maybe me and my AI are on the wrong path, but if so, how would an offline public API device come online again in your understanding?

@tolwi
Copy link
Copy Markdown
Owner

tolwi commented Apr 25, 2026

When a device comes back online and emits MQTT messages, on_data_received() is called in status_tracker — clears _explicit_offline and flips status to ONLINE automatically.

REST calls to /device/list are for the ASSUME_OFFLINE stage, to actualize the state when MQTT has gone quiet but we're not yet sure if the device is truly offline.

@michikrug
Copy link
Copy Markdown
Author

michikrug commented Apr 25, 2026

Thanks.

Still this seem to have not happened for my PowerStream device :/

Could it be that those status messages are not reliably sent or received?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants