homebridge-eufy-security 4.4.2-beta.2 → 4.4.2-beta.20

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/FUNDING.yml +1 -0
  3. package/README.md +14 -17
  4. package/dist/accessories/AutoSyncStationAccessory.js +26 -30
  5. package/dist/accessories/AutoSyncStationAccessory.js.map +1 -1
  6. package/dist/accessories/BaseAccessory.js +33 -46
  7. package/dist/accessories/BaseAccessory.js.map +1 -1
  8. package/dist/accessories/CameraAccessory.js +92 -167
  9. package/dist/accessories/CameraAccessory.js.map +1 -1
  10. package/dist/accessories/Device.js +11 -15
  11. package/dist/accessories/Device.js.map +1 -1
  12. package/dist/accessories/EntrySensorAccessory.js +7 -12
  13. package/dist/accessories/EntrySensorAccessory.js.map +1 -1
  14. package/dist/accessories/LockAccessory.js +20 -24
  15. package/dist/accessories/LockAccessory.js.map +1 -1
  16. package/dist/accessories/MotionSensorAccessory.js +7 -12
  17. package/dist/accessories/MotionSensorAccessory.js.map +1 -1
  18. package/dist/accessories/StationAccessory.js +40 -45
  19. package/dist/accessories/StationAccessory.js.map +1 -1
  20. package/dist/config.js +1 -4
  21. package/dist/config.js.map +1 -1
  22. package/dist/controller/LocalLivestreamManager.js +85 -89
  23. package/dist/controller/LocalLivestreamManager.js.map +1 -1
  24. package/dist/controller/recordingDelegate.js +116 -108
  25. package/dist/controller/recordingDelegate.js.map +1 -1
  26. package/dist/controller/snapshotDelegate.js +379 -0
  27. package/dist/controller/snapshotDelegate.js.map +1 -0
  28. package/dist/controller/streamingDelegate.js +202 -207
  29. package/dist/controller/streamingDelegate.js.map +1 -1
  30. package/dist/index.js +9 -7
  31. package/dist/index.js.map +1 -1
  32. package/dist/interfaces.js +1 -2
  33. package/dist/interfaces.js.map +1 -1
  34. package/dist/platform.js +145 -165
  35. package/dist/platform.js.map +1 -1
  36. package/dist/settings.js +26 -19
  37. package/dist/settings.js.map +1 -1
  38. package/dist/utils/Talkback.js +9 -13
  39. package/dist/utils/Talkback.js.map +1 -1
  40. package/dist/utils/configTypes.js +12 -7
  41. package/dist/utils/configTypes.js.map +1 -1
  42. package/dist/utils/ffmpeg.js +44 -52
  43. package/dist/utils/ffmpeg.js.map +1 -1
  44. package/dist/utils/interfaces.js +1 -5
  45. package/dist/utils/interfaces.js.map +1 -1
  46. package/dist/utils/utils.js +32 -134
  47. package/dist/utils/utils.js.map +1 -1
  48. package/dist/version.js +1 -4
  49. package/dist/version.js.map +1 -1
  50. package/eslint.config.mjs +25 -47
  51. package/homebridge-eufy-security.png +0 -0
  52. package/homebridge-ui/public/app.js +221 -0
  53. package/homebridge-ui/public/assets/devices/eufycam3pro_large.png +0 -0
  54. package/homebridge-ui/public/assets/devices/homebase3_large.png +0 -0
  55. package/homebridge-ui/public/assets/devices/homebasemini_large.jpg +0 -0
  56. package/homebridge-ui/public/assets/devices/indoorcamC210_large.png +0 -0
  57. package/homebridge-ui/public/assets/devices/indoorcamC220_large.png +0 -0
  58. package/homebridge-ui/public/assets/devices/indoorcamE30_large.png +0 -0
  59. package/homebridge-ui/public/assets/devices/solocamc35_large.png +0 -0
  60. package/homebridge-ui/public/assets/devices/solocame30_large.png +0 -0
  61. package/homebridge-ui/public/components/device-card.js +141 -0
  62. package/homebridge-ui/public/components/guard-modes.js +88 -0
  63. package/homebridge-ui/public/components/number-input.js +121 -0
  64. package/homebridge-ui/public/components/select.js +73 -0
  65. package/homebridge-ui/public/components/toggle.js +68 -0
  66. package/homebridge-ui/public/index.html +24 -14
  67. package/homebridge-ui/public/services/api.js +129 -0
  68. package/homebridge-ui/public/services/config.js +144 -0
  69. package/homebridge-ui/public/style.css +705 -0
  70. package/homebridge-ui/public/utils/countries.js +73 -0
  71. package/homebridge-ui/public/utils/device-images.js +69 -0
  72. package/homebridge-ui/public/utils/helpers.js +47 -0
  73. package/homebridge-ui/public/views/dashboard.js +211 -0
  74. package/homebridge-ui/public/views/device-detail.js +631 -0
  75. package/homebridge-ui/public/views/login.js +625 -0
  76. package/homebridge-ui/public/views/settings.js +389 -0
  77. package/homebridge-ui/public/views/unsupported-detail.js +216 -0
  78. package/homebridge-ui/server.js +567 -450
  79. package/package.json +19 -59
  80. package/dist/accessories/AutoSyncStationAccessory.d.ts +0 -42
  81. package/dist/accessories/AutoSyncStationAccessory.d.ts.map +0 -1
  82. package/dist/accessories/BaseAccessory.d.ts +0 -56
  83. package/dist/accessories/BaseAccessory.d.ts.map +0 -1
  84. package/dist/accessories/CameraAccessory.d.ts +0 -84
  85. package/dist/accessories/CameraAccessory.d.ts.map +0 -1
  86. package/dist/accessories/Device.d.ts +0 -19
  87. package/dist/accessories/Device.d.ts.map +0 -1
  88. package/dist/accessories/EntrySensorAccessory.d.ts +0 -25
  89. package/dist/accessories/EntrySensorAccessory.d.ts.map +0 -1
  90. package/dist/accessories/LockAccessory.d.ts +0 -45
  91. package/dist/accessories/LockAccessory.d.ts.map +0 -1
  92. package/dist/accessories/MotionSensorAccessory.d.ts +0 -25
  93. package/dist/accessories/MotionSensorAccessory.d.ts.map +0 -1
  94. package/dist/accessories/StationAccessory.d.ts +0 -86
  95. package/dist/accessories/StationAccessory.d.ts.map +0 -1
  96. package/dist/config.d.ts +0 -31
  97. package/dist/config.d.ts.map +0 -1
  98. package/dist/controller/LocalLivestreamManager.d.ts +0 -31
  99. package/dist/controller/LocalLivestreamManager.d.ts.map +0 -1
  100. package/dist/controller/SnapshotManager.d.ts +0 -64
  101. package/dist/controller/SnapshotManager.d.ts.map +0 -1
  102. package/dist/controller/SnapshotManager.js +0 -434
  103. package/dist/controller/SnapshotManager.js.map +0 -1
  104. package/dist/controller/recordingDelegate.d.ts +0 -27
  105. package/dist/controller/recordingDelegate.d.ts.map +0 -1
  106. package/dist/controller/streamingDelegate.d.ts +0 -52
  107. package/dist/controller/streamingDelegate.d.ts.map +0 -1
  108. package/dist/index.d.ts +0 -7
  109. package/dist/index.d.ts.map +0 -1
  110. package/dist/interfaces.d.ts +0 -15
  111. package/dist/interfaces.d.ts.map +0 -1
  112. package/dist/platform.d.ts +0 -94
  113. package/dist/platform.d.ts.map +0 -1
  114. package/dist/settings.d.ts +0 -23
  115. package/dist/settings.d.ts.map +0 -1
  116. package/dist/utils/Talkback.d.ts +0 -21
  117. package/dist/utils/Talkback.d.ts.map +0 -1
  118. package/dist/utils/configTypes.d.ts +0 -68
  119. package/dist/utils/configTypes.d.ts.map +0 -1
  120. package/dist/utils/ffmpeg.d.ts +0 -111
  121. package/dist/utils/ffmpeg.d.ts.map +0 -1
  122. package/dist/utils/interfaces.d.ts +0 -8
  123. package/dist/utils/interfaces.d.ts.map +0 -1
  124. package/dist/utils/utils.d.ts +0 -35
  125. package/dist/utils/utils.d.ts.map +0 -1
  126. package/dist/version.d.ts +0 -2
  127. package/dist/version.d.ts.map +0 -1
  128. package/homebridge-ui/configui/app/util/types.d.ts +0 -65
  129. package/homebridge-ui/configui/app/util/types.d.ts.map +0 -1
  130. package/homebridge-ui/configui/app/util/types.js +0 -18
  131. package/homebridge-ui/configui/app/util/types.js.map +0 -1
  132. package/homebridge-ui/public/3rdpartylicenses.txt +0 -561
  133. package/homebridge-ui/public/assets/devices/homebase2_large.jpg +0 -0
  134. package/homebridge-ui/public/assets/devices/homebase3_large.jpg +0 -0
  135. package/homebridge-ui/public/assets/images/homebridge-eufy-security.png +0 -0
  136. package/homebridge-ui/public/favicon.ico +0 -0
  137. package/homebridge-ui/public/main.f6423287e0411c87.js +0 -1
  138. package/homebridge-ui/public/polyfills.efa2f09ba3e49167.js +0 -1
  139. package/homebridge-ui/public/runtime.ccde331d62c423b3.js +0 -1
  140. package/homebridge-ui/public/styles.13e635bf7a488639.css +0 -5
  141. package/homebridge-ui/server.d.ts +0 -2
  142. package/homebridge-ui/server.d.ts.map +0 -1
  143. package/homebridge-ui/server.js.map +0 -1
  144. package/homebridge-ui/version.d.ts +0 -2
  145. package/homebridge-ui/version.d.ts.map +0 -1
  146. package/homebridge-ui/version.js +0 -5
  147. package/homebridge-ui/version.js.map +0 -1
@@ -0,0 +1,379 @@
1
+ import * as fs from 'fs';
2
+ import { PropertyName } from 'eufy-security-client';
3
+ import { SNAPSHOT_CACHE_BALANCED_SECONDS, SNAPSHOT_CACHE_FRESH_SECONDS, SNAPSHOT_CLOUD_SKIP_MS, SNAPSHOT_FETCH_TIMEOUT_MS, SNAPSHOT_MIN_REFRESH_INTERVAL_MINUTES, SNAPSHOT_RING_DEBOUNCE_SECONDS, } from '../settings.js';
4
+ import { SnapshotHandlingMethod } from '../utils/configTypes.js';
5
+ import { FFmpeg, FFmpegParameters } from '../utils/ffmpeg.js';
6
+ import { isRtspReady } from '../utils/utils.js';
7
+ import { fileURLToPath } from 'url';
8
+ import path from 'path';
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+ const PLACEHOLDER_PATHS = {
12
+ offline: path.resolve(__dirname, '../../media/camera-offline.png'),
13
+ disabled: path.resolve(__dirname, '../../media/camera-disabled.png'),
14
+ black: path.resolve(__dirname, '../../media/Snapshot-black.png'),
15
+ unavailable: path.resolve(__dirname, '../../media/Snapshot-Unavailable.png'),
16
+ };
17
+ /**
18
+ * possible performance settings:
19
+ * 1. snapshots as current as possible (weak homebridge performance)
20
+ * - always get a new image from cloud or cam
21
+ * 2. balanced
22
+ * - start snapshot refresh but return snapshot as fast as possible
23
+ * if request takes too long old snapshot will be returned
24
+ * 3. get an old snapshot immediately
25
+ * - wait on cloud snapshot with new events
26
+ *
27
+ * extra options:
28
+ * - force refresh snapshots with interval
29
+ * - force immediate snapshot-reject when ringing
30
+ *
31
+ * Drawbacks: elapsed time in homekit might be wrong
32
+ */
33
+ export class snapshotDelegate {
34
+ livestreamManager;
35
+ static instanceCount = 0;
36
+ eufyPath;
37
+ device;
38
+ cameraConfig;
39
+ currentSnapshot;
40
+ placeholders = new Map();
41
+ pendingFetch;
42
+ lastRingEvent = 0;
43
+ isDeviceOffline = false;
44
+ log;
45
+ snapshotRefreshTimer;
46
+ snapshotRefreshInterval;
47
+ constructor(camera, livestreamManager) {
48
+ this.livestreamManager = livestreamManager;
49
+ this.eufyPath = camera.platform.eufyPath;
50
+ this.device = camera.device;
51
+ this.cameraConfig = camera.cameraConfig;
52
+ this.log = camera.log;
53
+ this.setupEventListeners();
54
+ this.setupAutomaticRefresh();
55
+ this.logSnapshotHandlingMethod();
56
+ this.loadPlaceholderImages();
57
+ this.initializeDeviceState();
58
+ this.loadInitialSnapshot();
59
+ }
60
+ setupEventListeners() {
61
+ this.device.on('property changed', this.onPropertyValueChanged.bind(this));
62
+ const detectionEvents = [
63
+ 'motion detected',
64
+ 'person detected',
65
+ 'pet detected',
66
+ 'sound detected',
67
+ 'crying detected',
68
+ 'vehicle detected',
69
+ 'dog detected',
70
+ 'dog lick detected',
71
+ 'dog poop detected',
72
+ 'stranger person detected',
73
+ 'rings',
74
+ ];
75
+ detectionEvents.forEach(eventType => {
76
+ this.device.on(eventType, this.onDeviceEvent.bind(this, eventType));
77
+ });
78
+ }
79
+ setupAutomaticRefresh() {
80
+ if (!this.cameraConfig.refreshSnapshotIntervalMinutes) {
81
+ return;
82
+ }
83
+ if (this.cameraConfig.refreshSnapshotIntervalMinutes < SNAPSHOT_MIN_REFRESH_INTERVAL_MINUTES) {
84
+ this.log.warn(`The interval to automatically refresh snapshots is set too low. Minimum is ${SNAPSHOT_MIN_REFRESH_INTERVAL_MINUTES} minutes.`);
85
+ this.cameraConfig.refreshSnapshotIntervalMinutes = SNAPSHOT_MIN_REFRESH_INTERVAL_MINUTES;
86
+ }
87
+ const intervalMs = this.cameraConfig.refreshSnapshotIntervalMinutes * 60 * 1000;
88
+ const staggerMs = (++snapshotDelegate.instanceCount) * 60 * 1000;
89
+ this.log.info(`Setting up automatic snapshot refresh every ${this.cameraConfig.refreshSnapshotIntervalMinutes}` +
90
+ ` minutes. This may decrease battery life dramatically. First refresh in ~${Math.ceil(staggerMs / 60000)} minute(s).`);
91
+ // Stagger first refresh per instance, then repeat at fixed interval
92
+ this.snapshotRefreshTimer = setTimeout(() => {
93
+ this.doAutomaticRefresh();
94
+ this.snapshotRefreshInterval = setInterval(() => this.doAutomaticRefresh(), intervalMs);
95
+ }, staggerMs);
96
+ }
97
+ doAutomaticRefresh() {
98
+ this.log.debug('Automatic snapshot refresh triggered.');
99
+ this.fetchCurrentCameraSnapshot().catch((error) => this.log.warn('Automatic snapshot refresh failed:', error));
100
+ }
101
+ logSnapshotHandlingMethod() {
102
+ const method = this.cameraConfig.snapshotHandlingMethod;
103
+ switch (method) {
104
+ case SnapshotHandlingMethod.AlwaysFresh:
105
+ this.log.info('is set to generate new snapshots on events every time. This might reduce homebridge performance and increase power consumption.');
106
+ if (this.cameraConfig.refreshSnapshotIntervalMinutes) {
107
+ this.log.warn('You have enabled automatic snapshot refreshing. It is recommended not to use this setting with forced snapshot refreshing.');
108
+ }
109
+ break;
110
+ case SnapshotHandlingMethod.Balanced:
111
+ this.log.info('is set to balanced snapshot handling.');
112
+ break;
113
+ case SnapshotHandlingMethod.CloudOnly:
114
+ this.log.info('is set to handle snapshots with cloud images. Snapshots might be older than they appear.');
115
+ break;
116
+ default:
117
+ this.log.warn('unknown snapshot handling method. Snapshots will not be generated.');
118
+ }
119
+ if (this.cameraConfig.immediateRingNotificationWithoutSnapshot) {
120
+ this.log.info('Empty snapshot will be sent on ring events immediately to speed up homekit notifications.');
121
+ }
122
+ }
123
+ loadPlaceholderImages() {
124
+ for (const [key, path] of Object.entries(PLACEHOLDER_PATHS)) {
125
+ try {
126
+ this.placeholders.set(key, fs.readFileSync(path));
127
+ }
128
+ catch (error) {
129
+ this.log.error(`Could not cache ${key} placeholder for further use: ${error}`);
130
+ }
131
+ }
132
+ }
133
+ getPlaceholder(key) {
134
+ const buf = this.placeholders.get(key);
135
+ if (!buf) {
136
+ throw new Error(`Placeholder image '${key}' is not available.`);
137
+ }
138
+ return buf;
139
+ }
140
+ initializeDeviceState() {
141
+ try {
142
+ const state = this.device.getPropertyValue(PropertyName.DeviceState);
143
+ this.isDeviceOffline = (state === 0 || state === 3);
144
+ if (this.isDeviceOffline) {
145
+ this.log.info('Device is currently offline (state: ' + state + ').');
146
+ }
147
+ }
148
+ catch (error) {
149
+ this.log.debug('Could not read initial device state: ' + error);
150
+ }
151
+ }
152
+ loadInitialSnapshot() {
153
+ try {
154
+ const picture = this.device.getPropertyValue(PropertyName.DevicePicture);
155
+ if (picture && picture.type) {
156
+ this.storeSnapshotForCache(picture.data, 0);
157
+ return;
158
+ }
159
+ }
160
+ catch (error) {
161
+ this.log.debug('Could not fetch snapshot from device property: ' + error);
162
+ }
163
+ // Fallback: try to load a previously cached snapshot from disk
164
+ this.loadSnapshotFromDisk();
165
+ }
166
+ loadSnapshotFromDisk() {
167
+ const serial = this.device.getSerial();
168
+ const extensions = ['jpg', 'png', 'bmp'];
169
+ for (const ext of extensions) {
170
+ const filePath = `${this.eufyPath}/${serial}.${ext}`;
171
+ try {
172
+ if (fs.existsSync(filePath)) {
173
+ const data = fs.readFileSync(filePath);
174
+ if (data.length > 0) {
175
+ const mtime = fs.statSync(filePath).mtimeMs;
176
+ this.storeSnapshotForCache(data, mtime);
177
+ this.log.info(`Loaded cached snapshot from disk: ${filePath}`);
178
+ return;
179
+ }
180
+ }
181
+ }
182
+ catch (error) {
183
+ this.log.debug(`Failed to load snapshot from ${filePath}: ${error}`);
184
+ }
185
+ }
186
+ this.log.warn('No cached snapshot found on disk for device ' + serial);
187
+ }
188
+ onDeviceEvent(eventType, device, state) {
189
+ if (!state) {
190
+ return;
191
+ }
192
+ this.log.debug(`Snapshot handler detected event: ${eventType}`);
193
+ if (eventType === 'rings') {
194
+ this.lastRingEvent = Date.now();
195
+ }
196
+ // Pre-fetch a fresh snapshot so it's ready when HomeKit asks
197
+ this.fetchCurrentCameraSnapshot().catch((error) => this.log.debug(`Background snapshot refresh on ${eventType} failed: ${error}`));
198
+ }
199
+ storeSnapshotForCache(data, time) {
200
+ this.currentSnapshot = { timestamp: time ??= Date.now(), image: data };
201
+ }
202
+ async getSnapshotBufferResized(request) {
203
+ return await this.resizeSnapshot(await this.getSnapshotBuffer(), request);
204
+ }
205
+ async getSnapshotBuffer() {
206
+ if (!this.device.isEnabled()) {
207
+ this.log.debug('Device is disabled, returning disabled snapshot.');
208
+ return this.getPlaceholder('disabled');
209
+ }
210
+ if (this.isDeviceOffline) {
211
+ this.log.debug('Device is offline, returning offline snapshot.');
212
+ return this.getPlaceholder('offline');
213
+ }
214
+ if (this.isCacheFresh(SNAPSHOT_CACHE_FRESH_SECONDS)) {
215
+ return this.currentSnapshot.image;
216
+ }
217
+ const ringAge = (Date.now() - this.lastRingEvent) / 1000;
218
+ if (this.cameraConfig.immediateRingNotificationWithoutSnapshot && ringAge < SNAPSHOT_RING_DEBOUNCE_SECONDS) {
219
+ this.log.debug('Sending empty snapshot to speed up homekit notification for ring event.');
220
+ return this.getPlaceholder('black');
221
+ }
222
+ return this.resolveByHandlingMethod();
223
+ }
224
+ async resolveByHandlingMethod() {
225
+ try {
226
+ switch (this.cameraConfig.snapshotHandlingMethod) {
227
+ case SnapshotHandlingMethod.AlwaysFresh:
228
+ return await this.fetchSnapshotFromStream();
229
+ case SnapshotHandlingMethod.Balanced:
230
+ if (this.isCacheFresh(SNAPSHOT_CACHE_BALANCED_SECONDS)) {
231
+ return this.currentSnapshot.image;
232
+ }
233
+ return await this.fetchSnapshotFromStream();
234
+ case SnapshotHandlingMethod.CloudOnly:
235
+ return this.getCachedOrPlaceholder();
236
+ default:
237
+ throw new Error('No suitable handling method for snapshots defined');
238
+ }
239
+ }
240
+ catch (err) {
241
+ this.log.warn('Snapshot retrieval failed, falling back to cache:', err);
242
+ return this.getCachedOrPlaceholder();
243
+ }
244
+ }
245
+ /**
246
+ * Fetches a fresh snapshot from a live stream.
247
+ */
248
+ async fetchSnapshotFromStream() {
249
+ this.log.info('Begin live streaming to access the most recent snapshot (significant battery drain on the device)');
250
+ await this.fetchCurrentCameraSnapshot();
251
+ if (this.currentSnapshot) {
252
+ return this.currentSnapshot.image;
253
+ }
254
+ throw new Error('Snapshot fetch completed but no snapshot stored');
255
+ }
256
+ /**
257
+ * Returns cached snapshot or the unavailable placeholder.
258
+ */
259
+ getCachedOrPlaceholder() {
260
+ if (this.currentSnapshot) {
261
+ return this.currentSnapshot.image;
262
+ }
263
+ this.log.warn('No currentSnapshot available, using fallback unavailable snapshot image');
264
+ return this.getPlaceholder('unavailable');
265
+ }
266
+ isCacheFresh(maxAgeSeconds) {
267
+ return !!this.currentSnapshot &&
268
+ (Date.now() - this.currentSnapshot.timestamp) / 1000 <= maxAgeSeconds;
269
+ }
270
+ storeImage(file, image) {
271
+ const filePath = `${this.eufyPath}/${file}`;
272
+ try {
273
+ fs.writeFileSync(filePath, image);
274
+ this.log.debug(`Stored Image: ${filePath}`);
275
+ }
276
+ catch (error) {
277
+ this.log.warn(`Failed to store image: ${filePath} - ${error}`);
278
+ }
279
+ }
280
+ async onPropertyValueChanged(device, name) {
281
+ switch (name) {
282
+ case 'picture': {
283
+ const picture = device.getPropertyValue(PropertyName.DevicePicture);
284
+ if (picture && picture.type) {
285
+ this.storeImage(`${device.getSerial()}.${picture.type.ext}`, picture.data);
286
+ if (this.currentSnapshot && (Date.now() - this.currentSnapshot.timestamp) < SNAPSHOT_CLOUD_SKIP_MS) {
287
+ this.log.debug('Skipping cloud snapshot update, a recent stream snapshot already exists.');
288
+ }
289
+ else {
290
+ this.storeSnapshotForCache(picture.data);
291
+ }
292
+ }
293
+ break;
294
+ }
295
+ case 'enabled': {
296
+ const enabled = device.getPropertyValue(PropertyName.DeviceEnabled);
297
+ this.log.info(`Device enabled state changed to: ${enabled}`);
298
+ if (enabled) {
299
+ this.currentSnapshot = undefined;
300
+ }
301
+ break;
302
+ }
303
+ case 'state': {
304
+ const state = device.getPropertyValue(PropertyName.DeviceState);
305
+ const wasOffline = this.isDeviceOffline;
306
+ this.isDeviceOffline = (state === 0 || state === 3);
307
+ if (this.isDeviceOffline && !wasOffline) {
308
+ this.log.warn(`Device went offline (state: ${state}).`);
309
+ }
310
+ else if (!this.isDeviceOffline && wasOffline) {
311
+ this.log.info(`Device came back online (state: ${state}).`);
312
+ this.currentSnapshot = undefined;
313
+ }
314
+ break;
315
+ }
316
+ }
317
+ }
318
+ /**
319
+ * Fetches a snapshot from the camera, stores it in cache, and deduplicates concurrent calls.
320
+ */
321
+ async fetchCurrentCameraSnapshot() {
322
+ if (this.pendingFetch) {
323
+ return this.pendingFetch;
324
+ }
325
+ this.log.debug('Fetching new snapshot from camera.');
326
+ this.pendingFetch = this.withTimeout((async () => {
327
+ const source = await this.getCameraSource();
328
+ const isLocalStream = source.type === 'local';
329
+ try {
330
+ const buffer = await this.runFFmpegSnapshot('[Snapshot Process]', async (params) => {
331
+ if (source.type === 'rtsp') {
332
+ params.setInputSource(source.url);
333
+ }
334
+ else {
335
+ await params.setInputStream(source.stream);
336
+ }
337
+ if (this.cameraConfig.delayCameraSnapshot) {
338
+ params.setDelayedSnapshot();
339
+ }
340
+ });
341
+ this.storeSnapshotForCache(buffer);
342
+ }
343
+ finally {
344
+ if (isLocalStream) {
345
+ this.livestreamManager.stopLocalLiveStream();
346
+ }
347
+ }
348
+ })(), SNAPSHOT_FETCH_TIMEOUT_MS).finally(() => {
349
+ this.pendingFetch = undefined;
350
+ });
351
+ return this.pendingFetch;
352
+ }
353
+ async getCameraSource() {
354
+ if (isRtspReady(this.device, this.cameraConfig)) {
355
+ const url = this.device.getPropertyValue(PropertyName.DeviceRTSPStreamUrl);
356
+ this.log.debug('RTSP URL: ' + url);
357
+ return { type: 'rtsp', url };
358
+ }
359
+ const streamData = await this.livestreamManager.getLocalLiveStream();
360
+ return { type: 'local', stream: streamData.videostream };
361
+ }
362
+ withTimeout(promise, ms) {
363
+ return new Promise((resolve, reject) => {
364
+ const timer = setTimeout(() => reject(new Error(`Snapshot fetch timed out after ${ms}ms`)), ms);
365
+ promise.then(resolve, reject).finally(() => clearTimeout(timer));
366
+ });
367
+ }
368
+ async resizeSnapshot(snapshot, request) {
369
+ return this.runFFmpegSnapshot('[Snapshot Resize]', (params) => {
370
+ params.setup(this.cameraConfig, request);
371
+ }, snapshot);
372
+ }
373
+ async runFFmpegSnapshot(label, configure, input) {
374
+ const params = await FFmpegParameters.forSnapshot(this.cameraConfig.videoConfig?.debug);
375
+ await configure(params);
376
+ return new FFmpeg(label, params).getResult(input);
377
+ }
378
+ }
379
+ //# sourceMappingURL=snapshotDelegate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshotDelegate.js","sourceRoot":"","sources":["../../src/controller/snapshotDelegate.ts"],"names":[],"mappings":"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"}