src.nth.io/

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Hoersten <[email protected]>2026-06-20 10:11:57 -0500
committerLuke Hoersten <[email protected]>2026-06-20 10:11:57 -0500
commit521de7ef844a4b5c1eb660ff54382b958fb62bd7 (patch)
tree510379eca4d301017f0a7f5d5902a2da2fe10ae0
parentf93179d9d1cd9e2f2b3977cd7020e13f133588b2 (diff)
scrypted: show Wake triggers on new-device dialog + stop leaking re-register interval
#1 — Wake triggers in the new-device dialog The "+ Add Device" form was missing the Wake triggers multi-select, so a new viewport defaulted to the per-getter fallback of all three (doorbell + motion + person) silently and the user only saw the field after first edit. Now the dialog includes it up front with all three pre-selected, and createDevice persists whatever the user ticked into storage in the same JSON shape Viewport.putSetting uses for subsequent edits. #2 — Stop leaking the periodic re-register interval Why the user was seeing the "registered ..." log line repeat 14 times in steady-state with nothing happening: Scrypted's Scripts sandbox does NOT garbage-collect setInterval handles when a script is re-pasted/reloaded. Every re-paste left an orphan interval running against the previous Provider instance, accumulating one extra timer per reload. Every 5 minutes (REREGISTER_INTERVAL_MS), all N timers fired at once, producing N "registered ..." log lines in rapid succession. Fix: keep the timer handle on globalThis under a well-known key. At script start, clearInterval the previous one (if any) before arming the new one. Idempotent across reloads.
-rw-r--r--scrypted/scrypted-viewport.ts30
1 files changed, 28 insertions, 2 deletions
diff --git a/scrypted/scrypted-viewport.ts b/scrypted/scrypted-viewport.ts
index 996d18e..90cabd1 100644
--- a/scrypted/scrypted-viewport.ts
+++ b/scrypted/scrypted-viewport.ts
@@ -6,7 +6,7 @@
// short git hash of the commit that added this constant — if the
// hash in the log doesn't match the HEAD this file came from, the
// Scrypted Script editor is still on stale code.
-const SCRIPT_VERSION = "f982b88";
+const SCRIPT_VERSION = "pending";
//
// Architecture
// ------------
@@ -452,7 +452,18 @@ class ScryptedViewportProvider extends ScryptedDeviceBase
// Periodic re-register so a device that rebooted or got a new IP
// re-syncs without manual intervention.
- setInterval(() => {
+ //
+ // Important: Scrypted's Scripts sandbox does NOT garbage-collect
+ // setInterval handles when the script is re-pasted/reloaded.
+ // Without the globalThis cancel below, every re-paste leaves an
+ // orphan interval still running against the previous Provider
+ // instance. After N reloads the user gets N rapid-fire
+ // "registered ..." log lines every 5 minutes.
+ const G = globalThis as any;
+ if (G.__viewportRegisterInterval) {
+ try { clearInterval(G.__viewportRegisterInterval); } catch {}
+ }
+ G.__viewportRegisterInterval = setInterval(() => {
for (const v of this.viewports.values()) {
this.registerViewport(v).catch(() => {});
}
@@ -509,6 +520,14 @@ class ScryptedViewportProvider extends ScryptedDeviceBase
deviceFilter: `interfaces.includes('${ScryptedInterface.Camera}')`,
},
{
+ key: "triggers",
+ title: "Wake triggers",
+ description: "Which camera-event types automatically wake the viewport. Clear all of them for tap-only mode (the viewport never wakes from Scrypted; user must tap to see the camera).",
+ choices: ["doorbell", "motion", "person"],
+ multiple: true,
+ value: ["doorbell", "motion", "person"],
+ } as any,
+ {
key: "orientation",
title: "Orientation",
choices: ["portrait", "landscape"],
@@ -543,6 +562,13 @@ class ScryptedViewportProvider extends ScryptedDeviceBase
childStore.setItem("host", String(settings.host || ""));
childStore.setItem("cameraId", String(settings.cameraId || ""));
childStore.setItem("orientation", String(settings.orientation || "portrait"));
+ // settings.triggers arrives as an array from the multi-select.
+ // JSON-encode to match how Viewport.putSetting stores it on
+ // subsequent edits.
+ const trigs = Array.isArray(settings.triggers)
+ ? settings.triggers
+ : ["doorbell", "motion", "person"];
+ childStore.setItem("triggers", JSON.stringify(trigs));
this.childIds = [...this.childIds, nativeId];
this.console.log(`created viewport "${name}" (${nativeId})`);