From fd48eee7b2cb0c4f1b5c3cdb19cf4f11918cd0f2 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Tue, 5 Mar 2024 08:47:49 -0800 Subject: [PATCH] cameras: add default request timeouts on snapshots --- plugins/amcrest/package-lock.json | 4 ++-- plugins/amcrest/package.json | 2 +- plugins/amcrest/src/amcrest-api.ts | 4 ++-- plugins/amcrest/src/main.ts | 6 +++--- plugins/hikvision/package-lock.json | 4 ++-- plugins/hikvision/package.json | 2 +- plugins/hikvision/src/hikvision-camera-api.ts | 6 +++--- plugins/hikvision/src/main.ts | 6 +++--- plugins/onvif/package-lock.json | 4 ++-- plugins/onvif/package.json | 2 +- plugins/onvif/src/main.ts | 6 +++--- plugins/onvif/src/onvif-api.ts | 4 ++-- plugins/onvif/src/onvif-ptz.ts | 6 +++--- plugins/reolink/package-lock.json | 4 ++-- plugins/reolink/package.json | 2 +- plugins/reolink/src/main.ts | 6 +++--- plugins/reolink/src/reolink-api.ts | 4 ++-- plugins/rtsp/src/rtsp.ts | 6 +++--- 18 files changed, 39 insertions(+), 39 deletions(-) diff --git a/plugins/amcrest/package-lock.json b/plugins/amcrest/package-lock.json index efb86dd63..df5f45d7a 100644 --- a/plugins/amcrest/package-lock.json +++ b/plugins/amcrest/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/amcrest", - "version": "0.0.133", + "version": "0.0.134", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/amcrest", - "version": "0.0.133", + "version": "0.0.134", "license": "Apache", "dependencies": { "@scrypted/common": "file:../../common", diff --git a/plugins/amcrest/package.json b/plugins/amcrest/package.json index 4a083c201..796868199 100644 --- a/plugins/amcrest/package.json +++ b/plugins/amcrest/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/amcrest", - "version": "0.0.133", + "version": "0.0.134", "description": "Amcrest Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/amcrest/src/amcrest-api.ts b/plugins/amcrest/src/amcrest-api.ts index 4a402a6e8..3637708e1 100644 --- a/plugins/amcrest/src/amcrest-api.ts +++ b/plugins/amcrest/src/amcrest-api.ts @@ -69,10 +69,10 @@ export class AmcrestCameraClient { return getDeviceInfo(this.credential, this.ip); } - async jpegSnapshot(): Promise { + async jpegSnapshot(timeout = 10000): Promise { const response = await this.request({ url: `http://${this.ip}/cgi-bin/snapshot.cgi`, - timeout: 60000, + timeout, }); return response.body; diff --git a/plugins/amcrest/src/main.ts b/plugins/amcrest/src/main.ts index 072aa5621..0b4d11590 100644 --- a/plugins/amcrest/src/main.ts +++ b/plugins/amcrest/src/main.ts @@ -1,6 +1,6 @@ import { ffmpegLogInitialOutput } from '@scrypted/common/src/media-helpers'; import { readLength } from "@scrypted/common/src/read-stream"; -import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, PictureOptions, Reboot, RequestRecordingStreamOptions, ResponseMediaStreamOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, VideoCameraConfiguration, VideoRecorder } from "@scrypted/sdk"; +import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, PictureOptions, Reboot, RequestPictureOptions, RequestRecordingStreamOptions, ResponseMediaStreamOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, VideoCameraConfiguration, VideoRecorder } from "@scrypted/sdk"; import child_process, { ChildProcess } from 'child_process'; import { PassThrough, Readable, Stream } from "stream"; import { OnvifIntercom } from "../../onvif/src/onvif-intercom"; @@ -318,8 +318,8 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration, } - async takeSmartCameraPicture(option?: PictureOptions): Promise { - return this.createMediaObject(await this.getClient().jpegSnapshot(), 'image/jpeg'); + async takeSmartCameraPicture(options?: RequestPictureOptions): Promise { + return this.createMediaObject(await this.getClient().jpegSnapshot(options?.timeout), 'image/jpeg'); } async getUrlSettings() { diff --git a/plugins/hikvision/package-lock.json b/plugins/hikvision/package-lock.json index e668c30f8..09540647a 100644 --- a/plugins/hikvision/package-lock.json +++ b/plugins/hikvision/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/hikvision", - "version": "0.0.136", + "version": "0.0.137", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/hikvision", - "version": "0.0.136", + "version": "0.0.137", "license": "Apache", "dependencies": { "@scrypted/common": "file:../../common", diff --git a/plugins/hikvision/package.json b/plugins/hikvision/package.json index dfcce95ba..a8712a7eb 100644 --- a/plugins/hikvision/package.json +++ b/plugins/hikvision/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/hikvision", - "version": "0.0.136", + "version": "0.0.137", "description": "Hikvision Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/hikvision/src/hikvision-camera-api.ts b/plugins/hikvision/src/hikvision-camera-api.ts index 25c178040..5e2d6bb4f 100644 --- a/plugins/hikvision/src/hikvision-camera-api.ts +++ b/plugins/hikvision/src/hikvision-camera-api.ts @@ -1,4 +1,4 @@ -import { AuthFetchCredentialState, HttpFetchOptions, HttpFetchResponseType, authHttpFetch } from '@scrypted/common/src/http-auth-fetch'; +import { AuthFetchCredentialState, HttpFetchOptions, authHttpFetch } from '@scrypted/common/src/http-auth-fetch'; import { IncomingMessage } from 'http'; import { Readable } from 'stream'; import { getDeviceInfo } from './probe'; @@ -118,12 +118,12 @@ export class HikvisionCameraAPI { } } - async jpegSnapshot(channel: string): Promise { + async jpegSnapshot(channel: string, timeout = 10000): Promise { const url = `http://${this.ip}/ISAPI/Streaming/channels/${getChannel(channel)}/picture?snapShotImageType=JPEG` const response = await this.request({ url: url, - timeout: 60000, + timeout, }); return response.body; diff --git a/plugins/hikvision/src/main.ts b/plugins/hikvision/src/main.ts index bef5fecf9..61fd54a2c 100644 --- a/plugins/hikvision/src/main.ts +++ b/plugins/hikvision/src/main.ts @@ -1,4 +1,4 @@ -import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, Reboot, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting } from "@scrypted/sdk"; +import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting } from "@scrypted/sdk"; import { PassThrough } from "stream"; import xml2js from 'xml2js'; import { RtpPacket } from '../../../external/werift/packages/rtp/src/rtp/rtp'; @@ -121,9 +121,9 @@ class HikvisionCamera extends RtspSmartCamera implements Camera, Intercom, Reboo return this.client; } - async takeSmartCameraPicture(): Promise { + async takeSmartCameraPicture(options?: RequestPictureOptions): Promise { const api = this.getClient(); - return mediaManager.createMediaObject(await api.jpegSnapshot(this.getRtspChannel()), 'image/jpeg'); + return mediaManager.createMediaObject(await api.jpegSnapshot(this.getRtspChannel(), options?.timeout), 'image/jpeg'); } async getRtspUrlSettings(): Promise { diff --git a/plugins/onvif/package-lock.json b/plugins/onvif/package-lock.json index 600e4ac05..f579edf7e 100644 --- a/plugins/onvif/package-lock.json +++ b/plugins/onvif/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/onvif", - "version": "0.1.8", + "version": "0.1.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/onvif", - "version": "0.1.8", + "version": "0.1.10", "license": "Apache", "dependencies": { "@scrypted/common": "file:../../common", diff --git a/plugins/onvif/package.json b/plugins/onvif/package.json index 28c3ba0de..93f7115ba 100644 --- a/plugins/onvif/package.json +++ b/plugins/onvif/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/onvif", - "version": "0.1.8", + "version": "0.1.10", "description": "ONVIF Camera Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/onvif/src/main.ts b/plugins/onvif/src/main.ts index 8ee7bd2ec..bc120071b 100644 --- a/plugins/onvif/src/main.ts +++ b/plugins/onvif/src/main.ts @@ -1,4 +1,4 @@ -import sdk, { AdoptDevice, Device, DeviceCreatorSettings, DeviceDiscovery, DeviceInformation, DiscoveredDevice, Intercom, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, Settings, SettingValue, VideoCamera, VideoCameraConfiguration } from "@scrypted/sdk"; +import sdk, { AdoptDevice, Device, DeviceCreatorSettings, DeviceDiscovery, DeviceInformation, DiscoveredDevice, Intercom, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, Settings, SettingValue, VideoCamera, VideoCameraConfiguration } from "@scrypted/sdk"; import { AddressInfo } from "net"; import onvif from 'onvif'; import { Stream } from "stream"; @@ -159,7 +159,7 @@ class OnvifCamera extends RtspSmartCamera implements ObjectDetector, Intercom, V } } - async takeSmartCameraPicture(options?: PictureOptions): Promise { + async takeSmartCameraPicture(options?: RequestPictureOptions): Promise { const client = await this.getClient(); let snapshot: Buffer; let id = options?.id; @@ -170,7 +170,7 @@ class OnvifCamera extends RtspSmartCamera implements ObjectDetector, Intercom, V id = vso?.id; } - snapshot = await client.jpegSnapshot(id); + snapshot = await client.jpegSnapshot(id, options?.timeout); // it is possible that onvif does not support snapshots, in which case return the video stream if (!snapshot) { diff --git a/plugins/onvif/src/onvif-api.ts b/plugins/onvif/src/onvif-api.ts index fb24f9526..847bf33b0 100644 --- a/plugins/onvif/src/onvif-api.ts +++ b/plugins/onvif/src/onvif-api.ts @@ -270,7 +270,7 @@ export class OnvifCameraAPI { return this.rtspUrls.get(profileToken); } - async jpegSnapshot(profileToken?: string): Promise { + async jpegSnapshot(profileToken?: string, timeout = 10000): Promise { if (!profileToken) profileToken = await this.getMainProfileToken(); if (!this.snapshotUrls.has(profileToken)) { @@ -294,7 +294,7 @@ export class OnvifCameraAPI { const response = await this.request({ url: snapshotUri, - timeout: 60000, + timeout, }); return response.body; diff --git a/plugins/onvif/src/onvif-ptz.ts b/plugins/onvif/src/onvif-ptz.ts index de29c18ce..63ed71218 100644 --- a/plugins/onvif/src/onvif-ptz.ts +++ b/plugins/onvif/src/onvif-ptz.ts @@ -1,7 +1,7 @@ -import { DeviceState, MixinDeviceBase, MixinDeviceOptions, MixinProvider, PanTiltZoom, PanTiltZoomCommand, PanTiltZoomMovement, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, Setting, Settings, SettingValue } from "@scrypted/sdk"; +import { MixinProvider, PanTiltZoom, PanTiltZoomCommand, PanTiltZoomMovement, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, Setting, Settings, SettingValue, WritableDeviceState } from "@scrypted/sdk"; import { StorageSettings } from "@scrypted/sdk/storage-settings"; -import { connectCameraAPI } from "./onvif-api"; import { SettingsMixinDeviceBase, SettingsMixinDeviceOptions } from '../../../common/src/settings-mixin'; +import { connectCameraAPI } from "./onvif-api"; export class OnvifPtzMixin extends SettingsMixinDeviceBase implements PanTiltZoom, Settings { storageSettings = new StorageSettings(this, { @@ -121,7 +121,7 @@ export class OnvifPTZMixinProvider extends ScryptedDeviceBase implements MixinPr ]; } - async getMixin(mixinDevice: any, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: DeviceState): Promise { + async getMixin(mixinDevice: any, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: WritableDeviceState): Promise { return new OnvifPtzMixin({ group: 'ONVIF PTZ', groupKey: 'ptz', diff --git a/plugins/reolink/package-lock.json b/plugins/reolink/package-lock.json index 5d7db4aad..1c27f31a4 100644 --- a/plugins/reolink/package-lock.json +++ b/plugins/reolink/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/reolink", - "version": "0.0.60", + "version": "0.0.61", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/reolink", - "version": "0.0.60", + "version": "0.0.61", "license": "Apache", "dependencies": { "@scrypted/common": "file:../../common", diff --git a/plugins/reolink/package.json b/plugins/reolink/package.json index 2f563a7c6..49a444619 100644 --- a/plugins/reolink/package.json +++ b/plugins/reolink/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/reolink", - "version": "0.0.60", + "version": "0.0.61", "description": "Reolink Plugin for Scrypted", "author": "Scrypted", "license": "Apache", diff --git a/plugins/reolink/src/main.ts b/plugins/reolink/src/main.ts index 9898336d6..8e30e4353 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, DeviceCreatorSettings, DeviceInformation, Intercom, MediaObject, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, ScryptedDeviceType, ScryptedInterface, Setting } from "@scrypted/sdk"; +import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, Intercom, MediaObject, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, Setting } from "@scrypted/sdk"; import { StorageSettings } from '@scrypted/sdk/storage-settings'; import { EventEmitter } from "stream"; import { Destroyable, RtspProvider, RtspSmartCamera, UrlMediaStreamOptions } from "../../rtsp/src/rtsp"; @@ -302,8 +302,8 @@ class ReolinkCamera extends RtspSmartCamera implements Camera, Reboot, Intercom, return ret; } - async takeSmartCameraPicture(option?: PictureOptions): Promise { - return this.createMediaObject(await this.getClient().jpegSnapshot(), 'image/jpeg'); + async takeSmartCameraPicture(options?: RequestPictureOptions): Promise { + return this.createMediaObject(await this.getClient().jpegSnapshot(options?.timeout), 'image/jpeg'); } async getUrlSettings(): Promise { diff --git a/plugins/reolink/src/reolink-api.ts b/plugins/reolink/src/reolink-api.ts index fb34054b4..c773f14f2 100644 --- a/plugins/reolink/src/reolink-api.ts +++ b/plugins/reolink/src/reolink-api.ts @@ -127,7 +127,7 @@ export class ReolinkCameraClient { }; } - async jpegSnapshot() { + async jpegSnapshot(timeout = 10000) { const url = new URL(`http://${this.host}/cgi-bin/api.cgi`); const params = url.searchParams; params.set('cmd', 'Snap'); @@ -138,7 +138,7 @@ export class ReolinkCameraClient { const response = await this.request({ url, - timeout: 60000, + timeout, }); return response.body; diff --git a/plugins/rtsp/src/rtsp.ts b/plugins/rtsp/src/rtsp.ts index 693d65012..cbde88259 100644 --- a/plugins/rtsp/src/rtsp.ts +++ b/plugins/rtsp/src/rtsp.ts @@ -1,5 +1,5 @@ import { timeoutPromise } from '@scrypted/common/src/promise-utils'; -import sdk, { MediaObject, MediaStreamUrl, PictureOptions, ResponseMediaStreamOptions, ScryptedInterface, ScryptedMimeTypes, Setting, SettingValue } from "@scrypted/sdk"; +import sdk, { MediaObject, MediaStreamUrl, PictureOptions, RequestPictureOptions, ResponseMediaStreamOptions, ScryptedInterface, ScryptedMimeTypes, Setting, SettingValue } from "@scrypted/sdk"; import url from 'url'; import { CameraBase, CameraProviderBase, UrlMediaStreamOptions } from "../../ffmpeg-camera/src/common"; @@ -234,8 +234,8 @@ export abstract class RtspSmartCamera extends RtspCamera { this.listener.then(l => l.emit('error', new Error("new settings"))); } - async takePicture(option?: PictureOptions) { - return this.takeSmartCameraPicture(option);; + async takePicture(options?: RequestPictureOptions) { + return this.takeSmartCameraPicture(options); } abstract takeSmartCameraPicture(options?: PictureOptions): Promise;