@apocaliss92/scrypted-reolink-native 0.4.46 → 0.4.48
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/README.md +3 -29
- package/dist/main.nodejs.js +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
- package/src/accessories/chime.ts +39 -41
- package/src/camera.ts +1 -1
- package/src/intercom-provider.ts +9 -1
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/accessories/chime.ts
CHANGED
|
@@ -6,17 +6,18 @@ import {
|
|
|
6
6
|
SettingValue,
|
|
7
7
|
} from "@scrypted/sdk";
|
|
8
8
|
import { StorageSettings } from "@scrypted/sdk/storage-settings";
|
|
9
|
-
import type { ChimeCfg } from "@apocaliss92/reolink-baichuan-js" with { "resolution-mode": "import" };
|
|
10
9
|
import type { ReolinkCamera } from "../camera";
|
|
11
10
|
|
|
11
|
+
const DEFAULT_SILENT_DURATION_MINUTES = 30;
|
|
12
|
+
|
|
12
13
|
/**
|
|
13
14
|
* Chime: enable/disable a paired wireless Reolink Chime receiver.
|
|
14
15
|
*
|
|
15
|
-
* Uses
|
|
16
|
-
*
|
|
16
|
+
* Uses SetDingDongSilent (cmd 610) to silence/unsilence the chime for a
|
|
17
|
+
* configurable duration in minutes.
|
|
17
18
|
*
|
|
18
|
-
* turnOn()
|
|
19
|
-
* turnOff()
|
|
19
|
+
* turnOn() → setDingDongSilent(chimeId, 0) — un-silence the chime.
|
|
20
|
+
* turnOff() → setDingDongSilent(chimeId, seconds) — silence the chime for the configured duration.
|
|
20
21
|
*
|
|
21
22
|
* The chime ID is auto-synced from getDingDongList during alignAuxDevicesState.
|
|
22
23
|
*/
|
|
@@ -36,6 +37,14 @@ export class ReolinkCameraChime
|
|
|
36
37
|
defaultValue: -1,
|
|
37
38
|
readonly: true,
|
|
38
39
|
},
|
|
40
|
+
silentDurationMinutes: {
|
|
41
|
+
title: "Silent Duration (minutes)",
|
|
42
|
+
description:
|
|
43
|
+
"How long the chime stays silent when turned off, in minutes. " +
|
|
44
|
+
"After this time the chime automatically becomes active again.",
|
|
45
|
+
type: "number",
|
|
46
|
+
defaultValue: DEFAULT_SILENT_DURATION_MINUTES,
|
|
47
|
+
},
|
|
39
48
|
});
|
|
40
49
|
|
|
41
50
|
constructor(
|
|
@@ -57,6 +66,12 @@ export class ReolinkCameraChime
|
|
|
57
66
|
return this.storageSettings.values.wirelessChimeId ?? -1;
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
/** Silent duration in seconds derived from the user-facing minutes setting. */
|
|
70
|
+
private get silentDurationSeconds(): number {
|
|
71
|
+
const minutes = this.storageSettings.values.silentDurationMinutes ?? DEFAULT_SILENT_DURATION_MINUTES;
|
|
72
|
+
return Math.max(1, Math.round(minutes)) * 60;
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
/**
|
|
61
76
|
* Refresh chime ID from device when -1.
|
|
62
77
|
* Python lib: GetDingDongList uses deviceId; GetDingDongCfg uses ringId (skips if < 0).
|
|
@@ -82,25 +97,18 @@ export class ReolinkCameraChime
|
|
|
82
97
|
return false;
|
|
83
98
|
}
|
|
84
99
|
|
|
85
|
-
private async getChimeCfg(): Promise<ChimeCfg | undefined> {
|
|
86
|
-
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
87
|
-
const chimeId = this.wirelessChimeId;
|
|
88
|
-
if (chimeId < 0) return undefined;
|
|
89
|
-
const api = await this.camera.ensureClient();
|
|
90
|
-
const configs = await api.getDingDongCfg(channel);
|
|
91
|
-
return configs.find(c => c.id === chimeId);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
100
|
/**
|
|
95
|
-
* Determine if the chime is active by
|
|
101
|
+
* Determine if the chime is active by querying the silent-mode state (cmd 609).
|
|
102
|
+
* active === true means the chime is NOT silenced (on).
|
|
96
103
|
*/
|
|
97
104
|
async syncStateFromDevice(): Promise<boolean | undefined> {
|
|
98
105
|
await this.ensureChimeId();
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
const chimeId = this.wirelessChimeId;
|
|
107
|
+
if (chimeId < 0) return undefined;
|
|
108
|
+
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
109
|
+
const api = await this.camera.ensureClient();
|
|
110
|
+
const state = await api.getDingDongSilent(chimeId, channel);
|
|
111
|
+
return state.active;
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
async turnOn(): Promise<void> {
|
|
@@ -115,22 +123,15 @@ export class ReolinkCameraChime
|
|
|
115
123
|
}
|
|
116
124
|
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
117
125
|
const chimeId = this.wirelessChimeId;
|
|
118
|
-
this.logger.log(`Chime:
|
|
119
|
-
const cfg = await this.getChimeCfg();
|
|
120
|
-
if (!cfg) throw new Error(`Chime config not found for chimeId=${chimeId}`);
|
|
126
|
+
this.logger.log(`Chime: un-silence (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
121
127
|
const api = await this.camera.ensureClient();
|
|
122
|
-
|
|
123
|
-
if (alarmCfg.valid !== 1) {
|
|
124
|
-
const musicId = alarmCfg.musicId || 1;
|
|
125
|
-
await api.setDingDongCfg(chimeId, eventType, 1, musicId, channel);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
+
await api.setDingDongSilent(chimeId, 0, channel);
|
|
128
129
|
});
|
|
129
130
|
this.on = true;
|
|
130
|
-
this.logger.log(`Chime:
|
|
131
|
+
this.logger.log(`Chime: un-silence ok (device=${this.nativeId})`);
|
|
131
132
|
} catch (e: any) {
|
|
132
133
|
this.logger.error(
|
|
133
|
-
`Chime:
|
|
134
|
+
`Chime: un-silence failed (device=${this.nativeId})`,
|
|
134
135
|
e?.message || String(e),
|
|
135
136
|
);
|
|
136
137
|
throw e;
|
|
@@ -149,21 +150,18 @@ export class ReolinkCameraChime
|
|
|
149
150
|
}
|
|
150
151
|
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
151
152
|
const chimeId = this.wirelessChimeId;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
const seconds = this.silentDurationSeconds;
|
|
154
|
+
this.logger.log(
|
|
155
|
+
`Chime: silence for ${seconds}s (device=${this.nativeId}, chimeId=${chimeId})`,
|
|
156
|
+
);
|
|
155
157
|
const api = await this.camera.ensureClient();
|
|
156
|
-
|
|
157
|
-
if (alarmCfg.valid !== 0) {
|
|
158
|
-
await api.setDingDongCfg(chimeId, eventType, 0, alarmCfg.musicId, channel);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
158
|
+
await api.setDingDongSilent(chimeId, seconds, channel);
|
|
161
159
|
});
|
|
162
160
|
this.on = false;
|
|
163
|
-
this.logger.log(`Chime:
|
|
161
|
+
this.logger.log(`Chime: silence ok (device=${this.nativeId})`);
|
|
164
162
|
} catch (e: any) {
|
|
165
163
|
this.logger.error(
|
|
166
|
-
`Chime:
|
|
164
|
+
`Chime: silence failed (device=${this.nativeId})`,
|
|
167
165
|
e?.message || String(e),
|
|
168
166
|
);
|
|
169
167
|
throw e;
|
package/src/camera.ts
CHANGED
|
@@ -2838,7 +2838,7 @@ export class ReolinkCamera
|
|
|
2838
2838
|
}
|
|
2839
2839
|
}
|
|
2840
2840
|
|
|
2841
|
-
// Align wireless chime state via
|
|
2841
|
+
// Align wireless chime state via getDingDongSilent (cmd 609)
|
|
2842
2842
|
if (hasWirelessChime && this.chime) {
|
|
2843
2843
|
if (isInCooldown(this.auxDeviceCooldowns.chime)) {
|
|
2844
2844
|
logger.log(`[alignAuxDevicesState] Skipping chime (in cooldown)`);
|
package/src/intercom-provider.ts
CHANGED
|
@@ -67,7 +67,15 @@ export class ReolinkNativeIntercom
|
|
|
67
67
|
if (!match) return;
|
|
68
68
|
|
|
69
69
|
// Only auto-enable for cameras provided by our own plugin
|
|
70
|
-
|
|
70
|
+
const camera = this.plugin?.camerasMap?.get(device.id);
|
|
71
|
+
if (!camera) return;
|
|
72
|
+
|
|
73
|
+
// Only auto-enable if the camera actually supports intercom.
|
|
74
|
+
// If capabilities aren't loaded yet, skip — we'll be called again
|
|
75
|
+
// when the device descriptor updates after capability detection.
|
|
76
|
+
const caps = camera.cachedCapabilities;
|
|
77
|
+
if (!caps) return;
|
|
78
|
+
if (!caps.hasIntercom) return;
|
|
71
79
|
|
|
72
80
|
this.console.log(`Auto-enabling intercom mixin for ${device.name}`);
|
|
73
81
|
const mixins = (device.mixins || []).slice();
|