@apocaliss92/scrypted-reolink-native 0.1.12 → 0.1.13

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.1.12",
3
+ "version": "0.1.13",
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
@@ -1,4 +1,4 @@
1
- import type { DebugOptions, ReolinkBaichuanApi } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
1
+ import type { ReolinkBaichuanApi } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
2
2
  import sdk, { MediaObject, ObjectsDetected, RequestPictureOptions, ResponsePictureOptions, ScryptedInterface, Setting } from "@scrypted/sdk";
3
3
  import { UrlMediaStreamOptions } from "../../scrypted/plugins/rtsp/src/rtsp";
4
4
  import {
@@ -6,10 +6,6 @@ import {
6
6
  } from "./common";
7
7
  import { createBaichuanApi } from './connect';
8
8
  import ReolinkNativePlugin from "./main";
9
- import {
10
- buildVideoStreamOptionsFromRtspRtmp,
11
- fetchVideoStreamOptionsFromApi
12
- } from './stream-utils';
13
9
 
14
10
  export const moToB64 = async (mo: MediaObject) => {
15
11
  const bufferImage = await sdk.mediaManager.convertMediaObjectToBuffer(mo, 'image/jpeg');
package/src/common.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DeviceCapabilities, PtzCommand, PtzPreset, ReolinkBaichuanApi, ReolinkSimpleEvent } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
1
+ import type { DeviceCapabilities, PtzCommand, PtzPreset, ReolinkBaichuanApi, ReolinkSimpleEvent, StreamSamplingSelection } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
2
2
  import sdk, { BinarySensor, Brightness, Camera, Device, DeviceProvider, Intercom, MediaObject, MediaStreamUrl, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, OnOff, PanTiltZoom, PanTiltZoomCommand, RequestMediaStreamOptions, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, Settings, SettingValue, VideoCamera, VideoTextOverlay, VideoTextOverlays } from "@scrypted/sdk";
3
3
  import { StorageSettings } from "@scrypted/sdk/storage-settings";
4
4
  import type { UrlMediaStreamOptions } from "../../scrypted/plugins/rtsp/src/rtsp";
@@ -10,7 +10,7 @@ import ReolinkNativePlugin from "./main";
10
10
  import { ReolinkNativeNvrDevice } from "./nvr";
11
11
  import { ReolinkPtzPresets } from "./presets";
12
12
  import {
13
- buildVideoStreamOptionsFromRtspRtmp,
13
+ buildVideoStreamOptions,
14
14
  createRfc4571MediaObjectFromStreamManager,
15
15
  expectedVideoTypeFromUrlMediaStreamOptions,
16
16
  isNativeStreamId,
@@ -19,6 +19,7 @@ import {
19
19
  StreamManager
20
20
  } from "./stream-utils";
21
21
  import { getDeviceInterfaces, updateDeviceInfo } from "./utils";
22
+ import path from 'path';
22
23
 
23
24
  export type CameraType = 'battery' | 'regular';
24
25
 
@@ -238,38 +239,6 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
238
239
  type: 'boolean',
239
240
  hide: true,
240
241
  },
241
- // snapshotCacheMinutes: {
242
- // title: "Snapshot Cache Minutes",
243
- // subgroup: 'Advanced',
244
- // description: "Return a cached snapshot if taken within the last N minutes.",
245
- // type: "number",
246
- // defaultValue: 60,
247
- // hide: true,
248
- // },
249
- batteryUpdateIntervalMinutes: {
250
- title: "Battery Update Interval (minutes)",
251
- subgroup: 'Advanced',
252
- description: "How often to wake up the camera and update battery status and snapshot (default: 60 minutes).",
253
- type: "number",
254
- defaultValue: 60,
255
- hide: true,
256
- },
257
- lowThresholdBatteryRecording: {
258
- title: "Low Threshold Battery Recording (%)",
259
- subgroup: 'Recording',
260
- description: "Battery level threshold below which recording is disabled (default: 15%).",
261
- type: "number",
262
- defaultValue: 15,
263
- hide: true,
264
- },
265
- highThresholdBatteryRecording: {
266
- title: "High Threshold Battery Recording (%)",
267
- subgroup: 'Recording',
268
- description: "Battery level threshold above which recording is enabled (default: 35%).",
269
- type: "number",
270
- defaultValue: 35,
271
- hide: true,
272
- },
273
242
  // Regular camera specific
274
243
  dispatchEvents: {
275
244
  subgroup: 'Advanced',
@@ -479,6 +448,47 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
479
448
  logger.log(`PTZ presets: delete ok (presetId=${presetId})`);
480
449
  },
481
450
  },
451
+ batteryUpdateIntervalMinutes: {
452
+ title: "Battery Update Interval (minutes)",
453
+ subgroup: 'Advanced',
454
+ description: "How often to wake up the camera and update battery status and snapshot (default: 60 minutes).",
455
+ type: "number",
456
+ defaultValue: 60,
457
+ hide: true,
458
+ },
459
+ lowThresholdBatteryRecording: {
460
+ title: "Low Threshold Battery Recording (%)",
461
+ subgroup: 'Recording',
462
+ description: "Battery level threshold below which recording is disabled (default: 15%).",
463
+ type: "number",
464
+ defaultValue: 15,
465
+ hide: true,
466
+ },
467
+ highThresholdBatteryRecording: {
468
+ title: "High Threshold Battery Recording (%)",
469
+ subgroup: 'Recording',
470
+ description: "Battery level threshold above which recording is enabled (default: 35%).",
471
+ type: "number",
472
+ defaultValue: 35,
473
+ hide: true,
474
+ },
475
+ diagnosticsOutputPath: {
476
+ title: "Diagnostics Output Path",
477
+ subgroup: 'Diagnostics',
478
+ description: "Directory where diagnostics files will be saved (default: plugin volume).",
479
+ type: "string",
480
+ defaultValue: path.join(process.env.SCRYPTED_PLUGIN_VOLUME, 'diagnostics', this.name),
481
+ },
482
+ diagnosticsRun: {
483
+ subgroup: 'Diagnostics',
484
+ title: 'Run Diagnostics',
485
+ description: 'Run all diagnostics and save results to the output path.',
486
+ type: 'button',
487
+ immediate: true,
488
+ onPut: async () => {
489
+ await this.runDiagnostics();
490
+ },
491
+ },
482
492
  });
483
493
 
484
494
  ptzPresets = new ReolinkPtzPresets(this);
@@ -571,6 +581,42 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
571
581
  return this.name || 'Camera';
572
582
  }
573
583
 
584
+ private async runDiagnostics(): Promise<void> {
585
+ const logger = this.getBaichuanLogger();
586
+ const outputPath = this.storageSettings.values.diagnosticsOutputPath || process.env.SCRYPTED_PLUGIN_VOLUME || "";
587
+
588
+ if (!outputPath) {
589
+ throw new Error('Diagnostics output path is required');
590
+ }
591
+
592
+ const channel = this.storageSettings.values.rtspChannel || 0;
593
+ const durationSeconds = 15;
594
+ const selection: StreamSamplingSelection = {
595
+ kinds: ['native'],
596
+ profiles: ['main', 'ext', 'sub'],
597
+ };
598
+
599
+ logger.log(`Starting diagnostics with parameters: outDir=${outputPath}, channel=${channel}, durationSeconds=${durationSeconds}, selection=${JSON.stringify(selection)}`);
600
+
601
+ try {
602
+ const api = await this.ensureClient();
603
+
604
+ const result = await api.runAllDiagnosticsConsecutively({
605
+ outDir: outputPath,
606
+ channel,
607
+ durationSeconds,
608
+ selection,
609
+ });
610
+
611
+ logger.log(`Diagnostics completed successfully. Output directory: ${result.runDir}`);
612
+ logger.log(`Diagnostics file: ${result.diagnosticsPath}`);
613
+ logger.log(`Streams directory: ${result.streamsDir}`);
614
+ } catch (e) {
615
+ logger.error('Failed to run diagnostics', e);
616
+ throw e;
617
+ }
618
+ }
619
+
574
620
  protected async onBeforeCleanup(): Promise<void> {
575
621
  // Unsubscribe from events if needed
576
622
  if (this.onSimpleEvent && this.baichuanApi) {
@@ -1278,7 +1324,7 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
1278
1324
 
1279
1325
  const client = await this.ensureClient();
1280
1326
 
1281
- const { ipAddress, rtspChannel, isFromNvr } = this.storageSettings.values;
1327
+ const { ipAddress, rtspChannel } = this.storageSettings.values;
1282
1328
 
1283
1329
  try {
1284
1330
  await this.ensureNetPortCache();
@@ -1289,7 +1335,7 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
1289
1335
  }
1290
1336
 
1291
1337
  try {
1292
- streams = await buildVideoStreamOptionsFromRtspRtmp(
1338
+ streams = await buildVideoStreamOptions(
1293
1339
  {
1294
1340
  client,
1295
1341
  ipAddress,
@@ -1,7 +1,7 @@
1
1
  import type {
2
2
  ReolinkBaichuanApi,
3
- StreamProfile,
4
3
  ScryptedRfc4571TcpServer,
4
+ StreamProfile,
5
5
  VideoType,
6
6
  } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
7
7
 
@@ -97,7 +97,7 @@ export async function fetchVideoStreamOptionsFromApi(
97
97
  return streams;
98
98
  }
99
99
 
100
- export async function buildVideoStreamOptionsFromRtspRtmp(
100
+ export async function buildVideoStreamOptions(
101
101
  props: {
102
102
  client: ReolinkBaichuanApi,
103
103
  ipAddress: string,