@apocaliss92/scrypted-reolink-native 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apocaliss92/scrypted-reolink-native",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Use any reolink camera with Scrypted, even older/unsupported models without HTTP protocol support",
5
5
  "author": "@apocaliss92",
6
6
  "license": "Apache",
package/src/camera.ts CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  StreamManager,
21
21
  StreamManagerOptions
22
22
  } from "./stream-utils";
23
- import { floodlightSuffix, getDeviceInterfaces, pirSuffix, recordingsToVideoClips, sanitizeFfmpegOutput, sirenSuffix, updateDeviceInfo } from "./utils";
23
+ import { floodlightSuffix, getDeviceInterfaces, pirSuffix, recordingsToVideoClips, removeAuthUrls, sanitizeFfmpegOutput, sirenSuffix, updateDeviceInfo } from "./utils";
24
24
 
25
25
  export type CameraType = 'battery' | 'regular' | 'multi-focal' | 'multi-focal-battery';
26
26
 
@@ -2405,9 +2405,9 @@ export class ReolinkCamera extends BaseBaichuanClass implements VideoCamera, Cam
2405
2405
  });
2406
2406
 
2407
2407
  logger.debug(`Supported streams: ${JSON.stringify({
2408
- nativeStreams,
2409
- rtmpStreams,
2410
- rtspStreams,
2408
+ nativeStreams: removeAuthUrls(nativeStreams),
2409
+ rtmpStreams: removeAuthUrls(rtmpStreams),
2410
+ rtspStreams: removeAuthUrls(rtspStreams),
2411
2411
  variantType,
2412
2412
  onNvr: this.isOnNvr,
2413
2413
  channel: rtspChannel,
@@ -2534,7 +2534,12 @@ export class ReolinkCamera extends BaseBaichuanClass implements VideoCamera, Cam
2534
2534
  if (!this.streamManager) {
2535
2535
  const logger = this.getBaichuanLogger();
2536
2536
  logger.warn('StreamManager not initialized, initializing now...');
2537
- this.initStreamManager(logger);
2537
+ try {
2538
+ this.initStreamManager(logger);
2539
+ } catch (e) {
2540
+ logger.error('Failed to initialize StreamManager in getVideoStream', e?.message || String(e), e);
2541
+ throw e;
2542
+ }
2538
2543
  }
2539
2544
 
2540
2545
  const streamKey = selected.id;
@@ -2731,7 +2736,7 @@ export class ReolinkCamera extends BaseBaichuanClass implements VideoCamera, Cam
2731
2736
  this.initStreamManager();
2732
2737
  }
2733
2738
  catch (e) {
2734
- logger.error('Failed to initialize StreamManager', e?.message || String(e));
2739
+ logger.error('Failed to initialize StreamManager in init', e?.message || String(e), e);
2735
2740
  }
2736
2741
 
2737
2742
  const { hasIntercom, hasPtz } = await this.getAbilities();
package/src/main.ts CHANGED
@@ -5,6 +5,7 @@ import { ReolinkNativeNvrDevice } from "./nvr";
5
5
  import { batteryCameraSuffix, batteryMultifocalSuffix, cameraSuffix, extractThumbnailFromVideo, getDeviceInterfaces, handleVideoClipRequest, multifocalSuffix, nvrSuffix } from "./utils";
6
6
  import { randomBytes } from "crypto";
7
7
  import { ReolinkCamera } from "./camera";
8
+ import type { AutoDetectMode } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
8
9
 
9
10
  interface ThumbnailRequest {
10
11
  deviceId: string;
@@ -65,8 +66,19 @@ class ReolinkNativePlugin extends ScryptedDeviceBase implements DeviceProvider,
65
66
  throw new Error('IP address, username, and password are required');
66
67
  }
67
68
 
68
- this.console.log(`[AutoDetect] Starting device type detection for ${ipAddress}...`);
69
+ const deviceTypeSetting = settings.deviceType?.toString() || 'Auto';
70
+ const forceType = deviceTypeSetting === 'Auto' ? undefined : deviceTypeSetting.toLowerCase();
71
+
72
+ this.console.log(`[AutoDetect] Starting device type detection for ${ipAddress}...${forceType ? ` (forcing type: ${forceType})` : ''}`);
69
73
  const { autoDetectDeviceType } = await import("@apocaliss92/reolink-baichuan-js");
74
+ // 'Auto', 'NVR', 'Battery Camera', 'Regular Camera
75
+ const mode: AutoDetectMode = forceType === 'Auto' ? 'auto' :
76
+ forceType === 'Battery Camera' ? 'udp' :
77
+ forceType === 'Regular Camera' ? 'tcp' :
78
+ forceType === 'NVR' ? 'tcp' :
79
+ 'auto';
80
+
81
+ const maxRetries = mode === 'auto' ? 2 : 10;
70
82
 
71
83
  const detection = await autoDetectDeviceType(
72
84
  {
@@ -75,6 +87,8 @@ class ReolinkNativePlugin extends ScryptedDeviceBase implements DeviceProvider,
75
87
  password,
76
88
  uid,
77
89
  logger: this.console,
90
+ mode,
91
+ maxRetries,
78
92
  },
79
93
  );
80
94
  const { ip, mac } = detection.hostNetworkInfo ?? {}
@@ -235,6 +249,14 @@ class ReolinkNativePlugin extends ScryptedDeviceBase implements DeviceProvider,
235
249
  key: 'uid',
236
250
  title: 'UID',
237
251
  description: 'Reolink UID (optional, required for battery cameras if TCP connection fails)',
252
+ },
253
+ {
254
+ key: 'deviceType',
255
+ title: 'Device Type',
256
+ description: 'Device type detection mode. Use "Auto" for automatic detection, or force a specific type.',
257
+ type: 'string',
258
+ choices: ['Auto', 'NVR', 'Battery Camera', 'Regular Camera'],
259
+ value: 'Auto',
238
260
  }
239
261
  ]
240
262
  }
package/src/utils.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DeviceCapabilities, EnrichedRecordingFile, NativeVideoStreamVariant, ParsedRecordingFileName, RecordingFile, ReolinkBaichuanApi, ReolinkDeviceInfo, VodFile, VodSearchResponse } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
1
+ import type { DeviceCapabilities, EnrichedRecordingFile, NativeVideoStreamVariant, ParsedRecordingFileName, RecordingFile, ReolinkBaichuanApi, ReolinkDeviceInfo, ReolinkSupportedStream, VodFile, VodSearchResponse } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
2
2
  import sdk, { DeviceBase, HttpRequest, HttpResponse, MediaObject, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, VideoClip, VideoClips } from "@scrypted/sdk";
3
3
  import { spawn } from "node:child_process";
4
4
  import { Readable } from "stream";
@@ -1071,4 +1071,6 @@ export async function vodSearchResultsToVideoClips(
1071
1071
  }
1072
1072
 
1073
1073
  return clips;
1074
- }
1074
+ }
1075
+
1076
+ export const removeAuthUrls = (streams: ReolinkSupportedStream[]) => streams.map(({ urlWithAuth, ...rest }) => ({ rest }));