Smart outlets: the panel can power-cycle a device through a SmartLife (Tuya) plug
settings/outlet.py talks to Tuya's cloud with the campus's own project keys (kept in outlets.json beside the config, 0600, never in the repo): list, status, on/off, and 'cycle <outlet> --ping <address>' which leaves a unit that answers alone, cuts power 8 s, and waits for the address to answer; refused while a HyperDeck is recording. A builder 'Power-cycle a smart outlet' makes the fix from fields; the TASCAM key's ping check now holds to it (verified live: the hung DA-6400 answered again 26 s after the cycle and Companion reconnected). Settings > Outlets: keys, the outlet list with live state and on/off, + Outlet from the account's devices. Calendar in 12-hour time. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -124,3 +124,13 @@ class TestQuotingAndGuards(unittest.TestCase):
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
|
||||
class TestOutlet(unittest.TestCase):
|
||||
def test_outlet_cycle_renders_and_is_local(self):
|
||||
f = b.build(CFG, {"template": "outlet_cycle", "params": {"outlet": "tascam", "address": "10.1.11.74", "wait_seconds": 8}})
|
||||
self.assertEqual(f["run"], '/usr/bin/python3 "$HOME/Library/Application Support/status-panel/settings/outlet.py" cycle tascam --ping 10.1.11.74 --wait 8')
|
||||
self.assertEqual(f["kind"], "local")
|
||||
self.assertIn("tascam", b.suggest_label(CFG, {"template": "outlet_cycle", "params": {"outlet": "tascam"}}))
|
||||
f = b.build(CFG, {"template": "outlet_cycle", "params": {"outlet": "x; rm", "address": "a b"}})
|
||||
self.assertIn("cycle 'x; rm' --ping 'a b'", f["run"]) # quoted, never run as shell
|
||||
|
||||
Reference in New Issue
Block a user