@apocaliss92/scrypted-reolink-native 0.5.30 → 0.5.32

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.5.30",
3
+ "version": "0.5.32",
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",
@@ -766,6 +766,20 @@ export abstract class BaseBaichuanClass extends ScryptedDeviceBase {
766
766
  return;
767
767
  }
768
768
 
769
+ // Battery cameras on UDP transport spend most of their lifetime
770
+ // asleep — event silence is the *normal* operating mode, not a
771
+ // failure. Running `unsubscribeFromEvents + subscribeToEvents`
772
+ // here wakes the device every 10 minutes for no real benefit
773
+ // (the cam emits its own sleep/awake push when it wakes for
774
+ // motion, and the lib's own watchdog has the same UDP-skip
775
+ // guard for the same reason).
776
+ if (this.isBatteryDevice()) {
777
+ logger.debug?.(
778
+ "Event check: skipping silence-based restart for battery camera (UDP sleep is normal)",
779
+ );
780
+ return;
781
+ }
782
+
769
783
  try {
770
784
  const now = Date.now();
771
785
  const timeSinceLastEvent = now - this.lastEventTime;
package/src/camera.ts CHANGED
@@ -2838,6 +2838,17 @@ export class ReolinkCamera
2838
2838
  * `takePicture()` on the back of the motion get the trigger frame
2839
2839
  * instead of the previous cached one. Fire-and-forget; per-camera
2840
2840
  * debounce so an event burst doesn't trigger overlapping fetches.
2841
+ *
2842
+ * Critical for Reolink battery cams: must call `client.wakeUp()`
2843
+ * before fetching the snapshot. Reolink firmwares can put the cam
2844
+ * back to sleep within a few seconds of the email/motion push, so
2845
+ * by the time `getSnapshot` (cmd 109) hits the device it may
2846
+ * already be unreachable — the snapshot push response never
2847
+ * arrives, the lib times out, and the cmdId=109 hang knocks the
2848
+ * UDP session into the reconnect path which itself wakes the cam.
2849
+ * `wakeUp` explicitly tells the cam to stay awake long enough to
2850
+ * service the snapshot — same pattern as the regular `takePicture`
2851
+ * battery path (see line ~2945).
2841
2852
  */
2842
2853
  private lastMotionSnapshotAtMs = 0;
2843
2854
  private motionSnapshotInFlight = false;
@@ -2849,6 +2860,13 @@ export class ReolinkCamera
2849
2860
  const logger = this.getBaichuanLogger();
2850
2861
  try {
2851
2862
  const client = await this.ensureClient();
2863
+ if (this.isBattery) {
2864
+ // Keep the cam awake for the snapshot fetch — without this the
2865
+ // cmdId=109 (snapshot push) frequently times out on battery
2866
+ // cams and we end up triggering a full socket reconnect which
2867
+ // ironically wakes the cam more than the original snapshot.
2868
+ await client.wakeUp();
2869
+ }
2852
2870
  const mo = await this.takePictureInternal(client);
2853
2871
  this.lastPicture = { mo, atMs: timestampMs };
2854
2872
  this.forceNewSnapshot = false;
@@ -2856,8 +2874,13 @@ export class ReolinkCamera
2856
2874
  `Motion snapshot refreshed — next takePicture will serve the trigger frame`,
2857
2875
  );
2858
2876
  } catch (e) {
2859
- logger.warn(
2860
- `Motion snapshot refresh failed: ${e?.message || String(e)}`,
2877
+ // Demote to debug — for battery cams the cam goes back to sleep
2878
+ // aggressively and a snapshot miss is normal: the motion event
2879
+ // itself was already dispatched on the bus, MQTT/HA will reuse
2880
+ // the previous cached frame, no functional impact. Warn would
2881
+ // pollute the device log on every motion in noisy environments.
2882
+ logger.debug?.(
2883
+ `Motion snapshot refresh failed (cam may have slept already): ${e?.message || String(e)}`,
2861
2884
  );
2862
2885
  } finally {
2863
2886
  this.motionSnapshotInFlight = false;