diff --git a/plugins/unifi-protect/package-lock.json b/plugins/unifi-protect/package-lock.json index 992b137b5..22ce2cf17 100644 --- a/plugins/unifi-protect/package-lock.json +++ b/plugins/unifi-protect/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/unifi-protect", - "version": "0.0.144", + "version": "0.0.145", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/unifi-protect", - "version": "0.0.144", + "version": "0.0.145", "license": "Apache", "dependencies": { "@koush/unifi-protect": "file:../../external/unifi-protect", diff --git a/plugins/unifi-protect/package.json b/plugins/unifi-protect/package.json index 6e6fc624f..41fb22cfe 100644 --- a/plugins/unifi-protect/package.json +++ b/plugins/unifi-protect/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/unifi-protect", - "version": "0.0.144", + "version": "0.0.145", "description": "Unifi Protect Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/unifi-protect/src/camera.ts b/plugins/unifi-protect/src/camera.ts index 3eae84013..e39f7e66e 100644 --- a/plugins/unifi-protect/src/camera.ts +++ b/plugins/unifi-protect/src/camera.ts @@ -1,13 +1,13 @@ import { ffmpegLogInitialOutput, safeKillFFmpeg } from '@scrypted/common/src/media-helpers'; import { fitHeightToWidth } from "@scrypted/common/src/resolution-utils"; -import sdk, { Camera, DeviceProvider, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, MediaStreamUrl, MotionSensor, Notifier, NotifierOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, OnOff, Online, PanTiltZoom, PanTiltZoomCommand, PictureOptions, ResponseMediaStreamOptions, ResponsePictureOptions, ScryptedDeviceBase, ScryptedInterface, ScryptedMimeTypes, Setting, Settings, VideoCamera, VideoCameraConfiguration } from "@scrypted/sdk"; +import sdk, { Camera, DeviceProvider, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, MediaStreamUrl, MotionSensor, Notifier, NotifierOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, OnOff, Online, PanTiltZoom, PanTiltZoomCommand, PictureOptions, PrivacyMasks, ResponseMediaStreamOptions, ResponsePictureOptions, ScryptedDeviceBase, ScryptedInterface, ScryptedMimeTypes, Setting, Settings, VideoCamera, VideoCameraConfiguration, VideoCameraMask } from "@scrypted/sdk"; import child_process, { ChildProcess } from 'child_process'; import { once } from "events"; import { PassThrough, Readable } from "stream"; import WS from 'ws'; import { UnifiProtect } from "./main"; import { MOTION_SENSOR_TIMEOUT, UnifiMotionDevice, debounceMotionDetected } from './motion'; -import { FeatureFlagsShim } from "./shim"; +import { FeatureFlagsShim, PrivacyZone } from "./shim"; import { ProtectCameraChannelConfig, ProtectCameraConfigInterface, ProtectCameraLcdMessagePayload } from "./unifi-protect"; import { readLength } from '@scrypted/common/src/read-stream'; @@ -41,7 +41,7 @@ export class UnifiPackageCamera extends ScryptedDeviceBase implements Camera, Vi } } -export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Intercom, Camera, VideoCamera, VideoCameraConfiguration, MotionSensor, Settings, ObjectDetector, DeviceProvider, OnOff, PanTiltZoom, Online, UnifiMotionDevice { +export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Intercom, Camera, VideoCamera, VideoCameraConfiguration, MotionSensor, Settings, ObjectDetector, DeviceProvider, OnOff, PanTiltZoom, Online, UnifiMotionDevice, VideoCameraMask { motionTimeout: NodeJS.Timeout; detectionTimeout: NodeJS.Timeout; ringTimeout: NodeJS.Timeout; @@ -63,6 +63,40 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco this.console.log(protectCamera); } + async getPrivacyMasks(): Promise { + const camera = this.findCamera(); + const privacyZones = (camera as any).privacyZones as PrivacyZone[] || []; + + const masks: PrivacyMasks = { + masks: privacyZones.map(zone => { + return { + id: zone.id.toString(), + name: zone.name, + points: zone.points, + } + }), + }; + + return masks; + } + + async setPrivacyMasks(masks: PrivacyMasks): Promise { + const privacyZones: PrivacyZone[] = masks.masks.map((mask, index) => { + return { + id: index, + name: mask.name || `Privacy Zone ${index}`, + points: mask.points, + color: 'red', + } + }); + + const camera = this.findCamera() as any; + + await this.protect.api.updateCamera(camera, { + privacyZones, + } as any); + } + async ptzCommand(command: PanTiltZoomCommand): Promise { const camera = this.findCamera() as any; await this.protect.api.updateCamera(camera, { diff --git a/plugins/unifi-protect/src/main.ts b/plugins/unifi-protect/src/main.ts index ec1265fdf..58a146ccc 100644 --- a/plugins/unifi-protect/src/main.ts +++ b/plugins/unifi-protect/src/main.ts @@ -345,6 +345,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device ScryptedInterface.Settings, ScryptedInterface.Camera, ScryptedInterface.VideoCamera, + ScryptedInterface.VideoCameraMask, ScryptedInterface.VideoCameraConfiguration, ScryptedInterface.MotionSensor, ], diff --git a/plugins/unifi-protect/src/shim.ts b/plugins/unifi-protect/src/shim.ts index f9b079f6f..1b89ea9a8 100644 --- a/plugins/unifi-protect/src/shim.ts +++ b/plugins/unifi-protect/src/shim.ts @@ -6,3 +6,10 @@ export interface FeatureFlagsShim { export interface LastSeenShim { lastSeen: number; } + +export interface PrivacyZone { + id: number; + name: string; + color: string; + points: [number, number][]; +} diff --git a/sdk/types/scrypted_python/scrypted_sdk/types.py b/sdk/types/scrypted_python/scrypted_sdk/types.py index 685605761..3ec1fe049 100644 --- a/sdk/types/scrypted_python/scrypted_sdk/types.py +++ b/sdk/types/scrypted_python/scrypted_sdk/types.py @@ -323,6 +323,7 @@ class PictureDimensions(TypedDict): class PrivacyMask(TypedDict): + name: str points: list[Point] class RequestMediaStreamAdaptiveOptions(TypedDict): diff --git a/sdk/types/src/types.input.ts b/sdk/types/src/types.input.ts index ba6a2b9f5..e0ef4d04a 100644 --- a/sdk/types/src/types.input.ts +++ b/sdk/types/src/types.input.ts @@ -821,6 +821,7 @@ export interface Intercom { } export interface PrivacyMask { + name?: string; points: Point[]; }