Wiring view: every machine and what connects it (Companion, MIDI, Dante, watchdog, web, Art-Net), hide types or single links, scripts per computer
RESI LIVE NOT REC follows the Resi auto-record service (custom autorec_status, not during its REC hold; stale heartbeat = no verdict); INGEST watches AUTO REC (running, heartbeat, Resi reachable), hold restarts it. Probes list each computer's scripts by file name only. HyperDeck addresses read from bonjourHost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+46
-6
@@ -484,6 +484,25 @@ def check_launchd(chk, snap, ctx):
|
||||
return [("svc", Result(OK))]
|
||||
|
||||
|
||||
def check_heartbeat(chk, snap, ctx):
|
||||
"""A service that writes the time into a Companion variable (the Resi auto-record: custom autorec_hb):
|
||||
older than max_age_seconds is stuck. With status_var, a status containing warn_if is amber."""
|
||||
conn = chk.get("conn", "custom")
|
||||
raw = snap.var(conn, chk["var"])
|
||||
if raw in (None, ""):
|
||||
return [("hb", Result(OK))] # not read yet
|
||||
try:
|
||||
age = ctx["now"] - float(raw)
|
||||
except ValueError:
|
||||
age = None
|
||||
if age is None or age > chk.get("max_age_seconds", 90):
|
||||
return [("hb", Result(ERR, chk.get("msg", "STUCK"), named=True))]
|
||||
status = (snap.var(conn, chk["status_var"]) or "") if chk.get("status_var") else ""
|
||||
if chk.get("warn_if") and chk["warn_if"].upper() in status.upper():
|
||||
return [("hb", Result(WARN, chk.get("warn_msg", chk["warn_if"]), named=True))]
|
||||
return [("hb", Result(OK))]
|
||||
|
||||
|
||||
def check_process(chk, snap, ctx):
|
||||
running = snap.procs.get(chk["match"])
|
||||
if running is False:
|
||||
@@ -956,7 +975,7 @@ CHECKS = {
|
||||
"psm": check_psm, "tascam": check_tascam, "ping": check_ping, "launchd": check_launchd,
|
||||
"process": check_process, "http": check_http, "disk": check_disk, "midi_peer": check_midi_peer, "midi_wired": check_midi_wired, "pref": check_pref, "spotify": check_spotify,
|
||||
"mdns": check_mdns, "midi_rx": check_midi_rx, "remote": check_remote, "artnet": check_artnet,
|
||||
"ready": check_ready, "ready_manual": check_ready_manual, "tune_rx": check_tune_rx,
|
||||
"ready": check_ready, "ready_manual": check_ready_manual, "tune_rx": check_tune_rx, "heartbeat": check_heartbeat,
|
||||
}
|
||||
|
||||
|
||||
@@ -1040,6 +1059,14 @@ def needed_variables(cfg):
|
||||
rw = cfg.get("rec_watch") or {}
|
||||
if rw.get("conn"):
|
||||
fast.append((rw["conn"], rw.get("var", "playback_state")))
|
||||
if rw.get("heartbeat"):
|
||||
fast.append((rw["conn"], rw["heartbeat"]))
|
||||
for tile in all_tiles(cfg):
|
||||
for chk in tile.get("checks", []):
|
||||
if chk["type"] == "heartbeat":
|
||||
fast.append((chk.get("conn", "custom"), chk["var"]))
|
||||
if chk.get("status_var"):
|
||||
fast.append((chk.get("conn", "custom"), chk["status_var"]))
|
||||
dedupe = lambda xs: list(dict.fromkeys(xs))
|
||||
return dedupe(fast), dedupe(slow)
|
||||
|
||||
@@ -1957,13 +1984,22 @@ class Engine:
|
||||
self.toggle_bypass(tid, comp, now)
|
||||
|
||||
def resi_playing(self, snap, now):
|
||||
"""config "rec_watch": Resi's playback (resi-studio-cues "playback_state") has read PLAYING for
|
||||
after_seconds, with the module itself connected. The decks must record then."""
|
||||
"""config "rec_watch": Resi is live and the decks should record, for after_seconds. NA reads the Resi
|
||||
auto-record service's own verdict (custom variable autorec_status: RECORDING / STARTING / LIVE, NOT
|
||||
RECORDING; not while it holds REC until 10 minutes before a service), and nothing while its heartbeat
|
||||
is stale. Without a heartbeat the connection must be up (a module's playback_state PLAYING)."""
|
||||
rw = self.cfg.get("rec_watch") or {}
|
||||
if not rw.get("conn"):
|
||||
return False
|
||||
value = (snap.var(rw["conn"], rw.get("var", "playback_state")) or "").strip().upper()
|
||||
if value != rw.get("playing", "PLAYING").upper() or conn_result(snap, rw["conn"], now).level != OK:
|
||||
value = (snap.var(rw["conn"], rw.get("var", "playback_state")) or "").upper()
|
||||
if rw.get("heartbeat"):
|
||||
try:
|
||||
fresh = now - float(snap.var(rw["conn"], rw["heartbeat"]) or 0) < rw.get("stale_seconds", 90)
|
||||
except ValueError:
|
||||
fresh = False
|
||||
else:
|
||||
fresh = conn_result(snap, rw["conn"], now).level == OK
|
||||
if not fresh or not any(w.upper() in value for w in rw.get("live", ["PLAYING"])):
|
||||
self.resi_since = None
|
||||
return False
|
||||
self.resi_since = self.resi_since or now
|
||||
@@ -2865,7 +2901,11 @@ def companion_conn_hosts(path):
|
||||
inst = json.loads(value)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
host = (inst.get("config") or {}).get("host") if isinstance(inst, dict) else None
|
||||
conf = (inst.get("config") or {}) if isinstance(inst, dict) else {}
|
||||
host = conf.get("host")
|
||||
if not (isinstance(host, str) and host.strip()) and isinstance(conf.get("bonjourHost"), str):
|
||||
host = conf["bonjourHost"].rsplit(":", 1)[0] if re.match(r"^[\d.]+:\d+$", conf["bonjourHost"].strip()) \
|
||||
else conf["bonjourHost"] # HyperDecks: "10.1.10.11:9993"
|
||||
if inst.get("label") and isinstance(host, str) and host.strip():
|
||||
hosts[inst["label"]] = host.strip()
|
||||
return hosts
|
||||
|
||||
Reference in New Issue
Block a user