Repository navigation
Conversation
This branch has not been deployed
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.
Local (
RiscoLocal) sessions could fail in ways that only a manual reload of the consumer fixed. A dropped connection left commands waiting and the listener running. A failed setup left the panel session open. A late reply could answer a different command. This PR makes the local client detect lost or unusable sessions, close them cleanly, and report the loss to the consumer. It also paces the consumer's nextconnect()to what the panel accepts.It is split into 10 commits, one concern each, and is meant to be reviewed commit by commit. Each behaviour change comes with its tests, and the suite passes at every commit.
UnauthorizedErroronly for anN06that answers the login-X devdiagnosticsLibrary: +711 / -149 lines in
pyrisco/andREADME.md. Tests and CI: +4,053 lines.Related PRs
This covers the fix proposed in #44 (cancel pending futures and stop the listener at end of stream). Credit to @rhalutz for the original fix; that PR's test file is not included here. The keep-alive changes overlap #22.
Field failures that motivated it
These happened on one RISCO LightSYS 2 (RP432M firmware 6.07, RP512IP), used through Home Assistant 2026.9 at concurrency 1:
KeyError, and then the keep-alive got id-lessN05answers, 8,021 times in 15 hours, until a manual reload.connect()failed whenFSVER?was answeredN05, and the panel then refused TCP connections for about 30 minutes.How it fails today
Reproduced on that installation with released 0.8.1 and Home Assistant 2026.9's own
riscointegration, by black-holing the panel connection at the firewall, so the socket stays open and the panel's answers never arrive:The session is never given up, so the consumer is never told and never reconnects. Only a manual reload or a restart recovers. The 2026-09-10 incident above is the same shape, with
N05answers in place of timeouts.The other half of that incident also reproduces against released 0.8.1, with a stand-in panel object that answers
N05to one zone's status query duringconnect():Setup reports success without zone 4, and every status the panel pushes for it reaches the consumer as that
KeyError. With this PR, the zone is read again; if the panel still refuses it, the zone is left out and its pushes are reported once as a status for an unknown zone (test_a_zone_whose_status_is_refused_twice_is_left_out_and_reported).Behaviour changes to review
CommunicationError(a subclass ofOperationError) is raised for lost or malformed answers.ConnectionLostErroralso subclassesConnectionResetError, so existing reconnect checks keep working. Communication failures during setup raiseCannotConnectError. Errors reported while no error handler is registered are kept (the last 20) and delivered to the first handler added. The backlog is reset at eachconnect(), and setup errors that the connect recovered from are not reported.disconnect()to the nextconnect().PNLCNF,FSVER?,PNLSERDorSSTT?fails the connect withCannotConnectError. A missing label, partition or group gets a placeholder and is reported to the error handlers; a placeholder partition or group reads as "in none", not as "unknown". A zone whose status is refused twice is left out until the next connect. Setup now fails without a usable system status or without an enabled partition.CannotConnectErrorimmediately, instead of holdingconnect()open.N06carrying the login's command ID raisesUnauthorizedError. Other refusals, unexpected replies and timeouts are retryable. An id-lessN06therefore times out as a retryable failure.Testsworkflow runs on pull requests andmaster(Ubuntu, Python 3.11-3.14,-X dev). It fails on asyncio or resource diagnostics (leaked sockets, never-awaited coroutines, unhandled task exceptions) even when unittest passes.Testing
tests/scripted_panel.py), each added with the commit it tests: 220 tests at the last commit.riscointegration does on a lost connection, with that integration unchanged. That check needs Home Assistant, so it lives outside this repository.riscointegration was adapted for these runs, so that it disconnects when Home Assistant stops or setup fails. Like the released integration, it reloads on a reported connection loss.connect()paced the retries. That includes a cut in the middle of discovery and three cuts in a row, where the reconnect delay grew to 10 s and then 20 s.*from the query key (ZSTT*1?is answeredZSTT1=...), and a reply the panel had withheld arrived on the next connection.N06carrying the login's command ID.These results come from one panel model and firmware. They do not validate every policy above on other panels.