src.nth.io/

summaryrefslogtreecommitdiff
path: root/scrypted/tsconfig.json
AgeCommit message (Collapse)AuthorFilesLines
4 daysscrypted: code-review fixes — reload drain order, reconnect storm, wake guardsLuke Hoersten1-1/+1
- bootstrap: drain the shutdown-cleaner array FIRST, not after the child re-discovery loop. The old order tore down the listeners the loop had just attached, and since the instance maps still referenced them the attachListener fast-path blocked the 5-min register-cycle self-heal from ever re-attaching after a warm re-paste. The attach cleaner now also invalidates listeners/attachedCameraId (one cleaner per attach), so a drain by another instance can't strand dead registrations either. - stream socket: single-flight reconnect scheduled from 'close' only. A failed connect emits 'error' then 'close'; scheduling from both doubled outstanding attempts every 500ms against a rebooting device. openStreamSocket also destroys the previous socket first. - onRequest wake: same streams/streamStarting guard as every other start path (a concurrent second startStream overwrote the streams entry and orphaned the first ffmpeg), respond 204 immediately (the device's POST times out at 1s — awaiting startStream turned every tap-wake into a firmware state_post_failure), and skip the redundant wake POST back. - startStream: bail-out paths after the wake POST (camera missing, no usable stream, ffmpeg-input conversion failure) now send a compensating sleep instead of stranding the panel on Loading; the last-ditch getVideoStream fallback no longer rejects out of the call. - key streams/streamStarting/stopStream by nativeId — v.name drifts to the nativeId on reload, stranding or duplicating streams keyed under the drifted value; findByName matches display_name first for the same reason. - idle_timeout_ms=0: the Scrypted-side safety timeout still reclaims ffmpeg/socket but no longer POSTs sleep over the always-on setting. - pending bindingDebounce timers cleared across re-paste (they fired against the dead instance and attached duplicate listeners); releaseDevice drops lastRegisterSig/streamStarting/debounce entries. - start() single-flights bootstrap; createDevice drops its redundant second registerViewport; streamLogger rolls its window on quiet ticks (post-lull rates were diluted) and lastLogUs -> lastLogMs; hoist the JPEG EOI needle + resume-scan offset in the demux loop; postJSON drops the dead 204 check; remove unused sandbox declares and the legacy streams.interval field. - tsconfig: moduleResolution Node -> Bundler (removed in TS 6).
2026-06-14Path B: per-viewport Scrypted devices with UI-driven settingsLuke Hoersten1-0/+14
Convert the Scripts-plugin script from a hardcoded BINDINGS constant into a DeviceProvider + DeviceCreator + HttpRequestHandler. Each viewport is now a child Scrypted device under the parent script with its own Settings page; operators add, edit, and delete viewports entirely through the Scrypted UI. Parent (ScryptedViewportProvider): - DeviceProvider: getDevice(nativeId) instantiates a Viewport, attaches its camera event listener, and posts /config. releaseDevice tears down stream + listener + child storage entry. - DeviceCreator: "+ Add Device" on the parent's page shows a small form (name / host / camera picker filtered to Camera interfaces / orientation choice). createDevice() pre-populates the child's storage via deviceManager.getDeviceStorage(nativeId) and registers it under the parent. - Tracks known child nativeIds in its own storage as a JSON array so it can eagerly instantiate every child on plugin start (each registration + camera subscription happens at load time, not lazily). - 5-min re-register loop catches devices that rebooted or got new DHCP leases. - HttpRequestHandler routes POST <base>/state on the parent's endpoint; body {viewport, state} is matched against child names. Honors the spec race rules: every callback cancels any prior stream + safety timer for that viewport before applying the new state, and a /frame 409 stops the stream without echoing sleep back. - Global tuning (frame_interval_ms) lives on the parent's Settings. Child (Viewport): - Settings: host (string), camera (type=device with deviceFilter for the Camera interface — the UX win), orientation (choices), idle timeout, brightness. All persisted via this.storage. - putSetting fires onBindingChanged() on the parent so re-register + re-subscribe happen immediately when any field changes. scrypted/README.md rewritten for the UI-driven flow — install + add device + edit + remove + global tuning + smoke test — no more "edit BINDINGS and re-save." scrypted/package.json + tsconfig.json: optional `npm install` so editors can resolve @scrypted/sdk types. Nothing here ships — install remains "paste into Scripts plugin." node_modules ignored.