From f6d8e75c9c2e12b1527dc0a5464b576c4b94640b Mon Sep 17 00:00:00 2001 From: Luke Hoersten Date: Sun, 21 Jun 2026 11:40:02 -0500 Subject: scrypted: override parent device type to Bridge (was hardcoded Unknown by Scripts plugin) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'Unknown' text the user saw above the Status and Controls panel is the device TYPE, not the lifecycle state. Scripts plugin (plugins/core/src/script.ts:65) hardcodes type=ScryptedDeviceType.Unknown when it registers any script device, regardless of what interfaces the loaded class actually implements. Override it from inside the script: call deviceManager.onDeviceDiscovered ourselves with type=Bridge, which semantically fits our DeviceProvider that bridges multiple child viewport devices. The override runs after Scripts plugin's postRunScript-driven discovery so the later call wins. Pass the full interface set explicitly (auto-detection found from method names: Settings/DeviceProvider/DeviceCreator/HttpRequestHandler/ StartStop, plus Scripts base Scriptable+Program) — partial lists drop interfaces. The override is wrapped in try/catch — if the device record's provider mapping changes in a future Scrypted version, we degrade to the old Unknown label rather than the script failing to boot. --- scrypted/scrypted-viewport.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'scrypted') diff --git a/scrypted/scrypted-viewport.ts b/scrypted/scrypted-viewport.ts index 554c081..acfb44f 100644 --- a/scrypted/scrypted-viewport.ts +++ b/scrypted/scrypted-viewport.ts @@ -450,6 +450,37 @@ class ScryptedViewportProvider extends ScryptedDeviceBase this.scryptedBase = raw.replace(/\/$/, ""); this.console.log(`Scrypted Viewport up (script=${SCRIPT_VERSION}). Callback URL base: ${this.scryptedBase}`); + // Override the device type that the @scrypted/core Scripts plugin + // hardcodes (`ScryptedDeviceType.Unknown` at plugins/core/src/ + // script.ts:65) so the UI displays a meaningful label above the + // Status and Controls panel instead of "Unknown". This Provider + // semantically bridges multiple child viewport devices, so Bridge + // fits. The call happens after Scripts plugin's postRunScript- + // driven discovery, so this update wins. + // + // We pass the full interface set explicitly: passing a partial + // list would drop interfaces the auto-detection found. Order + // mirrors the class's implements clause. + try { + await deviceManager.onDeviceDiscovered({ + providerNativeId: "scriptcore", + nativeId: this.nativeId, + name: this.name || this.providedName, + type: ScryptedDeviceType.Bridge, + interfaces: [ + ScryptedInterface.Scriptable, + ScryptedInterface.Program, + ScryptedInterface.Settings, + ScryptedInterface.DeviceProvider, + ScryptedInterface.DeviceCreator, + ScryptedInterface.HttpRequestHandler, + ScryptedInterface.StartStop, + ], + }); + } catch (e) { + this.console.warn(`type override failed: ${(e as Error).message}`); + } + // Re-discover every known child so Scrypted reattaches its storage // to the nativeId. Without this, `new Viewport(...)` instantiates // with `this.storage === undefined` and every storage-backed getter -- cgit v1.2.3