@apocaliss92/scrypted-reolink-native 0.5.14 → 0.5.19
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/.claude/agent-memory/baichuan-reolink-engineer/MEMORY.md +4 -0
- package/.claude/agent-memory/baichuan-reolink-engineer/baichuan_talk_sequence.md +62 -0
- package/.claude/agent-memory/baichuan-reolink-engineer/camstack_probe_gated_cap_registration.md +38 -0
- package/dist/main.nodejs.js +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +3 -3
- package/src/camera.ts +48 -6
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.19",
|
|
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",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
]
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"@apocaliss92/nodelink-js": "^0.4.26",
|
|
47
48
|
"@scrypted/common": "file:../../scrypted/common",
|
|
48
49
|
"@scrypted/rtsp": "file:../../scrypted/plugins/rtsp",
|
|
49
|
-
"@scrypted/sdk": "^0.3.118"
|
|
50
|
-
"@apocaliss92/nodelink-js": "0.4.19"
|
|
50
|
+
"@scrypted/sdk": "^0.3.118"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "^22.0.2"
|
package/src/camera.ts
CHANGED
|
@@ -2795,10 +2795,38 @@ export class ReolinkCamera
|
|
|
2795
2795
|
}
|
|
2796
2796
|
}
|
|
2797
2797
|
|
|
2798
|
-
//
|
|
2799
|
-
// The
|
|
2800
|
-
// so
|
|
2801
|
-
//
|
|
2798
|
+
// Align siren direct-control state.
|
|
2799
|
+
// The siren has a built-in playback duration enforced by the camera firmware,
|
|
2800
|
+
// so once the audio finishes the device flips back to OFF on its own. Rely
|
|
2801
|
+
// on the cmd 547 (SirenStatusList) push to catch that transition; fall back
|
|
2802
|
+
// to an active getSirenStatus() request when no push has arrived yet so the
|
|
2803
|
+
// switch matches the device state after a plugin restart.
|
|
2804
|
+
if (hasSiren && this.siren) {
|
|
2805
|
+
if (isInCooldown(this.auxDeviceCooldowns.siren)) {
|
|
2806
|
+
logger.log(`[alignAuxDevicesState] Skipping siren (in cooldown)`);
|
|
2807
|
+
} else {
|
|
2808
|
+
try {
|
|
2809
|
+
const cached = api.getCachedSirenStatus(channel);
|
|
2810
|
+
if (cached) {
|
|
2811
|
+
this.siren.on =
|
|
2812
|
+
cached.value.status || cached.value.playing === true;
|
|
2813
|
+
} else {
|
|
2814
|
+
const status = await api.getSirenStatus({ timeoutMs: 2000 });
|
|
2815
|
+
const list = status?.body?.SirenStatusList;
|
|
2816
|
+
const playing =
|
|
2817
|
+
typeof list?.playing === "number" ? list.playing === 1 : false;
|
|
2818
|
+
const enabled =
|
|
2819
|
+
typeof list?.status === "number" ? list.status === 1 : false;
|
|
2820
|
+
this.siren.on = enabled || playing;
|
|
2821
|
+
}
|
|
2822
|
+
} catch (e) {
|
|
2823
|
+
logger.warn(
|
|
2824
|
+
"Failed to align siren state",
|
|
2825
|
+
e?.message || String(e),
|
|
2826
|
+
);
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2802
2830
|
|
|
2803
2831
|
// Align motion-floodlight state
|
|
2804
2832
|
if (hasFloodlight && this.motionFloodlight) {
|
|
@@ -2822,14 +2850,28 @@ export class ReolinkCamera
|
|
|
2822
2850
|
}
|
|
2823
2851
|
}
|
|
2824
2852
|
|
|
2825
|
-
// Align floodlight state (direct control)
|
|
2853
|
+
// Align floodlight state (direct control).
|
|
2854
|
+
// The camera's cmd 289 returns FloodlightTask (the scheduled task config) and
|
|
2855
|
+
// does NOT reflect the current manual ON/OFF — `<enable>` there is the task
|
|
2856
|
+
// enable, which is 0 for any camera without a configured schedule. The only
|
|
2857
|
+
// reliable source for the actual current state is the cmd 291 push
|
|
2858
|
+
// (FloodlightStatusList) that the firmware emits on every transition,
|
|
2859
|
+
// including the auto-off after the FloodlightManual duration expires.
|
|
2860
|
+
//
|
|
2861
|
+
// Brightness is still safe to read from cmd 289 because <brightness_cur> is
|
|
2862
|
+
// the persisted brightness setting and matches what the camera will apply
|
|
2863
|
+
// on next turnOn.
|
|
2826
2864
|
if (hasFloodlight && this.floodlight) {
|
|
2827
2865
|
if (isInCooldown(this.auxDeviceCooldowns.floodlight)) {
|
|
2828
2866
|
logger.log(`[alignAuxDevicesState] Skipping floodlight (in cooldown)`);
|
|
2829
2867
|
} else {
|
|
2830
2868
|
try {
|
|
2869
|
+
const cached = api.getCachedFloodlightStatus(channel);
|
|
2870
|
+
if (cached) {
|
|
2871
|
+
this.floodlight.on = cached.value.status;
|
|
2872
|
+
}
|
|
2873
|
+
// Brightness is still meaningful from the task config.
|
|
2831
2874
|
const ledState = await api.getWhiteLedState(channel);
|
|
2832
|
-
this.floodlight.on = ledState.enabled;
|
|
2833
2875
|
if (ledState.brightness !== undefined) {
|
|
2834
2876
|
this.floodlight.brightness = ledState.brightness;
|
|
2835
2877
|
}
|