fix(gecloud): report API access-denied instead of false inverter clock skew#4001
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes a misdiagnosis in the GivEnergy cloud integration where HTTP 401/403 (now commonly returned for non-Premium accounts) was treated as missing data, leaving the GE cloud “time” sensor stale and triggering false inverter clock-skew detection and auto-restart loops.
Changes:
- Track and expose GE cloud API auth failures (
api_auth_failed), mark the GE cloud time sensor asunavailableon access-denied to avoid “frozen timestamp” skew. - Update inverter time parsing to treat
unavailable/unknown/empty readings as “no reading” and skip clock-skew detection. - Add tests covering the new GE cloud auth behavior and inverter time handling.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| apps/predbat/gecloud.py | Track auth failures, publish unavailable time sensor, and surface a clearer status for access-denied scenarios. |
| apps/predbat/inverter.py | Treat unavailable/unknown inverter time readings as absent so skew detection and auto-restart are skipped. |
| apps/predbat/tests/test_ge_cloud.py | Add tests validating auth flag behavior and that auth failure marks the time sensor unavailable. |
| apps/predbat/tests/test_inverter.py | Add test ensuring unavailable time doesn’t trigger skew/restart while real skew is still detected. |
…k skew
GivEnergy moved cloud API access behind a paid Premium tier (May 2026).
Accounts without an active subscription now get HTTP 401/403, but PredBat
misdiagnosed this as an "inverter clock skew" error and entered an
auto-restart loop:
- A 401/403 returned {} (indistinguishable from a successful empty
response), so the GE cloud time sensor was left holding a frozen
timestamp. As wall-clock advanced, the frozen time drifted past the
30-minute threshold, so inverter.py reported clock skew (had_errors) and
called auto_restart() — wrong cause, wrong advice, restart loop.
Changes:
- gecloud: track auth failure in api_auth_failed. The flag is set ONLY for
401/403 and cleared for every other outcome (success, 404/422, 429, 5xx,
connection error) so a transient failure after an auth failure is not
reported as an ongoing access-denied condition.
- gecloud: on auth failure, mark the time sensor unavailable (so it is not
left stale) and surface a correct status — "GivEnergy cloud API access
denied — a GivEnergy Premium subscription is now required". The status is
emitted inside the 120s poll guard, scoped to inverter (not EVC) auth
failures, and reported only once per episode (on transition) to avoid
inflating the HA error_count.
- inverter: treat an unavailable/unknown/empty time reading as "no reading"
(skip skew detection, no auto-restart); a genuine clock skew is still
detected.
Tests (TDD): 403 sets the flag and a non-401/403 response clears it;
success clears it; auth failure marks the time sensor unavailable; the
access-denied status is scoped to the inverter poll cycle and reported once
per episode; unavailable inverter time no longer triggers skew/auto-restart
while a real 2-hour skew still is.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
91aa1ba to
ceb9fd6
Compare
|
Thanks @copilot — both points addressed (history squashed into a single commit
Also scoped the status to inverter (not EVC) auth failures so an EVC-only 403 can't raise a false "cannot read inverter data". Full quick suite green; ruff/black/cspell pass. |
Problem
Since GivEnergy moved cloud API access behind a paid Premium tier (May 2026), accounts without an active subscription now get HTTP 401/403 from the cloud API. PredBat misdiagnoses this as an "inverter clock skew" error and enters an auto-restart loop, telling users to fix their inverter clock / HA sync / timezone — none of which is the real cause.
Root cause (traced)
gecloud.py async_get_inverter_datareturned{}for a 401/403 — indistinguishable from a successful empty response. Soasync_get_inverter_statuskept serving it andpublish_statusno-op'd, leaving the GE cloud time sensor (sensor.{prefix}_gecloud_{device}_time) frozen at its last value.Inverter.__init__, which calledrecord_status(... "minutes skewed", had_errors=True)andauto_restart()— repeatedly.Fix
api_auth_failed); split401/403(auth) from404/422(client_error); clear the flag on success.unavailableinstead of leaving it stale.unavailable/unknown/empty time reading as "no reading" → skip skew detection, no auto-restart. A genuine clock skew is still detected.Tests (TDD)
New, all passing (full quick suite green; ruff/black/cspell pass):
ge_cloud:api_auth_sets_flag(403 sets the flag),api_success_clears_auth_flag,publish_status_auth_unavailable.inverter:inverter_time_handling— an unavailable inverter time no longer triggers skew or auto-restart, while a real 2-hour skew still is detected.