eufy-security-client 1.5.0 → 1.6.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 (57) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +31 -28
  3. package/build/eufysecurity.d.ts +2 -0
  4. package/build/eufysecurity.js +146 -9
  5. package/build/eufysecurity.js.map +1 -1
  6. package/build/http/api.d.ts +15 -5
  7. package/build/http/api.js +431 -126
  8. package/build/http/api.js.map +1 -1
  9. package/build/http/device.d.ts +13 -10
  10. package/build/http/device.js +86 -45
  11. package/build/http/device.js.map +1 -1
  12. package/build/http/interfaces.d.ts +23 -7
  13. package/build/http/models.d.ts +153 -82
  14. package/build/http/station.d.ts +14 -9
  15. package/build/http/station.js +2072 -954
  16. package/build/http/station.js.map +1 -1
  17. package/build/http/types.d.ts +31 -1
  18. package/build/http/types.js +212 -14
  19. package/build/http/types.js.map +1 -1
  20. package/build/http/utils.d.ts +9 -0
  21. package/build/http/utils.js +3041 -1
  22. package/build/http/utils.js.map +1 -1
  23. package/build/interfaces.d.ts +6 -1
  24. package/build/mqtt/interface.d.ts +6 -0
  25. package/build/mqtt/interface.js +3 -0
  26. package/build/mqtt/interface.js.map +1 -0
  27. package/build/mqtt/model.d.ts +24 -0
  28. package/build/mqtt/model.js +3 -0
  29. package/build/mqtt/model.js.map +1 -0
  30. package/build/mqtt/mqtt-eufy.crt +79 -0
  31. package/build/mqtt/proto/lock.proto +33 -0
  32. package/build/mqtt/service.d.ts +26 -0
  33. package/build/mqtt/service.js +157 -0
  34. package/build/mqtt/service.js.map +1 -0
  35. package/build/p2p/index.d.ts +2 -2
  36. package/build/p2p/index.js +2 -1
  37. package/build/p2p/index.js.map +1 -1
  38. package/build/p2p/interfaces.d.ts +13 -3
  39. package/build/p2p/models.d.ts +36 -3
  40. package/build/p2p/session.d.ts +13 -10
  41. package/build/p2p/session.js +233 -132
  42. package/build/p2p/session.js.map +1 -1
  43. package/build/p2p/types.d.ts +23 -1
  44. package/build/p2p/types.js +24 -1
  45. package/build/p2p/types.js.map +1 -1
  46. package/build/p2p/utils.d.ts +9 -7
  47. package/build/p2p/utils.js +68 -39
  48. package/build/p2p/utils.js.map +1 -1
  49. package/build/push/models.d.ts +10 -1
  50. package/build/push/models.js.map +1 -1
  51. package/build/push/service.d.ts +1 -0
  52. package/build/push/service.js +49 -19
  53. package/build/push/service.js.map +1 -1
  54. package/build/push/types.d.ts +15 -6
  55. package/build/push/types.js +12 -3
  56. package/build/push/types.js.map +1 -1
  57. package/package.json +7 -6
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 bropat <patrick.broetto@gmail.com>
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2022 bropat <patrick.broetto@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -61,39 +61,13 @@ One client instance will show all devices from one Eufy Cloud account and allows
61
61
 
62
62
  ## Documentation
63
63
 
64
- * WIP
64
+ Look [here](https://bropat.github.io/eufy-security-client/).
65
65
 
66
66
  *As an example, you can look at the following projects: [ioBroker.eufy-security](https://github.com/bropat/ioBroker.eufy-security), [eufy-security-ws](https://github.com/bropat/eufy-security-ws), [eufy_security](https://github.com/fuatakgun/eufy_security)*
67
67
 
68
68
  ## Known working devices
69
69
 
70
- * HomeBase (T8001)
71
- * HomeBase E (T8002)
72
- * HomeBase 2 (T8010)
73
- * Smart Lock Wi-Fi Bridge (T8021)
74
- * eufyCam (T8111)
75
- * eufyCam E (T8112)
76
- * eufyCam 2 (T8114)
77
- * eufyCam 2C (T8113)
78
- * eufyCam 2 Pro (T8140)
79
- * eufyCam 2C Pro (T8141)
80
- * SoloCam E40 (T8131)
81
- * Floodlight Camera (T8420)
82
- * Floodlight Cam (T8422)
83
- * Floodlight Cam 2 Pro (T8423)
84
- * Floodlight Cam 2 (T8424)
85
- * Wired Doorbell 2k (T8200)
86
- * Wired Doorbell 1080p (T8201)
87
- * Battery Doorbell 2K (T8210)
88
- * Battery Doorbell 1080p (T8222)
89
- * Entry Sensor (T8900)
90
- * Motion sensor (T8910)
91
- * Indoor Cam Pan&Tilt 2K (T8410)
92
- * Indoor Cam 2K (T8400)
93
- * Indoor Cam Pan&Tilt 1080p (T8411)
94
- * Indoor Cam 1080p (T8401)
95
- * Smart Lock Front Door (T8500)
96
- * Keypad (T8960)
70
+ For a list of supported devices, please see [here](https://bropat.github.io/eufy-security-client/#/supported_devices).
97
71
 
98
72
  If more devices work (or also not) please report them by opening a GitHub issue.
99
73
 
@@ -103,6 +77,35 @@ Please use GitHub issues for this.
103
77
 
104
78
  ## Changelog
105
79
 
80
+ ### 1.6.0 (2022-02-05)
81
+
82
+ * (bropat) Supports new [Home Management](https://communitysecurity.eufylife.com/t/tips-for-eufy-security-app-v4-0/2420747) feature of Eufy Security 4.0
83
+ * (bropat) Added support for Smart Lock Touch & Wifi (T8520; #89)
84
+ * (bropat) Implemented Eufy MQTT notification subscription for Smart Lock Touch & Wifi (T8520)
85
+ * (bropat) Added auto lock setting for Smart Lock Touch & Wifi (T8520)
86
+ * (bropat) Added auto lock schedule setting for Smart Lock Touch & Wifi (T8520)
87
+ * (bropat) Added auto lock schedule start time setting for Smart Lock Touch & Wifi (T8520)
88
+ * (bropat) Added auto lock schedule end time setting for Smart Lock Touch & Wifi (T8520)
89
+ * (bropat) Added auto lock timer setting for Smart Lock Touch & Wifi (T8520)
90
+ * (bropat) Added notification setting for Smart Lock Touch & Wifi (T8520)
91
+ * (bropat) Added notification locked setting for Smart Lock Touch & Wifi (T8520)
92
+ * (bropat) Added notification unlocked setting for Smart Lock Touch & Wifi (T8520)
93
+ * (bropat) Added one touch locking setting for Smart Lock Touch & Wifi (T8520)
94
+ * (bropat) Added scramble passcode setting for Smart Lock Touch & Wifi (T8520)
95
+ * (bropat) Added sound setting for Smart Lock Touch & Wifi (T8520)
96
+ * (bropat) Added wrong try protection setting for Smart Lock Touch & Wifi (T8520)
97
+ * (bropat) Added wrong try attempts setting for Smart Lock Touch & Wifi (T8520)
98
+ * (bropat) Added wrong try lockdown time setting for Smart Lock Touch & Wifi (T8520)
99
+ * (bropat) Added lock/unlock command for Smart Lock Touch & Wifi (T8520)
100
+ * (bropat) Added lock calibration command for Smart Lock Touch & Wifi (T8520)
101
+ * (bropat) Improved p2p communication with energy saving devices
102
+ * (bropat) Added new HTTPApi methods supporting Eufy Security 4.0
103
+ * (bropat) Some small improvements were made to the HTTPApi
104
+ * (bropat) Fixed issue #97
105
+ * (bropat) Fixed issue #102
106
+ * (bropat) Fixed issue #109
107
+ * (bropat) Updated versions of the package dependencies
108
+
106
109
  ### 1.5.0 (2021-12-19)
107
110
 
108
111
  * (bropat) Added support for floodlight cam 2 pro (T8423)
@@ -18,6 +18,7 @@ export declare class EufySecurity extends TypedEmitter<EufySecurityEvents> {
18
18
  private cameraStationLivestreamTimeout;
19
19
  private cameraCloudLivestreamTimeout;
20
20
  private pushService;
21
+ private mqttService;
21
22
  private pushCloudRegistered;
22
23
  private pushCloudChecked;
23
24
  private persistentFile;
@@ -26,6 +27,7 @@ export declare class EufySecurity extends TypedEmitter<EufySecurityEvents> {
26
27
  private refreshEufySecurityCloudTimeout?;
27
28
  private refreshEufySecurityP2PTimeout;
28
29
  constructor(config: EufySecurityConfig, log?: Logger);
30
+ private initMQTT;
29
31
  getPushService(): PushNotificationService;
30
32
  private addStation;
31
33
  private removeStation;
@@ -19,6 +19,7 @@ const error_1 = require("./error");
19
19
  const _1 = require(".");
20
20
  const error_2 = require("./http/error");
21
21
  const push_1 = require("./push");
22
+ const service_2 = require("./mqtt/service");
22
23
  class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
23
24
  constructor(config, log = ts_log_1.dummyLogger) {
24
25
  super();
@@ -39,7 +40,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
39
40
  push_credentials: undefined,
40
41
  push_persistentIds: [],
41
42
  login_hash: "",
42
- version: ""
43
+ version: "",
44
+ httpApi: undefined
43
45
  };
44
46
  this.connected = false;
45
47
  this.refreshEufySecurityP2PTimeout = {};
@@ -100,7 +102,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
100
102
  catch (error) {
101
103
  this.log.error("Handling update - Error:", error);
102
104
  }
103
- this.api = new api_1.HTTPApi(this.config.username, this.config.password, this.log);
105
+ this.api = new api_1.HTTPApi(this.config.username, this.config.password, this.log, this.persistentData.httpApi);
104
106
  this.api.setCountry(this.config.country);
105
107
  this.api.setLanguage(this.config.language);
106
108
  this.api.setPhoneModel(this.config.trustedDeviceName);
@@ -116,6 +118,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
116
118
  this.persistentData.cloud_token = "";
117
119
  this.persistentData.cloud_token_expiration = 0;
118
120
  this.persistentData.api_base = "";
121
+ this.persistentData.httpApi = undefined;
119
122
  }
120
123
  }
121
124
  else {
@@ -163,6 +166,32 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
163
166
  this.log.info("Push notification connection closed");
164
167
  this.emit("push close");
165
168
  });
169
+ this.initMQTT();
170
+ }
171
+ async initMQTT() {
172
+ this.mqttService = await service_2.MQTTService.init(this.log);
173
+ this.mqttService.on("connect", () => {
174
+ this.log.info("MQTT connection successfully established");
175
+ this.emit("mqtt connect");
176
+ });
177
+ this.mqttService.on("close", () => {
178
+ this.log.info("MQTT connection closed");
179
+ this.emit("mqtt close");
180
+ });
181
+ this.mqttService.on("lock message", (message) => {
182
+ try {
183
+ const device = this.getDevice(message.data.data.deviceSn);
184
+ device.processMQTTNotification(message.data.data);
185
+ }
186
+ catch (error) {
187
+ if (error instanceof error_1.DeviceNotFoundError) {
188
+ }
189
+ else {
190
+ this.log.error("Lock MQTT Message Error", error);
191
+ }
192
+ }
193
+ this.emit("mqtt lock message", message);
194
+ });
166
195
  }
167
196
  getPushService() {
168
197
  return this.pushService;
@@ -209,6 +238,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
209
238
  if (serial && !Object.keys(this.devices).includes(serial)) {
210
239
  this.devices[serial] = device;
211
240
  this.emit("device added", device);
241
+ if (device.isLock())
242
+ this.mqttService.subscribeLock(device.getSerial());
212
243
  }
213
244
  else {
214
245
  throw new error_1.DuplicateDeviceError(`Device with this serial ${device.getSerial()} exists already and couldn't be added again!`);
@@ -327,7 +358,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
327
358
  }
328
359
  onStationConnect(station) {
329
360
  this.emit("station connect", station);
330
- if (station.getDeviceType() !== types_1.DeviceType.DOORBELL) {
361
+ if (device_1.Device.isCamera(station.getDeviceType()) && !device_1.Device.isWiredDoorbell(station.getDeviceType())) {
331
362
  station.getCameraInfo().catch(error => {
332
363
  this.log.error(`Error during station ${station.getSerial()} p2p data refreshing`, error);
333
364
  });
@@ -447,6 +478,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
447
478
  });
448
479
  this.savePushPersistentIds();
449
480
  this.pushService.close();
481
+ this.mqttService.close();
450
482
  Object.values(this.stations).forEach(station => {
451
483
  station.close();
452
484
  });
@@ -535,6 +567,13 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
535
567
  this.saveCloudToken();
536
568
  this.registerPushNotifications(this.persistentData.push_credentials, this.persistentData.push_persistentIds);
537
569
  this.refreshCloudData();
570
+ const loginData = this.api.getPersistentData();
571
+ if (loginData) {
572
+ this.mqttService.connect(loginData.user_id, this.persistentData.openudid, this.persistentData.api_base);
573
+ }
574
+ else {
575
+ this.log.warn("No login data recevied to initialize MQTT connection...");
576
+ }
538
577
  }
539
578
  async startStationLivestream(deviceSN) {
540
579
  const device = this.getDevice(deviceSN);
@@ -614,6 +653,7 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
614
653
  }
615
654
  writePersistentData() {
616
655
  this.persistentData.login_hash = (0, utils_1.md5)(`${this.config.username}:${this.config.password}`);
656
+ this.persistentData.httpApi = this.api.getPersistentData();
617
657
  try {
618
658
  fs_extra_1.default.writeFileSync(this.persistentFile, JSON.stringify(this.persistentData));
619
659
  }
@@ -655,7 +695,11 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
655
695
  return this.connected;
656
696
  }
657
697
  async processInvitations() {
658
- const invites = await this.api.getInvites();
698
+ let refreshCloud = false;
699
+ const invites = await this.api.getInvites().catch(error => {
700
+ this.log.error("processInvitations - getInvites - Error:", error);
701
+ return error;
702
+ });
659
703
  if (Object.keys(invites).length > 0) {
660
704
  const confirmInvites = [];
661
705
  for (const invite of Object.values(invites)) {
@@ -672,26 +716,55 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
672
716
  }
673
717
  }
674
718
  if (confirmInvites.length > 0) {
675
- const result = await this.api.confirmInvites(confirmInvites);
719
+ const result = await this.api.confirmInvites(confirmInvites).catch(error => {
720
+ this.log.error("processInvitations - confirmInvites - Error:", error);
721
+ return error;
722
+ });
676
723
  if (result) {
677
724
  this.log.info(`Accepted received invitations`, confirmInvites);
678
- this.refreshCloudData();
725
+ refreshCloud = true;
679
726
  }
680
727
  }
681
728
  }
729
+ const houseInvites = await this.api.getHouseInviteList().catch(error => {
730
+ this.log.error("processInvitations - getHouseInviteList - Error:", error);
731
+ return error;
732
+ });
733
+ if (Object.keys(houseInvites).length > 0) {
734
+ for (const invite of Object.values(houseInvites)) {
735
+ const result = await this.api.confirmHouseInvite(invite.house_id, invite.id).catch(error => {
736
+ this.log.error("processInvitations - confirmHouseInvite - Error:", error);
737
+ return error;
738
+ });
739
+ if (result) {
740
+ this.log.info(`Accepted received house invitation from ${invite.action_user_email}`, invite);
741
+ refreshCloud = true;
742
+ }
743
+ }
744
+ }
745
+ if (refreshCloud)
746
+ this.refreshCloudData();
682
747
  }
683
748
  async onPushMessage(message) {
684
749
  this.emit("push message", message);
685
750
  try {
686
751
  this.log.debug("Received push message", message);
687
752
  try {
688
- if (message.type === push_1.ServerPushEvent.INVITE_DEVICE && this.config.acceptInvitations) {
753
+ if ((message.type === push_1.ServerPushEvent.INVITE_DEVICE || message.type === push_1.ServerPushEvent.HOUSE_INVITE) && this.config.acceptInvitations) {
689
754
  this.processInvitations();
690
755
  }
691
756
  }
692
757
  catch (error) {
693
758
  this.log.error(`Error processing server push notification for device invitation`, error);
694
759
  }
760
+ try {
761
+ if (message.type === push_1.ServerPushEvent.REMOVE_DEVICE || message.type === push_1.ServerPushEvent.REMOVE_HOMEBASE || message.type === push_1.ServerPushEvent.HOUSE_REMOVE) {
762
+ this.refreshCloudData();
763
+ }
764
+ }
765
+ catch (error) {
766
+ this.log.error(`Error processing server push notification for device/station/house removal`, error);
767
+ }
695
768
  this.getStations().forEach(station => {
696
769
  try {
697
770
  station.processPushNotification(message);
@@ -953,6 +1026,48 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
953
1026
  case types_1.PropertyName.DeviceAutoCalibration:
954
1027
  await station.setAutoCalibration(device, value);
955
1028
  break;
1029
+ case types_1.PropertyName.DeviceLockSettingsAutoLock:
1030
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsAutoLock, value);
1031
+ break;
1032
+ case types_1.PropertyName.DeviceLockSettingsAutoLockSchedule:
1033
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsAutoLockSchedule, value);
1034
+ break;
1035
+ case types_1.PropertyName.DeviceLockSettingsAutoLockScheduleStartTime:
1036
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsAutoLockScheduleStartTime, value);
1037
+ break;
1038
+ case types_1.PropertyName.DeviceLockSettingsAutoLockScheduleEndTime:
1039
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsAutoLockScheduleEndTime, value);
1040
+ break;
1041
+ case types_1.PropertyName.DeviceLockSettingsAutoLockTimer:
1042
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsAutoLockTimer, value);
1043
+ break;
1044
+ case types_1.PropertyName.DeviceLockSettingsNotification:
1045
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsNotification, value);
1046
+ break;
1047
+ case types_1.PropertyName.DeviceLockSettingsNotificationLocked:
1048
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsNotificationLocked, value);
1049
+ break;
1050
+ case types_1.PropertyName.DeviceLockSettingsNotificationUnlocked:
1051
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsNotificationUnlocked, value);
1052
+ break;
1053
+ case types_1.PropertyName.DeviceLockSettingsOneTouchLocking:
1054
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsOneTouchLocking, value);
1055
+ break;
1056
+ case types_1.PropertyName.DeviceLockSettingsScramblePasscode:
1057
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsScramblePasscode, value);
1058
+ break;
1059
+ case types_1.PropertyName.DeviceLockSettingsSound:
1060
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsSound, value);
1061
+ break;
1062
+ case types_1.PropertyName.DeviceLockSettingsWrongTryProtection:
1063
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsWrongTryProtection, value);
1064
+ break;
1065
+ case types_1.PropertyName.DeviceLockSettingsWrongTryAttempts:
1066
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsWrongTryAttempts, value);
1067
+ break;
1068
+ case types_1.PropertyName.DeviceLockSettingsWrongTryLockdownTime:
1069
+ await station.setAdvancedLockParams(device, types_1.PropertyName.DeviceLockSettingsWrongTryLockdownTime, value);
1070
+ break;
956
1071
  default:
957
1072
  if (!Object.values(types_1.PropertyName).includes(name))
958
1073
  throw new error_1.ReadOnlyPropertyError(`Property ${name} is read only`);
@@ -1066,9 +1181,30 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1066
1181
  async onStationCommandResult(station, result) {
1067
1182
  try {
1068
1183
  this.emit("station command result", station, result);
1184
+ if (result.return_code === 0) {
1185
+ try {
1186
+ const device = this.getStationDevice(station.getSerial(), result.channel);
1187
+ if (result.property !== undefined) {
1188
+ device.updateProperty(result.property.name, {
1189
+ value: result.property.value,
1190
+ timestamp: +new Date,
1191
+ });
1192
+ }
1193
+ }
1194
+ catch (error) {
1195
+ if (error instanceof error_1.DeviceNotFoundError) {
1196
+ if (result.property !== undefined) {
1197
+ station.updateProperty(result.property.name, {
1198
+ value: result.property.value,
1199
+ timestamp: +new Date,
1200
+ });
1201
+ }
1202
+ }
1203
+ }
1204
+ }
1069
1205
  if (result.return_code === 0 && result.command_type !== types_2.CommandType.CMD_CAMERA_INFO && result.command_type !== types_2.CommandType.CMD_PING) {
1070
1206
  await this.api.updateDeviceInfo();
1071
- if (station.isConnected() && station.getDeviceType() !== types_1.DeviceType.DOORBELL)
1207
+ if (station.isConnected() && device_1.Device.isCamera(station.getDeviceType()) && !device_1.Device.isWiredDoorbell(station.getDeviceType()))
1072
1208
  await station.getCameraInfo();
1073
1209
  }
1074
1210
  }
@@ -1185,7 +1321,8 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
1185
1321
  const device = this.getStationDevice(station.getSerial(), channel);
1186
1322
  if (device.hasProperty(types_1.PropertyName.DeviceBattery)) {
1187
1323
  const metadataBattery = device.getPropertyMetadata(types_1.PropertyName.DeviceBattery);
1188
- device.updateRawProperty(metadataBattery.key, { value: batteryLevel.toString(), timestamp: modified });
1324
+ if (chargeType !== types_2.ChargingType.PLUGGED)
1325
+ device.updateRawProperty(metadataBattery.key, { value: batteryLevel.toString(), timestamp: modified });
1189
1326
  }
1190
1327
  if (device.hasProperty(types_1.PropertyName.DeviceChargingStatus)) {
1191
1328
  const metadataChargingStatus = device.getPropertyMetadata(types_1.PropertyName.DeviceChargingStatus);