Skip to content

Commit

Permalink
unifi-protect: Implement privacy masking
Browse files Browse the repository at this point in the history
  • Loading branch information
koush committed Mar 20, 2024
1 parent a54978e commit 96ae2fc
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 6 deletions.
4 changes: 2 additions & 2 deletions plugins/unifi-protect/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion plugins/unifi-protect/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
40 changes: 37 additions & 3 deletions plugins/unifi-protect/src/camera.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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;
Expand All @@ -63,6 +63,40 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
this.console.log(protectCamera);
}

async getPrivacyMasks(): Promise<PrivacyMasks> {
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<void> {
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<void> {
const camera = this.findCamera() as any;
await this.protect.api.updateCamera(camera, {
Expand Down
1 change: 1 addition & 0 deletions plugins/unifi-protect/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
ScryptedInterface.Settings,
ScryptedInterface.Camera,
ScryptedInterface.VideoCamera,
ScryptedInterface.VideoCameraMask,
ScryptedInterface.VideoCameraConfiguration,
ScryptedInterface.MotionSensor,
],
Expand Down
7 changes: 7 additions & 0 deletions plugins/unifi-protect/src/shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ export interface FeatureFlagsShim {
export interface LastSeenShim {
lastSeen: number;
}

export interface PrivacyZone {
id: number;
name: string;
color: string;
points: [number, number][];
}
1 change: 1 addition & 0 deletions sdk/types/scrypted_python/scrypted_sdk/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ class PictureDimensions(TypedDict):

class PrivacyMask(TypedDict):

name: str
points: list[Point]

class RequestMediaStreamAdaptiveOptions(TypedDict):
Expand Down
1 change: 1 addition & 0 deletions sdk/types/src/types.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ export interface Intercom {
}

export interface PrivacyMask {
name?: string;
points: Point[];
}

Expand Down

0 comments on commit 96ae2fc

Please sign in to comment.