@apocaliss92/scrypted-reolink-native 0.4.43 → 0.4.45
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 +44 -6
- package/src/camera.ts +41 -8
- package/src/nvr.ts +20 -0
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/accessories/chime.ts
CHANGED
|
@@ -57,6 +57,31 @@ export class ReolinkCameraChime
|
|
|
57
57
|
return this.storageSettings.values.wirelessChimeId ?? -1;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Refresh chime ID from device when -1.
|
|
62
|
+
* Python lib: GetDingDongList uses deviceId; GetDingDongCfg uses ringId (skips if < 0).
|
|
63
|
+
* Returns true if we have a valid chimeId; false if still not discovered.
|
|
64
|
+
*/
|
|
65
|
+
private async ensureChimeId(): Promise<boolean> {
|
|
66
|
+
if (this.wirelessChimeId >= 0) return true;
|
|
67
|
+
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
68
|
+
const api = await this.camera.ensureClient();
|
|
69
|
+
const list = await api.getDingDongList(channel);
|
|
70
|
+
if (list.length > 0 && list[0].id >= 0) {
|
|
71
|
+
this.storageSettings.values.wirelessChimeId = list[0].id;
|
|
72
|
+
this.logger.log(`Chime: discovered chimeId=${list[0].id} from GetDingDongList`);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const configs = await api.getDingDongCfg(channel);
|
|
76
|
+
const cfg = configs.find(c => c.id >= 0);
|
|
77
|
+
if (cfg) {
|
|
78
|
+
this.storageSettings.values.wirelessChimeId = cfg.id;
|
|
79
|
+
this.logger.log(`Chime: discovered chimeId=${cfg.id} from GetDingDongCfg`);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
60
85
|
private async getChimeCfg(): Promise<ChimeCfg | undefined> {
|
|
61
86
|
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
62
87
|
const chimeId = this.wirelessChimeId;
|
|
@@ -70,6 +95,7 @@ export class ReolinkCameraChime
|
|
|
70
95
|
* Determine if the chime is active by checking if any event type is enabled.
|
|
71
96
|
*/
|
|
72
97
|
async syncStateFromDevice(): Promise<boolean | undefined> {
|
|
98
|
+
await this.ensureChimeId();
|
|
73
99
|
const cfg = await this.getChimeCfg();
|
|
74
100
|
if (!cfg) return undefined;
|
|
75
101
|
const eventTypes = Object.values(cfg.type);
|
|
@@ -78,12 +104,18 @@ export class ReolinkCameraChime
|
|
|
78
104
|
}
|
|
79
105
|
|
|
80
106
|
async turnOn(): Promise<void> {
|
|
81
|
-
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
82
|
-
const chimeId = this.wirelessChimeId;
|
|
83
|
-
this.logger.log(`Chime: enable all events (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
84
107
|
this.camera.auxDeviceCooldowns.chime = Date.now();
|
|
85
108
|
try {
|
|
86
109
|
await this.camera.withBaichuanRetry(async () => {
|
|
110
|
+
const discovered = await this.ensureChimeId();
|
|
111
|
+
if (!discovered) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"Wireless chime not discovered. Ensure a Reolink Chime is paired with the doorbell and try again.",
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
117
|
+
const chimeId = this.wirelessChimeId;
|
|
118
|
+
this.logger.log(`Chime: enable all events (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
87
119
|
const cfg = await this.getChimeCfg();
|
|
88
120
|
if (!cfg) throw new Error(`Chime config not found for chimeId=${chimeId}`);
|
|
89
121
|
const api = await this.camera.ensureClient();
|
|
@@ -106,12 +138,18 @@ export class ReolinkCameraChime
|
|
|
106
138
|
}
|
|
107
139
|
|
|
108
140
|
async turnOff(): Promise<void> {
|
|
109
|
-
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
110
|
-
const chimeId = this.wirelessChimeId;
|
|
111
|
-
this.logger.log(`Chime: disable all events (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
112
141
|
this.camera.auxDeviceCooldowns.chime = Date.now();
|
|
113
142
|
try {
|
|
114
143
|
await this.camera.withBaichuanRetry(async () => {
|
|
144
|
+
const discovered = await this.ensureChimeId();
|
|
145
|
+
if (!discovered) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
"Wireless chime not discovered. Ensure a Reolink Chime is paired with the doorbell and try again.",
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
const channel = this.camera.storageSettings.values.rtspChannel;
|
|
151
|
+
const chimeId = this.wirelessChimeId;
|
|
152
|
+
this.logger.log(`Chime: disable all events (device=${this.nativeId}, chimeId=${chimeId})`);
|
|
115
153
|
const cfg = await this.getChimeCfg();
|
|
116
154
|
if (!cfg) throw new Error(`Chime config not found for chimeId=${chimeId}`);
|
|
117
155
|
const api = await this.camera.ensureClient();
|
package/src/camera.ts
CHANGED
|
@@ -126,6 +126,30 @@ export class ReolinkCamera
|
|
|
126
126
|
title: "Debug logs",
|
|
127
127
|
type: "boolean",
|
|
128
128
|
immediate: true,
|
|
129
|
+
onPut: async (ov, value) => {
|
|
130
|
+
if (ov === value) return;
|
|
131
|
+
const logger = this.getBaichuanLogger();
|
|
132
|
+
if (this.resetBaichuanClient) {
|
|
133
|
+
if (this.debugLogsResetTimeout) {
|
|
134
|
+
clearTimeout(this.debugLogsResetTimeout);
|
|
135
|
+
this.debugLogsResetTimeout = undefined;
|
|
136
|
+
}
|
|
137
|
+
this.debugLogsResetTimeout = setTimeout(async () => {
|
|
138
|
+
this.debugLogsResetTimeout = undefined;
|
|
139
|
+
try {
|
|
140
|
+
await this.resetBaichuanClient("debugLogs changed");
|
|
141
|
+
this.baichuanApi = undefined;
|
|
142
|
+
this.ensureClientPromise = undefined;
|
|
143
|
+
await this.ensureClient();
|
|
144
|
+
} catch (e) {
|
|
145
|
+
logger.warn(
|
|
146
|
+
"Failed to reset client after debug logs change",
|
|
147
|
+
e?.message || String(e),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}, 2000);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
129
153
|
},
|
|
130
154
|
// Basic connection settings
|
|
131
155
|
ipAddress: {
|
|
@@ -1674,10 +1698,11 @@ export class ReolinkCamera
|
|
|
1674
1698
|
if (this.cachedCapabilities) return this.cachedCapabilities;
|
|
1675
1699
|
|
|
1676
1700
|
const client = await this.ensureClient();
|
|
1677
|
-
const { capabilities } = await client.getDeviceCapabilities(
|
|
1701
|
+
const { capabilities, debug } = await client.getDeviceCapabilities(
|
|
1678
1702
|
this.storageSettings.values.rtspChannel ?? 0,
|
|
1679
1703
|
);
|
|
1680
1704
|
this.cachedCapabilities = capabilities;
|
|
1705
|
+
logger.debug("Device capabilities retrieved", debug);
|
|
1681
1706
|
return capabilities;
|
|
1682
1707
|
}
|
|
1683
1708
|
} catch (e) {
|
|
@@ -2284,7 +2309,13 @@ export class ReolinkCamera
|
|
|
2284
2309
|
const logger = this.getBaichuanLogger();
|
|
2285
2310
|
logger.debug(`Reporting devices: ${JSON.stringify(abilities)}`);
|
|
2286
2311
|
|
|
2287
|
-
const {
|
|
2312
|
+
const {
|
|
2313
|
+
hasSiren,
|
|
2314
|
+
hasFloodlight,
|
|
2315
|
+
hasPir,
|
|
2316
|
+
hasAutotracking,
|
|
2317
|
+
hasWirelessChime,
|
|
2318
|
+
} = abilities;
|
|
2288
2319
|
|
|
2289
2320
|
// Define native IDs for all sub-devices
|
|
2290
2321
|
const motionSirenNativeId = `${this.nativeId}${motionSirenSuffix}`;
|
|
@@ -2670,8 +2701,13 @@ export class ReolinkCamera
|
|
|
2670
2701
|
const api = await this.ensureClient();
|
|
2671
2702
|
|
|
2672
2703
|
const channel = this.storageSettings.values.rtspChannel;
|
|
2673
|
-
const {
|
|
2674
|
-
|
|
2704
|
+
const {
|
|
2705
|
+
hasSiren,
|
|
2706
|
+
hasFloodlight,
|
|
2707
|
+
hasPir,
|
|
2708
|
+
hasAutotracking,
|
|
2709
|
+
hasWirelessChime,
|
|
2710
|
+
} = await this.getAbilities();
|
|
2675
2711
|
|
|
2676
2712
|
// Cooldown period: 15 seconds after a manual state change
|
|
2677
2713
|
// Camera can take 10+ seconds to reflect state changes in its API response
|
|
@@ -2818,10 +2854,7 @@ export class ReolinkCamera
|
|
|
2818
2854
|
}
|
|
2819
2855
|
}
|
|
2820
2856
|
} catch (e) {
|
|
2821
|
-
logger.warn(
|
|
2822
|
-
"Failed to align chime state",
|
|
2823
|
-
e?.message || String(e),
|
|
2824
|
-
);
|
|
2857
|
+
logger.warn("Failed to align chime state", e?.message || String(e));
|
|
2825
2858
|
}
|
|
2826
2859
|
}
|
|
2827
2860
|
}
|
package/src/nvr.ts
CHANGED
|
@@ -51,6 +51,26 @@ export class ReolinkNativeNvrDevice
|
|
|
51
51
|
title: "Debug Events",
|
|
52
52
|
type: "boolean",
|
|
53
53
|
immediate: true,
|
|
54
|
+
onPut: async (ov, value) => {
|
|
55
|
+
if (ov === value) return;
|
|
56
|
+
const logger = this.getBaichuanLogger();
|
|
57
|
+
if (this.debugLogsResetTimeout) {
|
|
58
|
+
clearTimeout(this.debugLogsResetTimeout);
|
|
59
|
+
this.debugLogsResetTimeout = undefined;
|
|
60
|
+
}
|
|
61
|
+
this.debugLogsResetTimeout = setTimeout(async () => {
|
|
62
|
+
this.debugLogsResetTimeout = undefined;
|
|
63
|
+
try {
|
|
64
|
+
await this.cleanupBaichuanApi();
|
|
65
|
+
await this.ensureBaichuanClient();
|
|
66
|
+
} catch (e) {
|
|
67
|
+
logger.warn(
|
|
68
|
+
"Failed to reset client after debug logs change",
|
|
69
|
+
e?.message || String(e),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}, 2000);
|
|
73
|
+
},
|
|
54
74
|
},
|
|
55
75
|
// eventSource: {
|
|
56
76
|
// title: 'Event Source',
|