@apocaliss92/scrypted-reolink-native 0.5.5 → 0.5.7
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/.vscode/settings.json +1 -1
- package/dist/main.nodejs.js +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +3 -2
- package/prepublish-patch.sh +28 -0
- package/src/accessories/siren.ts +1 -4
- package/src/camera.ts +31 -81
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.
|
|
3
|
+
"version": "0.5.7",
|
|
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",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"scrypted-setup-project": "scrypted-setup-project",
|
|
14
14
|
"prescrypted-setup-project": "scrypted-package-json",
|
|
15
15
|
"build": "scrypted-webpack",
|
|
16
|
-
"
|
|
16
|
+
"prepublish-patch": "./prepublish-patch.sh",
|
|
17
|
+
"prepublishOnly": "./prepublish-patch.sh && NODE_ENV=production scrypted-webpack",
|
|
17
18
|
"prescrypted-vscode-launch": "scrypted-webpack",
|
|
18
19
|
"scrypted-vscode-launch": "scrypted-deploy-debug",
|
|
19
20
|
"scrypted-deploy-debug": "scrypted-deploy-debug",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Prepublish: build linked library, reinstall, bump plugin patch version.
|
|
4
|
+
# Runs automatically before npm publish via prepublishOnly.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
|
+
LIB_DIR="${SCRIPT_DIR}/../reolink-baichuan-js"
|
|
11
|
+
|
|
12
|
+
# ── Step 1: Build the library ───────────────────────────────────
|
|
13
|
+
echo "Building reolink-baichuan-js..."
|
|
14
|
+
cd "${LIB_DIR}"
|
|
15
|
+
npm run build
|
|
16
|
+
echo "Library built."
|
|
17
|
+
|
|
18
|
+
# ── Step 2: Reinstall in plugin (picks up fresh dist/) ──────────
|
|
19
|
+
echo "Installing dependencies..."
|
|
20
|
+
cd "${SCRIPT_DIR}"
|
|
21
|
+
npm install
|
|
22
|
+
echo "Dependencies installed."
|
|
23
|
+
|
|
24
|
+
# ── Step 3: Bump plugin patch version ───────────────────────────
|
|
25
|
+
echo "Bumping plugin patch version..."
|
|
26
|
+
npm version patch --no-git-tag-version
|
|
27
|
+
NEW_VERSION=$(node -p "require('./package.json').version")
|
|
28
|
+
echo "Plugin version: ${NEW_VERSION}"
|
package/src/accessories/siren.ts
CHANGED
|
@@ -26,8 +26,6 @@ export class ReolinkCameraSiren extends ScryptedDeviceBase implements OnOff {
|
|
|
26
26
|
await this.camera.withBaichuanRetry(async () => {
|
|
27
27
|
const api = await this.camera.ensureClient();
|
|
28
28
|
await api.setSiren(channel, false);
|
|
29
|
-
const sirenState = await api.getSiren(channel);
|
|
30
|
-
this.on = sirenState.enabled;
|
|
31
29
|
});
|
|
32
30
|
this.logger.log(`Siren toggle: turnOff ok (device=${this.nativeId})`);
|
|
33
31
|
} catch (e: any) {
|
|
@@ -48,11 +46,10 @@ export class ReolinkCameraSiren extends ScryptedDeviceBase implements OnOff {
|
|
|
48
46
|
await this.camera.withBaichuanRetry(async () => {
|
|
49
47
|
const api = await this.camera.ensureClient();
|
|
50
48
|
await api.setSiren(channel, true);
|
|
51
|
-
const sirenState = await api.getSiren(channel);
|
|
52
|
-
this.on = sirenState.enabled;
|
|
53
49
|
});
|
|
54
50
|
this.logger.log(`Siren toggle: turnOn ok (device=${this.nativeId})`);
|
|
55
51
|
} catch (e: any) {
|
|
52
|
+
this.on = false;
|
|
56
53
|
this.logger.error(
|
|
57
54
|
`Siren toggle: turnOn failed (device=${this.nativeId})`,
|
|
58
55
|
e?.message || String(e),
|
package/src/camera.ts
CHANGED
|
@@ -1989,6 +1989,14 @@ export class ReolinkCamera
|
|
|
1989
1989
|
});
|
|
1990
1990
|
return;
|
|
1991
1991
|
|
|
1992
|
+
case "battery":
|
|
1993
|
+
if (ev.battery) {
|
|
1994
|
+
this.updateBatteryInfo(ev.battery as any).catch((e) => {
|
|
1995
|
+
logger.debug("Error updating battery from push", e?.message || String(e));
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
return;
|
|
1999
|
+
|
|
1992
2000
|
case "offline":
|
|
1993
2001
|
case "online":
|
|
1994
2002
|
this.updateOnlineState(ev.type === "online").catch((e) => {
|
|
@@ -2787,19 +2795,10 @@ export class ReolinkCamera
|
|
|
2787
2795
|
}
|
|
2788
2796
|
}
|
|
2789
2797
|
|
|
2790
|
-
//
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
} else {
|
|
2795
|
-
try {
|
|
2796
|
-
const sirenState = await api.getSiren(channel);
|
|
2797
|
-
this.siren.on = sirenState.enabled;
|
|
2798
|
-
} catch (e) {
|
|
2799
|
-
logger.warn("Failed to align siren state", e?.message || String(e));
|
|
2800
|
-
}
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2798
|
+
// Siren direct control: state is managed manually by turnOn/turnOff.
|
|
2799
|
+
// The camera reports siren as "off" immediately after triggering (fire-and-forget),
|
|
2800
|
+
// so polling would always reset the switch to OFF. We skip alignment entirely
|
|
2801
|
+
// and let the user control the switch: ON triggers the siren, OFF stops it.
|
|
2803
2802
|
|
|
2804
2803
|
// Align motion-floodlight state
|
|
2805
2804
|
if (hasFloodlight && this.motionFloodlight) {
|
|
@@ -3288,7 +3287,6 @@ export class ReolinkCamera
|
|
|
3288
3287
|
);
|
|
3289
3288
|
}
|
|
3290
3289
|
|
|
3291
|
-
logger.log(`Refreshed device capabilities`);
|
|
3292
3290
|
logger.log(
|
|
3293
3291
|
`Refreshed device capabilities: ${JSON.stringify({ capabilities, abilities, support, presets, objects })}`,
|
|
3294
3292
|
);
|
|
@@ -3539,6 +3537,7 @@ export class ReolinkCamera
|
|
|
3539
3537
|
}
|
|
3540
3538
|
|
|
3541
3539
|
if (wasSleeping) {
|
|
3540
|
+
this.updateBatteryInfo().catch(() => {});
|
|
3542
3541
|
this.alignAuxDevicesState().catch(() => {});
|
|
3543
3542
|
if (this.forceNewSnapshot) {
|
|
3544
3543
|
this.takePicture().catch(() => {});
|
|
@@ -3620,42 +3619,26 @@ export class ReolinkCamera
|
|
|
3620
3619
|
if (batteryInfo.batteryPercent !== undefined) {
|
|
3621
3620
|
const oldLevel = this.batteryLevel;
|
|
3622
3621
|
const oldChargeState = this.chargeState;
|
|
3623
|
-
// adapterStatus: "adapter" | "solarPanel"
|
|
3624
|
-
const
|
|
3622
|
+
// adapterStatus: "adapter" | "solarPanel" = charging, "none" = not charging
|
|
3623
|
+
const isCharging =
|
|
3625
3624
|
batteryInfo.adapterStatus === "adapter" ||
|
|
3626
3625
|
batteryInfo.adapterStatus === "solarPanel";
|
|
3627
|
-
const newChargeState =
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
? ChargeState.Charging
|
|
3631
|
-
: ChargeState.NotCharging
|
|
3632
|
-
: undefined;
|
|
3626
|
+
const newChargeState = isCharging
|
|
3627
|
+
? ChargeState.Charging
|
|
3628
|
+
: ChargeState.NotCharging;
|
|
3633
3629
|
|
|
3634
3630
|
this.batteryLevel = batteryInfo.batteryPercent;
|
|
3635
|
-
|
|
3636
|
-
this.chargeState = newChargeState;
|
|
3637
|
-
}
|
|
3631
|
+
this.chargeState = newChargeState;
|
|
3638
3632
|
|
|
3639
3633
|
// Log only if battery level changed
|
|
3640
3634
|
if (oldLevel !== batteryInfo.batteryPercent) {
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
);
|
|
3645
|
-
} else {
|
|
3646
|
-
logger.log(
|
|
3647
|
-
`Battery level changed: ${oldLevel}% → ${batteryInfo.batteryPercent}%`,
|
|
3648
|
-
);
|
|
3649
|
-
}
|
|
3635
|
+
logger.log(
|
|
3636
|
+
`Battery level changed: ${oldLevel}% → ${batteryInfo.batteryPercent}% (charging: ${isCharging}, adapter: ${batteryInfo.adapterStatus ?? "unknown"}, status: ${batteryInfo.chargeStatus ?? "unknown"})`,
|
|
3637
|
+
);
|
|
3650
3638
|
} else if (oldLevel === undefined) {
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
`Battery level set: ${batteryInfo.batteryPercent}% (sotto carica: ${isSottoCarica}, adapterStatus: ${batteryInfo.adapterStatus})`,
|
|
3655
|
-
);
|
|
3656
|
-
} else {
|
|
3657
|
-
logger.log(`Battery level set: ${batteryInfo.batteryPercent}%`);
|
|
3658
|
-
}
|
|
3639
|
+
logger.log(
|
|
3640
|
+
`Battery level set: ${batteryInfo.batteryPercent}% (charging: ${isCharging}, adapter: ${batteryInfo.adapterStatus ?? "unknown"})`,
|
|
3641
|
+
);
|
|
3659
3642
|
}
|
|
3660
3643
|
|
|
3661
3644
|
// Forward battery/charge state changes to Scrypted (plugin, HomeKit, etc.)
|
|
@@ -3703,49 +3686,16 @@ export class ReolinkCamera
|
|
|
3703
3686
|
return;
|
|
3704
3687
|
}
|
|
3705
3688
|
|
|
3706
|
-
// Check current sleep status
|
|
3707
|
-
|
|
3689
|
+
// Check current sleep status — only update if already awake
|
|
3690
|
+
const sleepStatus = api.getSleepStatus({ channel });
|
|
3708
3691
|
|
|
3709
|
-
// If camera is sleeping, wake it up
|
|
3710
3692
|
if (sleepStatus.state === "sleeping") {
|
|
3711
|
-
logger.
|
|
3712
|
-
|
|
3713
|
-
await api.wakeUp(channel, { waitAfterWakeMs: 2000 });
|
|
3714
|
-
logger.log("Wake command sent, waiting for camera to wake up...");
|
|
3715
|
-
} catch (wakeError) {
|
|
3716
|
-
logger.error(
|
|
3717
|
-
"Failed to wake up camera:",
|
|
3718
|
-
wakeError?.message || String(wakeError),
|
|
3719
|
-
);
|
|
3720
|
-
return;
|
|
3721
|
-
}
|
|
3722
|
-
|
|
3723
|
-
// Poll until camera is awake (with timeout)
|
|
3724
|
-
const wakeTimeoutMs = 30000; // 30 seconds max
|
|
3725
|
-
const startWakePoll = Date.now();
|
|
3726
|
-
let awake = false;
|
|
3727
|
-
|
|
3728
|
-
while (Date.now() - startWakePoll < wakeTimeoutMs) {
|
|
3729
|
-
await new Promise((resolve) => setTimeout(resolve, 1000)); // Check every second
|
|
3730
|
-
sleepStatus = api.getSleepStatus({ channel });
|
|
3731
|
-
if (sleepStatus.state === "awake") {
|
|
3732
|
-
awake = true;
|
|
3733
|
-
logger.log("Camera is now awake");
|
|
3734
|
-
this.sleeping = false;
|
|
3735
|
-
break;
|
|
3736
|
-
}
|
|
3737
|
-
}
|
|
3738
|
-
|
|
3739
|
-
if (!awake) {
|
|
3740
|
-
logger.error(
|
|
3741
|
-
"Camera did not wake up within timeout, skipping update",
|
|
3742
|
-
);
|
|
3743
|
-
return;
|
|
3744
|
-
}
|
|
3745
|
-
} else if (sleepStatus.state === "awake") {
|
|
3746
|
-
this.sleeping = false;
|
|
3693
|
+
logger.debug("Camera is sleeping, skipping periodic battery update");
|
|
3694
|
+
return;
|
|
3747
3695
|
}
|
|
3748
3696
|
|
|
3697
|
+
this.sleeping = false;
|
|
3698
|
+
|
|
3749
3699
|
// Now that camera is awake, update all states
|
|
3750
3700
|
// 1. Update battery info
|
|
3751
3701
|
try {
|