diff --git a/README.md b/README.md
index e6c3381..02b1410 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ There are two parts:
Row 0 holds the group buttons. Each one shows the first problem in its group, plus "+N" if there are more:
- REC: HD1–6 and the Tascam.
-- AUDIO: X32 and Dante.
+- AUDIO: X32, DiGiCo and Dante.
- RF: all six Shure units (AD4Q ×2, ULXD4, PSM1000 ×3).
- SHOW: MIDI, APPS, VISTA and SPOTIFY. SPOTIFY has no key of its own any more; it shows inside SHOW, and its
force-play key is on the Restart page.
@@ -177,6 +177,7 @@ The **page number key** on every page follows the ALL button. It's green when ev
| | HD2 and HD4 are `"optional": true` in `config.json`: with no disk they sit grey with no alarm, and once a disk is in they are watched like the others. Add or remove `"optional": true` on any deck to change that. |
| TASCAM | connection; the recorder's own Error / Caution. Use the **1.3.1-quiet** Tascam module (see below) so Companion's log isn't flooded.; pinged at the address on its Companion connection. |
| X32, ARENA, OBS | Companion connection |
+| DIGICO (inside AUDIO) | Companion's `DiGiCo_FOH` connection; the relay helper `org.waterschurch.digico-relay` on NA Ingest (`~/digico-bridge/relay.py`: Companion and the DiGiCo tablets share the console's one External Control slot through it), **DIGICO RELAY STOPPED** / **NOT LOADED**, hold AUDIO restarts it; the console itself answers ping at 10.1.60.100, **DIGICO NO PING**. Companion's OSC connection reads "good" even with the console off, so the ping is what catches that. |
| ATEM | Companion connection; the switcher's **audio** (every Fairlight input's on/off/AFV and fader, e.g. Resi on input 16 ON, TRS off) and **camera settings** (iris, white balance, shutter, gain, detail, ND, lift/gamma/gain/offset, contrast, saturation) must match the restore file `atem-reference.xml` (a copy of `4k plus 2026-10-07 14-59-55.xml` from Google Drive Backup/NA/ATEM): **ATEM AUDIO WRONG** / **ATEM CAMERA WRONG**; ATEM Software Control's *Enable MIDI control* must be off: **ATEM SW MIDI ON**. Hold 2 s (and Sunday auto-fix) sends back only what differs; MIDI is fixed by quitting the app, switching it off and reopening it (the switcher is not affected). `atem_watch.js` keeps one connection to the switcher. New restore file: copy it over `atem-reference.xml` and re-run install.sh. |
| LED | VX1000 and UHD Jr: Companion connection **and** each one answers ping (the NovaStar module keeps saying "Connected" after a processor is switched off). "UHDJR NO PING" = processor off or unreachable; "UHDJR OFFLINE" = Companion's connection failed; "UHDJR DISABLED" (amber) = connection turned off in Companion. |
| DANTE | All 19 Dante devices ("19/19"), named when one drops: "WING GONE", "TRACKS GONE", "PROP MAC GONE". |
diff --git a/config.json b/config.json
index 2d4a8ae..cf214ba 100644
--- a/config.json
+++ b/config.json
@@ -797,6 +797,18 @@
"wait_seconds": 45,
"dante": "STUDIO-B-Tascam"
}
+ },
+ "digico_relay": {
+ "kind": "local",
+ "short": "DIGICO",
+ "label": "restart the DiGiCo relay (Companion and the tablets to the FOH console)",
+ "run": "launchctl kickstart -k gui/$(id -u)/org.waterschurch.digico-relay || launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/org.waterschurch.digico-relay.plist",
+ "template": "helpers",
+ "params": {
+ "labels": [
+ "org.waterschurch.digico-relay"
+ ]
+ }
}
},
"atem": {
@@ -1337,6 +1349,7 @@
],
"members": [
"x32",
+ "digico",
"dante"
]
},
@@ -1542,6 +1555,28 @@
}
]
},
+ {
+ "id": "digico",
+ "label": "DIGICO",
+ "checks": [
+ {
+ "type": "conn",
+ "conn": "DiGiCo_FOH",
+ "tag": "DIGICO"
+ },
+ {
+ "type": "launchd",
+ "label": "org.waterschurch.digico-relay",
+ "name": "RELAY",
+ "fix": "digico_relay"
+ },
+ {
+ "type": "ping",
+ "host": "10.1.60.100",
+ "name": "DIGICO"
+ }
+ ]
+ },
{
"id": "dante",
"label": "DANTE",
diff --git a/settings/ui/app.js b/settings/ui/app.js
index 4daed26..b3ebf38 100644
--- a/settings/ui/app.js
+++ b/settings/ui/app.js
@@ -420,6 +420,9 @@
const c = cfg(), t = c.tiles[i];
const k = await api("/api/keys");
const kt = k.tiles.find((x) => x.id === t.id) || { says: [], holding: "", checks: [] };
+ // A Companion connection is picked from the ones Companion has (typing still works).
+ const cc = editing() ? await api("/api/companion").catch(() => ({})) : {};
+ const connList = ``;
const fixOptions = (cur) => `${Object.entries(c.fixes).map(([id, f]) => ``).join("")}`;
const short = (text, n) => { text = String(text || ""); return text.length > n ? text.slice(0, n - 1) + "…" : text; };
let lastQ = null;
@@ -432,7 +435,9 @@
const summary = ` ${esc(sentence)}
Put ${esc(conn)} inside a group key: its problems show on that key, and holding the key reconnects it.
`, (bx) => { + bx.querySelector("#dcancel").onclick = closeDialog; + bx.querySelector("#dok").onclick = () => { const g = d.tiles.find((x) => x.id === bx.querySelector("#ngroup").value); d.tiles.push(t); if (g) g.members.push(id); saveDraft(); closeDialog(); location.hash = "#keys/" + id; }; + }); }; for (const cb of main.querySelectorAll("[data-autofix]")) cb.onchange = () => { if (!ensureDraft()) return; const d = state.draft.config, id = cb.dataset.autofix, f = d.fixes[id]; const set = new Set(d.auto_fix.fixes || []); if (cb.checked) { set.add(id); if (closes(f)) f.restart_ok = true; if (f.never_auto) delete f.never_auto; } else set.delete(id); setPath("auto_fix.fixes", [...set]); }; for (const b of main.querySelectorAll("[data-rmcheck]")) b.onclick = () => confirmBox("Remove this MIDI link from its key?", "Remove", () => { if (!ensureDraft()) return; const [tid, j] = b.dataset.rmcheck.split("|"); const t = state.draft.config.tiles.find((x) => x.id === tid); t.checks.splice(+j, 1); saveDraft(); route(); }); const ds = q("#decksave"); if (ds) ds.onclick = () => applyDecks(main); diff --git a/tests/test_status_panel.py b/tests/test_status_panel.py index 5d62ef7..e36b023 100644 --- a/tests/test_status_panel.py +++ b/tests/test_status_panel.py @@ -68,7 +68,7 @@ def healthy_snapshot(now): snap.ping = {"10.1.3.227": 0, "10.6.7.13": 0, "10.1.0.1": 0} snap.link = True snap.launchd = {"org.waterschurch.resi-propresenter": 884, "org.waterschurch.lobby-captions": 900, - "org.waterschurch.lobby-captions-display": 901} + "org.waterschurch.lobby-captions-display": 901, "org.waterschurch.digico-relay": 902} snap.launchd_time = now snap.procs = {"/Applications/ProdDash.app/Contents/MacOS/ProdDash": True} snap.http = {"https://central.resi.io/": True, "http://10.6.7.13:8080/": True, "http://10.1.14.225:1025/": True}