Hi all,
I’m running an Italian Risco LightSYS Plus on HA OS 2026.4.4 and have been chasing the well-known pyrisco failure mode where the panel keeps beeping every ~20-30 minutes of supervision and the integration ends up in FAILED_UNLOAD. I’ve put together a tiny custom_component that monkey-patches pyrisco at runtime — no fork, no vendored copy, no manual edit of /usr/src — plus a configuration recommendation that stops the panel-side TCP reset cycle.
After 67+ minutes of continuous uptime with the patch + recommended config:
no more UnicodeDecodeError 'utf-8' codec can't decode byte 0xa7
no more FAILED_UNLOADrequiring a full HA restart
panel-side TCP reset cycle eliminated → no more periodic supervision beeps
real-time push events from PIR / arm-disarm working
Repo
GitHub: GitHub - polara-data/risco-patch: Workaround custom_component for pyrisco utf-8 / FAILED_UNLOAD / 0x17 split bugs (Italian Risco panels). Stops the ~30min supervision beep. · GitHub (HACS-compatible, full README inside)
What it does (TL;DR)
3 monkey-patches applied at module-load time (so they run before risco.async_setup_entry):
- Patch 1.
RiscoSocket.__init__defaultsencoding="latin-1"instead ofutf-8. Italian / EU panels send latin-1 / cp1252 bytes; UTF-8 raises on0x80-0xFF. - Patch 2.
RiscoSocket.disconnectwrapped intry/except (ConnectionResetError, OSError, BrokenPipeError). Same intent as @perceival’s PR home-assistant/core#165924 (still open after maintainer approval). - Patch 3.
RiscoCrypt.decodeusesrfind('\x17')instead ofsplit('\x17')so a0x17byte appearing in the payload doesn’t crash the listener withValueError: too many values to unpack. Pluserrors="replace"on the decode call.
+ 1 required config change — raise the integration’s scan_interval to 600 seconds (10 minutes):
In our testing, even with the three patches above the panel kept TCP-resetting every ~23 minutes (and emitting a beep at every reset) when scan_interval=30s (default). Raising it to 600 eliminated the cycle entirely (60+ min observed uptime). The cycle was polling-induced, not a firmware timer. To change it: Settings → Devices & services → Risco → Configure → Scan interval (sec) = 600. Real-time push events are unaffected.
Why this matters
The integration’s normal failure loop (without the patch) is:
panel sends byte 0xa7 → UnicodeDecodeError → listener task dies →
ConnectionResetError → reload triggered → reload fails because
unload raises → entry stuck in FAILED_UNLOAD → HA restart needed
Multiple users have reported variants of this:
- #169279 —
FAILED_UNLOADafter VM migration - Forum threads about constant beeping on Italian / Spanish / French panels
- PR #165924 by @perceival — addresses (2) but not (1) or (3); approved by @OnFreund, not yet merged
Install (4 steps)
<config>/custom_components/risco_patch/
├── __init__.py
└── manifest.json
Add one line to configuration.yaml:
risco_patch:
Restart HA. Look for these WARNING lines in the log (one-shot at boot):
[risco_patch] RiscoSocket encoding default -> latin-1
[risco_patch] RiscoSocket.disconnect hardened
[risco_patch] RiscoCrypt.decode patched (rsplit + errors=replace)
Then raise scan_interval to 600 in Risco’s options.
Caveats — read before installing
- English/US panels that already speak pure ASCII: this patch is harmless but unnecessary.
- Panels actually needing UTF-8 (rare — emoji in zone labels, custom firmware): change
_DEFAULT_ENCODING = "latin-1"at the top of__init__.pyto"utf-8"to keep only Patches 2 & 3. - Encoding is set via
setdefault, so if a future HA version starts passingencoding=...explicitly the patch becomes a no-op for Patch 1. scan_interval=600is the value that worked for our LightSYS Plus. Other panel models / firmwares may have a different optimal value — try 300 or 900 if 600 doesn’t fully eliminate resets.- Tested on HA OS 2026.4.4 + pyrisco 0.6.8 + Risco LightSYS Plus (IT). Reports from other panels welcome.
Happy to submit this upstream as proper PRs against pyrisco (and an extension of #165924), but in the meantime the custom_component path is the lowest-risk way to get out of the reconnect loop without waiting on a release cycle.
Tags / search keywords: risco local, pyrisco, UnicodeDecodeError 0xa7, FAILED_UNLOAD, panel beeping every 30 minutes, Italian Risco, LightSYS, Agility, ProSYS, scan_interval