From adbc2aaed9769104b2ab39882002b919eb96ae8d Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Sat, 8 Feb 2025 09:41:48 -0800 Subject: [PATCH] onvif: add text overlays --- plugins/onvif/package-lock.json | 31 ++++++++++++++----------- plugins/onvif/package.json | 2 +- plugins/onvif/src/main.ts | 41 +++++++++++++++++++++++++++++++-- plugins/onvif/src/onvif-api.ts | 13 +++++++++++ 4 files changed, 71 insertions(+), 16 deletions(-) diff --git a/plugins/onvif/package-lock.json b/plugins/onvif/package-lock.json index 419fdd36c..bdf1293c0 100644 --- a/plugins/onvif/package-lock.json +++ b/plugins/onvif/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/onvif", - "version": "0.1.28", + "version": "0.1.29", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/onvif", - "version": "0.1.28", + "version": "0.1.29", "license": "Apache", "dependencies": { "@scrypted/common": "file:../../common", @@ -39,21 +39,28 @@ }, "../../sdk": { "name": "@scrypted/sdk", - "version": "0.3.62", + "version": "0.3.116", "license": "ISC", "dependencies": { - "@babel/preset-typescript": "^7.24.7", - "adm-zip": "^0.5.14", - "axios": "^1.7.3", - "babel-loader": "^9.1.3", + "@babel/preset-typescript": "^7.26.0", + "@rollup/plugin-commonjs": "^28.0.1", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.3.0", + "@rollup/plugin-typescript": "^12.1.1", + "@rollup/plugin-virtual": "^3.0.2", + "adm-zip": "^0.5.16", + "axios": "^1.7.8", + "babel-loader": "^9.2.1", "babel-plugin-const-enum": "^1.2.0", "ncp": "^2.0.0", "raw-loader": "^4.0.2", "rimraf": "^6.0.1", + "rollup": "^4.27.4", "tmp": "^0.2.3", "ts-loader": "^9.5.1", - "typescript": "^5.5.4", - "webpack": "^5.93.0", + "tslib": "^2.8.1", + "typescript": "^5.6.3", + "webpack": "^5.96.1", "webpack-bundle-analyzer": "^4.10.2" }, "bin": { @@ -66,11 +73,9 @@ "scrypted-webpack": "bin/scrypted-webpack.js" }, "devDependencies": { - "@types/node": "^22.1.0", - "@types/stringify-object": "^4.0.5", - "stringify-object": "^3.3.0", + "@types/node": "^22.10.1", "ts-node": "^10.9.2", - "typedoc": "^0.26.5" + "typedoc": "^0.26.11" } }, "node_modules/@scrypted/common": { diff --git a/plugins/onvif/package.json b/plugins/onvif/package.json index 60bc9d243..46ad87180 100644 --- a/plugins/onvif/package.json +++ b/plugins/onvif/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/onvif", - "version": "0.1.28", + "version": "0.1.29", "description": "ONVIF Camera Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/onvif/src/main.ts b/plugins/onvif/src/main.ts index add951a12..77a1b57d3 100644 --- a/plugins/onvif/src/main.ts +++ b/plugins/onvif/src/main.ts @@ -1,4 +1,4 @@ -import sdk, { AdoptDevice, Device, DeviceCreatorSettings, DeviceDiscovery, DeviceInformation, DiscoveredDevice, Intercom, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, PictureOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, SettingValue, VideoCamera, VideoCameraConfiguration } from "@scrypted/sdk"; +import sdk, { AdoptDevice, Device, DeviceCreatorSettings, DeviceDiscovery, DeviceInformation, DiscoveredDevice, Intercom, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, PictureOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, SettingValue, VideoCamera, VideoCameraConfiguration, VideoTextOverlay, VideoTextOverlays } from "@scrypted/sdk"; import { AddressInfo } from "net"; import onvif from 'onvif'; import { Stream } from "stream"; @@ -13,7 +13,7 @@ import { automaticallyConfigureSettings, checkPluginNeedsAutoConfigure, onvifAut const { mediaManager, systemManager, deviceManager } = sdk; -class OnvifCamera extends RtspSmartCamera implements ObjectDetector, Intercom, VideoCameraConfiguration, Reboot { +class OnvifCamera extends RtspSmartCamera implements ObjectDetector, Intercom, VideoCameraConfiguration, Reboot, VideoTextOverlays { eventStream: Stream; client: OnvifCameraAPI; rtspMediaStreamOptions: Promise; @@ -64,6 +64,42 @@ class OnvifCamera extends RtspSmartCamera implements ObjectDetector, Intercom, V this.info = info; } + async getVideoTextOverlays(): Promise> { + const client = await this.getClient(); + const osds = await client.getOSDs(); + const ret: Record = {}; + for (const osd of osds.getOSDsResponse.OSDs) { + const id = osd.$.token; + const readonly = osd.textString.type !== 'Plain' ? true : undefined; + // readonly toggling not supported + if (readonly) + continue; + ret[id] = { + text: !readonly ? osd.textString.plainText : osd.textString.type, + readonly, + } + } + return ret; + } + + async setVideoTextOverlay(id: string, value: VideoTextOverlay): Promise { + const client = await this.getClient(); + const osds = await client.getOSDs(); + const osd = osds.getOSDsResponse.OSDs.find(osd => osd.$.token === id); + if (!osd) + throw new Error('osd not found'); + osd.textString.plainText = value.text; + await client.setOSD({ + OSDToken: osd.$.token, + plaintext: value.text, + position: osd.position.type === 'Custom' + ? { + ...osd.position.pos.$, + } + : osd.position, + }); + } + getDetectionInput(detectionId: any, eventId?: any): Promise { throw new Error("Method not implemented."); } @@ -418,6 +454,7 @@ class OnvifProvider extends RtspProvider implements DeviceDiscovery { ScryptedInterface.AudioSensor, ScryptedInterface.MotionSensor, ScryptedInterface.VideoCameraConfiguration, + ScryptedInterface.VideoTextOverlays, ]; } diff --git a/plugins/onvif/src/onvif-api.ts b/plugins/onvif/src/onvif-api.ts index 3fa82f842..5f70c1db1 100644 --- a/plugins/onvif/src/onvif-api.ts +++ b/plugins/onvif/src/onvif-api.ts @@ -368,6 +368,19 @@ export class OnvifCameraAPI { this.cam.getDeviceInformation(cb); }) } + + async getOSDs(): Promise { + // this function accept video token but why? + return promisify(cb => { + this.cam.getOSDs(cb); + }); + } + + async setOSD(osd: any) { + return promisify(cb => { + this.cam.setOSD(osd, cb); + }); + } } export async function connectCameraAPI(ipAndPort: string, username: string, password: string, console: Console, binaryStateEvent: string) {