From bc64d14f7c102048cc4271bb1dfd8ed7a797f17c Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Wed, 22 Feb 2023 20:09:50 -0800 Subject: [PATCH] cameras: clean up device validation --- plugins/amcrest/package-lock.json | 4 +- plugins/amcrest/package.json | 2 +- plugins/amcrest/src/main.ts | 2 +- plugins/reolink/package-lock.json | 4 +- plugins/reolink/package.json | 2 +- plugins/reolink/src/main.ts | 79 +++++++++++++++++++++++++++++-- 6 files changed, 82 insertions(+), 11 deletions(-) diff --git a/plugins/amcrest/package-lock.json b/plugins/amcrest/package-lock.json index d548d3d71..6c13520b6 100644 --- a/plugins/amcrest/package-lock.json +++ b/plugins/amcrest/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/amcrest", - "version": "0.0.114", + "version": "0.0.115", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/amcrest", - "version": "0.0.114", + "version": "0.0.115", "license": "Apache", "dependencies": { "@koush/axios-digest-auth": "^0.8.5", diff --git a/plugins/amcrest/package.json b/plugins/amcrest/package.json index 4660b2d74..672673d52 100644 --- a/plugins/amcrest/package.json +++ b/plugins/amcrest/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/amcrest", - "version": "0.0.114", + "version": "0.0.115", "description": "Amcrest Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/amcrest/src/main.ts b/plugins/amcrest/src/main.ts index 0d2e972e2..b3f01a836 100644 --- a/plugins/amcrest/src/main.ts +++ b/plugins/amcrest/src/main.ts @@ -560,7 +560,7 @@ class AmcrestProvider extends RtspProvider { info.serialNumber = deviceInfo.serialNumber; } catch (e) { - this.console.error('Error adding Hikvision camera', e); + this.console.error('Error adding Amcrest camera', e); throw e; } } diff --git a/plugins/reolink/package-lock.json b/plugins/reolink/package-lock.json index 1b6720141..c39153933 100644 --- a/plugins/reolink/package-lock.json +++ b/plugins/reolink/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/reolink", - "version": "0.0.12", + "version": "0.0.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/reolink", - "version": "0.0.12", + "version": "0.0.13", "license": "Apache", "dependencies": { "@koush/axios-digest-auth": "^0.8.5", diff --git a/plugins/reolink/package.json b/plugins/reolink/package.json index 88de5890e..023f04d15 100644 --- a/plugins/reolink/package.json +++ b/plugins/reolink/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/reolink", - "version": "0.0.12", + "version": "0.0.13", "description": "Reolink Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/reolink/src/main.ts b/plugins/reolink/src/main.ts index 7df19a073..5a5edcd65 100644 --- a/plugins/reolink/src/main.ts +++ b/plugins/reolink/src/main.ts @@ -1,5 +1,5 @@ import { sleep } from '@scrypted/common/src/sleep'; -import sdk, { Camera, MediaObject, PictureOptions, ScryptedInterface, Setting } from "@scrypted/sdk"; +import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, MediaObject, PictureOptions, ScryptedInterface, Setting } from "@scrypted/sdk"; import { EventEmitter } from "stream"; import { Destroyable, RtspProvider, RtspSmartCamera, UrlMediaStreamOptions } from "../../rtsp/src/rtsp"; import { ReolinkCameraClient } from './reolink-api'; @@ -52,7 +52,7 @@ class ReolinkCamera extends RtspSmartCamera implements Camera { (async () => { while (!killed) { try { - const {value, data} = await client.getMotionState(); + const { value, data } = await client.getMotionState(); this.motionDetected = value; ret.emit('data', data); } @@ -96,7 +96,7 @@ class ReolinkCamera extends RtspSmartCamera implements Camera { async getConstructedVideoStreamOptions(): Promise { const ret: UrlMediaStreamOptions[] = []; - + const rtmpPreviews = [ `main.bcs`, `ext.bcs`, @@ -115,7 +115,7 @@ class ReolinkCamera extends RtspSmartCamera implements Camera { url: url.toString(), }); } - + const channel = (this.getRtspChannel() + 1).toString().padStart(2, '0'); const rtspPreviews = [ `h264Preview_${channel}_main`, @@ -178,6 +178,77 @@ class ReolinkProider extends RtspProvider { ]; } + async createDevice(settings: DeviceCreatorSettings, nativeId?: string): Promise { + const httpAddress = `${settings.ip}:${settings.httpPort || 80}`; + let info: DeviceInformation = {}; + + const username = settings.username?.toString(); + const password = settings.password?.toString(); + const skipValidate = settings.skipValidate === 'true'; + const rtspChannel = parseInt(settings.rtspChannel?.toString()) || 0; + if (!skipValidate) { + try { + const api = new ReolinkCameraClient(httpAddress, username, password, rtspChannel, this.console); + await api.jpegSnapshot(); + // there doesn't seem to be a way to get the actual model number information out of their api. + } + catch (e) { + this.console.error('Error adding Reolink camera', e); + throw e; + } + } + settings.newCamera ||= 'Hikvision Camera'; + + nativeId = await super.createDevice(settings, nativeId); + + const device = await this.getDevice(nativeId) as ReolinkCamera; + device.info = info; + device.putSetting('username', username); + device.putSetting('password', password); + device.setIPAddress(settings.ip?.toString()); + device.putSetting('rtspChannel', settings.rtspChannel?.toString()); + device.setHttpPortOverride(settings.httpPort?.toString()); + return nativeId; + } + + async getCreateDeviceSettings(): Promise { + return [ + { + key: 'username', + title: 'Username', + }, + { + key: 'password', + title: 'Password', + type: 'password', + }, + { + key: 'ip', + title: 'IP Address', + placeholder: '192.168.2.222', + }, + { + key: 'rtspChannel', + title: 'Channel Number Override', + description: "Optional: The channel number to use for snapshots and video. E.g., 0, 1, 2, etc.", + placeholder: '0', + type: 'number', + }, + { + key: 'httpPort', + title: 'HTTP Port', + description: 'Optional: Override the HTTP Port from the default value of 80', + placeholder: '80', + }, + { + key: 'skipValidate', + title: 'Skip Validation', + description: 'Add the device without verifying the credentials and network settings.', + type: 'boolean', + } + ] + } + createCamera(nativeId: string) { return new ReolinkCamera(nativeId, this); }