onvif: initial ptz preset support

This commit is contained in:
Koushik Dutta
2024-10-04 20:16:44 -07:00
parent f26b6c3bca
commit 511f348cbe
11 changed files with 75 additions and 15 deletions

View File

@@ -9,7 +9,7 @@
"version": "1.3.6",
"license": "ISC",
"dependencies": {
"@scrypted/types": "^0.3.59",
"@scrypted/types": "^0.3.60",
"engine.io-client": "^6.6.1",
"follow-redirects": "^1.15.9",
"rimraf": "^6.0.1"
@@ -75,9 +75,9 @@
}
},
"node_modules/@scrypted/types": {
"version": "0.3.59",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.3.59.tgz",
"integrity": "sha512-eX8HKYD/r47FbYHuAOzBOjtDFhqiw3DAkyanb1M+8RHNDk8kum3KPYerYafMUKg88sIybw+UeYSrdBq5D6m2+g=="
"version": "0.3.60",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.3.60.tgz",
"integrity": "sha512-oapFYQvyHLp0odCSx//USNnGNegS9ZL6a1HFIZzjDdMj2MNszTqiucAcu/wAlBwqjgURlP4/8xeLGVHEa4S2uQ=="
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.0",

View File

@@ -18,7 +18,7 @@
"typescript": "^5.6.2"
},
"dependencies": {
"@scrypted/types": "^0.3.59",
"@scrypted/types": "^0.3.60",
"engine.io-client": "^6.6.1",
"follow-redirects": "^1.15.9",
"rimraf": "^6.0.1"

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/onvif",
"version": "0.1.27",
"version": "0.1.28",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@scrypted/onvif",
"version": "0.1.27",
"version": "0.1.28",
"license": "Apache",
"dependencies": {
"@scrypted/common": "file:../../common",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/onvif",
"version": "0.1.27",
"version": "0.1.28",
"description": "ONVIF Camera Plugin for Scrypted",
"author": "Scrypted",
"license": "Apache",

View File

@@ -20,6 +20,7 @@ export class OnvifPtzMixin extends SettingsMixinDeviceBase<Settings> implements
],
onPut: (ov, ptz: string[]) => {
this.ptzCapabilities = {
...this.ptzCapabilities,
pan: ptz.includes('Pan'),
tilt: ptz.includes('Tilt'),
zoom: ptz.includes('Zoom'),
@@ -38,6 +39,34 @@ export class OnvifPtzMixin extends SettingsMixinDeviceBase<Settings> implements
],
defaultValue: 'Default',
},
presets: {
title: 'Presets',
description: 'PTZ Presets in the format "key=name". Where key is the PTZ Preset identifier and name is a friendly name.',
multiple: true,
defaultValue: [],
combobox: true,
onPut: async (ov, presets: string[]) => {
const caps = {
...this.ptzCapabilities,
presets: {},
};
for (const preset of presets) {
const [key, name] = preset.split('=');
caps.presets[key] = name;
}
this.ptzCapabilities = caps;
},
mapGet: () => {
const presets = this.ptzCapabilities?.presets || {};
return Object.entries(presets).map(([key, name]) => key + '=' + name);
},
},
cachedPresets: {
multiple: true,
hide: true,
json: true,
defaultValue: {},
},
});
constructor(options: SettingsMixinDeviceOptions<Settings>) {
@@ -45,6 +74,30 @@ export class OnvifPtzMixin extends SettingsMixinDeviceBase<Settings> implements
// force a read to set the state.
this.storageSettings.values.ptz;
this.refreshPresets();
this.storageSettings.settings.presets.onGet = async () => {
// getPresets is where the key is the name of the preset, and the value is the id.
// kind of weird and backwards.
const choices = Object.entries(this.storageSettings.values.cachedPresets).map(([name, key]) => key + '=' + name);
return {
choices,
};
};
}
async refreshPresets() {
const client = await this.getClient();
client.cam.getPresets({}, (e, result, xml) => {
if (e) {
this.console.error('failed to get presets', e);
}
else {
this.console.log('presets', result);
this.storageSettings.values.cachedPresets = result;
}
});
}
getMixinSettings(): Promise<Setting[]> {
@@ -83,7 +136,7 @@ export class OnvifPtzMixin extends SettingsMixinDeviceBase<Settings> implements
})
}
else if (movement === PanTiltZoomMovement.Continuous) {
let x= command.pan;
let x = command.pan;
let y = command.tilt;
let zoom = command.zoom;
if (command.speed?.pan)

4
sdk/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/sdk",
"version": "0.3.63",
"version": "0.3.65",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/sdk",
"version": "0.3.63",
"version": "0.3.65",
"license": "ISC",
"dependencies": {
"@babel/preset-typescript": "^7.24.7",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/sdk",
"version": "0.3.63",
"version": "0.3.65",
"description": "",
"main": "dist/src/index.js",
"exports": {

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/types",
"version": "0.3.59",
"version": "0.3.60",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/types",
"version": "0.3.59",
"version": "0.3.60",
"license": "ISC",
"devDependencies": {
"@types/node": "^22.1.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/types",
"version": "0.3.59",
"version": "0.3.60",
"description": "",
"main": "dist/index.js",
"author": "",

View File

@@ -706,6 +706,7 @@ class ObjectsDetected(TypedDict):
class PanTiltZoomCapabilities(TypedDict):
pan: bool
presets: Any # Preset id mapped to friendly name.
tilt: bool
zoom: bool

View File

@@ -1003,6 +1003,12 @@ export interface PanTiltZoomCapabilities {
pan?: boolean;
tilt?: boolean;
zoom?: boolean;
/**
* Preset id mapped to friendly name.
*/
presets?: {
[key: string]: string;
};
}
export interface PanTiltZoom {
ptzCapabilities?: PanTiltZoomCapabilities;