Skip to content

Fix duplicate devices on miner boot (#593), add reconfigure flow (#440), clearer power-limit errors (#564), add test suite - #609

Open
nalditopr wants to merge 3 commits into
Schnitzel:mainfrom
nalditopr:fix-duplicate-devices-reconfigure
Open

Fix duplicate devices on miner boot (#593), add reconfigure flow (#440), clearer power-limit errors (#564), add test suite#609
nalditopr wants to merge 3 commits into
Schnitzel:mainfrom
nalditopr:fix-duplicate-devices-reconfigure

Conversation

@nalditopr

Copy link
Copy Markdown
Contributor

Stacked on #608 (its commit is included here; merge #608 first or this together).

Fixes #593 — duplicate _2 devices after a hard boot

Entities and the device were keyed on whatever MAC the miner reported at setup time. A miner that is still booting (S19j Pro etc. — network up, control board API not yet) reports mac=None; the offline "zeroed data" path introduced for #538 also carries mac: None. Result: entities created as None-hashrate … and, once the real MAC arrived, a second device with _2 entities.

  • Pin the MAC in config_entry.data[CONF_MAC] the first time it is seen and fall back to it whenever the miner reports none.
  • Never return placeholder data during initial setup: raise ConfigEntryNotReady so HA retries later instead of creating None-* entities. After setup, keep the Offline miners keep stale sensor values and break global totals (energy/hashrate) (FIX INCLUDED) #538 behaviour (one tolerated failure → zeroed data, then UpdateFailed).
  • Remove the redundant async_config_entry_first_refresh() calls from the platform async_setup_entrys — __init__ already does it, and raising from a forwarded platform is flagged as an error by current HA.

Fixes #440 — change IP without re-adding

Adds a reconfigure step (Settings → Integrations → ⋮ → Reconfigure) to change the IP address and min/max power. Rejects the change if the device at the new IP has a different MAC.

Fixes #564 — clearer power-limit errors

number.set_value raises HomeAssistantError with an actionable message when the miner has no tunable presets (pyasic's max() iterable argument is empty), rejects the value, or does not support tuning — instead of a raw ValueError/TypeError in the websocket log.

Tests

Adds a pytest suite using pytest-homeassistant-custom-component (23 tests: patch.ensure_pyasic locking/reinstall-scope, coordinator MAC pinning + failure handling + VNish CONFIG retry, user/reconfigure config flows, number errors) and a GitHub Actions workflow running it on Python 3.14 / HA 2026.8.2. ruff check is clean; tests are exempted from docstring rules.

Verified live on HA 2026.8.2 with 4 miners (BOS+, VNish, stock): all entries load, MACs pinned, reconfigure available, no duplicate devices.

After a Core update the container has no pyasic, so every config entry
called _ensure_pyasic concurrently. Each ran 'uv pip install --reinstall
pyasic', which uninstalls/reinstalls all 30 dependencies (cryptography,
pydantic, httpx, ...) already imported by Core and other integrations,
while sibling entries imported half-unpacked packages -> ModuleNotFoundError
/ AttributeError and permanent setup_error.

- Move the logic to patch.ensure_pyasic(), serialized with a process lock
- Use --reinstall-package pyasic (no --upgrade) so only pyasic is touched
- Purge stale pyasic modules before and after install
- __init__ and config_flow share the single implementation

(cherry picked from commit d2cddb8)
…uite

Fixes Schnitzel#593: entities and the device were keyed on the MAC reported at
setup time. A miner that is still booting (or the offline zeroed-data
path) reports mac=None, so entities were created with 'None-...' unique
ids and a second '_2' device appeared once the real MAC came back.

- Pin the MAC in config_entry.data (CONF_MAC) the first time it is seen
  and fall back to it whenever the miner reports none.
- Never hand back placeholder data during initial setup: raise
  ConfigEntryNotReady so HA retries instead of creating None entities.
  Post-setup keeps the Schnitzel#538 behaviour (one tolerated failure -> zeroed
  data, then UpdateFailed).
- Drop the redundant async_config_entry_first_refresh() calls in the
  platform setups; __init__ already performed it and raising from a
  forwarded platform is an error in current HA.

Fixes Schnitzel#440: add a reconfigure step to change the IP / power range of an
existing miner without re-adding it (rejects a different miner by MAC).

Fixes Schnitzel#564: number/set_value now raises a HomeAssistantError with a
clear message when the miner has no tunable presets, rejects the value,
or does not support tuning, instead of a raw ValueError/TypeError.

Add a pytest suite (pytest-homeassistant-custom-component) covering
patch.ensure_pyasic locking, coordinator MAC pinning / failure handling,
config + reconfigure flows and number errors, plus a GitHub Actions
workflow to run it.
Some firmwares flip between upper- and lower-case MACs across versions,
which produced a second device for the same miner. Pin and compare the
MAC upper-cased.

Implement async_remove_config_entry_device so leftover devices whose
identifier is not the pinned MAC (e.g. the lowercase duplicate) get a
Delete button in the UI; the live device stays protected.
@nalditopr

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit: MAC is now pinned/compared upper-cased (some firmwares flip case between versions — that alone yields a duplicate device), and async_remove_config_entry_device is implemented so leftover duplicates get a Delete button in the device UI while the live device stays protected. Suite is now 25 tests, all green; verified live by deleting two lowercase-MAC leftovers on my install.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant