Spool Device Migration#
What it is: A one-time, automatic cleanup that runs on every integration startup to remove stale Home Assistant devices left over from a pre-v1.2.0 architecture, where spools were grouped under location devices rather than represented as individual spool devices.
Background#
Before v1.2.0, the integration created HA devices keyed by location (e.g., location_1, location_2), and sensors for all spools at that location lived under the same device. In v1.2.0 this was redesigned as a breaking change: each spool became its own device with a 3-tuple identifier (DOMAIN, url, "spool_<id>") . The old location devices were left orphaned in the HA device registry after an upgrade, so automatic cleanup was added in v1.2.0 .
Entry Points#
| Function | File | Purpose |
|---|---|---|
_async_remove_old_location_devices() | __init__.py | Removes devices whose identifier third element starts with "location_" |
_async_cleanup_orphaned_spool_devices() | __init__.py | Removes spool devices whose spool ID no longer exists in Spoolman |
_async_cleanup_extra_field_entities() | __init__.py | Removes extra-field sensor entities for fields deleted from Spoolman |
All three are called from async_setup_entry() on every startup, immediately after the coordinator's first data refresh.
How _async_remove_old_location_devices Works#
- Fetches all devices associated with the config entry from the HA device registry .
- Iterates each device's identifier tuples; any identifier whose third element starts with
"location_"marks the device as a legacy location device . - Calls
device_reg.async_remove_device()for each match and logs a summary count .
The check is safe to run repeatedly β on subsequent startups no location_ devices exist, so nothing is removed.
Device Identifier Format (old vs. new)#
# Old β removed by migration
(DOMAIN, url, "location_<id>")
# New β preserved
(DOMAIN, url, "spool_<id>")
The new 3-tuple format was itself a fix: the original pre-v1.2.0 code used a 2-tuple (DOMAIN, "spool_<id>"), which caused sensors to register as separate devices instead of being grouped under a single spool device .
Ongoing Orphan Cleanup#
Beyond the one-time location migration, _async_cleanup_orphaned_spool_devices() runs on every coordinator update (via the listener registered at startup) . It compares the set of spool IDs returned by the Spoolman API against all spool_* devices in the registry and removes any that no longer exist β addressing issue #292 .
Related Files#
custom_components/spoolman/__init__.pyβ all three cleanup/migration functionscustom_components/spoolman/sensor.pyβasync_setup_entrythat builds per-spool entity stacks using the new device modelCHANGELOG.mdβ v1.2.0 breaking-change notes and v1.3.0 orphan cleanup notes