Watch the DiGiCo FOH console inside AUDIO; "+ Key" asks for a group when the deck is full
- DIGICO (in the AUDIO group): Companion's DiGiCo_FOH connection, the digico-relay helper on NA Ingest (hold AUDIO restarts it), and a ping to the console at 10.1.60.100 (the OSC connection reads good even with the console off). - Settings page: "+ Key" on an unwatched Companion connection asks which group key to put it in when the Status page has no free spot (it used to make a key nobody could see); the connection field of a check suggests Companion's connection names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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". |
|
||||
|
||||
+35
@@ -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",
|
||||
|
||||
+14
-2
@@ -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 = `<datalist id="connlist">${(cc.connections || []).map((r) => `<option value="${esc(r.label)}">${esc(r.module || "")}</option>`).join("")}</datalist>`;
|
||||
const fixOptions = (cur) => `<option value="">none</option><option value="restart-connection" ${cur === "restart-connection" ? "selected" : ""}>reconnect its Companion connection</option><option value="dante-auto" ${cur === "dante-auto" ? "selected" : ""}>Dante auto (PoE port or the Dante module)</option>${Object.entries(c.fixes).map(([id, f]) => `<option value="${esc(id)}" ${cur === id ? "selected" : ""}>${esc(f.short || id)} – ${esc(f.label || "")}</option>`).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 = `<summary><b>${what}</b>${hint(sentence)}</summary>`;
|
||||
if (!editing()) return `${header}<details class="chk">${summary}<p class="small">${esc(sentence)}</p></details>`;
|
||||
const base = `tiles.${i}.checks.${j}.`;
|
||||
let fields = (spec.fields || []).filter((f) => !["fix", "type", "template", "params"].includes(f)).map((f) => inputHtml(base + f, F("tiles[].checks[]." + f), chk[f])).join("");
|
||||
let fields = (spec.fields || []).filter((f) => !["fix", "type", "template", "params"].includes(f)).map((f) => f === "conn"
|
||||
? inputHtml(base + f, F("tiles[].checks[]." + f), chk[f], connList).replace("<input ", '<input list="connlist" ')
|
||||
: inputHtml(base + f, F("tiles[].checks[]." + f), chk[f])).join("");
|
||||
if (chk.type === "remote") {
|
||||
const ctpls = state.builders.checks.concat([{ name: "custom", words: "Custom command (typed by hand)", params: [] }]);
|
||||
const ctName = chk.template || "custom", ct = ctpls.find((x) => x.name === ctName);
|
||||
@@ -1013,7 +1018,14 @@
|
||||
for (const b of main.querySelectorAll("[data-oremove]")) b.onclick = () => confirmBox(`Remove the ${b.dataset.oremove} outlet from the list? Fixes that use it stop working.`, "Remove", async () => { try { await post("/api/outlets", { name: b.dataset.oremove, remove: true }); route(); } catch (e) { alertBox(e.message); } });
|
||||
for (const td of main.querySelectorAll("[id^='ost-']")) api("/api/outlets/status?name=" + encodeURIComponent(td.id.slice(4))).then((r) => { td.innerHTML = r.ok ? `<span class="chip ${r.on ? "ok" : ""}">${r.on ? "on" : "off"}</span>` : `<span class="muted" data-hint="${esc(r.error)}">?</span>`; }).catch(() => {});
|
||||
for (const m of main.querySelectorAll("[data-map]")) m.onchange = () => { if (!m.value || !ensureDraft()) return; const [kind, name] = m.dataset.map.split("|"); (kind === "conn" ? renameConn : renameDante)(name, m.value); saveDraft(); route(); };
|
||||
for (const b of main.querySelectorAll("[data-addconn]")) b.onclick = () => { const conn = b.dataset.addconn; if (!ensureDraft()) return; const d = state.draft.config; let id = slug(conn) || "key", n = 2; while (d.tiles.some((t) => t.id === id)) id = slug(conn) + "_" + n++; const t = { id, label: conn.toUpperCase().replace(/[_-]+/g, " ").slice(0, 10).trim(), checks: [{ type: "conn", conn, fix: "restart-connection" }] }; const pos = firstEmpty(d, "status"); if (pos) t.pos = pos; d.tiles.push(t); saveDraft(); location.hash = "#keys/" + id; };
|
||||
for (const b of main.querySelectorAll("[data-addconn]")) b.onclick = () => { const conn = b.dataset.addconn; if (!ensureDraft()) return; const d = state.draft.config; let id = slug(conn) || "key", n = 2; while (d.tiles.some((t) => t.id === id)) id = slug(conn) + "_" + n++; const t = { id, label: conn.toUpperCase().replace(/[_-]+/g, " ").slice(0, 10).trim(), checks: [{ type: "conn", conn, fix: "restart-connection" }] }; const pos = firstEmpty(d, "status");
|
||||
if (pos) { t.pos = pos; d.tiles.push(t); saveDraft(); location.hash = "#keys/" + id; return; }
|
||||
// The Status page is full: put it inside a group key, where it shows and a hold on the group fixes it.
|
||||
const groups = d.tiles.filter((g) => g.members);
|
||||
dialog(`<h3>No free spot on the Status page</h3><p class="small">Put ${esc(conn)} inside a group key: its problems show on that key, and holding the key reconnects it.</p><select id="ngroup">${groups.map((g) => `<option value="${esc(g.id)}">${esc(g.label)} (${esc(g.members.join(", "))})</option>`).join("")}</select><div class="row"><button class="primary" id="dok">Add</button><button id="dcancel">Cancel</button></div>`, (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);
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user