diff options
| author | Luke Hoersten <[email protected]> | 2026-06-20 10:11:57 -0500 |
|---|---|---|
| committer | Luke Hoersten <[email protected]> | 2026-06-20 10:11:57 -0500 |
| commit | 521de7ef844a4b5c1eb660ff54382b958fb62bd7 (patch) | |
| tree | 510379eca4d301017f0a7f5d5902a2da2fe10ae0 | |
| parent | f93179d9d1cd9e2f2b3977cd7020e13f133588b2 (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.ts | 30 |
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})`); |
