Add the Companion status page and its watchdog for NA Ingest.

status_panel.py runs on NA Ingest as a LaunchAgent. Every second it reads
Companion's connection statuses and module variables, adds what Companion
cannot see (network MIDI peers, Bonjour sessions, pings, launchd services,
disk, Resi cloud, the Bible TV app), and writes one JSON custom variable that
page 19 renders. Buttons acknowledge alarms, mute them, and restart a stuck
Companion connection on a two second hold. If the watchdog stops, the page
turns purple instead of freezing on stale green.

make_page.py builds the page export from config.json; tests/ runs offline
against a fake Companion and a CoreMIDI loopback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 09:00:56 -04:00
co-authored by Claude Opus 5.5
commit 246500f965
9 changed files with 2481 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
{
"companion": { "host": "127.0.0.1", "port": 8000 },
"page": 19,
"page_name": "19\\nStatus",
"variables": { "state": "sp_state", "heartbeat": "sp_hb", "command": "sp_cmd" },
"service_windows": [
{ "days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"], "start": "00:00", "end": "23:59" }
],
"debounce_seconds": 3,
"flap": { "count": 3, "window_seconds": 600 },
"network": {
"interface": "en0",
"gateway": "10.1.0.1",
"burst_connections": 4,
"burst_groups": 3,
"burst_window_seconds": 10,
"remember_seconds": 180
},
"alert_webhook": "",
"tiles": [
{ "id": "all", "label": "ALL", "pos": [0, 1], "kind": "master" },
{ "id": "rec", "label": "REC", "pos": [0, 2], "members": ["hd1", "hd2", "hd3", "hd4", "hd5", "hd6", "tascam"] },
{ "id": "audio", "label": "AUDIO", "pos": [0, 3], "members": ["x32", "dante", "superrack"] },
{ "id": "rf", "label": "RF", "pos": [0, 4], "members": ["axient1", "axient2", "ulxd", "psm1", "psm2", "psm3"] },
{ "id": "show", "label": "SHOW", "pos": [0, 5], "members": ["propres", "lightpc", "tracks", "bibletv"] },
{ "id": "video", "label": "VIDEO", "pos": [0, 6], "members": ["atem", "led", "arena"] },
{ "id": "stream", "label": "STREAM", "pos": [0, 7], "members": ["obs", "resi"] },
{ "id": "hd1", "label": "HD1", "pos": [1, 1], "checks": [{ "type": "hyperdeck", "conn": "HyperDeck_1" }] },
{ "id": "hd2", "label": "HD2", "pos": [1, 2], "checks": [{ "type": "hyperdeck", "conn": "HyperDeck_2", "optional": true }] },
{ "id": "hd3", "label": "HD3", "pos": [1, 3], "checks": [{ "type": "hyperdeck", "conn": "HyperDeck_3" }] },
{ "id": "hd4", "label": "HD4", "pos": [1, 4], "checks": [{ "type": "hyperdeck", "conn": "HyperDeck_4", "optional": true }] },
{ "id": "hd5", "label": "HD5", "pos": [1, 5], "checks": [{ "type": "hyperdeck", "conn": "HyperDeck_5" }] },
{ "id": "hd6", "label": "HD6", "pos": [1, 6], "checks": [{ "type": "hyperdeck", "conn": "HyperDeck_6" }] },
{ "id": "tascam", "label": "TASCAM", "pos": [1, 7], "checks": [{ "type": "tascam", "conn": "tascam" }] },
{ "id": "x32", "label": "X32", "pos": [2, 1], "checks": [{ "type": "conn", "conn": "x32" }] },
{ "id": "dante", "label": "DANTE", "pos": [2, 2], "checks": [
{ "type": "dante", "conn": "audinate-dantecontroller", "devices": {
"FOH-DiGiCo-DMI-1": "DMI-1", "FOH-DiGiCo-DMI-2": "DMI-2", "BOH-WING": "WING", "BOH-DQ-Rack": "DQ RACK",
"BOH-AD4Q-A": "AD4Q-A", "BOH-AD4Q-B": "AD4Q-B", "STUDIO-A-X32": "STA X32",
"STUDIO-A-Resi-AJA-SDI": "RESI AJA", "STUDIO-A-Ingest": "INGEST", "NA-Translation": "TRANSL" } }
] },
{ "id": "tracks", "label": "TRACKS", "pos": [2, 3], "checks": [
{ "type": "dante", "conn": "audinate-dantecontroller", "devices": { "NA-Tracks": "DANTE" } },
{ "type": "ping", "host": "10.1.3.227", "name": "MAC" },
{ "type": "mdns", "instance": "NA Tracks", "name": "MIDI SESS" },
{ "type": "conn", "conn": "ableton" },
{ "type": "midi_rx", "source": "Network NA Ingest Listen", "name": "TRK MIDI" }
] },
{ "id": "lightpc", "label": "LIGHT PC", "pos": [2, 4], "checks": [
{ "type": "midi_peer", "session": "NA Ingest", "peer": "Lighting PC" },
{ "type": "mdns", "instance": "Lighting PC", "name": "MIDI SESS" },
{ "type": "midi_rx", "source": "Network NA Ingest", "name": "MIDI IN" }
] },
{ "id": "superrack", "label": "RACK", "pos": [2, 5], "checks": [
{ "type": "midi_peer", "session": "NA Ingest", "peer": "SuperRack-LiveBox" },
{ "type": "dante", "conn": "audinate-dantecontroller", "devices": { "FOH-SuperRack-LiveBox": "DANTE" } }
] },
{ "id": "bibletv", "label": "BIBLE TV", "pos": [2, 6], "checks": [
{ "type": "http", "url": "http://10.6.7.13:8080/", "msg": "APP DOWN", "interval_seconds": 5 },
{ "type": "conn", "conn": "BibleTV" }
] },
{ "id": "propres", "label": "PROP", "pos": [2, 7], "checks": [
{ "type": "conn", "conn": "Propresenter-API" },
{ "type": "dante", "conn": "audinate-dantecontroller", "devices": { "NA-ProPresenter-Mac": "DANTE" } }
] },
{ "id": "service", "label": "ALARMS", "pos": [3, 0], "kind": "service" },
{ "id": "atem", "label": "ATEM", "pos": [3, 1], "checks": [{ "type": "conn", "conn": "ATEM" }] },
{ "id": "obs", "label": "OBS", "pos": [3, 2], "checks": [{ "type": "conn", "conn": "OBS-Youtube", "service_only": true }] },
{ "id": "resi", "label": "RESI", "pos": [3, 3], "checks": [
{ "type": "conn", "conn": "RESI_Decoder" },
{ "type": "conn", "conn": "resi-studio-cues" },
{ "type": "http", "url": "https://central.resi.io/", "name": "CLOUD" }
] },
{ "id": "net", "label": "NET", "pos": [3, 4], "kind": "network" },
{ "id": "ingest", "label": "INGEST", "pos": [3, 5], "checks": [
{ "type": "launchd", "label": "org.waterschurch.resi-propresenter", "name": "BRIDGE" },
{ "type": "launchd", "label": "org.waterschurch.lobby-captions", "name": "CAPTIONS" },
{ "type": "process", "match": "/Applications/ProdDash.app/Contents/MacOS/ProdDash", "name": "PRODDASH" },
{ "type": "disk", "path": "/", "warn_gb": 25, "err_gb": 8 }
] },
{ "id": "led", "label": "LED", "pos": [3, 6], "checks": [{ "type": "conn", "conn": "VX1000" }, { "type": "conn", "conn": "UHDJr" }] },
{ "id": "arena", "label": "ARENA", "pos": [3, 7], "checks": [{ "type": "conn", "conn": "arena" }] },
{ "id": "axient1", "label": "AXIENT 1", "checks": [{ "type": "shure", "conn": "Axient_1", "channels": 4 }] },
{ "id": "axient2", "label": "AXIENT 2", "checks": [{ "type": "shure", "conn": "Axient_2", "channels": 4 }] },
{ "id": "ulxd", "label": "ULXD", "checks": [{ "type": "shure", "conn": "ULXD-4", "channels": 1 }] },
{ "id": "psm1", "label": "PSM 1", "checks": [{ "type": "psm", "conn": "PSM_1", "channels": 2 }] },
{ "id": "psm2", "label": "PSM 2", "checks": [{ "type": "psm", "conn": "PSM_2", "channels": 2 }] },
{ "id": "psm3", "label": "PSM 3", "checks": [{ "type": "psm", "conn": "PSM_3", "channels": 2 }] }
]
}