@apocaliss92/scrypted-reolink-native 0.4.41 → 0.4.43
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/main.nodejs.js +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
- package/src/accessories/chime.ts +53 -25
- package/src/camera.ts +5 -3
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/accessories/chime.ts
CHANGED
|
@@ -6,11 +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" };
|
|
9
10
|
import type { ReolinkCamera } from "../camera";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
|
-
* Chime:
|
|
13
|
-
*
|
|
13
|
+
* Chime: enable/disable a paired wireless Reolink Chime receiver.
|
|
14
|
+
*
|
|
15
|
+
* Uses SetDingDongCfg (cmd 487) to enable/disable all event types on the chime,
|
|
16
|
+
* matching the approach used by Home Assistant / reolink_aio.
|
|
17
|
+
*
|
|
18
|
+
* turnOn() enables all event types (chime rings on events).
|
|
19
|
+
* turnOff() disables all event types (chime stays silent).
|
|
20
|
+
*
|
|
14
21
|
* The chime ID is auto-synced from getDingDongList during alignAuxDevicesState.
|
|
15
22
|
*/
|
|
16
23
|
export class ReolinkCameraChime
|
|
@@ -29,13 +36,6 @@ export class ReolinkCameraChime
|
|
|
29
36
|
defaultValue: -1,
|
|
30
37
|
readonly: true,
|
|
31
38
|
},
|
|
32
|
-
muteDurationSec: {
|
|
33
|
-
title: "Mute Duration (seconds)",
|
|
34
|
-
description:
|
|
35
|
-
"How long to mute the wireless chime when turned off (default: 3600 = 1 hour).",
|
|
36
|
-
type: "number",
|
|
37
|
-
defaultValue: 3600,
|
|
38
|
-
},
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
constructor(
|
|
@@ -53,27 +53,52 @@ export class ReolinkCameraChime
|
|
|
53
53
|
await this.storageSettings.putSetting(key, value);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
get wirelessChimeId(): number {
|
|
57
57
|
return this.storageSettings.values.wirelessChimeId ?? -1;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
private async getChimeCfg(): Promise<ChimeCfg | undefined> {
|
|
61
|
+
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
62
|
+
const chimeId = this.wirelessChimeId;
|
|
63
|
+
if (chimeId < 0) return undefined;
|
|
64
|
+
const api = await this.camera.ensureClient();
|
|
65
|
+
const configs = await api.getDingDongCfg(channel);
|
|
66
|
+
return configs.find(c => c.id === chimeId);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Determine if the chime is active by checking if any event type is enabled.
|
|
71
|
+
*/
|
|
72
|
+
async syncStateFromDevice(): Promise<boolean | undefined> {
|
|
73
|
+
const cfg = await this.getChimeCfg();
|
|
74
|
+
if (!cfg) return undefined;
|
|
75
|
+
const eventTypes = Object.values(cfg.type);
|
|
76
|
+
if (eventTypes.length === 0) return undefined;
|
|
77
|
+
return eventTypes.some(e => e.valid === 1);
|
|
78
|
+
}
|
|
79
|
+
|
|
60
80
|
async turnOn(): Promise<void> {
|
|
61
81
|
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
62
82
|
const chimeId = this.wirelessChimeId;
|
|
63
|
-
this.logger.log(`Chime:
|
|
64
|
-
this.on = true;
|
|
83
|
+
this.logger.log(`Chime: enable all events (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
65
84
|
this.camera.auxDeviceCooldowns.chime = Date.now();
|
|
66
85
|
try {
|
|
67
86
|
await this.camera.withBaichuanRetry(async () => {
|
|
87
|
+
const cfg = await this.getChimeCfg();
|
|
88
|
+
if (!cfg) throw new Error(`Chime config not found for chimeId=${chimeId}`);
|
|
68
89
|
const api = await this.camera.ensureClient();
|
|
69
|
-
const
|
|
70
|
-
|
|
90
|
+
for (const [eventType, alarmCfg] of Object.entries(cfg.type)) {
|
|
91
|
+
if (alarmCfg.valid !== 1) {
|
|
92
|
+
const musicId = alarmCfg.musicId || 1;
|
|
93
|
+
await api.setDingDongCfg(chimeId, eventType, 1, musicId, channel);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
71
96
|
});
|
|
72
|
-
this.
|
|
97
|
+
this.on = true;
|
|
98
|
+
this.logger.log(`Chime: enable ok (device=${this.nativeId})`);
|
|
73
99
|
} catch (e: any) {
|
|
74
|
-
this.on = false;
|
|
75
100
|
this.logger.error(
|
|
76
|
-
`Chime:
|
|
101
|
+
`Chime: enable failed (device=${this.nativeId})`,
|
|
77
102
|
e?.message || String(e),
|
|
78
103
|
);
|
|
79
104
|
throw e;
|
|
@@ -83,21 +108,24 @@ export class ReolinkCameraChime
|
|
|
83
108
|
async turnOff(): Promise<void> {
|
|
84
109
|
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
85
110
|
const chimeId = this.wirelessChimeId;
|
|
86
|
-
|
|
87
|
-
this.logger.log(`Chime: mute for ${muteSec}s (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
88
|
-
this.on = false;
|
|
111
|
+
this.logger.log(`Chime: disable all events (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
89
112
|
this.camera.auxDeviceCooldowns.chime = Date.now();
|
|
90
113
|
try {
|
|
91
114
|
await this.camera.withBaichuanRetry(async () => {
|
|
115
|
+
const cfg = await this.getChimeCfg();
|
|
116
|
+
if (!cfg) throw new Error(`Chime config not found for chimeId=${chimeId}`);
|
|
92
117
|
const api = await this.camera.ensureClient();
|
|
93
|
-
const
|
|
94
|
-
|
|
118
|
+
for (const [eventType, alarmCfg] of Object.entries(cfg.type)) {
|
|
119
|
+
if (alarmCfg.valid !== 0) {
|
|
120
|
+
await api.setDingDongCfg(chimeId, eventType, 0, alarmCfg.musicId, channel);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
95
123
|
});
|
|
96
|
-
this.
|
|
124
|
+
this.on = false;
|
|
125
|
+
this.logger.log(`Chime: disable ok (device=${this.nativeId})`);
|
|
97
126
|
} catch (e: any) {
|
|
98
|
-
this.on = true;
|
|
99
127
|
this.logger.error(
|
|
100
|
-
`Chime:
|
|
128
|
+
`Chime: disable failed (device=${this.nativeId})`,
|
|
101
129
|
e?.message || String(e),
|
|
102
130
|
);
|
|
103
131
|
throw e;
|
package/src/camera.ts
CHANGED
|
@@ -2802,7 +2802,7 @@ export class ReolinkCamera
|
|
|
2802
2802
|
}
|
|
2803
2803
|
}
|
|
2804
2804
|
|
|
2805
|
-
// Align chime state (
|
|
2805
|
+
// Align wireless chime state via getDingDongCfg (cmd 486)
|
|
2806
2806
|
if (hasWirelessChime && this.chime) {
|
|
2807
2807
|
if (isInCooldown(this.auxDeviceCooldowns.chime)) {
|
|
2808
2808
|
logger.log(`[alignAuxDevicesState] Skipping chime (in cooldown)`);
|
|
@@ -2812,8 +2812,10 @@ export class ReolinkCamera
|
|
|
2812
2812
|
if (wirelessChimes.length > 0) {
|
|
2813
2813
|
const chimeId = wirelessChimes[0].id;
|
|
2814
2814
|
this.chime.storageSettings.values.wirelessChimeId = chimeId;
|
|
2815
|
-
const
|
|
2816
|
-
|
|
2815
|
+
const isActive = await this.chime.syncStateFromDevice();
|
|
2816
|
+
if (isActive !== undefined) {
|
|
2817
|
+
this.chime.on = isActive;
|
|
2818
|
+
}
|
|
2817
2819
|
}
|
|
2818
2820
|
} catch (e) {
|
|
2819
2821
|
logger.warn(
|