Ryan Malloy 4781f4d276
Some checks are pending
Validate / HACS validation (push) Waiting to run
Validate / Hassfest (push) Waiting to run
panel: trigger initial loadList from discover, prefer loaded entries
Two bugs surfaced when smoke-testing against a real OmniPro II:

1. Empty list after page load. _discoverViaList ran fire-and-forget;
   connectedCallback then synchronously checked _entryId (still null
   because await hadn't resolved) and skipped _loadList. The panel
   rendered "No programs match the current filters" forever — until
   the next 5-second poll tick, which never fires because
   _startRefreshTimer was also gated on the same null check.

   Fix: have _discoverViaList itself trigger _loadList and
   _startRefreshTimer after _entryId lands. The connectedCallback /
   updated paths can stay gated on _entryId; the discover path now
   takes ownership of "do the initial load too."

2. Dev installs with both a working entry and a setup_retry entry
   (mock container down, real panel up) had the panel pick the
   setup_retry one first and surface "panel not configured" on every
   call. Fix: prefer entries with state === "loaded" in the discover
   step, falling back to first entry only when none are loaded.

Also: screenshot.py drops the seed-via-WS step (was unsafe — would
write Programs to whatever entry is loaded, including real panels).
Updates the in-page click helpers to walk the shadow DOM recursively
instead of hardcoding HA's host-element path, so detail/editor
screenshots work on the actual depth-8 element location.

Smoke test against real panel: 154 programs render correctly with
structured English, BEDTIME / OPEN BIG GAR / Zone 133 events all
decoded, B. GAR MAN DOOR [SECURE] live-state badge visible.
Detail panel + editor mode both function end-to-end.
2026-05-16 17:48:17 -06:00
..

Dev stack

Local Home Assistant + MockPanel for clicking around the integration without a real Omni controller. Useful for screenshots, manual smoke tests, and seeing what the entity layout looks like.

Quick start

cd dev/
make dev-up         # docker compose up -d
# wait ~30s for HA to boot
open http://localhost:8123

First time: HA onboarding wizard (any name / location works). Then:

  1. Settings → Devices & Services → Add Integration
  2. Search for HAI/Leviton Omni Panel
  3. Fill in:
    • host: host.docker.internal
    • port: 14369
    • controller key: 000102030405060708090a0b0c0d0e0f
  4. Submit. Within a few seconds you should see the Omni Pro II device with ~25 entities (binary sensors, lights, alarm panel, climate, sensors, buttons, switches, the events entity).

What the mock simulates

Five named zones, four units, two areas, two thermostats, three button macros. User codes 1234 (master, code index 1) and 5678 (code index 2).

Arming the alarm with code 1234 will succeed and the alarm_control_panel entity transitions through ARMING → ARMED_AWAY in real time via the panel's push-event simulation. Wrong code → HA error toast, panel stays disarmed.

Other targets

make dev-logs       # tail HA + mock logs
make dev-mock       # run only the mock on the host (no docker)
make dev-down       # stop the stack
make dev-reset      # wipe HA config and start fresh

Notes

  • The HA container mounts ../custom_components/omni_pca/ read-only, so edits to the integration need a restart (docker compose restart homeassistant) to take effect.
  • The mock panel binds 0.0.0.0:14369 inside the container. If you prefer to talk to it from the host directly (e.g. with omni-pca CLI), use make dev-mock to run it natively.