@apocaliss92/scrypted-reolink-native 0.1.9 → 0.1.10
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/baichuan-base.ts +478 -0
- package/src/camera-battery.ts +32 -32
- package/src/camera.ts +6 -9
- package/src/common.ts +107 -230
- package/src/connect.ts +1 -2
- package/src/debug-options.ts +1 -1
- package/src/intercom.ts +3 -3
- package/src/nvr.ts +66 -217
- package/src/stream-utils.ts +1 -1
package/src/camera-battery.ts
CHANGED
|
@@ -45,7 +45,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
45
45
|
(!this.sleeping && this.lastPicture && (now - this.lastPicture.atMs >= minSnapshotIntervalMs));
|
|
46
46
|
|
|
47
47
|
if (!shouldTakeNewSnapshot && this.lastPicture) {
|
|
48
|
-
this.
|
|
48
|
+
this.getBaichuanLogger().debug(`Returning cached snapshot, taken at ${new Date(this.lastPicture.atMs).toLocaleString()}`);
|
|
49
49
|
return this.lastPicture.mo;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -53,7 +53,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
53
53
|
return await this.takePictureInFlight;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
this.
|
|
56
|
+
this.getBaichuanLogger().log(`Taking new snapshot from camera (forceNewSnapshot: ${this.forceNewSnapshot})`);
|
|
57
57
|
this.forceNewSnapshot = false;
|
|
58
58
|
|
|
59
59
|
this.takePictureInFlight = (async () => {
|
|
@@ -63,7 +63,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
63
63
|
});
|
|
64
64
|
const mo = await sdk.mediaManager.createMediaObject(snapshotBuffer, 'image/jpeg');
|
|
65
65
|
this.lastPicture = { mo, atMs: Date.now() };
|
|
66
|
-
this.
|
|
66
|
+
this.getBaichuanLogger().log(`Snapshot taken at ${new Date(this.lastPicture.atMs).toLocaleString()}`);
|
|
67
67
|
return mo;
|
|
68
68
|
})();
|
|
69
69
|
|
|
@@ -106,7 +106,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
106
106
|
if (this.periodicStarted) return;
|
|
107
107
|
this.periodicStarted = true;
|
|
108
108
|
|
|
109
|
-
this.
|
|
109
|
+
this.getBaichuanLogger().log('Starting periodic tasks for battery camera');
|
|
110
110
|
|
|
111
111
|
// Check sleeping state every 5 seconds (non-blocking)
|
|
112
112
|
if (!this.nvrDevice) {
|
|
@@ -117,7 +117,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
117
117
|
|
|
118
118
|
if (!api) {
|
|
119
119
|
if (!this.sleeping) {
|
|
120
|
-
this.
|
|
120
|
+
this.getBaichuanLogger().log('Camera is sleeping: no active Baichuan client');
|
|
121
121
|
this.sleeping = true;
|
|
122
122
|
}
|
|
123
123
|
return;
|
|
@@ -126,7 +126,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
126
126
|
const sleepStatus = api.getSleepStatus({ channel });
|
|
127
127
|
await this.updateSleepingState(sleepStatus);
|
|
128
128
|
} catch (e) {
|
|
129
|
-
this.
|
|
129
|
+
this.getBaichuanLogger().warn('Error checking sleeping state:', e);
|
|
130
130
|
}
|
|
131
131
|
}, 5_000);
|
|
132
132
|
}
|
|
@@ -138,25 +138,25 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
138
138
|
this.updateBatteryAndSnapshot().catch(() => { });
|
|
139
139
|
}, updateIntervalMs);
|
|
140
140
|
|
|
141
|
-
this.
|
|
141
|
+
this.getBaichuanLogger().log(`Periodic tasks started: sleep check every 5s, battery update every ${batteryUpdateIntervalMinutes} minutes`);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
async updateSleepingState(sleepStatus: SleepStatus): Promise<void> {
|
|
145
145
|
try {
|
|
146
146
|
if (this.isBatteryInfoLoggingEnabled()) {
|
|
147
|
-
this.
|
|
147
|
+
this.getBaichuanLogger().debug('getSleepStatus result:', JSON.stringify(sleepStatus));
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
if (sleepStatus.state === 'sleeping') {
|
|
151
151
|
if (!this.sleeping) {
|
|
152
|
-
this.
|
|
152
|
+
this.getBaichuanLogger().log(`Camera is sleeping: ${sleepStatus.reason}`);
|
|
153
153
|
this.sleeping = true;
|
|
154
154
|
}
|
|
155
155
|
} else if (sleepStatus.state === 'awake') {
|
|
156
156
|
// Camera is awake
|
|
157
157
|
const wasSleeping = this.sleeping;
|
|
158
158
|
if (wasSleeping) {
|
|
159
|
-
this.
|
|
159
|
+
this.getBaichuanLogger().log(`Camera woke up: ${sleepStatus.reason}`);
|
|
160
160
|
this.sleeping = false;
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -168,11 +168,11 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
168
168
|
}
|
|
169
169
|
} else {
|
|
170
170
|
// Unknown state
|
|
171
|
-
this.
|
|
171
|
+
this.getBaichuanLogger().debug(`Sleep status unknown: ${sleepStatus.reason}`);
|
|
172
172
|
}
|
|
173
173
|
} catch (e) {
|
|
174
174
|
// Silently ignore errors in sleep check to avoid spam
|
|
175
|
-
this.
|
|
175
|
+
this.getBaichuanLogger().debug('Error in checkSleepingState:', e);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
@@ -182,7 +182,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
182
182
|
|
|
183
183
|
const batteryInfo = await api.getBatteryInfo(channel);
|
|
184
184
|
if (this.isBatteryInfoLoggingEnabled()) {
|
|
185
|
-
|
|
185
|
+
this.getBaichuanLogger().debug('getBatteryInfo result:', JSON.stringify(batteryInfo));
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
if (batteryInfo.batteryPercent !== undefined) {
|
|
@@ -195,17 +195,17 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
195
195
|
if (batteryInfo.chargeStatus !== undefined) {
|
|
196
196
|
// chargeStatus: "0"=charging, "1"=discharging, "2"=full
|
|
197
197
|
const charging = batteryInfo.chargeStatus === "0" || batteryInfo.chargeStatus === "2";
|
|
198
|
-
this.
|
|
198
|
+
this.getBaichuanLogger().log(`Battery level changed: ${oldLevel}% → ${batteryInfo.batteryPercent}% (charging: ${charging})`);
|
|
199
199
|
} else {
|
|
200
|
-
this.
|
|
200
|
+
this.getBaichuanLogger().log(`Battery level changed: ${oldLevel}% → ${batteryInfo.batteryPercent}%`);
|
|
201
201
|
}
|
|
202
202
|
} else if (oldLevel === undefined) {
|
|
203
203
|
// First time setting battery level
|
|
204
204
|
if (batteryInfo.chargeStatus !== undefined) {
|
|
205
205
|
const charging = batteryInfo.chargeStatus === "0" || batteryInfo.chargeStatus === "2";
|
|
206
|
-
this.
|
|
206
|
+
this.getBaichuanLogger().log(`Battery level set: ${batteryInfo.batteryPercent}% (charging: ${charging})`);
|
|
207
207
|
} else {
|
|
208
|
-
this.
|
|
208
|
+
this.getBaichuanLogger().log(`Battery level set: ${batteryInfo.batteryPercent}%`);
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
}
|
|
@@ -214,7 +214,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
214
214
|
private async updateBatteryAndSnapshot(): Promise<void> {
|
|
215
215
|
// Prevent multiple simultaneous calls
|
|
216
216
|
if (this.batteryUpdateInProgress) {
|
|
217
|
-
this.
|
|
217
|
+
this.getBaichuanLogger().debug('Battery update already in progress, skipping');
|
|
218
218
|
return;
|
|
219
219
|
}
|
|
220
220
|
|
|
@@ -222,12 +222,12 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
222
222
|
try {
|
|
223
223
|
const channel = this.storageSettings.values.rtspChannel;
|
|
224
224
|
const updateIntervalMinutes = this.storageSettings.values.batteryUpdateIntervalMinutes ?? 10;
|
|
225
|
-
this.
|
|
225
|
+
this.getBaichuanLogger().log(`Force battery update interval started (every ${updateIntervalMinutes} minutes)`);
|
|
226
226
|
|
|
227
227
|
// Ensure we have a client connection
|
|
228
228
|
const api = await this.ensureClient();
|
|
229
229
|
if (!api) {
|
|
230
|
-
this.
|
|
230
|
+
this.getBaichuanLogger().warn('Failed to ensure client connection for battery update');
|
|
231
231
|
return;
|
|
232
232
|
}
|
|
233
233
|
|
|
@@ -236,12 +236,12 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
236
236
|
|
|
237
237
|
// If camera is sleeping, wake it up
|
|
238
238
|
if (sleepStatus.state === 'sleeping') {
|
|
239
|
-
this.
|
|
239
|
+
this.getBaichuanLogger().log('Camera is sleeping, waking up for periodic update...');
|
|
240
240
|
try {
|
|
241
241
|
await api.wakeUp(channel, { waitAfterWakeMs: 2000 });
|
|
242
|
-
this.
|
|
242
|
+
this.getBaichuanLogger().log('Wake command sent, waiting for camera to wake up...');
|
|
243
243
|
} catch (wakeError) {
|
|
244
|
-
this.
|
|
244
|
+
this.getBaichuanLogger().warn('Failed to wake up camera:', wakeError);
|
|
245
245
|
return;
|
|
246
246
|
}
|
|
247
247
|
|
|
@@ -255,14 +255,14 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
255
255
|
sleepStatus = api.getSleepStatus({ channel });
|
|
256
256
|
if (sleepStatus.state === 'awake') {
|
|
257
257
|
awake = true;
|
|
258
|
-
this.
|
|
258
|
+
this.getBaichuanLogger().log('Camera is now awake');
|
|
259
259
|
this.sleeping = false;
|
|
260
260
|
break;
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
if (!awake) {
|
|
265
|
-
this.
|
|
265
|
+
this.getBaichuanLogger().warn('Camera did not wake up within timeout, skipping update');
|
|
266
266
|
return;
|
|
267
267
|
}
|
|
268
268
|
} else if (sleepStatus.state === 'awake') {
|
|
@@ -274,26 +274,26 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
274
274
|
try {
|
|
275
275
|
await this.updateBatteryInfo();
|
|
276
276
|
} catch (e) {
|
|
277
|
-
this.
|
|
277
|
+
this.getBaichuanLogger().warn('Failed to get battery info during periodic update:', e);
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// 2. Align auxiliary devices state
|
|
281
281
|
try {
|
|
282
282
|
await this.alignAuxDevicesState();
|
|
283
283
|
} catch (e) {
|
|
284
|
-
this.
|
|
284
|
+
this.getBaichuanLogger().warn('Failed to align auxiliary devices state:', e);
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
// 3. Update snapshot
|
|
288
288
|
try {
|
|
289
289
|
this.forceNewSnapshot = true;
|
|
290
290
|
await this.takePicture();
|
|
291
|
-
this.
|
|
291
|
+
this.getBaichuanLogger().log('Snapshot updated during periodic update');
|
|
292
292
|
} catch (snapshotError) {
|
|
293
|
-
this.
|
|
293
|
+
this.getBaichuanLogger().warn('Failed to update snapshot during periodic update:', snapshotError);
|
|
294
294
|
}
|
|
295
295
|
} catch (e) {
|
|
296
|
-
this.
|
|
296
|
+
this.getBaichuanLogger().warn('Failed to update battery and snapshot', e);
|
|
297
297
|
} finally {
|
|
298
298
|
this.batteryUpdateInProgress = false;
|
|
299
299
|
}
|
|
@@ -313,7 +313,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
313
313
|
await this.baichuanApi?.close();
|
|
314
314
|
}
|
|
315
315
|
catch (e) {
|
|
316
|
-
this.
|
|
316
|
+
this.getBaichuanLogger().warn('Error closing Baichuan client during reset', e);
|
|
317
317
|
}
|
|
318
318
|
finally {
|
|
319
319
|
this.baichuanApi = undefined;
|
|
@@ -331,7 +331,7 @@ export class ReolinkNativeBatteryCamera extends CommonCameraMixin {
|
|
|
331
331
|
|
|
332
332
|
if (reason) {
|
|
333
333
|
const message = reason?.message || reason?.toString?.() || reason;
|
|
334
|
-
this.
|
|
334
|
+
this.getBaichuanLogger().warn(`Baichuan client reset requested: ${message}`);
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
337
|
|
package/src/camera.ts
CHANGED
|
@@ -45,7 +45,7 @@ export class ReolinkNativeCamera extends CommonCameraMixin {
|
|
|
45
45
|
await this.baichuanApi?.close();
|
|
46
46
|
}
|
|
47
47
|
catch (e) {
|
|
48
|
-
this.
|
|
48
|
+
this.getBaichuanLogger().warn('Error closing Baichuan client during reset', e);
|
|
49
49
|
}
|
|
50
50
|
finally {
|
|
51
51
|
this.baichuanApi = undefined;
|
|
@@ -59,7 +59,7 @@ export class ReolinkNativeCamera extends CommonCameraMixin {
|
|
|
59
59
|
|
|
60
60
|
if (reason) {
|
|
61
61
|
const message = reason?.message || reason?.toString?.() || reason;
|
|
62
|
-
this.
|
|
62
|
+
this.getBaichuanLogger().warn(`Baichuan client reset requested: ${message}`);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -90,9 +90,6 @@ export class ReolinkNativeCamera extends CommonCameraMixin {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
public getLogger() {
|
|
94
|
-
return this.console;
|
|
95
|
-
}
|
|
96
93
|
|
|
97
94
|
async init() {
|
|
98
95
|
this.startPeriodicTasks();
|
|
@@ -141,13 +138,13 @@ export class ReolinkNativeCamera extends CommonCameraMixin {
|
|
|
141
138
|
if (this.periodicStarted) return;
|
|
142
139
|
this.periodicStarted = true;
|
|
143
140
|
|
|
144
|
-
this.
|
|
141
|
+
this.getBaichuanLogger().log('Starting periodic tasks for regular camera');
|
|
145
142
|
|
|
146
143
|
this.statusPollTimer = setInterval(() => {
|
|
147
144
|
this.periodic10sTick().catch(() => { });
|
|
148
145
|
}, 10_000);
|
|
149
146
|
|
|
150
|
-
this.
|
|
147
|
+
this.getBaichuanLogger().log('Periodic tasks started: status poll every 10s');
|
|
151
148
|
}
|
|
152
149
|
|
|
153
150
|
private async periodic10sTick(): Promise<void> {
|
|
@@ -160,7 +157,7 @@ export class ReolinkNativeCamera extends CommonCameraMixin {
|
|
|
160
157
|
}
|
|
161
158
|
|
|
162
159
|
async processEvents(events: { motion?: boolean; objects?: string[] }) {
|
|
163
|
-
const logger = this.
|
|
160
|
+
const logger = this.getBaichuanLogger();
|
|
164
161
|
|
|
165
162
|
if (!this.isEventDispatchEnabled()) return;
|
|
166
163
|
|
|
@@ -215,7 +212,7 @@ export class ReolinkNativeCamera extends CommonCameraMixin {
|
|
|
215
212
|
return mo;
|
|
216
213
|
});
|
|
217
214
|
} catch (e) {
|
|
218
|
-
this.
|
|
215
|
+
this.getBaichuanLogger().error('Error taking snapshot', e);
|
|
219
216
|
throw e;
|
|
220
217
|
}
|
|
221
218
|
}
|