A DANTE hold power-cycles a missing Studio B PoE box on its Netgear switch port.

STUDIO-B-SOLO-MON, MON, TB and TB-MON map to ports 0/14-0/17 on the Netgear
M4250 Dante switch 10.66.1.102. netgear.py poe_cycle first checks the port's
MAC table and refuses if a different device is plugged in there, then runs
poe reset. Tested 2026-10-08 13:10 on SOLO-MON: dropped off Dante and was
back about 17 s later. install.sh now copies netgear.py too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 13:12:45 -04:00
co-authored by Claude Opus 5.5
parent 9838ce9292
commit c8b9216ea5
6 changed files with 79 additions and 5 deletions
+24 -1
View File
@@ -538,6 +538,29 @@ class TestFixes(unittest.TestCase):
tiles = self.engine.step(self.snap, time.time())
self.assertEqual((tiles["dante"]["x"], level(tiles["dante"])), ("DANTE\nFIX FAILED\nDVS", "failed"))
def test_studio_b_poe_boxes_are_power_cycled(self):
devices = json.loads(self.snap.vars[("audinate-dantecontroller", "devices")])
devices.remove("STUDIO-B-MON")
devices.remove("STUDIO-B-TB")
self.snap.vars[("audinate-dantecontroller", "devices")] = json.dumps(devices)
self.assertEqual(self.plan("dante"), [("fix", "poe_stb_mon"), ("fix", "poe_stb_tb")])
for fid in ("poe_stb_solo", "poe_stb_mon", "poe_stb_tb", "poe_stb_tbmon"):
f = CONFIG["fixes"][fid]
self.assertEqual(f["switch"], "10.66.1.102")
self.assertRegex(f["mac"], r"^00:1d:c1:")
def test_netgear_fix_calls_the_switch_with_the_mac_guard(self):
import types
calls = []
fake = types.ModuleType("netgear")
fake.poe_cycle = lambda host, port, mac=None: calls.append((host, port, mac))
sys.modules["netgear"] = fake
try:
self.assertTrue(sp.execute_fix(CONFIG, "poe_stb_solo", {}))
finally:
del sys.modules["netgear"]
self.assertEqual(calls, [("10.66.1.102", "0/14", "00:1d:c1:51:34:c8")])
def test_ingest_dvs_and_no_auto_fix(self):
devices = json.loads(self.snap.vars[("audinate-dantecontroller", "devices")])
devices.remove("STUDIO-A-Ingest")
@@ -565,7 +588,7 @@ class TestFixes(unittest.TestCase):
def test_every_fix_is_valid(self):
for f in CONFIG["fixes"].values():
self.assertIn(f.get("kind", "ssh"), ("ssh", "local", "hyperdeck"))
self.assertIn(f.get("kind", "ssh"), ("ssh", "local", "hyperdeck", "netgear_poe"))
class FakeDeck: