eufy-security-client 2.6.2 → 2.7.0

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 (75) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +762 -745
  3. package/build/error.d.ts +126 -56
  4. package/build/error.js +80 -58
  5. package/build/error.js.map +1 -1
  6. package/build/eufysecurity.d.ts +4 -2
  7. package/build/eufysecurity.js +372 -184
  8. package/build/eufysecurity.js.map +1 -1
  9. package/build/http/api.js +164 -113
  10. package/build/http/api.js.map +1 -1
  11. package/build/http/cache.js +2 -2
  12. package/build/http/cache.js.map +1 -1
  13. package/build/http/device.d.ts +26 -1
  14. package/build/http/device.js +544 -167
  15. package/build/http/device.js.map +1 -1
  16. package/build/http/error.d.ts +64 -19
  17. package/build/http/error.js +53 -29
  18. package/build/http/error.js.map +1 -1
  19. package/build/http/interfaces.d.ts +3 -0
  20. package/build/http/models.d.ts +25 -0
  21. package/build/http/parameter.d.ts +1 -1
  22. package/build/http/parameter.js +19 -17
  23. package/build/http/parameter.js.map +1 -1
  24. package/build/http/station.d.ts +30 -6
  25. package/build/http/station.js +1599 -530
  26. package/build/http/station.js.map +1 -1
  27. package/build/http/types.d.ts +125 -2
  28. package/build/http/types.js +932 -53
  29. package/build/http/types.js.map +1 -1
  30. package/build/http/utils.js +11 -9
  31. package/build/http/utils.js.map +1 -1
  32. package/build/mqtt/service.js +19 -16
  33. package/build/mqtt/service.js.map +1 -1
  34. package/build/p2p/ble.js +14 -6
  35. package/build/p2p/ble.js.map +1 -1
  36. package/build/p2p/error.d.ts +48 -23
  37. package/build/p2p/error.js +25 -24
  38. package/build/p2p/error.js.map +1 -1
  39. package/build/p2p/interfaces.d.ts +23 -0
  40. package/build/p2p/models.d.ts +11 -1
  41. package/build/p2p/session.d.ts +5 -0
  42. package/build/p2p/session.js +210 -142
  43. package/build/p2p/session.js.map +1 -1
  44. package/build/p2p/talkback.js +1 -1
  45. package/build/p2p/talkback.js.map +1 -1
  46. package/build/p2p/types.d.ts +36 -1
  47. package/build/p2p/types.js +72 -31
  48. package/build/p2p/types.js.map +1 -1
  49. package/build/p2p/utils.d.ts +3 -1
  50. package/build/p2p/utils.js +13 -1
  51. package/build/p2p/utils.js.map +1 -1
  52. package/build/push/client.js +24 -15
  53. package/build/push/client.js.map +1 -1
  54. package/build/push/error.d.ts +73 -0
  55. package/build/push/error.js +101 -0
  56. package/build/push/error.js.map +1 -0
  57. package/build/push/index.d.ts +1 -0
  58. package/build/push/index.js +1 -0
  59. package/build/push/index.js.map +1 -1
  60. package/build/push/models.d.ts +17 -1
  61. package/build/push/models.js +9 -2
  62. package/build/push/models.js.map +1 -1
  63. package/build/push/parser.js +17 -13
  64. package/build/push/parser.js.map +1 -1
  65. package/build/push/service.js +160 -62
  66. package/build/push/service.js.map +1 -1
  67. package/build/push/types.d.ts +10 -0
  68. package/build/push/types.js +25 -14
  69. package/build/push/types.js.map +1 -1
  70. package/build/push/utils.js +2 -1
  71. package/build/push/utils.js.map +1 -1
  72. package/build/utils.d.ts +2 -1
  73. package/build/utils.js +56 -26
  74. package/build/utils.js.map +1 -1
  75. package/package.json +77 -77
@@ -48,34 +48,41 @@ const service_2 = require("./mqtt/service");
48
48
  const const_1 = require("./http/const");
49
49
  const utils_2 = require("./http/utils");
50
50
  class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
51
+ config;
52
+ log;
53
+ api;
54
+ houses = {};
55
+ stations = {};
56
+ devices = {};
57
+ P2P_REFRESH_INTERVAL_MIN = 720;
58
+ cameraMaxLivestreamSeconds = 30;
59
+ cameraStationLivestreamTimeout = new Map();
60
+ cameraCloudLivestreamTimeout = new Map();
61
+ pushService;
62
+ mqttService;
63
+ pushCloudRegistered = false;
64
+ pushCloudChecked = false;
65
+ persistentFile;
66
+ persistentData = {
67
+ country: "",
68
+ openudid: "",
69
+ serial_number: "",
70
+ push_credentials: undefined,
71
+ push_persistentIds: [],
72
+ login_hash: "",
73
+ version: "",
74
+ httpApi: undefined
75
+ };
76
+ connected = false;
77
+ retries = 0;
78
+ refreshEufySecurityCloudTimeout;
79
+ refreshEufySecurityP2PTimeout = {};
80
+ deviceSnoozeTimeout = {};
81
+ loadingEmitter = new events_1.default();
82
+ stationsLoaded;
83
+ devicesLoaded;
51
84
  constructor(config, log = ts_log_1.dummyLogger) {
52
85
  super();
53
- this.houses = {};
54
- this.stations = {};
55
- this.devices = {};
56
- this.P2P_REFRESH_INTERVAL_MIN = 720;
57
- this.cameraMaxLivestreamSeconds = 30;
58
- this.cameraStationLivestreamTimeout = new Map();
59
- this.cameraCloudLivestreamTimeout = new Map();
60
- this.pushCloudRegistered = false;
61
- this.pushCloudChecked = false;
62
- this.persistentData = {
63
- country: "",
64
- openudid: "",
65
- serial_number: "",
66
- push_credentials: undefined,
67
- push_persistentIds: [],
68
- login_hash: "",
69
- version: "",
70
- httpApi: undefined
71
- };
72
- this.connected = false;
73
- this.retries = 0;
74
- this.refreshEufySecurityP2PTimeout = {};
75
- this.deviceSnoozeTimeout = {};
76
- this.stationsLoaded = false;
77
- this.devicesLoaded = false;
78
- this.loadingEmitter = new events_1.default();
79
86
  this.config = config;
80
87
  this.log = log;
81
88
  }
@@ -123,7 +130,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
123
130
  }
124
131
  }
125
132
  catch (err) {
126
- this.log.debug("No stored data from last exit found");
133
+ const error = (0, error_1.ensureError)(err);
134
+ this.log.debug("No stored data from last exit found", error);
127
135
  }
128
136
  try {
129
137
  if (this.persistentData.version !== _1.libVersion) {
@@ -137,8 +145,9 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
137
145
  }
138
146
  }
139
147
  }
140
- catch (error) {
141
- this.log.error("Handling update - Error:", error);
148
+ catch (err) {
149
+ const error = (0, error_1.ensureError)(err);
150
+ this.log.error("Handling update - Error", error);
142
151
  }
143
152
  if (this.config.trustedDeviceName === undefined || this.config.trustedDeviceName === "") {
144
153
  if (this.persistentData.fallbackTrustedDeviceName !== undefined) {
@@ -239,7 +248,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
239
248
  this.mqttService.on("lock message", (message) => {
240
249
  this.getDevice(message.data.data.deviceSn).then((device) => {
241
250
  device.processMQTTNotification(message.data.data, this.config.eventDurationSeconds);
242
- }).catch((error) => {
251
+ }).catch((err) => {
252
+ const error = (0, error_1.ensureError)(err);
243
253
  if (error instanceof error_1.DeviceNotFoundError) {
244
254
  }
245
255
  else {
@@ -278,11 +288,11 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
278
288
  }
279
289
  }
280
290
  async updateStation(hub) {
281
- if (!this.stationsLoaded)
282
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "stations loaded");
291
+ if (this.stationsLoaded)
292
+ await this.stationsLoaded;
283
293
  if (Object.keys(this.stations).includes(hub.station_sn)) {
284
294
  this.stations[hub.station_sn].update(hub, this.stations[hub.station_sn] !== undefined && !this.stations[hub.station_sn].isIntegratedDevice() && this.stations[hub.station_sn].isConnected());
285
- if (!this.stations[hub.station_sn].isConnected() && !this.stations[hub.station_sn].isEnergySavingDevice()) {
295
+ if (!this.stations[hub.station_sn].isConnected() && !this.stations[hub.station_sn].isEnergySavingDevice() && this.stations[hub.station_sn].isP2PConnectableDevice()) {
286
296
  this.stations[hub.station_sn].setConnectionType(this.config.p2pConnectionSetup);
287
297
  this.stations[hub.station_sn].connect();
288
298
  }
@@ -299,7 +309,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
299
309
  await station.getStorageInfoEx();
300
310
  }
301
311
  }
302
- catch (error) {
312
+ catch (err) {
313
+ const error = (0, error_1.ensureError)(err);
303
314
  this.log.error("getStorageInfo Error", error);
304
315
  }
305
316
  }
@@ -327,16 +338,16 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
327
338
  }
328
339
  }
329
340
  async updateDevice(device) {
330
- if (!this.devicesLoaded)
331
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
341
+ if (this.devicesLoaded)
342
+ await this.devicesLoaded;
332
343
  if (Object.keys(this.devices).includes(device.device_sn))
333
344
  this.devices[device.device_sn].update(device, this.stations[device.station_sn] !== undefined && !this.stations[device.station_sn].isIntegratedDevice() && this.stations[device.station_sn].isConnected());
334
345
  else
335
346
  this.log.debug(`Device with this serial ${device.device_sn} doesn't exists and couldn't be updated!`);
336
347
  }
337
348
  async getDevices() {
338
- if (!this.devicesLoaded)
339
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
349
+ if (this.devicesLoaded)
350
+ await this.devicesLoaded;
340
351
  const arr = [];
341
352
  Object.keys(this.devices).forEach((serialNumber) => {
342
353
  arr.push(this.devices[serialNumber]);
@@ -344,8 +355,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
344
355
  return arr;
345
356
  }
346
357
  async getDevicesFromStation(stationSN) {
347
- if (!this.devicesLoaded)
348
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
358
+ if (this.devicesLoaded)
359
+ await this.devicesLoaded;
349
360
  const arr = [];
350
361
  Object.keys(this.devices).forEach((serialNumber) => {
351
362
  if (this.devices[serialNumber].getStationSerial() === stationSN)
@@ -354,25 +365,25 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
354
365
  return arr;
355
366
  }
356
367
  async getDevice(deviceSN) {
357
- if (!this.devicesLoaded)
358
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
368
+ if (this.devicesLoaded)
369
+ await this.devicesLoaded;
359
370
  if (Object.keys(this.devices).includes(deviceSN))
360
371
  return this.devices[deviceSN];
361
- throw new error_1.DeviceNotFoundError(`Device with this serial ${deviceSN} doesn't exists!`);
372
+ throw new error_1.DeviceNotFoundError("Device doesn't exists", { context: { device: deviceSN } });
362
373
  }
363
374
  async getStationDevice(stationSN, channel) {
364
- if (!this.devicesLoaded)
365
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
375
+ if (this.devicesLoaded)
376
+ await this.devicesLoaded;
366
377
  for (const device of Object.values(this.devices)) {
367
378
  if ((device.getStationSerial() === stationSN && device.getChannel() === channel) || (device.getStationSerial() === stationSN && device.getSerial() === stationSN)) {
368
379
  return device;
369
380
  }
370
381
  }
371
- throw new error_1.DeviceNotFoundError(`No device with channel ${channel} found on station with serial number: ${stationSN}!`);
382
+ throw new error_1.DeviceNotFoundError("No device with passed channel found on station", { context: { station: stationSN, channel: channel } });
372
383
  }
373
384
  async getStations() {
374
- if (!this.stationsLoaded)
375
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "stations loaded");
385
+ if (this.stationsLoaded)
386
+ await this.stationsLoaded;
376
387
  const arr = [];
377
388
  Object.keys(this.stations).forEach((serialNumber) => {
378
389
  arr.push(this.stations[serialNumber]);
@@ -380,19 +391,21 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
380
391
  return arr;
381
392
  }
382
393
  async getStation(stationSN) {
383
- if (!this.stationsLoaded)
384
- await (0, utils_1.waitForEvent)(this.loadingEmitter, "stations loaded");
394
+ if (this.stationsLoaded)
395
+ await this.stationsLoaded;
385
396
  if (Object.keys(this.stations).includes(stationSN))
386
397
  return this.stations[stationSN];
387
- throw new error_1.StationNotFoundError(`No station with serial number: ${stationSN}!`);
398
+ throw new error_1.StationNotFoundError("Station doesn't exists", { context: { station: stationSN } });
388
399
  }
389
400
  getApi() {
390
401
  return this.api;
391
402
  }
392
403
  async connectToStation(stationSN, p2pConnectionType = types_2.P2PConnectionType.QUICKEST) {
393
404
  const station = await this.getStation(stationSN);
394
- station.setConnectionType(p2pConnectionType);
395
- station.connect();
405
+ if (station.isP2PConnectableDevice()) {
406
+ station.setConnectionType(p2pConnectionType);
407
+ station.connect();
408
+ }
396
409
  }
397
410
  async isStationConnected(stationSN) {
398
411
  const station = await this.getStation(stationSN);
@@ -417,7 +430,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
417
430
  this.updateStation(hub);
418
431
  }
419
432
  else {
420
- this.stationsLoaded = false;
433
+ this.stationsLoaded = (0, utils_1.waitForEvent)(this.loadingEmitter, "stations loaded");
421
434
  let ipAddress;
422
435
  if (this.config.stationIPAddresses !== undefined) {
423
436
  ipAddress = this.config.stationIPAddresses[hub.station_sn];
@@ -466,29 +479,33 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
466
479
  station.on("database query local", (station, returnCode, data) => this.onStationDatabaseQueryLocal(station, returnCode, data));
467
480
  station.on("database count by date", (station, returnCode, data) => this.onStationDatabaseCountByDate(station, returnCode, data));
468
481
  station.on("database delete", (station, returnCode, failedIds) => this.onStationDatabaseDelete(station, returnCode, failedIds));
482
+ station.on("sensor status", (station, channel, status) => this.onStationSensorStatus(station, channel, status));
483
+ station.on("garage door status", (station, channel, doorId, status) => this.onStationGarageDoorStatus(station, channel, doorId, status));
469
484
  this.addStation(station);
470
485
  station.initialize();
471
486
  }
472
- catch (error) {
473
- this.log.error("Error", error);
487
+ catch (err) {
488
+ const error = (0, error_1.ensureError)(err);
489
+ this.log.error("HandleHubs Error", error);
474
490
  }
475
491
  return station;
476
492
  }));
477
493
  }
478
494
  }
479
495
  Promise.all(promises).then(() => {
480
- this.stationsLoaded = true;
481
496
  this.loadingEmitter.emit("stations loaded");
497
+ this.stationsLoaded = undefined;
482
498
  });
483
499
  if (promises.length === 0) {
484
- this.stationsLoaded = true;
485
500
  this.loadingEmitter.emit("stations loaded");
501
+ this.stationsLoaded = undefined;
486
502
  }
487
503
  for (const stationSN of stationsSNs) {
488
504
  if (!newStationsSNs.includes(stationSN)) {
489
505
  this.getStation(stationSN).then((station) => {
490
506
  this.removeStation(station);
491
- }).catch((error) => {
507
+ }).catch((err) => {
508
+ const error = (0, error_1.ensureError)(err);
492
509
  this.log.error("Error removing station", error);
493
510
  });
494
511
  }
@@ -497,7 +514,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
497
514
  onStationConnect(station) {
498
515
  this.emit("station connect", station);
499
516
  if ((device_1.Device.isCamera(station.getDeviceType()) && !device_1.Device.isWiredDoorbell(station.getDeviceType()) || device_1.Device.isSmartSafe(station.getDeviceType()))) {
500
- station.getCameraInfo().catch(error => {
517
+ station.getCameraInfo().catch(err => {
518
+ const error = (0, error_1.ensureError)(err);
501
519
  this.log.error(`Error during station ${station.getSerial()} p2p data refreshing`, error);
502
520
  });
503
521
  if (this.refreshEufySecurityP2PTimeout[station.getSerial()] !== undefined) {
@@ -506,7 +524,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
506
524
  }
507
525
  if (!station.isEnergySavingDevice()) {
508
526
  this.refreshEufySecurityP2PTimeout[station.getSerial()] = setTimeout(() => {
509
- station.getCameraInfo().catch(error => {
527
+ station.getCameraInfo().catch(err => {
528
+ const error = (0, error_1.ensureError)(err);
510
529
  this.log.error(`Error during station ${station.getSerial()} p2p data refreshing`, error);
511
530
  });
512
531
  }, this.P2P_REFRESH_INTERVAL_MIN * 60 * 1000);
@@ -524,8 +543,9 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
524
543
  clearTimeout(this.cameraStationLivestreamTimeout.get(device_sn));
525
544
  this.cameraStationLivestreamTimeout.delete(device_sn);
526
545
  }
527
- }).catch((error) => {
528
- this.log.error(`Station ${station.getSerial()} - Error:`, error);
546
+ }).catch((err) => {
547
+ const error = (0, error_1.ensureError)(err);
548
+ this.log.error(`Station ${station.getSerial()} - Error`, error);
529
549
  });
530
550
  }
531
551
  }
@@ -539,7 +559,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
539
559
  this.updateDevice(device);
540
560
  }
541
561
  else {
542
- this.devicesLoaded = false;
562
+ this.devicesLoaded = (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
543
563
  let new_device;
544
564
  if (device_1.Device.isIndoorCamera(device.device_type)) {
545
565
  new_device = device_1.IndoorCamera.getInstance(this.api, device);
@@ -556,6 +576,12 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
556
576
  else if (device_1.Device.isFloodLight(device.device_type)) {
557
577
  new_device = device_1.FloodlightCamera.getInstance(this.api, device);
558
578
  }
579
+ else if (device_1.Device.isWallLightCam(device.device_type)) {
580
+ new_device = device_1.WallLightCam.getInstance(this.api, device);
581
+ }
582
+ else if (device_1.Device.isGarageCamera(device.device_type)) {
583
+ new_device = device_1.GarageCamera.getInstance(this.api, device);
584
+ }
559
585
  else if (device_1.Device.isCamera(device.device_type)) {
560
586
  new_device = device_1.Camera.getInstance(this.api, device);
561
587
  }
@@ -609,8 +635,9 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
609
635
  this.addDevice(device);
610
636
  device.initialize();
611
637
  }
612
- catch (error) {
613
- this.log.error("Error", error);
638
+ catch (err) {
639
+ const error = (0, error_1.ensureError)(err);
640
+ this.log.error("HandleDevices Error", error);
614
641
  }
615
642
  return device;
616
643
  }));
@@ -619,26 +646,28 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
619
646
  Promise.all(promises).then((devices) => {
620
647
  devices.forEach((device) => {
621
648
  this.getStation(device.getStationSerial()).then((station) => {
622
- if (!station.isConnected()) {
649
+ if (!station.isConnected() && station.isP2PConnectableDevice()) {
623
650
  station.setConnectionType(this.config.p2pConnectionSetup);
624
651
  station.connect();
625
652
  }
626
- }).catch((error) => {
653
+ }).catch((err) => {
654
+ const error = (0, error_1.ensureError)(err);
627
655
  this.log.error("Error trying to connect to station afte device loaded", error);
628
656
  });
629
657
  });
630
- this.devicesLoaded = true;
631
658
  this.loadingEmitter.emit("devices loaded");
659
+ this.devicesLoaded = undefined;
632
660
  });
633
661
  if (promises.length === 0) {
634
- this.devicesLoaded = true;
635
662
  this.loadingEmitter.emit("devices loaded");
663
+ this.devicesLoaded = undefined;
636
664
  }
637
665
  for (const deviceSN of deviceSNs) {
638
666
  if (!newDeviceSNs.includes(deviceSN)) {
639
667
  this.getDevice(deviceSN).then((device) => {
640
668
  this.removeDevice(device);
641
- }).catch((error) => {
669
+ }).catch((err) => {
670
+ const error = (0, error_1.ensureError)(err);
642
671
  this.log.error("Error removing device", error);
643
672
  });
644
673
  }
@@ -646,11 +675,13 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
646
675
  }
647
676
  async refreshCloudData() {
648
677
  if (this.config.acceptInvitations) {
649
- await this.processInvitations().catch(error => {
678
+ await this.processInvitations().catch(err => {
679
+ const error = (0, error_1.ensureError)(err);
650
680
  this.log.error("Error in processing invitations", error);
651
681
  });
652
682
  }
653
- await this.api.refreshAllData().catch(error => {
683
+ await this.api.refreshAllData().catch(err => {
684
+ const error = (0, error_1.ensureError)(err);
654
685
  this.log.error("Error during API data refreshing", error);
655
686
  });
656
687
  if (this.refreshEufySecurityCloudTimeout !== undefined)
@@ -703,7 +734,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
703
734
  async connect(options) {
704
735
  await this.api.login(options)
705
736
  .then(async () => {
706
- if (options === null || options === void 0 ? void 0 : options.verifyCode) {
737
+ if (options?.verifyCode) {
707
738
  let trusted = false;
708
739
  const trusted_devices = await this.api.listTrustDevice();
709
740
  trusted_devices.forEach(trusted_device => {
@@ -712,10 +743,11 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
712
743
  }
713
744
  });
714
745
  if (!trusted)
715
- return await this.api.addTrustDevice(options === null || options === void 0 ? void 0 : options.verifyCode);
746
+ return await this.api.addTrustDevice(options?.verifyCode);
716
747
  }
717
748
  })
718
- .catch((error) => {
749
+ .catch((err) => {
750
+ const error = (0, error_1.ensureError)(err);
719
751
  this.log.error("Connect Error", error);
720
752
  });
721
753
  }
@@ -725,7 +757,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
725
757
  updateDeviceProperties(deviceSN, values) {
726
758
  this.getDevice(deviceSN).then((device) => {
727
759
  device.updateRawProperties(values);
728
- }).catch((error) => {
760
+ }).catch((err) => {
761
+ const error = (0, error_1.ensureError)(err);
729
762
  this.log.error(`Update device ${deviceSN} properties error`, error);
730
763
  });
731
764
  }
@@ -764,7 +797,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
764
797
  const device = await this.getDevice(deviceSN);
765
798
  const station = await this.getStation(device.getStationSerial());
766
799
  if (!device.hasCommand(types_1.CommandName.DeviceStartLivestream))
767
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
800
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStartLivestream } });
768
801
  const camera = device;
769
802
  if (!station.isLiveStreaming(camera)) {
770
803
  await station.startLivestream(camera);
@@ -783,7 +816,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
783
816
  const device = await this.getDevice(deviceSN);
784
817
  const station = await this.getStation(device.getStationSerial());
785
818
  if (!device.hasCommand(types_1.CommandName.DeviceStartLivestream))
786
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
819
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStartLivestream } });
787
820
  const camera = device;
788
821
  if (!camera.isStreaming()) {
789
822
  const url = await camera.startStream();
@@ -808,7 +841,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
808
841
  const device = await this.getDevice(deviceSN);
809
842
  const station = await this.getStation(device.getStationSerial());
810
843
  if (!device.hasCommand(types_1.CommandName.DeviceStopLivestream))
811
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
844
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStopLivestream } });
812
845
  if (station.isConnected() && station.isLiveStreaming(device)) {
813
846
  await station.stopLivestream(device);
814
847
  }
@@ -825,7 +858,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
825
858
  const device = await this.getDevice(deviceSN);
826
859
  const station = await this.getStation(device.getStationSerial());
827
860
  if (!device.hasCommand(types_1.CommandName.DeviceStopLivestream))
828
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
861
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStopLivestream } });
829
862
  const camera = device;
830
863
  if (camera.isStreaming()) {
831
864
  await camera.stopStream();
@@ -841,15 +874,15 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
841
874
  }
842
875
  }
843
876
  writePersistentData() {
844
- var _a, _b;
845
877
  this.persistentData.login_hash = (0, utils_1.md5)(`${this.config.username}:${this.config.password}`);
846
- this.persistentData.httpApi = (_a = this.api) === null || _a === void 0 ? void 0 : _a.getPersistentData();
847
- this.persistentData.country = (_b = this.api) === null || _b === void 0 ? void 0 : _b.getCountry();
878
+ this.persistentData.httpApi = this.api?.getPersistentData();
879
+ this.persistentData.country = this.api?.getCountry();
848
880
  try {
849
881
  fse.writeFileSync(this.persistentFile, JSON.stringify(this.persistentData));
850
882
  }
851
- catch (error) {
852
- this.log.error("Error:", error);
883
+ catch (err) {
884
+ const error = (0, error_1.ensureError)(err);
885
+ this.log.error("WritePersistentData Error", error);
853
886
  }
854
887
  }
855
888
  saveCloudToken() {
@@ -884,8 +917,9 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
884
917
  }
885
918
  async processInvitations() {
886
919
  let refreshCloud = false;
887
- const invites = await this.api.getInvites().catch(error => {
888
- this.log.error("processInvitations - getInvites - Error:", error);
920
+ const invites = await this.api.getInvites().catch(err => {
921
+ const error = (0, error_1.ensureError)(err);
922
+ this.log.error("processInvitations - getInvites - Error", error);
889
923
  return error;
890
924
  });
891
925
  if (Object.keys(invites).length > 0) {
@@ -904,8 +938,9 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
904
938
  }
905
939
  }
906
940
  if (confirmInvites.length > 0) {
907
- const result = await this.api.confirmInvites(confirmInvites).catch(error => {
908
- this.log.error("processInvitations - confirmInvites - Error:", error);
941
+ const result = await this.api.confirmInvites(confirmInvites).catch(err => {
942
+ const error = (0, error_1.ensureError)(err);
943
+ this.log.error("processInvitations - confirmInvites - Error", error);
909
944
  return error;
910
945
  });
911
946
  if (result) {
@@ -914,14 +949,16 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
914
949
  }
915
950
  }
916
951
  }
917
- const houseInvites = await this.api.getHouseInviteList().catch(error => {
918
- this.log.error("processInvitations - getHouseInviteList - Error:", error);
952
+ const houseInvites = await this.api.getHouseInviteList().catch(err => {
953
+ const error = (0, error_1.ensureError)(err);
954
+ this.log.error("processInvitations - getHouseInviteList - Error", error);
919
955
  return error;
920
956
  });
921
957
  if (Object.keys(houseInvites).length > 0) {
922
958
  for (const invite of Object.values(houseInvites)) {
923
- const result = await this.api.confirmHouseInvite(invite.house_id, invite.id).catch(error => {
924
- this.log.error("processInvitations - confirmHouseInvite - Error:", error);
959
+ const result = await this.api.confirmHouseInvite(invite.house_id, invite.id).catch(err => {
960
+ const error = (0, error_1.ensureError)(err);
961
+ this.log.error("processInvitations - confirmHouseInvite - Error", error);
925
962
  return error;
926
963
  });
927
964
  if (result) {
@@ -943,7 +980,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
943
980
  this.processInvitations();
944
981
  }
945
982
  }
946
- catch (error) {
983
+ catch (err) {
984
+ const error = (0, error_1.ensureError)(err);
947
985
  this.log.error(`Error processing server push notification for device invitation`, error);
948
986
  }
949
987
  try {
@@ -952,7 +990,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
952
990
  this.refreshCloudData();
953
991
  }
954
992
  }
955
- catch (error) {
993
+ catch (err) {
994
+ const error = (0, error_1.ensureError)(err);
956
995
  this.log.error(`Error processing server push notification for device/station/house removal`, error);
957
996
  }
958
997
  this.getStations().then((stations) => {
@@ -960,11 +999,13 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
960
999
  try {
961
1000
  station.processPushNotification(message);
962
1001
  }
963
- catch (error) {
1002
+ catch (err) {
1003
+ const error = (0, error_1.ensureError)(err);
964
1004
  this.log.error(`Error processing push notification for station ${station.getSerial()}`, error);
965
1005
  }
966
1006
  });
967
- }).catch((error) => {
1007
+ }).catch((err) => {
1008
+ const error = (0, error_1.ensureError)(err);
968
1009
  this.log.error("Process push notification for stations", error);
969
1010
  });
970
1011
  this.getDevices().then((devices) => {
@@ -972,23 +1013,26 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
972
1013
  try {
973
1014
  device.processPushNotification(message, this.config.eventDurationSeconds);
974
1015
  }
975
- catch (error) {
1016
+ catch (err) {
1017
+ const error = (0, error_1.ensureError)(err);
976
1018
  this.log.error(`Error processing push notification for device ${device.getSerial()}`, error);
977
1019
  }
978
1020
  });
979
- }).catch((error) => {
1021
+ }).catch((err) => {
1022
+ const error = (0, error_1.ensureError)(err);
980
1023
  this.log.error("Process push notification for devices", error);
981
1024
  });
982
1025
  }
983
- catch (error) {
984
- this.log.error("Generic Error:", error);
1026
+ catch (err) {
1027
+ const error = (0, error_1.ensureError)(err);
1028
+ this.log.error("OnPushMessage Generic Error", error);
985
1029
  }
986
1030
  }
987
1031
  async startStationDownload(deviceSN, path, cipherID) {
988
1032
  const device = await this.getDevice(deviceSN);
989
1033
  const station = await this.getStation(device.getStationSerial());
990
- if (!device.isCamera())
991
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
1034
+ if (!device.hasCommand(types_1.CommandName.DeviceStartDownload))
1035
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStartDownload, path: path, cipherID: cipherID } });
992
1036
  if (!station.isDownloading(device)) {
993
1037
  await station.startDownload(device, path, cipherID);
994
1038
  }
@@ -999,8 +1043,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
999
1043
  async cancelStationDownload(deviceSN) {
1000
1044
  const device = await this.getDevice(deviceSN);
1001
1045
  const station = await this.getStation(device.getStationSerial());
1002
- if (!device.isCamera())
1003
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
1046
+ if (!device.hasCommand(types_1.CommandName.DeviceCancelDownload))
1047
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceCancelDownload } });
1004
1048
  if (station.isConnected() && station.isDownloading(device)) {
1005
1049
  await station.cancelDownload(device);
1006
1050
  }
@@ -1420,7 +1464,12 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1420
1464
  await station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.HUMAN_RECOGNITION, value);
1421
1465
  break;
1422
1466
  case types_1.PropertyName.DeviceMotionDetectionTypeHuman:
1423
- await station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.HUMAN_DETECTION, value);
1467
+ if (device.isWallLightCam()) {
1468
+ await station.setMotionDetectionTypeHuman(device, value);
1469
+ }
1470
+ else {
1471
+ await station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.HUMAN_DETECTION, value);
1472
+ }
1424
1473
  break;
1425
1474
  case types_1.PropertyName.DeviceMotionDetectionTypePet:
1426
1475
  await station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.PET_DETECTION, value);
@@ -1429,12 +1478,68 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1429
1478
  await station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.VEHICLE_DETECTION, value);
1430
1479
  break;
1431
1480
  case types_1.PropertyName.DeviceMotionDetectionTypeAllOtherMotions:
1432
- await station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.ALL_OTHER_MOTION, value);
1481
+ if (device.isWallLightCam()) {
1482
+ await station.setMotionDetectionTypeAllOtherMotions(device, value);
1483
+ }
1484
+ else {
1485
+ await station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.ALL_OTHER_MOTION, value);
1486
+ }
1487
+ break;
1488
+ case types_1.PropertyName.DeviceLightSettingsManualLightingActiveMode:
1489
+ await station.setLightSettingsManualLightingActiveMode(device, value);
1490
+ break;
1491
+ case types_1.PropertyName.DeviceLightSettingsManualDailyLighting:
1492
+ await station.setLightSettingsManualDailyLighting(device, value);
1493
+ break;
1494
+ case types_1.PropertyName.DeviceLightSettingsManualColoredLighting:
1495
+ await station.setLightSettingsManualColoredLighting(device, value);
1496
+ break;
1497
+ case types_1.PropertyName.DeviceLightSettingsManualDynamicLighting:
1498
+ await station.setLightSettingsManualDynamicLighting(device, value);
1499
+ break;
1500
+ case types_1.PropertyName.DeviceLightSettingsMotionLightingActiveMode:
1501
+ await station.setLightSettingsMotionLightingActiveMode(device, value);
1502
+ break;
1503
+ case types_1.PropertyName.DeviceLightSettingsMotionDailyLighting:
1504
+ await station.setLightSettingsMotionDailyLighting(device, value);
1505
+ break;
1506
+ case types_1.PropertyName.DeviceLightSettingsMotionColoredLighting:
1507
+ await station.setLightSettingsMotionColoredLighting(device, value);
1508
+ break;
1509
+ case types_1.PropertyName.DeviceLightSettingsMotionDynamicLighting:
1510
+ await station.setLightSettingsMotionDynamicLighting(device, value);
1511
+ break;
1512
+ case types_1.PropertyName.DeviceLightSettingsScheduleLightingActiveMode:
1513
+ await station.setLightSettingsScheduleLightingActiveMode(device, value);
1514
+ break;
1515
+ case types_1.PropertyName.DeviceLightSettingsScheduleDailyLighting:
1516
+ await station.setLightSettingsScheduleDailyLighting(device, value);
1517
+ break;
1518
+ case types_1.PropertyName.DeviceLightSettingsScheduleColoredLighting:
1519
+ await station.setLightSettingsScheduleColoredLighting(device, value);
1520
+ break;
1521
+ case types_1.PropertyName.DeviceLightSettingsScheduleDynamicLighting:
1522
+ await station.setLightSettingsScheduleDynamicLighting(device, value);
1523
+ break;
1524
+ case types_1.PropertyName.DeviceLightSettingsColoredLightingColors:
1525
+ await station.setLightSettingsColoredLightingColors(device, value);
1526
+ break;
1527
+ case types_1.PropertyName.DeviceLightSettingsDynamicLightingThemes:
1528
+ await station.setLightSettingsDynamicLightingThemes(device, value);
1529
+ break;
1530
+ case types_1.PropertyName.DeviceDoorControlWarning:
1531
+ await station.setDoorControlWarning(device, value);
1532
+ break;
1533
+ case types_1.PropertyName.DeviceDoor1Open:
1534
+ await station.openDoor(device, value, 1);
1535
+ break;
1536
+ case types_1.PropertyName.DeviceDoor2Open:
1537
+ await station.openDoor(device, value, 2);
1433
1538
  break;
1434
1539
  default:
1435
1540
  if (!Object.values(types_1.PropertyName).includes(name))
1436
- throw new error_1.ReadOnlyPropertyError(`Property ${name} is read only`);
1437
- throw new error_2.InvalidPropertyError(`Device ${deviceSN} has no writable property named ${name}`);
1541
+ throw new error_1.ReadOnlyPropertyError("Property is read only", { context: { device: deviceSN, propertyName: name, propertyValue: value } });
1542
+ throw new error_2.InvalidPropertyError("Device has no writable property", { context: { device: deviceSN, propertyName: name, propertyValue: value } });
1438
1543
  }
1439
1544
  }
1440
1545
  async setStationProperty(stationSN, name, value) {
@@ -1483,72 +1588,95 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1483
1588
  break;
1484
1589
  default:
1485
1590
  if (!Object.values(types_1.PropertyName).includes(name))
1486
- throw new error_1.ReadOnlyPropertyError(`Property ${name} is read only`);
1487
- throw new error_2.InvalidPropertyError(`Station ${stationSN} has no writable property named ${name}`);
1591
+ throw new error_1.ReadOnlyPropertyError("Property is read only", { context: { station: stationSN, propertyName: name, propertyValue: value } });
1592
+ throw new error_2.InvalidPropertyError("Station has no writable property", { context: { station: stationSN, propertyName: name, propertyValue: value } });
1488
1593
  }
1489
1594
  }
1490
1595
  onStartStationLivestream(station, channel, metadata, videostream, audiostream) {
1491
1596
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1492
1597
  this.emit("station livestream start", station, device, metadata, videostream, audiostream);
1493
- }).catch((error) => {
1598
+ }).catch((err) => {
1599
+ const error = (0, error_1.ensureError)(err);
1494
1600
  this.log.error(`Station start livestream error (station: ${station.getSerial()} channel: ${channel})`, error);
1495
1601
  });
1496
1602
  }
1497
1603
  onStopStationLivestream(station, channel) {
1498
1604
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1499
1605
  this.emit("station livestream stop", station, device);
1500
- }).catch((error) => {
1606
+ }).catch((err) => {
1607
+ const error = (0, error_1.ensureError)(err);
1501
1608
  this.log.error(`Station stop livestream error (station: ${station.getSerial()} channel: ${channel})`, error);
1502
1609
  });
1503
1610
  }
1504
1611
  onErrorStationLivestream(station, channel, _error) {
1505
1612
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1506
- station.stopLivestream(device).catch((error) => {
1613
+ station.stopLivestream(device).catch((err) => {
1614
+ const error = (0, error_1.ensureError)(err);
1507
1615
  this.log.error(`Station livestream error (station: ${station.getSerial()} channel: ${channel} error: ${_error}})`, error);
1508
1616
  });
1509
- }).catch((error) => {
1617
+ }).catch((err) => {
1618
+ const error = (0, error_1.ensureError)(err);
1510
1619
  this.log.error(`Station livestream error (station: ${station.getSerial()} channel: ${channel} error: ${_error}})`, error);
1511
1620
  });
1512
1621
  }
1513
1622
  onStartStationRTSPLivestream(station, channel) {
1514
1623
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1515
1624
  this.emit("station rtsp livestream start", station, device);
1516
- }).catch((error) => {
1625
+ }).catch((err) => {
1626
+ const error = (0, error_1.ensureError)(err);
1517
1627
  this.log.error(`Station start rtsp livestream error (station: ${station.getSerial()} channel: ${channel})`, error);
1518
1628
  });
1519
1629
  }
1520
1630
  onStopStationRTSPLivestream(station, channel) {
1521
1631
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1522
1632
  this.emit("station rtsp livestream stop", station, device);
1523
- }).catch((error) => {
1633
+ }).catch((err) => {
1634
+ const error = (0, error_1.ensureError)(err);
1524
1635
  this.log.error(`Station stop rtsp livestream error (station: ${station.getSerial()} channel: ${channel})`, error);
1525
1636
  });
1526
1637
  }
1527
1638
  onStationStartDownload(station, channel, metadata, videoStream, audioStream) {
1528
1639
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1529
1640
  this.emit("station download start", station, device, metadata, videoStream, audioStream);
1530
- }).catch((error) => {
1641
+ }).catch((err) => {
1642
+ const error = (0, error_1.ensureError)(err);
1531
1643
  this.log.error(`Station start download error (station: ${station.getSerial()} channel: ${channel})`, error);
1532
1644
  });
1533
1645
  }
1534
1646
  onStationFinishDownload(station, channel) {
1535
1647
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1536
1648
  this.emit("station download finish", station, device);
1537
- }).catch((error) => {
1649
+ }).catch((err) => {
1650
+ const error = (0, error_1.ensureError)(err);
1538
1651
  this.log.error(`Station finish download error (station: ${station.getSerial()} channel: ${channel})`, error);
1539
1652
  });
1540
1653
  }
1541
1654
  onStationCommandResult(station, result) {
1542
1655
  this.emit("station command result", station, result);
1543
1656
  if (result.return_code === 0) {
1657
+ if (result.customData !== undefined && result.customData.onSuccess !== undefined) {
1658
+ try {
1659
+ result.customData.onSuccess();
1660
+ }
1661
+ catch (err) {
1662
+ const error = (0, error_1.ensureError)(err);
1663
+ this.log.error(`Station command result (station: ${station.getSerial()}) - onSuccess callback error`, error);
1664
+ }
1665
+ }
1544
1666
  this.getStationDevice(station.getSerial(), result.channel).then((device) => {
1545
1667
  if ((result.customData !== undefined && result.customData.property !== undefined && !device.isLockWifiR10() && !device.isLockWifiR20() && !device.isLockWifiVideo() && !device.isSmartSafe()) ||
1546
1668
  (result.customData !== undefined && result.customData.property !== undefined && device.isSmartSafe() && result.command_type !== types_2.CommandType.CMD_SMARTSAFE_SETTINGS)) {
1547
1669
  if (device.hasProperty(result.customData.property.name)) {
1548
- device.updateProperty(result.customData.property.name, result.customData.property.value);
1670
+ const metadata = device.getPropertyMetadata(result.customData.property.name);
1671
+ if (typeof result.customData.property.value !== "object" || metadata.type === "object") {
1672
+ device.updateProperty(result.customData.property.name, result.customData.property.value);
1673
+ }
1549
1674
  }
1550
1675
  else if (station.hasProperty(result.customData.property.name)) {
1551
- station.updateProperty(result.customData.property.name, result.customData.property.value);
1676
+ const metadata = station.getPropertyMetadata(result.customData.property.name);
1677
+ if (typeof result.customData.property.value !== "object" || metadata.type === "object") {
1678
+ station.updateProperty(result.customData.property.name, result.customData.property.value);
1679
+ }
1552
1680
  }
1553
1681
  }
1554
1682
  else if (result.customData !== undefined && result.customData.command !== undefined && result.customData.command.name === types_1.CommandName.DeviceSnooze) {
@@ -1582,11 +1710,13 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1582
1710
  }
1583
1711
  delete this.deviceSnoozeTimeout[device.getSerial()];
1584
1712
  }, timeoutMS);
1585
- }).catch(error => {
1713
+ }).catch(err => {
1714
+ const error = (0, error_1.ensureError)(err);
1586
1715
  this.log.error("Error during API data refreshing", error);
1587
1716
  });
1588
1717
  }
1589
- }).catch((error) => {
1718
+ }).catch((err) => {
1719
+ const error = (0, error_1.ensureError)(err);
1590
1720
  if (error instanceof error_1.DeviceNotFoundError) {
1591
1721
  if (result.customData !== undefined && result.customData.property !== undefined) {
1592
1722
  station.updateProperty(result.customData.property.name, result.customData.property.value);
@@ -1600,6 +1730,17 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1600
1730
  station.getCameraInfo();
1601
1731
  }
1602
1732
  }
1733
+ else {
1734
+ if (result.customData !== undefined && result.customData.onFailure !== undefined) {
1735
+ try {
1736
+ result.customData.onFailure();
1737
+ }
1738
+ catch (err) {
1739
+ const error = (0, error_1.ensureError)(err);
1740
+ this.log.error(`Station command result (station: ${station.getSerial()}) - onFailure callback error`, error);
1741
+ }
1742
+ }
1743
+ }
1603
1744
  if (result.customData !== undefined && result.customData.command !== undefined) {
1604
1745
  const customValue = result.customData.command.value;
1605
1746
  switch (result.customData.command.name) {
@@ -1610,10 +1751,10 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1610
1751
  this.emit("user added", device, customValue.username, customValue.schedule);
1611
1752
  break;
1612
1753
  case 4:
1613
- this.emit("user error", device, customValue.username, new error_1.AddUserError("Passcode already used by another user, please choose a different one"));
1754
+ this.emit("user error", device, customValue.username, new error_1.AddUserError("Passcode already used by another user, please choose a different one", { context: { device: device.getSerial(), username: customValue.username, schedule: customValue.schedule } }));
1614
1755
  break;
1615
1756
  default:
1616
- this.emit("user error", device, customValue.username, new error_1.AddUserError(`Error creating user with return code ${result.return_code}`));
1757
+ this.emit("user error", device, customValue.username, new error_1.AddUserError("Error creating user", { context: { device: device.getSerial(), username: customValue.username, schedule: customValue.schedule, returnode: result.return_code } }));
1617
1758
  break;
1618
1759
  }
1619
1760
  });
@@ -1627,12 +1768,12 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1627
1768
  this.emit("user deleted", device, customValue.username);
1628
1769
  }
1629
1770
  else {
1630
- this.emit("user error", device, customValue.username, new error_1.DeleteUserError(`Error in deleting user "${customValue.username}" with id "${customValue.short_user_id}" through cloud api call`));
1771
+ this.emit("user error", device, customValue.username, new error_1.DeleteUserError("Error in deleting user through cloud api call", { context: { device: device.getSerial(), username: customValue.username, shortUserId: customValue.short_user_id } }));
1631
1772
  }
1632
1773
  });
1633
1774
  break;
1634
1775
  default:
1635
- this.emit("user error", device, customValue.username, new Error(`Error deleting user with return code ${result.return_code}`));
1776
+ this.emit("user error", device, customValue.username, new error_1.DeleteUserError("Error deleting user", { context: { device: device.getSerial(), username: customValue.username, shortUserId: customValue.short_user_id, returnCode: result.return_code } }));
1636
1777
  break;
1637
1778
  }
1638
1779
  });
@@ -1644,7 +1785,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1644
1785
  this.emit("user passcode updated", device, customValue.username);
1645
1786
  break;
1646
1787
  default:
1647
- this.emit("user error", device, customValue.username, new error_1.UpdateUserPasscodeError(`Error updating user passcode with return code ${result.return_code}`));
1788
+ this.emit("user error", device, customValue.username, new error_1.UpdateUserPasscodeError("Error updating user passcode", { context: { device: device.getSerial(), username: customValue.username, returnCode: result.return_code } }));
1648
1789
  break;
1649
1790
  }
1650
1791
  });
@@ -1656,7 +1797,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1656
1797
  this.emit("user schedule updated", device, customValue.username, customValue.schedule);
1657
1798
  break;
1658
1799
  default:
1659
- this.emit("user error", device, customValue.username, new error_1.UpdateUserScheduleError(`Error updating user schedule with return code ${result.return_code}`));
1800
+ this.emit("user error", device, customValue.username, new error_1.UpdateUserScheduleError("Error updating user schedule", { context: { device: device.getSerial(), username: customValue.username, schedule: customValue.schedule, returnCode: result.return_code } }));
1660
1801
  break;
1661
1802
  }
1662
1803
  });
@@ -1674,7 +1815,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1674
1815
  station.updateProperty(result.customData.property.name, result.customData.property.value);
1675
1816
  }
1676
1817
  }
1677
- }).catch((error) => {
1818
+ }).catch((err) => {
1819
+ const error = (0, error_1.ensureError)(err);
1678
1820
  if (error instanceof error_1.DeviceNotFoundError) {
1679
1821
  if (result.customData !== undefined && result.customData.property !== undefined) {
1680
1822
  station.updateProperty(result.customData.property.name, result.customData.property.value);
@@ -1690,7 +1832,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1690
1832
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1691
1833
  this.emit("station rtsp url", station, device, value);
1692
1834
  device.setCustomPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl, value);
1693
- }).catch((error) => {
1835
+ }).catch((err) => {
1836
+ const error = (0, error_1.ensureError)(err);
1694
1837
  this.log.error(`Station rtsp url error (station: ${station.getSerial()} channel: ${channel})`, error);
1695
1838
  });
1696
1839
  }
@@ -1721,7 +1864,6 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1721
1864
  this.emit("station alarm armed", station);
1722
1865
  }
1723
1866
  onDevicePropertyChanged(device, name, value, ready) {
1724
- var _a;
1725
1867
  try {
1726
1868
  if (ready && !name.startsWith("hidden-")) {
1727
1869
  this.emit("device property changed", device, name, value);
@@ -1729,7 +1871,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1729
1871
  if (name === types_1.PropertyName.DeviceRTSPStream && value === true && (device.getPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl) === undefined || (device.getPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl) !== undefined && device.getPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl) === ""))) {
1730
1872
  this.getStation(device.getStationSerial()).then((station) => {
1731
1873
  station.setRTSPStream(device, true);
1732
- }).catch((error) => {
1874
+ }).catch((err) => {
1875
+ const error = (0, error_1.ensureError)(err);
1733
1876
  this.log.error(`Device property changed error (device: ${device.getSerial()} name: ${name}) - station enable rtsp (station: ${device.getStationSerial()})`, error);
1734
1877
  });
1735
1878
  }
@@ -1738,16 +1881,20 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1738
1881
  }
1739
1882
  else if (name === types_1.PropertyName.DevicePictureUrl && value !== "") {
1740
1883
  const picture = device.getPropertyValue(types_1.PropertyName.DevicePicture);
1741
- if (picture === undefined || picture === null || (picture && ((_a = picture.data) === null || _a === void 0 ? void 0 : _a.length) === 0)) {
1884
+ if (picture === undefined || picture === null || (picture && picture.data?.length === 0)) {
1742
1885
  this.getStation(device.getStationSerial()).then((station) => {
1743
- station.downloadImage(value);
1744
- }).catch((error) => {
1886
+ if (station.hasCommand(types_1.CommandName.StationDownloadImage)) {
1887
+ station.downloadImage(value);
1888
+ }
1889
+ }).catch((err) => {
1890
+ const error = (0, error_1.ensureError)(err);
1745
1891
  this.log.error(`Device property changed error (device: ${device.getSerial()} name: ${name}) - station download image (station: ${device.getStationSerial()} image_path: ${value})`, error);
1746
1892
  });
1747
1893
  }
1748
1894
  }
1749
1895
  }
1750
- catch (error) {
1896
+ catch (err) {
1897
+ const error = (0, error_1.ensureError)(err);
1751
1898
  this.log.error(`Device property changed error (device: ${device.getSerial()} name: ${name})`, error);
1752
1899
  }
1753
1900
  }
@@ -1831,12 +1978,14 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1831
1978
  if (device.getPropertyValue(types_1.PropertyName.DeviceRTSPStream) !== undefined && device.getPropertyValue(types_1.PropertyName.DeviceRTSPStream) === true) {
1832
1979
  this.getStation(device.getStationSerial()).then((station) => {
1833
1980
  station.setRTSPStream(device, true);
1834
- }).catch((error) => {
1981
+ }).catch((err) => {
1982
+ const error = (0, error_1.ensureError)(err);
1835
1983
  this.log.error(`Device ready error (device: ${device.getSerial()}) - station enable rtsp (station: ${device.getStationSerial()})`, error);
1836
1984
  });
1837
1985
  }
1838
1986
  }
1839
- catch (error) {
1987
+ catch (err) {
1988
+ const error = (0, error_1.ensureError)(err);
1840
1989
  this.log.error(`Device ready error (device: ${device.getSerial()})`, error);
1841
1990
  }
1842
1991
  }
@@ -1850,7 +1999,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1850
1999
  const metadataBatteryTemperature = device.getPropertyMetadata(types_1.PropertyName.DeviceBatteryTemp);
1851
2000
  device.updateRawProperty(metadataBatteryTemperature.key, temperature.toString());
1852
2001
  }
1853
- }).catch((error) => {
2002
+ }).catch((err) => {
2003
+ const error = (0, error_1.ensureError)(err);
1854
2004
  this.log.error(`Station runtime state error (station: ${station.getSerial()} channel: ${channel})`, error);
1855
2005
  });
1856
2006
  }
@@ -1865,7 +2015,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1865
2015
  const metadataChargingStatus = device.getPropertyMetadata(types_1.PropertyName.DeviceChargingStatus);
1866
2016
  device.updateRawProperty(metadataChargingStatus.key, chargeType.toString());
1867
2017
  }
1868
- }).catch((error) => {
2018
+ }).catch((err) => {
2019
+ const error = (0, error_1.ensureError)(err);
1869
2020
  this.log.error(`Station charging state error (station: ${station.getSerial()} channel: ${channel})`, error);
1870
2021
  });
1871
2022
  }
@@ -1875,7 +2026,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1875
2026
  const metadataWifiRssi = device.getPropertyMetadata(types_1.PropertyName.DeviceWifiRSSI);
1876
2027
  device.updateRawProperty(metadataWifiRssi.key, rssi.toString());
1877
2028
  }
1878
- }).catch((error) => {
2029
+ }).catch((err) => {
2030
+ const error = (0, error_1.ensureError)(err);
1879
2031
  this.log.error(`Station wifi rssi error (station: ${station.getSerial()} channel: ${channel})`, error);
1880
2032
  });
1881
2033
  }
@@ -1888,7 +2040,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1888
2040
  const metadataLight = device.getPropertyMetadata(types_1.PropertyName.DeviceLight);
1889
2041
  device.updateRawProperty(metadataLight.key, enabled === true ? "1" : "0");
1890
2042
  }
1891
- }).catch((error) => {
2043
+ }).catch((err) => {
2044
+ const error = (0, error_1.ensureError)(err);
1892
2045
  this.log.error(`Station floodlight manual switch error (station: ${station.getSerial()} channel: ${channel})`, error);
1893
2046
  });
1894
2047
  }
@@ -1903,21 +2056,24 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1903
2056
  onStationTalkbackStart(station, channel, talkbackStream) {
1904
2057
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1905
2058
  this.emit("station talkback start", station, device, talkbackStream);
1906
- }).catch((error) => {
2059
+ }).catch((err) => {
2060
+ const error = (0, error_1.ensureError)(err);
1907
2061
  this.log.error(`Station talkback start error (station: ${station.getSerial()} channel: ${channel})`, error);
1908
2062
  });
1909
2063
  }
1910
2064
  onStationTalkbackStop(station, channel) {
1911
2065
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1912
2066
  this.emit("station talkback stop", station, device);
1913
- }).catch((error) => {
2067
+ }).catch((err) => {
2068
+ const error = (0, error_1.ensureError)(err);
1914
2069
  this.log.error(`Station talkback stop error (station: ${station.getSerial()} channel: ${channel})`, error);
1915
2070
  });
1916
2071
  }
1917
2072
  onStationTalkbackError(station, channel, _error) {
1918
2073
  this.getStationDevice(station.getSerial(), channel).then((device) => {
1919
2074
  station.stopTalkback(device);
1920
- }).catch((error) => {
2075
+ }).catch((err) => {
2076
+ const error = (0, error_1.ensureError)(err);
1921
2077
  this.log.error(`Station talkback error (station: ${station.getSerial()} channel: ${channel} error: ${_error}})`, error);
1922
2078
  });
1923
2079
  }
@@ -1925,7 +2081,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1925
2081
  const device = await this.getDevice(deviceSN);
1926
2082
  const station = await this.getStation(device.getStationSerial());
1927
2083
  if (!device.hasCommand(types_1.CommandName.DeviceStartTalkback))
1928
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
2084
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStartTalkback } });
1929
2085
  if (station.isLiveStreaming(device)) {
1930
2086
  if (!station.isTalkbackOngoing(device)) {
1931
2087
  station.startTalkback(device);
@@ -1942,7 +2098,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1942
2098
  const device = await this.getDevice(deviceSN);
1943
2099
  const station = await this.getStation(device.getStationSerial());
1944
2100
  if (!device.hasCommand(types_1.CommandName.DeviceStopTalkback))
1945
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
2101
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStopTalkback } });
1946
2102
  if (station.isLiveStreaming(device)) {
1947
2103
  if (station.isTalkbackOngoing(device)) {
1948
2104
  station.stopTalkback(device);
@@ -1959,7 +2115,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1959
2115
  this.getDevice(deviceSN).then((device) => {
1960
2116
  if (device.isSmartSafe())
1961
2117
  device.shakeEvent(event, this.config.eventDurationSeconds);
1962
- }).catch((error) => {
2118
+ }).catch((err) => {
2119
+ const error = (0, error_1.ensureError)(err);
1963
2120
  this.log.error(`onStationShakeAlarm device ${deviceSN} error`, error);
1964
2121
  });
1965
2122
  }
@@ -1967,7 +2124,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1967
2124
  this.getDevice(deviceSN).then((device) => {
1968
2125
  if (device.isSmartSafe())
1969
2126
  device.alarm911Event(event, this.config.eventDurationSeconds);
1970
- }).catch((error) => {
2127
+ }).catch((err) => {
2128
+ const error = (0, error_1.ensureError)(err);
1971
2129
  this.log.error(`onStation911Alarm device ${deviceSN} error`, error);
1972
2130
  });
1973
2131
  }
@@ -1975,7 +2133,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1975
2133
  this.getDevice(deviceSN).then((device) => {
1976
2134
  if (device.isSmartSafe())
1977
2135
  device.jammedEvent(this.config.eventDurationSeconds);
1978
- }).catch((error) => {
2136
+ }).catch((err) => {
2137
+ const error = (0, error_1.ensureError)(err);
1979
2138
  this.log.error(`onStationDeviceJammed device ${deviceSN} error`, error);
1980
2139
  });
1981
2140
  }
@@ -1983,7 +2142,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1983
2142
  this.getDevice(deviceSN).then((device) => {
1984
2143
  if (device.isSmartSafe())
1985
2144
  device.lowBatteryEvent(this.config.eventDurationSeconds);
1986
- }).catch((error) => {
2145
+ }).catch((err) => {
2146
+ const error = (0, error_1.ensureError)(err);
1987
2147
  this.log.error(`onStationDeviceLowBattery device ${deviceSN} error`, error);
1988
2148
  });
1989
2149
  }
@@ -1991,7 +2151,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1991
2151
  this.getDevice(deviceSN).then((device) => {
1992
2152
  if (device.isSmartSafe())
1993
2153
  device.wrongTryProtectAlarmEvent(this.config.eventDurationSeconds);
1994
- }).catch((error) => {
2154
+ }).catch((err) => {
2155
+ const error = (0, error_1.ensureError)(err);
1995
2156
  this.log.error(`onStationDeviceWrongTryProtectAlarm device ${deviceSN} error`, error);
1996
2157
  });
1997
2158
  }
@@ -2000,25 +2161,26 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2000
2161
  const station = await this.getStation(device.getStationSerial());
2001
2162
  try {
2002
2163
  if (!device.hasCommand(types_1.CommandName.DeviceAddUser))
2003
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
2164
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceAddUser, username: username, passcode: "[redacted]", schedule: schedule } });
2004
2165
  const addUserResponse = await this.api.addUser(deviceSN, username, device.getStationSerial());
2005
2166
  if (addUserResponse !== null) {
2006
2167
  await station.addUser(device, username, addUserResponse.short_user_id, passcode, schedule);
2007
2168
  }
2008
2169
  else {
2009
- this.emit("user error", device, username, new error_1.AddUserError("Error on creating user through cloud api call"));
2170
+ this.emit("user error", device, username, new error_1.AddUserError("Error on creating user through cloud api call", { context: { deivce: deviceSN, username: username, passcode: "[redacted]", schedule: schedule } }));
2010
2171
  }
2011
2172
  }
2012
- catch (error) {
2173
+ catch (err) {
2174
+ const error = (0, error_1.ensureError)(err);
2013
2175
  this.log.error(`addUser device ${deviceSN} error`, error);
2014
- this.emit("user error", device, username, new error_1.AddUserError(`Got exception: ${error}`));
2176
+ this.emit("user error", device, username, new error_1.AddUserError("Generic error", { cause: error, context: { device: deviceSN, username: username, passcode: "[redacted]", schedule: schedule } }));
2015
2177
  }
2016
2178
  }
2017
2179
  async deleteUser(deviceSN, username) {
2018
2180
  const device = await this.getDevice(deviceSN);
2019
2181
  const station = await this.getStation(device.getStationSerial());
2020
2182
  if (!device.hasCommand(types_1.CommandName.DeviceDeleteUser))
2021
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
2183
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceDeleteUser, username: username } });
2022
2184
  try {
2023
2185
  const users = await this.api.getUsers(deviceSN, device.getStationSerial());
2024
2186
  if (users !== null) {
@@ -2031,22 +2193,23 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2031
2193
  }
2032
2194
  }
2033
2195
  if (!found) {
2034
- this.emit("user error", device, username, new error_1.DeleteUserError(`User with username "${username}" not found`));
2196
+ this.emit("user error", device, username, new error_1.DeleteUserError("User not found", { context: { device: deviceSN, username: username } }));
2035
2197
  }
2036
2198
  }
2037
2199
  else {
2038
- this.emit("user error", device, username, new error_1.DeleteUserError("Error on getting user list through cloud api call"));
2200
+ this.emit("user error", device, username, new error_1.DeleteUserError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username } }));
2039
2201
  }
2040
2202
  }
2041
- catch (error) {
2203
+ catch (err) {
2204
+ const error = (0, error_1.ensureError)(err);
2042
2205
  this.log.error(`deleteUser device ${deviceSN} error`, error);
2043
- this.emit("user error", device, username, new error_1.DeleteUserError(`Got exception: ${error}`));
2206
+ this.emit("user error", device, username, new error_1.DeleteUserError("Generic error", { cause: error, context: { device: deviceSN, username: username } }));
2044
2207
  }
2045
2208
  }
2046
2209
  async updateUser(deviceSN, username, newUsername) {
2047
2210
  const device = await this.getDevice(deviceSN);
2048
2211
  if (!device.hasCommand(types_1.CommandName.DeviceUpdateUsername))
2049
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
2212
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceUpdateUsername, usernmae: username, newUsername: newUsername } });
2050
2213
  try {
2051
2214
  const users = await this.api.getUsers(deviceSN, device.getStationSerial());
2052
2215
  if (users !== null) {
@@ -2058,30 +2221,31 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2058
2221
  this.emit("user username updated", device, username);
2059
2222
  }
2060
2223
  else {
2061
- this.emit("user error", device, username, new error_1.UpdateUserUsernameError(`Error in changing username "${username}" to "${newUsername}" through cloud api call`));
2224
+ this.emit("user error", device, username, new error_1.UpdateUserUsernameError("Error in changing username through cloud api call", { context: { device: deviceSN, username: username, newUsername: newUsername } }));
2062
2225
  }
2063
2226
  found = true;
2064
2227
  break;
2065
2228
  }
2066
2229
  }
2067
2230
  if (!found) {
2068
- this.emit("user error", device, username, new error_1.UpdateUserUsernameError(`Error in changing username "${username}" to "${newUsername}" through cloud api call`));
2231
+ this.emit("user error", device, username, new error_1.UpdateUserUsernameError("User not found", { context: { device: deviceSN, username: username, newUsername: newUsername } }));
2069
2232
  }
2070
2233
  }
2071
2234
  else {
2072
- this.emit("user error", device, username, new error_1.UpdateUserUsernameError("Error on getting user list through cloud api call"));
2235
+ this.emit("user error", device, username, new error_1.UpdateUserUsernameError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username, newUsername: newUsername } }));
2073
2236
  }
2074
2237
  }
2075
- catch (error) {
2238
+ catch (err) {
2239
+ const error = (0, error_1.ensureError)(err);
2076
2240
  this.log.error(`updateUser device ${deviceSN} error`, error);
2077
- this.emit("user error", device, username, new error_1.UpdateUserUsernameError(`Got exception: ${error}`));
2241
+ this.emit("user error", device, username, new error_1.UpdateUserUsernameError("Generic error", { cause: error, context: { device: deviceSN, username: username, newUsername: newUsername } }));
2078
2242
  }
2079
2243
  }
2080
2244
  async updateUserPasscode(deviceSN, username, passcode) {
2081
2245
  const device = await this.getDevice(deviceSN);
2082
2246
  const station = await this.getStation(device.getStationSerial());
2083
2247
  if (!device.hasCommand(types_1.CommandName.DeviceUpdateUserPasscode))
2084
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
2248
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceUpdateUserPasscode, username: username, passcode: "[redacted]" } });
2085
2249
  try {
2086
2250
  const users = await this.api.getUsers(deviceSN, device.getStationSerial());
2087
2251
  if (users !== null) {
@@ -2093,23 +2257,24 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2093
2257
  }
2094
2258
  }
2095
2259
  if (!found) {
2096
- this.emit("user error", device, username, new error_1.UpdateUserPasscodeError(`User with username "${username}" not found`));
2260
+ this.emit("user error", device, username, new error_1.UpdateUserPasscodeError("User not found", { context: { device: deviceSN, username: username, passcode: "[redacted]" } }));
2097
2261
  }
2098
2262
  }
2099
2263
  else {
2100
- this.emit("user error", device, username, new error_1.UpdateUserPasscodeError("Error on getting user list through cloud api call"));
2264
+ this.emit("user error", device, username, new error_1.UpdateUserPasscodeError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username, passcode: "[redacted]" } }));
2101
2265
  }
2102
2266
  }
2103
- catch (error) {
2267
+ catch (err) {
2268
+ const error = (0, error_1.ensureError)(err);
2104
2269
  this.log.error(`updateUserPasscode device ${deviceSN} error`, error);
2105
- this.emit("user error", device, username, new error_1.UpdateUserPasscodeError(`Got exception: ${error}`));
2270
+ this.emit("user error", device, username, new error_1.UpdateUserPasscodeError("Generic error", { cause: error, context: { device: deviceSN, username: username, passcode: "[redacted]" } }));
2106
2271
  }
2107
2272
  }
2108
2273
  async updateUserSchedule(deviceSN, username, schedule) {
2109
2274
  const device = await this.getDevice(deviceSN);
2110
2275
  const station = await this.getStation(device.getStationSerial());
2111
- if (!device.hasCommand(types_1.CommandName.DeviceUpdateUserPasscode))
2112
- throw new error_1.NotSupportedError(`This functionality is not implemented or supported by ${device.getSerial()}`);
2276
+ if (!device.hasCommand(types_1.CommandName.DeviceUpdateUserSchedule))
2277
+ throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceUpdateUserSchedule, usernmae: username, schedule: schedule } });
2113
2278
  try {
2114
2279
  const users = await this.api.getUsers(deviceSN, device.getStationSerial());
2115
2280
  if (users !== null) {
@@ -2121,22 +2286,24 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2121
2286
  }
2122
2287
  }
2123
2288
  if (!found) {
2124
- this.emit("user error", device, username, new error_1.UpdateUserScheduleError(`User with username "${username}" not found`));
2289
+ this.emit("user error", device, username, new error_1.UpdateUserScheduleError("User not found", { context: { device: deviceSN, username: username, schedule: schedule } }));
2125
2290
  }
2126
2291
  }
2127
2292
  else {
2128
- this.emit("user error", device, username, new error_1.UpdateUserScheduleError("Error on getting user list through cloud api call"));
2293
+ this.emit("user error", device, username, new error_1.UpdateUserScheduleError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username, schedule: schedule } }));
2129
2294
  }
2130
2295
  }
2131
- catch (error) {
2296
+ catch (err) {
2297
+ const error = (0, error_1.ensureError)(err);
2132
2298
  this.log.error(`updateUserSchedule device ${deviceSN} error`, error);
2133
- this.emit("user error", device, username, new error_1.UpdateUserScheduleError(`Got exception: ${error}`));
2299
+ this.emit("user error", device, username, new error_1.UpdateUserScheduleError("Generic error", { cause: error, context: { device: deviceSN, username: username, schedule: schedule } }));
2134
2300
  }
2135
2301
  }
2136
2302
  onStationDevicePinVerified(deviceSN, successfull) {
2137
2303
  this.getDevice(deviceSN).then((device) => {
2138
2304
  this.emit("device pin verified", device, successfull);
2139
- }).catch((error) => {
2305
+ }).catch((err) => {
2306
+ const error = (0, error_1.ensureError)(err);
2140
2307
  this.log.error(`onStationDevicePinVerified device ${deviceSN} error`, error);
2141
2308
  });
2142
2309
  }
@@ -2166,7 +2333,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2166
2333
  break;
2167
2334
  }
2168
2335
  }
2169
- }).catch((error) => {
2336
+ }).catch((err) => {
2337
+ const error = (0, error_1.ensureError)(err);
2170
2338
  this.log.error(`onStationImageDownload - Set first picture error`, error);
2171
2339
  });
2172
2340
  }
@@ -2183,8 +2351,9 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2183
2351
  raw.cover_path = element.crop_cloud_path;
2184
2352
  }
2185
2353
  device.update(raw);
2186
- }).catch((error) => {
2187
- this.log.error("onStationDatabaseQueryLatest Error:", error);
2354
+ }).catch((err) => {
2355
+ const error = (0, error_1.ensureError)(err);
2356
+ this.log.error("onStationDatabaseQueryLatest Error", error);
2188
2357
  });
2189
2358
  }
2190
2359
  }
@@ -2200,6 +2369,25 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2200
2369
  onStationDatabaseDelete(station, returnCode, failedIds) {
2201
2370
  this.emit("station database delete", station, returnCode, failedIds);
2202
2371
  }
2372
+ onStationSensorStatus(station, channel, status) {
2373
+ this.getStationDevice(station.getSerial(), channel).then((device) => {
2374
+ if (device.hasProperty(types_1.PropertyName.DeviceSensorOpen)) {
2375
+ const metadataSensorOpen = device.getPropertyMetadata(types_1.PropertyName.DeviceSensorOpen);
2376
+ device.updateRawProperty(metadataSensorOpen.key, status.toString());
2377
+ }
2378
+ }).catch((err) => {
2379
+ const error = (0, error_1.ensureError)(err);
2380
+ this.log.error(`Station sensor status error (station: ${station.getSerial()} channel: ${channel})`, error);
2381
+ });
2382
+ }
2383
+ onStationGarageDoorStatus(station, channel, doorId, status) {
2384
+ this.getStationDevice(station.getSerial(), channel).then((device) => {
2385
+ device.updateRawProperty(types_2.CommandType.CMD_CAMERA_GARAGE_DOOR_STATUS, status.toString());
2386
+ }).catch((err) => {
2387
+ const error = (0, error_1.ensureError)(err);
2388
+ this.log.error(`Station garage door status error (station: ${station.getSerial()} channel: ${channel})`, error);
2389
+ });
2390
+ }
2203
2391
  }
2204
2392
  exports.EufySecurity = EufySecurity;
2205
2393
  //# sourceMappingURL=eufysecurity.js.map