Import UniFi Protect live views + optional auto-resync

views ls/dump/import copy a Protect live view (cameras + grid) into a
layout; grid inferred from slot count (asymmetric presets TBD, see
views dump). Imported layouts link back via protect_view.

Daemon re-syncs the active linked view every view_refresh_seconds (0=
off), so Protect-side edits appear on the wall. Needs the controller
password at runtime; off by default keeps the wall credential-free.

Shared viewmap package used by CLI and daemon.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Levi Woodard
2026-07-02 07:13:51 -05:00
parent 9da5ace150
commit 291d37ec83
8 changed files with 420 additions and 3 deletions

View File

@@ -36,6 +36,11 @@ type Config struct {
// ActiveLayout is the name of the layout the daemon renders.
ActiveLayout string `yaml:"active_layout"`
// ViewRefreshSeconds, when > 0, makes the daemon periodically re-sync the
// active layout from its linked UniFi Protect live view (ProtectView).
// Requires controller credentials available to the daemon. 0 = off.
ViewRefreshSeconds int `yaml:"view_refresh_seconds,omitempty"`
}
// Controller holds UniFi Protect connection details.
@@ -169,6 +174,10 @@ type Layout struct {
// Slots is the legacy one-camera-per-cell model (row-major). Kept for
// backward compatibility; EffectiveTiles converts it to tiles.
Slots []string `yaml:"slots,omitempty"`
// ProtectView, when set, is the name of the UniFi Protect live view this
// layout mirrors. `views import` sets it; the daemon re-syncs it on a timer
// when view_refresh_seconds > 0 and controller creds are available.
ProtectView string `yaml:"protect_view,omitempty"`
}
// Tile places one camera at a rectangular region of the base grid.