Skip to content

Build 14: rate-limit/SSE reconnect fixes + device status no-op guards#2

Merged
bumaas merged 7 commits into
masterfrom
release/build-14
Jun 29, 2026
Merged

Build 14: rate-limit/SSE reconnect fixes + device status no-op guards#2
bumaas merged 7 commits into
masterfrom
release/build-14

Conversation

@bumaas

@bumaas bumaas commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Fasst zwei Korrektur-Stränge in einem Release (Build 14) zusammen.

1. Device-Status nur bei Änderung setzen

Baut auf Thomas' (ThomasM65) PR #1 auf und vervollständigt ihn: Seit „Fix/device status refresh and setting constraints (symcon#10)" rief das Home-Connect-Device-Modul SetStatus() bei jedem Refresh (Parent-Statuswechsel, CONNECT, Reconnect, ApplyChanges) bedingungslos auf. Das triggerte Status-Monitoring (EventControl-Skripte) auch ohne tatsächliche Änderung und erzeugte viele unnötige Log-/Trigger-Einträge.

Alle drei Status-Setzer (IS_ACTIVE in refreshDeviceState() sowie beide IS_INACTIVE-Aufrufe in refreshDeviceState() und im FM_DISCONNECT-Handler) laufen jetzt über eine neue Hilfsmethode setInstanceStatus(), die den aktuellen Status zuerst vergleicht und nur bei echter Änderung schreibt — analog zum bereits im Cloud-Modul vorhandenen Guard.

2. Rate-Limit-/SSE-Reconnect-Fixes

  • Verhindert, dass die SSE-Reconnect-Schleife /events weiter anfragt, während ein Rate-Limit aktiv ist.
  • Behebt eine Re-Init-Schleife, die das API-Kontingent bei Geräten ohne OperationState aufbraucht.
  • Neue Tests: HomeConnectCloudTest, HomeConnectFridgeFreezerTest.

Build

library.json: build 11 → 14, date → 1782691200 (2026-06-29).

Tests

PHPUnit: 30 Tests, 519 Assertions – grün.

bumaas and others added 7 commits June 24, 2026 12:00
Devices without an OperationState in /status (e.g. FridgeFreezer) never
created that variable, so needsInitialization() returned true on every
IM_CHANGESTATUS. Each parent status flap re-ran a full InitializeDevice(),
burning through the rate limit within seconds (observed: 3 full cycles
before the 429).

Replace the fragile "OperationState variable exists" check with a dedicated
Initialized attribute that is only set true after a fully successful
initialization. The signature is written at the same point, so a partial
failure (offline / rate limit mid-way) leaves Initialized=false and a retry
happens on the next CONNECTED event - not on every status flap.

Also suppress the echo for rate-limit responses (key 429) in
RequestDataFromParent so blocked requests no longer spam the kernel log as
"Fehler bei Instanz ... IM_CHANGESTATUS".

Add a FridgeFreezer fixture and regression test (with an API request counter
in the test API) that fails on the old code (5 calls) and passes now (0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The keep-alive watchdog (60s timer) reconnected the event stream whenever no
KEEP-ALIVE arrived. When /events itself returns 429 (daily limit), no keep-alive
ever arrives, so the watchdog reconnected every ~60s - ~1440 calls/day, which on
its own exceeds the 1000/day limit and keeps the account permanently blocked.
This was independent of the device re-init loop and is why the problem persisted.

- Guard RegisterServerEvents() on isRateLimitActive(): defer the reconnect to the
  end of the block window instead of retrying immediately. This covers all
  reconnect paths (Reconnect timer, keep-alive check, FM_CONNECT).
- CheckServerEvents() returns early while rate limited (the missing keep-alive is
  expected then).
- ResetRateLimit() resumes the stream exactly once when the window ends.
- Feed a 429 carried by the SSE stream into the shared rate-limit machinery
  (ReceiveData -> applyRateLimitFromStream), so the limit is honored even when no
  REST call ran. Extracted applyRateLimit() so REST and SSE share one code path.

Add HomeConnectCloudTest covering: 429-from-stream activates the limit, reconnect
is deferred while limited, keep-alive check skips while limited. These fail on the
old code (reconnect despite limit) and pass now.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends Thomas' fix (#1) so the Home Connect Device instance status is only
written when it actually changes. Before, refreshDeviceState() and the
FM_DISCONNECT handler called SetStatus() unconditionally on every refresh
(parent status change, CONNECT, reconnect, ApplyChanges), which re-triggered
status monitoring (EventControl scripts) even when nothing changed.

Route the IS_ACTIVE and both IS_INACTIVE setters through a new
setInstanceStatus() helper that compares the current status first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bumaas bumaas merged commit f90a1c4 into master Jun 29, 2026
2 of 4 checks passed
@bumaas bumaas deleted the release/build-14 branch June 29, 2026 14:59
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.

1 participant