From 176e8e9073f4dfd158e8dbd38034b91bf7d9d08d Mon Sep 17 00:00:00 2001 From: christian Date: Wed, 21 Oct 2026 14:10:42 -0400 Subject: [PATCH] SC Lighting PC joined: VISTA key and Restart key, rtpMIDI watched on MIDI - a helper program (rtpMIDI) on a computer that joins after the MIDI key exists is added to it (it was marked seen and never added) Co-Authored-By: Claude Opus 5.5 --- settings/autoconf.py | 15 +++++++ sites/sc/config.json | 98 +++++++++++++++++++++++++++++++++++++++++++- tests/test_campus.py | 14 +++++++ 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/settings/autoconf.py b/settings/autoconf.py index d6e21e1..2e68917 100644 --- a/settings/autoconf.py +++ b/settings/autoconf.py @@ -351,6 +351,7 @@ def items(inv, nets): home["checks"] += it["checks"] home["fixes"].update(it["fixes"]) home["also"].append(it["ident"]) + home.setdefault("folded", {})[it["ident"]] = {"checks": it["checks"], "fixes": it["fixes"], "label": it["label"]} out.remove(it) return out, hosts @@ -561,6 +562,20 @@ def merge_parts(cfg, it, fresh): wired_at += 1 words.append("MIDI link %s" % c["peer"]) cfg["fixes"].setdefault("midi_reconnect", dict(SHARED_FIXES["midi_reconnect"])) + # A helper program found later (Southcoast's Lighting PC joined after its MIDI key existed: rtpMIDI was + # marked seen but never added, 2026-10-21) joins the key it rides in. + for ident, part in (it.get("folded") or {}).items(): + if ident not in fresh: + continue + home = next((t for t in cfg["tiles"] if any(c.get("type") == "midi_wired" for c in t.get("checks", []))), None) \ + if it["ident"] == "midi_wired" else None + if home is None: + continue + at = next((i for i, c in enumerate(home["checks"]) if c.get("type") == "midi_wired"), len(home["checks"])) + home["checks"][at:at] = [c for c in part["checks"] if c not in home["checks"]] + for fid, f in part["fixes"].items(): + cfg["fixes"].setdefault(fid, f) + words.append("%s checks on the %s key" % (key_text(part["label"]), home["label"])) return words diff --git a/sites/sc/config.json b/sites/sc/config.json index f3582df..0985c14 100644 --- a/sites/sc/config.json +++ b/sites/sc/config.json @@ -66,7 +66,9 @@ "midi_reconnect", "ableton_sc_tracks_new", "superrack_sc_foh", - "x32edit_sc_foh" + "x32edit_sc_foh", + "vista_desktop_cucshqg", + "rtpmidi_desktop_cucshqg" ] }, "tiles": [ @@ -229,6 +231,18 @@ "tag": "TRACKS LIGHTS", "host": "sc_tracks_new" }, + { + "type": "remote", + "template": "win_program", + "params": { + "host": "desktop_cucshqg", + "exe": "rtpMIDI.exe" + }, + "msg": "RTPMIDI NOT RUNNING", + "fix": "rtpmidi_desktop_cucshqg", + "host": "desktop_cucshqg", + "cmd": "tasklist /NH /FI \"IMAGENAME eq rtpMIDI.exe\" | find /I \"rtpMIDI.exe\" >nul" + }, { "type": "midi_wired", "nets": [ @@ -344,6 +358,28 @@ 1, 5 ] + }, + { + "id": "vista", + "label": "VISTA", + "checks": [ + { + "type": "remote", + "template": "win_program", + "params": { + "host": "desktop_cucshqg", + "exe": "Vista.exe" + }, + "msg": "VISTA NOT RUNNING", + "fix": "vista_desktop_cucshqg", + "host": "desktop_cucshqg", + "cmd": "tasklist /NH /FI \"IMAGENAME eq Vista.exe\" | find /I \"Vista.exe\" >nul" + } + ], + "pos": [ + 1, + 6 + ] } ], "fixes": { @@ -471,6 +507,45 @@ "kind": "ssh", "host": "sc_foh", "run": "pgrep -xq X32-Edit || open /Applications/X32-Edit.app" + }, + "vista_desktop_cucshqg": { + "template": "win_start", + "params": { + "host": "desktop_cucshqg", + "task": "Start Vista", + "exe": "Vista.exe" + }, + "label": "start Vista on SC Lighting PC if it is not running", + "short": "VISTA", + "kind": "ssh", + "host": "desktop_cucshqg", + "run": "tasklist /NH /FI \"IMAGENAME eq Vista.exe\" | find /I \"Vista.exe\" >nul || (schtasks /Run /TN \"\\StatusPanel\\Start Vista\" >nul && ping -n 9 127.0.0.1 >nul && tasklist /NH /FI \"IMAGENAME eq Vista.exe\" | find /I \"Vista.exe\" >nul)" + }, + "restart_vista_desktop_cucshqg": { + "template": "win_restart", + "params": { + "host": "desktop_cucshqg", + "task": "Start Vista", + "exe": "Vista.exe" + }, + "label": "restart Vista on SC Lighting PC (closes it first)", + "short": "VISTA", + "kind": "ssh", + "host": "desktop_cucshqg", + "run": "taskkill /F /T /IM \"Vista.exe\" >nul 2>&1 & ping -n 3 127.0.0.1 >nul & schtasks /Run /TN \"\\StatusPanel\\Start Vista\" >nul && ping -n 9 127.0.0.1 >nul && tasklist /NH /FI \"IMAGENAME eq Vista.exe\" | find /I \"Vista.exe\" >nul" + }, + "rtpmidi_desktop_cucshqg": { + "template": "win_start", + "params": { + "host": "desktop_cucshqg", + "task": "Start rtpMIDI", + "exe": "rtpMIDI.exe" + }, + "label": "start rtpMIDI on SC Lighting PC if it is not running", + "short": "RTPMIDI", + "kind": "ssh", + "host": "desktop_cucshqg", + "run": "tasklist /NH /FI \"IMAGENAME eq rtpMIDI.exe\" | find /I \"rtpMIDI.exe\" >nul || (schtasks /Run /TN \"\\StatusPanel\\Start rtpMIDI\" >nul && ping -n 9 127.0.0.1 >nul && tasklist /NH /FI \"IMAGENAME eq rtpMIDI.exe\" | find /I \"rtpMIDI.exe\" >nul)" } }, "hosts": { @@ -520,6 +595,18 @@ "kind": "sshd" } ] + }, + "desktop_cucshqg": { + "name": "SC Lighting PC", + "os": "windows", + "ssh": "Lighting@10.5.1.168", + "role": "found by auto-setup", + "runs": [ + { + "kind": "sshd" + } + ], + "mac": "40:a8:f0:69:ce:c9" } }, "gear": {}, @@ -578,6 +665,15 @@ 0, 3 ] + }, + { + "id": "rs_vista", + "label": "VISTA", + "fix": "restart_vista_desktop_cucshqg", + "pos": [ + 0, + 4 + ] } ] }, diff --git a/tests/test_campus.py b/tests/test_campus.py index 6fc1297..20bfcc8 100644 --- a/tests/test_campus.py +++ b/tests/test_campus.py @@ -559,3 +559,17 @@ class TestJoinWindowsAdmin(unittest.TestCase): check = text.index("IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)") self.assertLess(check, text.index("Get-WindowsCapability")) # before anything needs it self.assertIn("Run as administrator", text) + + +class TestHelperJoinsLater(unittest.TestCase): + def test_rtpmidi_on_a_pc_that_joins_later_lands_on_the_midi_key(self): + inv = small() + inv["computers"].pop("lighting_pc") + cfg, seen = ac.build(BASE, inv, {"id": "sc", "name": "Southcoast"}, "1234") + midi = next((t for t in cfg["tiles"] if any(c.get("type") == "midi_wired" for c in t.get("checks", []))), None) + self.assertIsNotNone(midi) # the MIDI key is there first + new, added, now_seen = ac.extend(cfg, small(), seen) + midi = next(t for t in new["tiles"] if any(c.get("type") == "midi_wired" for c in t.get("checks", []))) + self.assertTrue(any((c.get("params") or {}).get("exe") == "rtpMIDI.exe" for c in midi["checks"]), added) + self.assertTrue(any("RTPMIDI" in a for a in added), added) + self.assertEqual(schema.validate(new)[0], [])