v2.2.0: Merge pull request #81 from jnimmo/claude/pyintesishome-issue-80
What's Changed
A local device that stops responding after setup is now reported as
unreachable, instead of indefinitely serving its last-known state. Reported in
#80, following on from #79 which covered the setup path only.
Fixed
IntesisHomeLocal.is_connectednow reflects whether the device is actually
reachable. Previously it was only ever written byconnect()andstop(),
so it meant "connect() succeeded once and stop() hasn't been called" — a unit
that went dead after setup kept reporting its last-known temperature and mode
forever, and consumers received a byte-identical signal in the healthy and
dead cases (#80)- The updater no longer retries indefinitely when the device rejects the
credentials — for example after the password is changed on the unit. It
records the error and stops, mirroring the cloud reconnect loop, which has
always given up on authentication failures
Added
last_successful_update— a UTC datetime of when data was last received, or
None. Populated forIntesisHomeLocalfrom its poll loop, and for
IntesisHomeandIntesisBoxfrom the shared socket read loop. Gives
consumers a staleness signal on a tighter schedule thanis_connected, which
only goesFalseonce the controller has given up on the device entirely
Changed
IntesisHomeLocal.is_connectedgoesFalseafter 5 minutes without a
successful poll, and back toTrueon the next success. Recovery is
automatic — a device that comes back needs no intervention from the consumer- Polling now backs off while the device is failing: 6 seconds, doubling to a
30 second ceiling. These units are not powerful, and polling a struggling one
at the full rate can make matters worse. The failure count decays rather than
resetting on success, so a unit alternating timeouts and successes still gets
the easing off instead of being held at the full rate throughout IntesisHomeLocal._request_values()no longer absorbs connection and
authentication errors; the updater classifies them instead. Only relevant if
you subclass or call it directly
Upgrading
For IntesisHomeLocal, is_connected can now return False on a live
controller. That is the point of the release. Consumers that gate availability
on it need no change — the behaviour they already assume now actually happens.
Anything treating it as "was set up successfully" will see new False values.
One visible consequence: a device that reboots, or an access point that
reassociates, will surface as a brief unavailable period if it takes more than
five minutes to answer again.
The grace period, poll interval and backoff ceiling are instance attributes on
IntesisHomeLocal (_unavailable_after, _scan_interval,
_max_scan_interval). They can be adjusted, but being underscore-prefixed they
carry no stability guarantee.
IntesisHome (cloud) and IntesisBox availability behaviour is unchanged —
they gain last_successful_update and nothing else. In particular this release
does not change cloud availability being gated on the push socket
(jnimmo/hass-intesishome#50).
Internal
- Regression tests covering the full transition: healthy, unavailable after the
grace period, then recovering, with an assertion that the updater task
survives the outage — that last one is what a naive fix breaks - Tests for mid-run credential rejection and for the backoff schedule
- The test harness gained a switch that makes the mocked local device stop
answering, or start rejecting logins, part way through a run
Full Changelog: v2.1.0...v2.2.0