Skip to content

Serial and connection reliability - #8

Open
theharshl wants to merge 11 commits into
hikirsch:mainfrom
theharshl:up/l2
Open

Serial and connection reliability#8
theharshl wants to merge 11 commits into
hikirsch:mainfrom
theharshl:up/l2

Conversation

@theharshl

Copy link
Copy Markdown

Four fixes, all from real MCA-66-over-USB-serial failures reported by @steve28:

  • Model probe read too eagerly. It used a single StreamReader.read(), which returns as soon as any bytes are buffered. A cheap adapter delivering the reply across several USB packets was misread as a failed probe. Reads now accumulate until the reply matches a known model, the line goes quiet, or a deadline expires.
  • Retries reset the device they were probing. Each retry re-opened the port, and every open can toggle DTR and reset the gateway. The probe now opens once, pays the settle delay once, and retries on the open connection.
  • Checksum failures discarded good data. A bad checksum now resyncs minimally instead of trusting the frame or dropping the buffer wholesale.
  • Unreachable devices raised raw ValueError/OSError. They now raise HtdConnectionError with the address in the message, so callers can distinguish "can't reach it" from a bug.

Tests: 174 passing.


Part of the fork-upstreaming stack — see hikirsch/htd-home-assistant#34. Based on L1; until that merges the diff above includes its changes too. Please merge with a plain merge commit so the rest of the stack stays intact.

kingfetty and others added 11 commits March 27, 2026 00:43
…and Lync clients, data models, constants, and tests.
- Update MCA bass/treble/balance range to -12..12
- Enforce step size of 4 for bass/treble and 6 for balance
- Remove scaling logic from client and HA integration
- Add unit tests for MCA audio control logic and rounding
- Bump version to 0.0.26
…ance declaration

SET_ECHO_COMMAND_CODE and QUERY_ID_CODE are already defined in constants.py — drop the defensive hasattr ternaries in lync_client.py. Also add the missing @AbstractMethod declaration for async_set_balance in base_client.py alongside async_set_bass and async_set_treble.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Populate _zone_names on every ZONE_NAME_RECEIVE_COMMAND regardless of
whether zone_data exists yet. Expose get_zone_name(zone) -> str | None
mirroring get_source_name(). Also initialize _zone_names in async_connect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… cache tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
async_get_model_info() previously probed once with no retry, so a bad
read (partial data, or a gateway that resets on DTR toggle when a USB
serial adapter opens the port) left model_info as None, which crashed
async_get_client() with a bare TypeError on model_info["kind"].

Wires the existing retry_attempts into the model probe, adds a settle
delay after opening the serial port before the first write, and raises
a clear ValueError instead of crashing when detection still fails.

Fixes theharshl/htd-home-assistant#6
The model probe read the reply with a single StreamReader.read(), which
returns as soon as any bytes are buffered — a cheap USB-serial adapter
delivering a reply across several USB packets was misread as a failed
probe. Reads now accumulate until the reply matches a known model, the
line goes quiet, or an overall deadline expires; a silent device no
longer hangs the probe forever.

Probe retries also re-opened the serial port on every attempt, and each
open can toggle DTR and reset the gateway — so retries kept resetting
the device they were probing. The probe now opens the connection once,
pays the settle delay once, and retries on the open connection. The
persistent connection now waits out the same settle delay before its
first refresh write, which was previously sent immediately after the
port opened and could be lost to the same reset.

Replaces utils.async_send_command with async_open_connection +
async_read_response; renames MODEL_PROBE_SETTLE_DELAY to
SERIAL_SETTLE_DELAY now that it also guards the persistent connection.

Reported by @steve28 in theharshl/htd-home-assistant#19 (MCA-66 over
USB-serial).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A checksum mismatch means the parsed zone/command/length can't be
trusted -- it may be a coincidental match on misaligned or corrupted
bytes -- so skipping the full presumed frame length left the parser
permanently desynced after a single dropped/corrupted byte from a
flaky USB-serial adapter. Resync by header length only, matching the
existing unknown-command recovery path, so one bad frame no longer
cascades into a stream of "Bad sync buffer" / "Invalid command value"
errors during normal zone control.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

3 participants