Skip to content

[Bug]: Electrical readings cleared during HTS reconnect — should stay at last known value #146

@bvis

Description

@bvis

Background

1.4.0 shipped RestoreSensor on the four electrical-reading sensors (current, voltage, energy_consumed, power_derived) so they survive HA restarts (#144). That covers the boot path but not the mid-session transient HTS disconnect path, which can be 5+ minutes long on a busy install and surfaces as the sensors going unavailable even though we have a perfectly good last-known value.

Example from bvis-home on 1.4.0 (HTS dropped + reconnected ~5 min later, healthy install):

21:30:12.257 WARNING [aegis_ajax.api.hts.client]   ACK failed: Connection lost
21:30:12.360 WARNING [aegis_ajax.api.hts.client] HTS connection error in listen: Connection closed by remote
21:35:12.299 INFO    [aegis_ajax.coordinator] HTS connected, 1 hub(s)

During those 5 minutes, the four electrical-reading sensors render as unavailable because coordinator._handle_hts_disconnect() calls self.device_readings.clear() (coordinator.py:569). The sensor entity's available property then short-circuits to False.

Desired behaviour

Three scenarios, with the contract the integration should honour for the electrical-reading sensors:

  1. Active HTS connection — values update as deltas arrive (current behaviour, unchanged). HA's recorder/state_machine persists each state change automatically, so the "last value at next restart" is always the most recent live value.
  2. HTS disconnected mid-session — keep the last known value visible to the user. The hub remembers device state across our socket outages; our cached value is the truth until proven otherwise by a fresh delta when HTS reconnects.
  3. Boot / fresh entityRestoreSensor seeds the entity from HA's persisted last state until the first live delta lands (already works after 1.4.0).

Scope

In:

  • The four sensor classes in _AjaxDeviceReadingsBase subclasses (AjaxDeviceCurrentSensor, AjaxDeviceVoltageSensor, AjaxDeviceEnergyConsumedSensor, AjaxDeviceDerivedPowerSensor).
  • AjaxCobrandedCoordinator._handle_hts_disconnect().

Out:

  • Hub-network sensors (ethernet_ip, wifi_ssid, gsm_signal_level, mains power, etc.) — these intentionally go unavailable during HTS outages. Their value reflects "what we currently know about the hub's network state" and during an outage we genuinely don't know. Showing a 5-minute-old wifi_ssid would be misleading. The existing hub_network.clear() in _handle_hts_disconnect stays.

Proposed fix

One line, plus tests.

coordinator.py:567-570, current:

if self.hub_network or self.device_readings:
    self.hub_network.clear()
    self.device_readings.clear()
    self.async_set_updated_data({"spaces": self.spaces, "devices": self.devices})

Change to:

# Hub-network state IS stale once HTS drops (we don't know the hub's
# current connection state without the stream). Per-device electrical
# readings are device-state the hub itself remembers — keep them
# visible so a transient reconnect cycle doesn't blow away the value
# the user was just looking at.
if self.hub_network:
    self.hub_network.clear()
    self.async_set_updated_data({"spaces": self.spaces, "devices": self.devices})

With the clear removed, after disconnect:

  • device_readings[device_id] retains the cached value.
  • The sensor's _live_native_value keeps returning that value.
  • HA continues to persist the unchanged state on each periodic snapshot.
  • When HTS reconnects, the first STATUS_UPDATE delta for the device updates the cached value as usual.

Test plan

  • New TestHandleHtsDisconnect coordinator case: pre-seed device_readings, call _handle_hts_disconnect(), assert the dict is untouched but hub_network is cleared.
  • Adjust the existing test_hts_disconnect_clears_device_readings test to assert the opposite (rename it accordingly).
  • New sensor integration test: with _handle_hts_disconnect() called mid-session, entity.available stays True and native_value keeps returning the cached value.
  • Hub-network sensors should keep their existing unavailable behaviour (no change to that path).

Release target

1.4.1 patch — pure bug fix, no new functionality, no breaking changes. SemVer PATCH (consistent with the SemVer-strict-from-1.3.0 policy).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions