# Local dev stack: real Home Assistant talking to a MockPanel running on # the host. Lets you click around the UI and grab screenshots without a # physical Omni controller. # # make dev-up # start # make dev-logs # tail HA logs # make dev-down # stop and clean # # On every container start the HA service pip-installs the local # `omni-pca` library from ../ into site-packages (the version pinned in # the integration manifest isn't on PyPI yet, and we want our latest # v1/ subpackage available either way). Source changes in src/omni_pca # require a ``docker compose restart homeassistant`` to take effect. # # Once running, open http://localhost:8123 and: # 1. Onboard with any name / location. # 2. Settings -> Devices & Services -> Add Integration -> # "HAI/Leviton Omni Panel". # 3. Use one of: # Mock panel (TCP): # host host.docker.internal # port 14369 # transport TCP # controller_key 000102030405060708090a0b0c0d0e0f # Real panel (UDP, v1 wire protocol): # host # port 4369 # transport UDP # controller_key <32 hex chars from the panel's .pca file> services: mock-panel: image: ghcr.io/astral-sh/uv:python3.14-bookworm-slim working_dir: /tmp/mock volumes: - ../src:/tmp/mock/src:ro - ./run_mock_panel.py:/tmp/mock/run_mock_panel.py:ro # Mount the captured .pca fixtures read-only so the mock can # optionally seed its state from a real export. Set # OMNI_PCA_FIXTURE in dev/.env (or pass on the command line) to # activate; left unset, the mock uses the hard-coded sample. - /home/kdm/home-auto/HAI:/fixtures:ro environment: PYTHONPATH: /tmp/mock/src OMNI_PCA_FIXTURE: ${OMNI_PCA_FIXTURE:-} command: - sh - -c - "uv pip install --system --quiet cryptography && python /tmp/mock/run_mock_panel.py --host 0.0.0.0 --port 14369" ports: - "14369:14369" networks: - default homeassistant: image: ghcr.io/home-assistant/home-assistant:2026.5 container_name: omni-pca-dev-ha depends_on: - mock-panel volumes: - ./ha-config:/config - ../custom_components/omni_pca:/config/custom_components/omni_pca:ro # Make the whole library project (pyproject + src/ + dist/) available # so the entrypoint override below can pip-install from local source # before /init starts. This gives HA real dist-info for # ``omni-pca==2026.5.10`` (which isn't on PyPI yet) and ensures the # v1 subpackage is present. - ../:/opt/omni-pca-src:ro # Keep 8123 mapped on localhost for direct access during development; # public traffic comes in via caddy-docker-proxy on the `caddy` net. ports: - "8123:8123" extra_hosts: - "host.docker.internal:host-gateway" environment: - TZ=America/Boise networks: - default - caddy labels: caddy: juliet.warehack.ing caddy.reverse_proxy: "{{upstreams 8123}}" # HA uses WebSockets for the frontend (lovelace state updates, # config flow, etc.) so we need the streaming-friendly settings # from CLAUDE.md, otherwise caddy closes the socket every ~15s. caddy.reverse_proxy.flush_interval: "-1" caddy.reverse_proxy.transport: http caddy.reverse_proxy.transport.read_timeout: "0" caddy.reverse_proxy.transport.write_timeout: "0" caddy.reverse_proxy.transport.keepalive: 5m caddy.reverse_proxy.transport.keepalive_idle_conns: "10" caddy.reverse_proxy.stream_timeout: 24h caddy.reverse_proxy.stream_close_delay: 5s # HA's image entrypoint is /init (s6-overlay). We pre-install our # local library against site-packages so HA's manifest-requirement # check finds it, then exec /init normally. entrypoint: - sh - -c - | set -e pip install --quiet --no-deps --upgrade /opt/omni-pca-src exec /init networks: caddy: external: true