@apocaliss92/scrypted-reolink-native 0.1.11 → 0.1.12

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.11",
3
+ "version": "0.1.12",
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",
@@ -180,6 +180,26 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
180
180
  }
181
181
  }
182
182
 
183
+ async checkRecordingAction(newBatteryLevel: number) {
184
+ const nvrDeviceId = this.plugin.nvrDeviceId;
185
+ if (nvrDeviceId && this.mixins.includes(nvrDeviceId)) {
186
+ const logger = this.getBaichuanLogger();
187
+
188
+ const settings = await this.thisDevice.getSettings();
189
+ const isRecording = !settings.find(setting => setting.key === 'recording:privacyMode')?.value;
190
+ const { lowThresholdBatteryRecording, highThresholdBatteryRecording } = this.storageSettings.values;
191
+
192
+ if (isRecording && newBatteryLevel < lowThresholdBatteryRecording) {
193
+ logger.log(`Recording is enabled, but battery level is below low threshold (${newBatteryLevel}% < ${lowThresholdBatteryRecording}%), disabling recording`);
194
+ await this.thisDevice.putSetting('recording:privacyMode', true);
195
+ } else if (!isRecording && newBatteryLevel > highThresholdBatteryRecording) {
196
+ logger.log(`Recording is disabled, but battery level is above high threshold (${newBatteryLevel}% > ${highThresholdBatteryRecording}%), enabling recording`);
197
+ await this.thisDevice.putSetting('recording:privacyMode', false);
198
+ }
199
+
200
+ }
201
+ }
202
+
183
203
  async updateBatteryInfo() {
184
204
  const api = await this.ensureClient();
185
205
  const channel = this.storageSettings.values.rtspChannel;
@@ -194,6 +214,8 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
194
214
  this.batteryLevel = batteryInfo.batteryPercent;
195
215
  this.lastBatteryLevel = batteryInfo.batteryPercent;
196
216
 
217
+ let shouldCheckRecordingAction = true;
218
+
197
219
  // Log only if battery level changed
198
220
  if (oldLevel !== undefined && oldLevel !== batteryInfo.batteryPercent) {
199
221
  if (batteryInfo.chargeStatus !== undefined) {
@@ -211,6 +233,12 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
211
233
  } else {
212
234
  this.getBaichuanLogger().log(`Battery level set: ${batteryInfo.batteryPercent}%`);
213
235
  }
236
+ } else {
237
+ shouldCheckRecordingAction = false;
238
+ }
239
+
240
+ if (shouldCheckRecordingAction) {
241
+ await this.checkRecordingAction(batteryInfo.batteryPercent);
214
242
  }
215
243
  }
216
244
  }
package/src/common.ts CHANGED
@@ -2,8 +2,8 @@ import type { DeviceCapabilities, PtzCommand, PtzPreset, ReolinkBaichuanApi, Reo
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";
5
- import { BaseBaichuanClass, type BaichuanConnectionConfig, type BaichuanConnectionCallbacks } from "./baichuan-base";
6
- import { createBaichuanApi, normalizeUid, type BaichuanTransport } from "./connect";
5
+ import { BaseBaichuanClass, type BaichuanConnectionCallbacks, type BaichuanConnectionConfig } from "./baichuan-base";
6
+ import { normalizeUid, type BaichuanTransport } from "./connect";
7
7
  import { convertDebugLogsToApiOptions, DebugLogDisplayNames, DebugLogOption, getApiRelevantDebugLogs, getDebugLogChoices } from "./debug-options";
8
8
  import { ReolinkBaichuanIntercom } from "./intercom";
9
9
  import ReolinkNativePlugin from "./main";
@@ -254,6 +254,22 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
254
254
  defaultValue: 60,
255
255
  hide: true,
256
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
+ },
257
273
  // Regular camera specific
258
274
  dispatchEvents: {
259
275
  subgroup: 'Advanced',
@@ -330,7 +346,7 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
330
346
  },
331
347
  // PTZ Presets
332
348
  presets: {
333
- group: 'PTZ',
349
+ subgroup: 'PTZ',
334
350
  title: 'Presets to enable',
335
351
  description: 'PTZ Presets in the format "id=name". Where id is the PTZ Preset identifier and name is a friendly name.',
336
352
  multiple: true,
@@ -358,11 +374,11 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
358
374
  description: 'How long a PTZ command moves before sending stop. Higher = more movement per click.',
359
375
  type: 'number',
360
376
  defaultValue: 300,
361
- group: 'PTZ',
377
+ subgroup: 'PTZ',
362
378
  hide: true,
363
379
  },
364
380
  ptzZoomStep: {
365
- group: 'PTZ',
381
+ subgroup: 'PTZ',
366
382
  title: 'PTZ Zoom Step',
367
383
  description: 'How much to change zoom per zoom command (in zoom factor units, where 1.0 is normal).',
368
384
  type: 'number',
@@ -370,7 +386,7 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
370
386
  hide: true,
371
387
  },
372
388
  ptzCreatePreset: {
373
- group: 'PTZ',
389
+ subgroup: 'PTZ',
374
390
  title: 'Create Preset',
375
391
  description: 'Enter a name and press Save to create a new PTZ preset at the current position.',
376
392
  type: 'string',
@@ -407,7 +423,7 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
407
423
  },
408
424
  },
409
425
  ptzSelectedPreset: {
410
- group: 'PTZ',
426
+ subgroup: 'PTZ',
411
427
  title: 'Selected Preset',
412
428
  description: 'Select the preset to update or delete. Format: "id=name".',
413
429
  type: 'string',
@@ -416,7 +432,7 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
416
432
  hide: true,
417
433
  },
418
434
  ptzUpdateSelectedPreset: {
419
- group: 'PTZ',
435
+ subgroup: 'PTZ',
420
436
  title: 'Update Selected Preset Position',
421
437
  description: 'Overwrite the selected preset with the current PTZ position.',
422
438
  type: 'button',
@@ -439,7 +455,7 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
439
455
  },
440
456
  },
441
457
  ptzDeleteSelectedPreset: {
442
- group: 'PTZ',
458
+ subgroup: 'PTZ',
443
459
  title: 'Delete Selected Preset',
444
460
  description: 'Delete the selected preset (firmware dependent).',
445
461
  type: 'button',
@@ -497,15 +513,16 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
497
513
  initComplete?: boolean;
498
514
  resetBaichuanClient?(reason?: any): Promise<void>;
499
515
 
500
- protected nvrDevice?: any; // Optional reference to NVR device
516
+ protected nvrDevice?: ReolinkNativeNvrDevice;
517
+ thisDevice: Settings
501
518
 
502
519
  constructor(nativeId: string, public plugin: ReolinkNativePlugin, public options: CommonCameraMixinOptions) {
503
520
  super(nativeId);
504
- // Set protocol based on camera type
505
521
  this.protocol = !options.nvrDevice && options.type === 'battery' ? 'udp' : 'tcp';
506
522
 
507
523
  // Store NVR device reference if provided
508
524
  this.nvrDevice = options.nvrDevice;
525
+ this.thisDevice = sdk.systemManager.getDeviceById<Settings>(this.id);
509
526
 
510
527
  setTimeout(async () => {
511
528
  await this.parentInit();
@@ -1501,6 +1518,8 @@ export abstract class CommonCameraMixin extends BaseBaichuanClass implements Vid
1501
1518
  // this.storageSettings.settings.snapshotCacheMinutes.hide = !isBattery;
1502
1519
  this.storageSettings.settings.uid.hide = !isBattery;
1503
1520
  this.storageSettings.settings.batteryUpdateIntervalMinutes.hide = !isBattery;
1521
+ this.storageSettings.settings.lowThresholdBatteryRecording.hide = !isBattery;
1522
+ this.storageSettings.settings.highThresholdBatteryRecording.hide = !isBattery;
1504
1523
 
1505
1524
  if (isBattery && !this.storageSettings.values.mixinsSetup) {
1506
1525
  try {
package/src/main.ts CHANGED
@@ -7,6 +7,14 @@ import { getDeviceInterfaces } from "./utils";
7
7
 
8
8
  class ReolinkNativePlugin extends ScryptedDeviceBase implements DeviceProvider, DeviceCreator {
9
9
  devices = new Map<string, ReolinkNativeCamera | ReolinkNativeBatteryCamera | ReolinkNativeNvrDevice>();
10
+ nvrDeviceId: string;
11
+
12
+ constructor(nativeId: string) {
13
+ super(nativeId);
14
+
15
+ const nvrDevice = sdk.systemManager.getDeviceByName('Scrypted NVR');
16
+ this.nvrDeviceId = nvrDevice?.id;
17
+ }
10
18
 
11
19
  getScryptedDeviceCreator(): string {
12
20
  return 'Reolink Native camera';