Build 14: device status no-op guards + rate-limit/SSE reconnect fixes#17
Merged
Conversation
Write InitializationSignature at the start of InitializeDevice() instead of at the end. Previously, if createStates() failed (device offline) or setupSettings() was interrupted (rate limit hit mid-way), the signature was never written. Any subsequent IM_CHANGESTATUS or CONNECTED event would re-trigger InitializeDevice(), burning through the 1000 requests/day limit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
I'm using Eventcontrol-Scripts to monitor if Status of Instances has changed. Since last change Status is updated very often even if state has not changed. This will Trigger everytime a Eventcontrol message (no option on changed, always on updated). There is no way to check if status was already active (no $_IPS['LASTSTATUS']). So now EventControl will only get triggered if Status has really changed.
Set status to active only if not already active
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>
# Conflicts: # library.json
Build 14: rate-limit/SSE reconnect fixes + device status no-op guards
# Conflicts: # Home Connect Device/module.php # library.json
ordered_class_elements moved the private helpers below the public methods in Home Connect Cloud/module.php (applyRateLimitFromStream) and tests/HomeConnectCloudTest.php (cloud/invoke), fixing the checkstyle run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TillBrede
approved these changes
Jul 1, 2026
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.
Bringt
symcon/HomeConnectauf Build 14 und bündelt zwei Korrektur-Stränge.1. Device-Status nur bei Änderung setzen
Seit „Fix/device status refresh and setting constraints (#10)" rief das Home-Connect-Device-Modul
SetStatus()bei jedem Refresh (Parent-Statuswechsel, CONNECT, Reconnect, ApplyChanges) bedingungslos auf. Das triggerte Status-Monitoring (z. B. EventControl-Skripte) auch ohne tatsächliche Änderung und erzeugte viele unnötige Log-/Trigger-Einträge.Alle drei Status-Setzer (
IS_ACTIVEinrefreshDeviceState()sowie beideIS_INACTIVE-Aufrufe inrefreshDeviceState()und imFM_DISCONNECT-Handler) laufen jetzt über eine neue HilfsmethodesetInstanceStatus(), die den aktuellen Status zuerst vergleicht und nur bei echter Änderung schreibt — analog zum bereits im Cloud-Modul vorhandenen Guard. Ursprünglich gemeldet und angestoßen von @ThomasM65.2. Rate-Limit-/SSE-Reconnect-Fixes
/eventsweiter anfragt, während ein Rate-Limit aktiv ist.OperationStateaufbraucht (Initialized-Attribut statt vorab geschriebener Signatur).HomeConnectCloudTest,HomeConnectFridgeFreezerTest.Build
library.json: build → 14, date → 1782691200 (2026-06-29).Tests
PHPUnit: 30 Tests, 519 Assertions – grün.