eufy-security-client 2.4.4 → 2.5.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.
package/README.md CHANGED
@@ -80,6 +80,12 @@ Please use GitHub issues for this.
80
80
 
81
81
  ## Changelog
82
82
 
83
+ ### 2.5.0 (2023-05-07)
84
+
85
+ * (bropat) **Breaking Change** `picture_url` property is now hidden and was replaced by `picture` property for supported devices
86
+ * (bropat) Implemented new push notification picture gathering and decryption
87
+ * (bropat) Fixed sdcard info gathering for devices without sdcard inserted
88
+
83
89
  ### 2.4.4 (2023-04-21)
84
90
 
85
91
  * (bropat) Implemented feature request #313
@@ -46,6 +46,7 @@ export declare class EufySecurity extends TypedEmitter<EufySecurityEvents> {
46
46
  private removeDevice;
47
47
  private updateDevice;
48
48
  getDevices(): Promise<Array<Device>>;
49
+ getDevicesFromStation(stationSN: string): Promise<Array<Device>>;
49
50
  getDevice(deviceSN: string): Promise<Device>;
50
51
  getStationDevice(stationSN: string, channel: number): Promise<Device>;
51
52
  getStations(): Promise<Array<Station>>;
@@ -159,4 +160,5 @@ export declare class EufySecurity extends TypedEmitter<EufySecurityEvents> {
159
160
  updateUserSchedule(deviceSN: string, username: string, schedule: Schedule): Promise<void>;
160
161
  private onStationDevicePinVerified;
161
162
  private onStationSdInfoEx;
163
+ private onStationImageDownload;
162
164
  }
@@ -32,6 +32,7 @@ const ts_log_1 = require("ts-log");
32
32
  const fse = __importStar(require("fs-extra"));
33
33
  const path = __importStar(require("path"));
34
34
  const events_1 = __importDefault(require("events"));
35
+ const image_type_1 = __importDefault(require("image-type"));
35
36
  const api_1 = require("./http/api");
36
37
  const station_1 = require("./http/station");
37
38
  const types_1 = require("./http/types");
@@ -292,7 +293,15 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
292
293
  }
293
294
  }
294
295
  async getStorageInfo(stationSerial) {
295
- await this.stations[stationSerial].getStorageInfoEx();
296
+ try {
297
+ const station = await this.getStation(stationSerial);
298
+ if (station.isStation() || (station.hasProperty(types_1.PropertyName.StationSdStatus) && station.getPropertyValue(types_1.PropertyName.StationSdStatus) !== undefined && station.getPropertyValue(types_1.PropertyName.StationSdStatus) !== types_2.TFCardStatus.REMOVE)) {
299
+ await station.getStorageInfoEx();
300
+ }
301
+ }
302
+ catch (error) {
303
+ this.log.error("getStorageInfo Error", error);
304
+ }
296
305
  }
297
306
  addDevice(device) {
298
307
  const serial = device.getSerial();
@@ -334,6 +343,16 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
334
343
  });
335
344
  return arr;
336
345
  }
346
+ async getDevicesFromStation(stationSN) {
347
+ if (!this.devicesLoaded)
348
+ await (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
349
+ const arr = [];
350
+ Object.keys(this.devices).forEach((serialNumber) => {
351
+ if (this.devices[serialNumber].getStationSerial() === stationSN)
352
+ arr.push(this.devices[serialNumber]);
353
+ });
354
+ return arr;
355
+ }
337
356
  async getDevice(deviceSN) {
338
357
  if (!this.devicesLoaded)
339
358
  await (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
@@ -398,11 +417,12 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
398
417
  this.updateStation(hub);
399
418
  }
400
419
  else {
420
+ this.stationsLoaded = false;
401
421
  let ipAddress;
402
422
  if (this.config.stationIPAddresses !== undefined) {
403
423
  ipAddress = this.config.stationIPAddresses[hub.station_sn];
404
424
  }
405
- const station = station_1.Station.initialize(this.api, hub, ipAddress);
425
+ const station = station_1.Station.getInstance(this.api, hub, ipAddress);
406
426
  promises.push(station.then((station) => {
407
427
  try {
408
428
  station.on("connect", (station) => this.onStationConnect(station));
@@ -420,7 +440,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
420
440
  station.on("rtsp livestream start", (station, channel) => this.onStartStationRTSPLivestream(station, channel));
421
441
  station.on("rtsp livestream stop", (station, channel) => this.onStopStationRTSPLivestream(station, channel));
422
442
  station.on("rtsp url", (station, channel, value) => this.onStationRtspUrl(station, channel, value));
423
- station.on("property changed", (station, name, value) => this.onStationPropertyChanged(station, name, value));
443
+ station.on("property changed", (station, name, value, ready) => this.onStationPropertyChanged(station, name, value, ready));
424
444
  station.on("raw property changed", (station, type, value) => this.onStationRawPropertyChanged(station, type, value));
425
445
  station.on("alarm event", (station, alarmEvent) => this.onStationAlarmEvent(station, alarmEvent));
426
446
  station.on("runtime state", (station, channel, batteryLevel, temperature) => this.onStationRuntimeState(station, channel, batteryLevel, temperature));
@@ -441,7 +461,9 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
441
461
  station.on("device wrong try-protect alarm", (deviceSN) => this.onStationDeviceWrongTryProtectAlarm(deviceSN));
442
462
  station.on("device pin verified", (deviceSN, successfull) => this.onStationDevicePinVerified(deviceSN, successfull));
443
463
  station.on("sd info ex", (station, sdStatus, sdCapacity, sdCapacityAvailable) => this.onStationSdInfoEx(station, sdStatus, sdCapacity, sdCapacityAvailable));
464
+ station.on("image download", (station, file, image) => this.onStationImageDownload(station, file, image));
444
465
  this.addStation(station);
466
+ station.initialize();
445
467
  }
446
468
  catch (error) {
447
469
  this.log.error("Error", error);
@@ -509,46 +531,47 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
509
531
  this.updateDevice(device);
510
532
  }
511
533
  else {
534
+ this.devicesLoaded = false;
512
535
  let new_device;
513
536
  if (device_1.Device.isIndoorCamera(device.device_type)) {
514
- new_device = device_1.IndoorCamera.initialize(this.api, device);
537
+ new_device = device_1.IndoorCamera.getInstance(this.api, device);
515
538
  }
516
539
  else if (device_1.Device.isSoloCameras(device.device_type)) {
517
- new_device = device_1.SoloCamera.initialize(this.api, device);
540
+ new_device = device_1.SoloCamera.getInstance(this.api, device);
518
541
  }
519
542
  else if (device_1.Device.isBatteryDoorbell(device.device_type)) {
520
- new_device = device_1.BatteryDoorbellCamera.initialize(this.api, device);
543
+ new_device = device_1.BatteryDoorbellCamera.getInstance(this.api, device);
521
544
  }
522
545
  else if (device_1.Device.isWiredDoorbell(device.device_type) || device_1.Device.isWiredDoorbellDual(device.device_type)) {
523
- new_device = device_1.WiredDoorbellCamera.initialize(this.api, device);
546
+ new_device = device_1.WiredDoorbellCamera.getInstance(this.api, device);
524
547
  }
525
548
  else if (device_1.Device.isFloodLight(device.device_type)) {
526
- new_device = device_1.FloodlightCamera.initialize(this.api, device);
549
+ new_device = device_1.FloodlightCamera.getInstance(this.api, device);
527
550
  }
528
551
  else if (device_1.Device.isCamera(device.device_type)) {
529
- new_device = device_1.Camera.initialize(this.api, device);
552
+ new_device = device_1.Camera.getInstance(this.api, device);
530
553
  }
531
554
  else if (device_1.Device.isLock(device.device_type)) {
532
- new_device = device_1.Lock.initialize(this.api, device);
555
+ new_device = device_1.Lock.getInstance(this.api, device);
533
556
  }
534
557
  else if (device_1.Device.isMotionSensor(device.device_type)) {
535
- new_device = device_1.MotionSensor.initialize(this.api, device);
558
+ new_device = device_1.MotionSensor.getInstance(this.api, device);
536
559
  }
537
560
  else if (device_1.Device.isEntrySensor(device.device_type)) {
538
- new_device = device_1.EntrySensor.initialize(this.api, device);
561
+ new_device = device_1.EntrySensor.getInstance(this.api, device);
539
562
  }
540
563
  else if (device_1.Device.isKeyPad(device.device_type)) {
541
- new_device = device_1.Keypad.initialize(this.api, device);
564
+ new_device = device_1.Keypad.getInstance(this.api, device);
542
565
  }
543
566
  else if (device_1.Device.isSmartSafe(device.device_type)) {
544
- new_device = device_1.SmartSafe.initialize(this.api, device);
567
+ new_device = device_1.SmartSafe.getInstance(this.api, device);
545
568
  }
546
569
  else {
547
- new_device = device_1.UnknownDevice.initialize(this.api, device);
570
+ new_device = device_1.UnknownDevice.getInstance(this.api, device);
548
571
  }
549
572
  promises.push(new_device.then((device) => {
550
573
  try {
551
- device.on("property changed", (device, name, value) => this.onDevicePropertyChanged(device, name, value));
574
+ device.on("property changed", (device, name, value, ready) => this.onDevicePropertyChanged(device, name, value, ready));
552
575
  device.on("raw property changed", (device, type, value) => this.onDeviceRawPropertyChanged(device, type, value));
553
576
  device.on("crying detected", (device, state) => this.onDeviceCryingDetected(device, state));
554
577
  device.on("sound detected", (device, state) => this.onDeviceSoundDetected(device, state));
@@ -576,6 +599,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
576
599
  device.on("dog lick detected", (device, state) => this.onDeviceDogLickDetected(device, state));
577
600
  device.on("dog poop detected", (device, state) => this.onDeviceDogPoopDetected(device, state));
578
601
  this.addDevice(device);
602
+ device.initialize();
579
603
  }
580
604
  catch (error) {
581
605
  this.log.error("Error", error);
@@ -1664,8 +1688,10 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1664
1688
  onStationCurrentMode(station, currentMode) {
1665
1689
  this.emit("station current mode", station, currentMode);
1666
1690
  }
1667
- onStationPropertyChanged(station, name, value) {
1668
- this.emit("station property changed", station, name, value);
1691
+ onStationPropertyChanged(station, name, value, ready) {
1692
+ if (ready && !name.startsWith("hidden-")) {
1693
+ this.emit("station property changed", station, name, value);
1694
+ }
1669
1695
  }
1670
1696
  onStationRawPropertyChanged(station, type, value) {
1671
1697
  this.emit("station raw property changed", station, type, value);
@@ -1682,9 +1708,12 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1682
1708
  onStationAlarmArmedEvent(station) {
1683
1709
  this.emit("station alarm armed", station);
1684
1710
  }
1685
- onDevicePropertyChanged(device, name, value) {
1711
+ onDevicePropertyChanged(device, name, value, ready) {
1712
+ var _a;
1686
1713
  try {
1687
- this.emit("device property changed", device, name, value);
1714
+ if (ready && !name.startsWith("hidden-")) {
1715
+ this.emit("device property changed", device, name, value);
1716
+ }
1688
1717
  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) === ""))) {
1689
1718
  this.getStation(device.getStationSerial()).then((station) => {
1690
1719
  station.setRTSPStream(device, true);
@@ -1695,6 +1724,16 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1695
1724
  else if (name === types_1.PropertyName.DeviceRTSPStream && value === false) {
1696
1725
  device.setCustomPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl, "");
1697
1726
  }
1727
+ else if (name === types_1.PropertyName.DevicePictureUrl) { // && device.hasProperty(PropertyName.DevicePicture)) {
1728
+ const picture = device.getPropertyValue(types_1.PropertyName.DevicePicture);
1729
+ if (picture === undefined || (picture && ((_a = picture.data) === null || _a === void 0 ? void 0 : _a.length) === 0)) {
1730
+ this.getStation(device.getStationSerial()).then((station) => {
1731
+ station.downloadImage(value);
1732
+ }).catch((error) => {
1733
+ this.log.error(`Device property changed error (device: ${device.getSerial()} name: ${name}) - station download image (station: ${device.getStationSerial()} image_path: ${value})`, error);
1734
+ });
1735
+ }
1736
+ }
1698
1737
  }
1699
1738
  catch (error) {
1700
1739
  this.log.error(`Device property changed error (device: ${device.getSerial()} name: ${name})`, error);
@@ -2100,6 +2139,25 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
2100
2139
  station.updateProperty(types_1.PropertyName.StationSdCapacityAvailable, sdCapacityAvailable);
2101
2140
  }
2102
2141
  }
2142
+ onStationImageDownload(station, file, image) {
2143
+ const type = (0, image_type_1.default)(image);
2144
+ const picture = {
2145
+ data: image,
2146
+ type: type !== null ? type : { ext: "unknown", mime: "application/octet-stream" }
2147
+ };
2148
+ this.emit("station image download", station, file, picture);
2149
+ this.getDevicesFromStation(station.getSerial()).then((devices) => {
2150
+ for (const device of devices) {
2151
+ if (device.getPropertyValue(types_1.PropertyName.DevicePictureUrl) === file && device.getPropertyValue(types_1.PropertyName.DevicePicture) === undefined) {
2152
+ this.log.debug(`onStationImageDownload - Set first picture for device ${device.getSerial()} file: ${file} picture_ext: ${picture.type.ext} picture_mime: ${picture.type.mime}`);
2153
+ device.updateProperty(types_1.PropertyName.DevicePicture, picture);
2154
+ break;
2155
+ }
2156
+ }
2157
+ }).catch((error) => {
2158
+ this.log.error(`onStationImageDownload - Set first picture error`, error);
2159
+ });
2160
+ }
2103
2161
  }
2104
2162
  exports.EufySecurity = EufySecurity;
2105
2163
  //# sourceMappingURL=eufysecurity.js.map