diff --git a/plugins/objectdetector/package-lock.json b/plugins/objectdetector/package-lock.json index 381fe96f14..8dbd80bbf3 100644 --- a/plugins/objectdetector/package-lock.json +++ b/plugins/objectdetector/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/objectdetector", - "version": "0.0.92", + "version": "0.0.98", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/objectdetector", - "version": "0.0.92", + "version": "0.0.98", "license": "Apache-2.0", "dependencies": { "@scrypted/common": "file:../../common", diff --git a/plugins/objectdetector/package.json b/plugins/objectdetector/package.json index 27be3b4587..e432a35192 100644 --- a/plugins/objectdetector/package.json +++ b/plugins/objectdetector/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/objectdetector", - "version": "0.0.92", + "version": "0.0.98", "description": "Scrypted Video Analysis Plugin. Installed alongside a detection service like OpenCV or TensorFlow.", "author": "Scrypted", "license": "Apache-2.0", @@ -35,6 +35,7 @@ "name": "Video Analysis Plugin", "type": "API", "interfaces": [ + "Settings", "MixinProvider" ], "realfs": true diff --git a/plugins/objectdetector/src/main.ts b/plugins/objectdetector/src/main.ts index acf21751fb..bbb99c1b70 100644 --- a/plugins/objectdetector/src/main.ts +++ b/plugins/objectdetector/src/main.ts @@ -1,4 +1,4 @@ -import sdk, { Camera, DeviceState, EventListenerRegister, MediaObject, MixinDeviceBase, MixinProvider, MotionSensor, ObjectDetection, ObjectDetectionCallbacks, ObjectDetectionModel, ObjectDetectionResult, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, Settings, VideoCamera } from '@scrypted/sdk'; +import sdk, { Camera, DeviceState, EventListenerRegister, MediaObject, MixinDeviceBase, MixinProvider, MotionSensor, ObjectDetection, ObjectDetectionCallbacks, ObjectDetectionModel, ObjectDetectionResult, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, Settings, SettingValue, VideoCamera } from '@scrypted/sdk'; import { StorageSettings } from '@scrypted/sdk/storage-settings'; import crypto from 'crypto'; import cloneDeep from 'lodash/cloneDeep'; @@ -347,7 +347,7 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase= this.secondScoreThreshold) { - this.console.log('improved', d.id, d.bestSecondPassScore, d.score); + this.console.log('improved', d.id, secondPassScore, d.score); better = true; retainImage = true; } @@ -436,6 +436,8 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase this.analyzeStop) @@ -445,12 +447,13 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase 0) await sleep(diff); } - this.detectorRunning = false; - this.handleDetectionEvent({ - detectionId: this.detectionId, - running: false, - detections: [], - timestamp: Date.now(), - }, undefined, undefined); + this.endObjectDetection(); } async startStreamAnalysis() { @@ -545,7 +542,7 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase implements MixinProvider { + currentMixins = new Set(); + constructor(mixinDevice: ObjectDetection, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: DeviceState, mixinProviderNativeId: ScryptedNativeId, public model: ObjectDetectionModel) { super({ mixinDevice, mixinDeviceInterfaces, mixinDeviceState, mixinProviderNativeId }); @@ -1036,19 +1035,53 @@ class ObjectDetectorMixin extends MixinDeviceBase implements Mi const hasMotionType = this.model.classes.includes('motion'); const settings = this.model.settings; - return new ObjectDetectionMixin(mixinDevice, mixinDeviceInterfaces, mixinDeviceState, this.mixinProviderNativeId, objectDetection, this.model.name, group, hasMotionType, settings); + const ret = new ObjectDetectionMixin(mixinDevice, mixinDeviceInterfaces, mixinDeviceState, this.mixinProviderNativeId, objectDetection, this.model.name, group, hasMotionType, settings); + this.currentMixins.add(ret); + return ret; } async releaseMixin(id: string, mixinDevice: any) { + this.currentMixins.delete(mixinDevice); return mixinDevice.release(); } } -class ObjectDetectionPlugin extends AutoenableMixinProvider { +class ObjectDetectionPlugin extends AutoenableMixinProvider implements Settings { + currentMixins = new Set(); + + storageSettings = new StorageSettings(this, { + activeMotionDetections: { + title: 'Active Motion Detection Sessions', + readonly: true, + mapGet: () => { + return [...this.currentMixins.values()] + .reduce((c1, v1) => c1 + [...v1.currentMixins.values()] + .reduce((c2, v2) => c2 + (v2.hasMotionType && v2.detectorRunning ? 1 : 0), 0), 0); + } + }, + activeObjectDetections: { + title: 'Active Object Detection Sessions', + readonly: true, + mapGet: () => { + return [...this.currentMixins.values()] + .reduce((c1, v1) => c1 + [...v1.currentMixins.values()] + .reduce((c2, v2) => c2 + (!v2.hasMotionType && v2.detectorRunning ? 1 : 0), 0), 0); + } + } + }) + constructor(nativeId?: ScryptedNativeId) { super(nativeId); } + getSettings(): Promise { + return this.storageSettings.getSettings(); + } + + putSetting(key: string, value: SettingValue): Promise { + return this.storageSettings.putSetting(key, value); + } + async canMixin(type: ScryptedDeviceType, interfaces: string[]): Promise { if (!interfaces.includes(ScryptedInterface.ObjectDetection)) return; @@ -1057,12 +1090,15 @@ class ObjectDetectionPlugin extends AutoenableMixinProvider { async getMixin(mixinDevice: ObjectDetection, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: { [key: string]: any; }): Promise { const model = await mixinDevice.getDetectionModel(); - return new ObjectDetectorMixin(mixinDevice, mixinDeviceInterfaces, mixinDeviceState, this.nativeId, model); + const ret = new ObjectDetectorMixin(mixinDevice, mixinDeviceInterfaces, mixinDeviceState, this.nativeId, model); + this.currentMixins.add(ret); + return ret; } async releaseMixin(id: string, mixinDevice: any): Promise { // what does this mean to make a mixin provider no longer available? // just ignore it until reboot? + this.currentMixins.delete(mixinDevice); } }