Fix coordinator wiring after refactor

Two bugs left from the hass.data move that surfaced as soon as the
integration ran on the live HA:

* In async_setup_entry, devices were stored in hass.data AFTER
  coordinator.async_config_entry_first_refresh(), but
  _async_update_data reads them from hass.data — so the very first
  refresh raised KeyError 'devices' and the entry stayed in
  setup_retry. Move the hass.data update before first_refresh.

* SmartThingsDeviceTracker called self.async_on_update(...) which
  isn't a method on TrackerEntity. Without a working listener
  registration the tracker stayed restored=true / unavailable
  forever. Subscribe in async_added_to_hass and use async_on_remove
  for cleanup, which is the documented pattern.

Verified end-to-end on a live HA: phones/watch produce GPS, battery
sensors populate, and the Ring button triggers a SmartTag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeena 2026-05-05 02:01:05 +00:00
parent 73aa86cfb5
commit 7457a8284b
2 changed files with 17 additions and 9 deletions

View file

@ -62,18 +62,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
update_interval = entry.options.get(CONF_UPDATE_INTERVAL, CONF_UPDATE_INTERVAL_DEFAULT)
coordinator = SmartThingsFindCoordinator(hass, session, entry.entry_id, update_interval)
# This is what makes the whole integration slow to load (around 10-15
# seconds for my 15 devices) but it is the right way to do it. Only if
# it succeeds, the integration will be marked as successfully loaded.
await coordinator.async_config_entry_first_refresh()
# Store everything the coordinator needs BEFORE the first refresh,
# because _async_update_data reads `devices` out of hass.data.
hass.data[DOMAIN][entry.entry_id].update({
CONF_JSESSIONID: jsessionid,
"session": session,
"coordinator": coordinator,
"devices": devices
"devices": devices,
})
# This is what makes the whole integration slow to load (around 10-15
# seconds for my 15 devices) but it is the right way to do it. Only if
# it succeeds, the integration will be marked as successfully loaded.
await coordinator.async_config_entry_first_refresh()
hass.async_create_task(
hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
)

View file

@ -43,7 +43,13 @@ class SmartThingsDeviceTracker(DeviceTrackerEntity):
if 'icons' in device['data'] and 'coloredIcon' in device['data']['icons']:
self._attr_entity_picture = device['data']['icons']['coloredIcon']
self.async_on_update(coordinator.async_add_listener(self.async_write_ha_state))
async def async_added_to_hass(self) -> None:
"""Subscribe to coordinator updates once added to HA."""
await super().async_added_to_hass()
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state)
)
def async_write_ha_state(self):
if not self.enabled: