Skip to content

Fix IntesisBox local (WMP) path: CR terminator, tolerant init, ack returns, keepalive and reconnect - #87

Merged
jnimmo merged 1 commit into
jnimmo:masterfrom
i6media:fix-intesisbox-local-path
Aug 18, 2026
Merged

Fix IntesisBox local (WMP) path: CR terminator, tolerant init, ack returns, keepalive and reconnect#87
jnimmo merged 1 commit into
jnimmo:masterfrom
i6media:fix-intesisbox-local-path

Conversation

@i6media

@i6media i6media commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Fixes #86.

This makes the IntesisBox (WMP local protocol) path work end-to-end. All five issues from #86 are addressed, each verified against real hardware: an INWMPMHI001R000 (MH-RC-WMP-1, WMP firmware v1.3.3) on a Mitsubishi Heavy FDUM71VH ducted unit, driven through hass-intesishome. With this branch the device connects, initialises, polls, accepts commands and survives socket loss.

Changes

  1. CR terminatorIntesisBox now overrides _send_command to guarantee the \r the WMP protocol requires. Previously only SET carried one, so ID/LIMITS/GET were never parsed by the device and connecting always ended in cannot_connect.
  2. Tolerant init — the LIMITS:* discovery queries are sent with wait_for_response=False. A unit without a feature never answers that feature's LIMITS query (the ducted unit is completely silent on LIMITS:VANELR, no ERR), which used to trip the 5s timeout and close the socket mid-init.
  3. Ack returnsIntesisBase._send_command now returns a bool (written + response frame arrived in time), and the IntesisBox set_* methods return it, matching the cloud classes' documented contract. They returned None, which consumers like hass-intesishome treat as an unacknowledged command — every service call raised after the ONOFF byte had already gone out, aborting the mode/setpoint steps that follow. set_mode also returns False for a mode the map doesn't know instead of silently doing nothing.
  4. Keepalive actually runsconnect() now schedules the existing _send_keepalive loop, which was never created anywhere. Besides keeping the otherwise idle socket alive, its blocking wait doubles as a dead-socket detector (a missed reply closes the writer within ~35s instead of "whenever the user next sends a command").
  5. ReconnectIntesisBox implements the _handle_disconnect hook with a capped exponential backoff loop (15s → 300s), guarded by a stopped flag so an intentional stop() stays stopped.

Tests

Adds IntesisBox coverage via a fake WMP TCP device (FakeWMPServer in tests/__init__.py, replacing the NotImplementedError placeholder callback), mirroring the real device's behaviour including the silent LIMITS:VANELR. New tests cover: init with an unanswered LIMITS query, the CR-terminated command stream, keepalive task creation, bool returns for acknowledged / unanswered / invalid commands, reconnect after connection loss, and stop() suppressing the reconnect loop.

pytest (94 passed) and pylint (10.00/10) both clean.

…turns, keepalive and reconnect

Verified against an INWMPMHI001R000 (MH-RC-WMP-1, WMP v1.3.3) on a
Mitsubishi Heavy FDUM71VH ducted unit. Fixes jnimmo#86:

- Append the \r terminator the WMP protocol requires to every command;
  only SET carried one, so ID/LIMITS/GET were never parsed by the device
  and connecting always failed with a timeout.
- Send the LIMITS:* init queries without blocking on a reply: a unit
  without a feature never answers that feature's LIMITS query (e.g. a
  ducted unit is silent on LIMITS:VANELR), which used to close the
  socket mid-init.
- Return a bool from _send_command and the IntesisBox set_* methods,
  matching the cloud classes' contract; they returned None, which
  consumers such as hass-intesishome treat as an unacknowledged command.
- Start the existing _send_keepalive loop from connect(); it was never
  scheduled, leaving the socket idle and letting it die undetected.
- Reconnect with capped exponential backoff after an unexpected socket
  loss via the _handle_disconnect hook, guarded by a stopped flag so an
  intentional stop() stays stopped.

Adds IntesisBox coverage to the test suite through a fake WMP TCP
device, replacing the NotImplementedError placeholder callback.
@jnimmo
jnimmo merged commit e02a02d into jnimmo:master Aug 18, 2026
3 of 4 checks passed
@jnimmo

jnimmo commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Thanks very much @i6media

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.

IntesisBox (WMP) local path broken in 2.3.0: missing \r terminator, fatal timeout on unanswered LIMITS, set_* return None

2 participants