@homebridge-plugins/homebridge-eufy-security 0.0.1

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 (185) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/FUNDING.yml +1 -0
  3. package/LICENSE +176 -0
  4. package/README.md +67 -0
  5. package/config.schema.json +6 -0
  6. package/dist/accessories/AutoSyncStationAccessory.js +156 -0
  7. package/dist/accessories/AutoSyncStationAccessory.js.map +1 -0
  8. package/dist/accessories/BaseAccessory.js +247 -0
  9. package/dist/accessories/BaseAccessory.js.map +1 -0
  10. package/dist/accessories/CameraAccessory.js +431 -0
  11. package/dist/accessories/CameraAccessory.js.map +1 -0
  12. package/dist/accessories/Device.js +67 -0
  13. package/dist/accessories/Device.js.map +1 -0
  14. package/dist/accessories/EntrySensorAccessory.js +48 -0
  15. package/dist/accessories/EntrySensorAccessory.js.map +1 -0
  16. package/dist/accessories/LockAccessory.js +142 -0
  17. package/dist/accessories/LockAccessory.js.map +1 -0
  18. package/dist/accessories/MotionSensorAccessory.js +48 -0
  19. package/dist/accessories/MotionSensorAccessory.js.map +1 -0
  20. package/dist/accessories/SmartDropAccessory.js +145 -0
  21. package/dist/accessories/SmartDropAccessory.js.map +1 -0
  22. package/dist/accessories/StationAccessory.js +371 -0
  23. package/dist/accessories/StationAccessory.js.map +1 -0
  24. package/dist/config.js +25 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/controller/LocalLivestreamManager.js +116 -0
  27. package/dist/controller/LocalLivestreamManager.js.map +1 -0
  28. package/dist/controller/recordingDelegate.js +208 -0
  29. package/dist/controller/recordingDelegate.js.map +1 -0
  30. package/dist/controller/snapshotDelegate.js +345 -0
  31. package/dist/controller/snapshotDelegate.js.map +1 -0
  32. package/dist/controller/streamingDelegate.js +345 -0
  33. package/dist/controller/streamingDelegate.js.map +1 -0
  34. package/dist/index.js +11 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/interfaces.js +2 -0
  37. package/dist/interfaces.js.map +1 -0
  38. package/dist/media/Snapshot-Unavailable.png +0 -0
  39. package/dist/media/Snapshot-Unavailable.xcf +0 -0
  40. package/dist/media/Snapshot-black.png +0 -0
  41. package/dist/media/camera-disabled.png +0 -0
  42. package/dist/media/camera-offline.png +0 -0
  43. package/dist/media/media/Snapshot-Unavailable.png +0 -0
  44. package/dist/media/media/Snapshot-Unavailable.xcf +0 -0
  45. package/dist/media/media/Snapshot-black.png +0 -0
  46. package/dist/media/media/camera-disabled.png +0 -0
  47. package/dist/media/media/camera-offline.png +0 -0
  48. package/dist/platform.js +716 -0
  49. package/dist/platform.js.map +1 -0
  50. package/dist/settings.js +38 -0
  51. package/dist/settings.js.map +1 -0
  52. package/dist/utils/Talkback.js +92 -0
  53. package/dist/utils/Talkback.js.map +1 -0
  54. package/dist/utils/accessoriesStore.js +206 -0
  55. package/dist/utils/accessoriesStore.js.map +1 -0
  56. package/dist/utils/configTypes.js +35 -0
  57. package/dist/utils/configTypes.js.map +1 -0
  58. package/dist/utils/ffmpeg.js +843 -0
  59. package/dist/utils/ffmpeg.js.map +1 -0
  60. package/dist/utils/interfaces.js +8 -0
  61. package/dist/utils/interfaces.js.map +1 -0
  62. package/dist/utils/utils.js +44 -0
  63. package/dist/utils/utils.js.map +1 -0
  64. package/dist/version.js +2 -0
  65. package/dist/version.js.map +1 -0
  66. package/eslint.config.mjs +18 -0
  67. package/homebridge-eufy-security.png +0 -0
  68. package/homebridge-ui/public/app.js +225 -0
  69. package/homebridge-ui/public/assets/devices/4g_lte_starlight_large.jpg +0 -0
  70. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C30.png +0 -0
  71. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C31.png +0 -0
  72. package/homebridge-ui/public/assets/devices/batterydoorbell1080p_large.jpg +0 -0
  73. package/homebridge-ui/public/assets/devices/batterydoorbell2kdual_large.jpg +0 -0
  74. package/homebridge-ui/public/assets/devices/batterydoorbell_e340_large.png +0 -0
  75. package/homebridge-ui/public/assets/devices/eufy-security-client.png +0 -0
  76. package/homebridge-ui/public/assets/devices/eufycam2_large.png +0 -0
  77. package/homebridge-ui/public/assets/devices/eufycam2c_large.jpg +0 -0
  78. package/homebridge-ui/public/assets/devices/eufycam2cpro_large.jpg +0 -0
  79. package/homebridge-ui/public/assets/devices/eufycam2pro_large.jpg +0 -0
  80. package/homebridge-ui/public/assets/devices/eufycam3_large.jpg +0 -0
  81. package/homebridge-ui/public/assets/devices/eufycam3c_large.jpg +0 -0
  82. package/homebridge-ui/public/assets/devices/eufycam3pro_large.png +0 -0
  83. package/homebridge-ui/public/assets/devices/eufycam_large.jpg +0 -0
  84. package/homebridge-ui/public/assets/devices/eufycame330_large.jpg +0 -0
  85. package/homebridge-ui/public/assets/devices/floodlight2_large.jpg +0 -0
  86. package/homebridge-ui/public/assets/devices/floodlight2pro_large.jpg +0 -0
  87. package/homebridge-ui/public/assets/devices/floodlight_large.jpg +0 -0
  88. package/homebridge-ui/public/assets/devices/floodlightcame340_large.jpg +0 -0
  89. package/homebridge-ui/public/assets/devices/garage_camera_t8452_large.jpg +0 -0
  90. package/homebridge-ui/public/assets/devices/homebase2_large.png +0 -0
  91. package/homebridge-ui/public/assets/devices/homebase3_large.png +0 -0
  92. package/homebridge-ui/public/assets/devices/homebase_large.jpg +0 -0
  93. package/homebridge-ui/public/assets/devices/homebasemini_large.jpg +0 -0
  94. package/homebridge-ui/public/assets/devices/indoorcamC210_large.png +0 -0
  95. package/homebridge-ui/public/assets/devices/indoorcamC220_large.png +0 -0
  96. package/homebridge-ui/public/assets/devices/indoorcamE30_large.png +0 -0
  97. package/homebridge-ui/public/assets/devices/indoorcamc120_large.png +0 -0
  98. package/homebridge-ui/public/assets/devices/indoorcammini_large.jpg +0 -0
  99. package/homebridge-ui/public/assets/devices/indoorcamp24_large.png +0 -0
  100. package/homebridge-ui/public/assets/devices/indoorcams350_large.jpg +0 -0
  101. package/homebridge-ui/public/assets/devices/keypad_large.png +0 -0
  102. package/homebridge-ui/public/assets/devices/minibase_chime_T8023_large.jpg +0 -0
  103. package/homebridge-ui/public/assets/devices/motionsensor_large.png +0 -0
  104. package/homebridge-ui/public/assets/devices/sensor_large.png +0 -0
  105. package/homebridge-ui/public/assets/devices/smartdrop_t8790_large.png +0 -0
  106. package/homebridge-ui/public/assets/devices/smartlock_t8500_large.png +0 -0
  107. package/homebridge-ui/public/assets/devices/smartlock_t8500_wifibridge_large.jpg +0 -0
  108. package/homebridge-ui/public/assets/devices/smartlock_t8503_large.png +0 -0
  109. package/homebridge-ui/public/assets/devices/smartlock_t8504_large.jpg +0 -0
  110. package/homebridge-ui/public/assets/devices/smartlock_t8510P_t8520P_large.png +0 -0
  111. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8502_large.png +0 -0
  112. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8506_large.png +0 -0
  113. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8520_large.png +0 -0
  114. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_large.png +0 -0
  115. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_wifibridge_large.jpg +0 -0
  116. package/homebridge-ui/public/assets/devices/smartlock_video_t8530_large.png +0 -0
  117. package/homebridge-ui/public/assets/devices/smartlockwifibridge_t8021_large.jpg +0 -0
  118. package/homebridge-ui/public/assets/devices/smartsafe_s10_t7400_large.png +0 -0
  119. package/homebridge-ui/public/assets/devices/smartsafe_s12_t7401_large.png +0 -0
  120. package/homebridge-ui/public/assets/devices/smarttrack_card_t87B2_large.png +0 -0
  121. package/homebridge-ui/public/assets/devices/smarttrack_link_t87B0_large.png +0 -0
  122. package/homebridge-ui/public/assets/devices/solocamc210_large.jpg +0 -0
  123. package/homebridge-ui/public/assets/devices/solocamc35_large.png +0 -0
  124. package/homebridge-ui/public/assets/devices/solocame20_large.jpg +0 -0
  125. package/homebridge-ui/public/assets/devices/solocame30_large.png +0 -0
  126. package/homebridge-ui/public/assets/devices/solocame40_large.jpg +0 -0
  127. package/homebridge-ui/public/assets/devices/solocaml20_large.jpg +0 -0
  128. package/homebridge-ui/public/assets/devices/solocams220_large.jpg +0 -0
  129. package/homebridge-ui/public/assets/devices/solocams340_large.png +0 -0
  130. package/homebridge-ui/public/assets/devices/solocams40_large.jpg +0 -0
  131. package/homebridge-ui/public/assets/devices/soloindoorcamc24_large.jpg +0 -0
  132. package/homebridge-ui/public/assets/devices/solooutdoorcamc22_large.png +0 -0
  133. package/homebridge-ui/public/assets/devices/solooutdoorcamc24_large.jpg +0 -0
  134. package/homebridge-ui/public/assets/devices/unknown.png +0 -0
  135. package/homebridge-ui/public/assets/devices/walllight_s100_large.jpg +0 -0
  136. package/homebridge-ui/public/assets/devices/walllight_s120_large.jpg +0 -0
  137. package/homebridge-ui/public/assets/devices/wireddoorbell1080p_large.jpg +0 -0
  138. package/homebridge-ui/public/assets/devices/wireddoorbell2k_large.png +0 -0
  139. package/homebridge-ui/public/assets/devices/wireddoorbelldual_large.jpg +0 -0
  140. package/homebridge-ui/public/assets/icons/attach.svg +1 -0
  141. package/homebridge-ui/public/assets/icons/battery_0.svg +1 -0
  142. package/homebridge-ui/public/assets/icons/battery_1.svg +1 -0
  143. package/homebridge-ui/public/assets/icons/battery_2.svg +1 -0
  144. package/homebridge-ui/public/assets/icons/battery_3.svg +1 -0
  145. package/homebridge-ui/public/assets/icons/battery_4.svg +1 -0
  146. package/homebridge-ui/public/assets/icons/battery_5.svg +1 -0
  147. package/homebridge-ui/public/assets/icons/battery_6.svg +1 -0
  148. package/homebridge-ui/public/assets/icons/bolt.svg +1 -0
  149. package/homebridge-ui/public/assets/icons/bug-report.svg +1 -0
  150. package/homebridge-ui/public/assets/icons/copy.svg +1 -0
  151. package/homebridge-ui/public/assets/icons/delete.svg +1 -0
  152. package/homebridge-ui/public/assets/icons/download.svg +1 -0
  153. package/homebridge-ui/public/assets/icons/info.svg +1 -0
  154. package/homebridge-ui/public/assets/icons/inventory.svg +1 -0
  155. package/homebridge-ui/public/assets/icons/refresh.svg +1 -0
  156. package/homebridge-ui/public/assets/icons/satellite_alt.svg +1 -0
  157. package/homebridge-ui/public/assets/icons/settings.svg +1 -0
  158. package/homebridge-ui/public/assets/icons/settings_backup_restore.svg +1 -0
  159. package/homebridge-ui/public/assets/icons/solar_power.svg +1 -0
  160. package/homebridge-ui/public/assets/icons/warning.svg +1 -0
  161. package/homebridge-ui/public/components/device-card.js +162 -0
  162. package/homebridge-ui/public/components/guard-modes.js +88 -0
  163. package/homebridge-ui/public/components/number-input.js +121 -0
  164. package/homebridge-ui/public/components/select.js +73 -0
  165. package/homebridge-ui/public/components/toggle.js +68 -0
  166. package/homebridge-ui/public/index.html +27 -0
  167. package/homebridge-ui/public/services/api.js +214 -0
  168. package/homebridge-ui/public/services/config.js +144 -0
  169. package/homebridge-ui/public/style.css +775 -0
  170. package/homebridge-ui/public/utils/countries.js +73 -0
  171. package/homebridge-ui/public/utils/device-images.js +89 -0
  172. package/homebridge-ui/public/utils/helpers.js +87 -0
  173. package/homebridge-ui/public/views/dashboard.js +226 -0
  174. package/homebridge-ui/public/views/device-detail.js +610 -0
  175. package/homebridge-ui/public/views/diagnostics.js +296 -0
  176. package/homebridge-ui/public/views/login.js +636 -0
  177. package/homebridge-ui/public/views/settings.js +192 -0
  178. package/homebridge-ui/public/views/unsupported-detail.js +296 -0
  179. package/homebridge-ui/server.js +1327 -0
  180. package/media/Snapshot-Unavailable.png +0 -0
  181. package/media/Snapshot-Unavailable.xcf +0 -0
  182. package/media/Snapshot-black.png +0 -0
  183. package/media/camera-disabled.png +0 -0
  184. package/media/camera-offline.png +0 -0
  185. package/package.json +64 -0
@@ -0,0 +1,371 @@
1
+ import { BaseAccessory } from './BaseAccessory.js';
2
+ // @ts-ignore
3
+ import { DeviceType, PropertyName, AlarmEvent, GuardMode } from 'eufy-security-client';
4
+ import { CHAR, SERV, log } from '../utils/utils.js';
5
+ export var HKGuardMode;
6
+ (function (HKGuardMode) {
7
+ HKGuardMode[HKGuardMode["STAY_ARM"] = 0] = "STAY_ARM";
8
+ HKGuardMode[HKGuardMode["AWAY_ARM"] = 1] = "AWAY_ARM";
9
+ HKGuardMode[HKGuardMode["NIGHT_ARM"] = 2] = "NIGHT_ARM";
10
+ HKGuardMode[HKGuardMode["DISARM"] = 3] = "DISARM";
11
+ })(HKGuardMode || (HKGuardMode = {}));
12
+ /**
13
+ * Platform Accessory
14
+ * An instance of this class is created for each accessory your platform registers
15
+ * Each accessory may expose multiple services of different service types.
16
+ */
17
+ export class StationAccessory extends BaseAccessory {
18
+ stationConfig;
19
+ hasKeyPad = false;
20
+ modes;
21
+ alarm_triggered;
22
+ alarm_delayed;
23
+ alarm_delay_timeout;
24
+ guardModeChangeTimeout = { timeout: null, delay: 5000 };
25
+ constructor(platform, accessory, device) {
26
+ super(platform, accessory, device);
27
+ this.log.debug(`Constructed Station`);
28
+ this.hasKeyPad = this.device.hasDeviceWithType(DeviceType.KEYPAD);
29
+ this.log.debug(`has keypad:`, this.hasKeyPad);
30
+ this.stationConfig = this.getStationConfig();
31
+ this.modes = this.mappingHKEufy();
32
+ this.alarm_triggered = false;
33
+ this.alarm_delayed = false;
34
+ const validValues = [
35
+ CHAR.SecuritySystemTargetState.AWAY_ARM,
36
+ CHAR.SecuritySystemTargetState.STAY_ARM,
37
+ CHAR.SecuritySystemTargetState.DISARM,
38
+ ];
39
+ const SecuritySettings = [
40
+ PropertyName.StationHomeSecuritySettings,
41
+ PropertyName.StationAwaySecuritySettings,
42
+ PropertyName.StationOffSecuritySettings,
43
+ PropertyName.StationCustom1SecuritySettings,
44
+ PropertyName.StationCustom2SecuritySettings,
45
+ PropertyName.StationCustom3SecuritySettings,
46
+ ];
47
+ SecuritySettings.forEach(item => {
48
+ if (this.device.hasPropertyValue(item) && this.getPropertyValue(item) !== '') {
49
+ this.log.debug(`- ${item} :`, this.getPropertyValue(item));
50
+ }
51
+ });
52
+ // if (this.stationConfig.hkNight) {
53
+ validValues.push(CHAR.SecuritySystemTargetState.NIGHT_ARM);
54
+ // }
55
+ this.registerCharacteristic({
56
+ serviceType: SERV.SecuritySystem,
57
+ characteristicType: CHAR.SecuritySystemCurrentState,
58
+ getValue: () => this.handleSecuritySystemCurrentStateGet(),
59
+ onValue: (service, characteristic) => {
60
+ this.device.on('current mode', (station, currentMode) => {
61
+ this.onStationCurrentModePushNotification(characteristic, currentMode);
62
+ });
63
+ this.device.on('alarm event', (station, alarmEvent) => this.onStationAlarmEventPushNotification(characteristic, alarmEvent));
64
+ },
65
+ });
66
+ this.registerCharacteristic({
67
+ serviceType: SERV.SecuritySystem,
68
+ characteristicType: CHAR.SecuritySystemTargetState,
69
+ getValue: () => this.handleSecuritySystemTargetStateGet(),
70
+ setValue: (value) => this.handleSecuritySystemTargetStateSet(value),
71
+ onValue: (service, characteristic) => {
72
+ this.device.on('guard mode', (station, guardMode) => {
73
+ this.onStationGuardModePushNotification(characteristic, station, guardMode);
74
+ });
75
+ this.device.on('alarm arm delay event', this.onStationAlarmDelayedEvent.bind(this));
76
+ this.device.on('alarm armed event', this.onStationAlarmArmedEvent.bind(this));
77
+ },
78
+ });
79
+ this.getService(SERV.SecuritySystem)
80
+ .getCharacteristic(CHAR.SecuritySystemTargetState)
81
+ .setProps({ validValues });
82
+ this.registerCharacteristic({
83
+ serviceType: SERV.Switch,
84
+ characteristicType: CHAR.On,
85
+ name: this.accessory.displayName + ' Siren',
86
+ getValue: () => this.handleManualTriggerSwitchStateGet(),
87
+ setValue: (value) => this.handleManualTriggerSwitchStateSet(value),
88
+ });
89
+ this.pruneUnusedServices();
90
+ }
91
+ /**
92
+ * Get the current value of the "propertyName" characteristic
93
+ */
94
+ getPropertyValue(propertyName) {
95
+ return this.device.getPropertyValue(propertyName);
96
+ }
97
+ async setPropertyValue(propertyName, value) {
98
+ await this.platform.eufyClient.setStationProperty(this.SN, propertyName, value);
99
+ }
100
+ /**
101
+ * Gets the station configuration based on several possible sources.
102
+ * Priority is given to custom configurations (if available), then falls back to global configs,
103
+ * and lastly uses default values if neither custom nor global configs are set.
104
+ *
105
+ * @returns {StationConfig} The final configuration settings for the station
106
+ */
107
+ getStationConfig() {
108
+ // Find the station configuration based on the serial number, if it exists
109
+ const stationConfig = this.platform.config.stations?.find((station) => station.serialNumber === this.SN);
110
+ // Debug log to show the retrieved station configuration
111
+ this.log.debug(`Config:`, stationConfig);
112
+ // Initialize the config object with prioritized values
113
+ const config = {
114
+ // For each setting (e.g., hkHome), check if it is defined in the custom config,
115
+ // if not, check the global config, and as a last resort, use the default value
116
+ hkHome: stationConfig?.hkHome ?? this.platform.config.hkHome,
117
+ hkAway: stationConfig?.hkAway ?? this.platform.config.hkAway,
118
+ hkNight: stationConfig?.hkNight ?? this.platform.config.hkNight,
119
+ // Default HomeKit mode for 'Off':
120
+ // - If a keypad is present, set to 6 (Special value)
121
+ // - Otherwise, set to 63 (Default value)
122
+ hkOff: stationConfig?.hkOff ?? this.hasKeyPad ? 6 : this.platform.config.hkOff,
123
+ // Use optional chaining to safely access manualTriggerModes and manualAlarmSeconds
124
+ manualTriggerModes: stationConfig?.manualTriggerModes ?? [],
125
+ manualAlarmSeconds: stationConfig?.manualAlarmSeconds ?? 30,
126
+ };
127
+ // Log the manual trigger modes for debugging purposes
128
+ this.log.debug(`manual alarm will be triggered only in these hk modes:\r${config.manualTriggerModes}`);
129
+ // Return the final configuration object
130
+ return config;
131
+ }
132
+ mappingHKEufy() {
133
+ // Initialize the modes array with HomeKit and Eufy mode mappings
134
+ const modes = [
135
+ { hk: 0, eufy: this.stationConfig.hkHome },
136
+ { hk: 1, eufy: this.stationConfig.hkAway },
137
+ { hk: 2, eufy: this.stationConfig.hkNight },
138
+ { hk: 3, eufy: this.stationConfig.hkOff },
139
+ ];
140
+ // Log the mapping for station modes for debugging purposes
141
+ this.log.debug(`Mapping for station modes:`, modes);
142
+ return modes;
143
+ }
144
+ onStationGuardModePushNotification(characteristic, station, guardMode) {
145
+ this.log.debug(`ON SecurityGuardMode: ${guardMode}`);
146
+ const homekitCurrentMode = this.convertEufytoHK(guardMode);
147
+ characteristic.updateValue(homekitCurrentMode);
148
+ }
149
+ onStationCurrentModePushNotification(characteristic, currentMode) {
150
+ if (this.guardModeChangeTimeout.timeout) {
151
+ // If there's an existing timeout, clear it
152
+ clearTimeout(this.guardModeChangeTimeout.timeout);
153
+ }
154
+ this.log.debug(`ON SecuritySystemCurrentState: ${currentMode}`);
155
+ const homekitCurrentMode = this.convertEufytoHK(currentMode);
156
+ characteristic.updateValue(homekitCurrentMode);
157
+ }
158
+ onStationAlarmEventPushNotification(characteristic, alarmEvent) {
159
+ let currentValue = this.device.getPropertyValue(PropertyName.StationCurrentMode);
160
+ if (alarmEvent === 0) {
161
+ // do not resset alarm if alarm was triggered manually
162
+ // since the alarm can only be triggered for 30 seconds for now (limitation of @homebridge-eufy-security/eufy-security-client)
163
+ // this would mean that the alarm is always reset after 30 seconds
164
+ // see here: https://github.com/bropat/@homebridge-eufy-security/eufy-security-client/issues/178
165
+ currentValue = -1;
166
+ }
167
+ switch (alarmEvent) {
168
+ case 2: // Alarm triggered by GSENSOR
169
+ case 3: // Alarm triggered by PIR
170
+ case 4: // Alarm triggered by EUFY_APP
171
+ case 6: // Alarm triggered by DOOR
172
+ case 7: // Alarm triggered by CAMERA_PIR
173
+ case 8: // Alarm triggered by MOTION_SENSOR
174
+ case 9: // Alarm triggered by CAMERA_GSENSOR
175
+ log.warn('ON StationAlarmEvent - ALARM TRIGGERED - alarmEvent:', AlarmEvent[alarmEvent]);
176
+ this.alarm_triggered = true;
177
+ characteristic.updateValue(CHAR.SecuritySystemCurrentState.ALARM_TRIGGERED); // Alarm !!!
178
+ break;
179
+ case 0: // Alarm off by Hub
180
+ case 15: // Alarm off by Keypad
181
+ case 16: // Alarm off by Eufy App
182
+ case 17: // Alarm off by HomeBase button
183
+ log.warn('ON StationAlarmEvent - ALARM OFF - alarmEvent:', AlarmEvent[alarmEvent]);
184
+ this.alarm_triggered = false;
185
+ if (currentValue !== -1) {
186
+ characteristic.updateValue(this.convertEufytoHK(currentValue)); // reset alarm state
187
+ }
188
+ break;
189
+ default:
190
+ log.warn('ON StationAlarmEvent - ALARM UNKNOWN - alarmEvent:', AlarmEvent[alarmEvent]);
191
+ characteristic.updateValue(CHAR.StatusFault.GENERAL_FAULT);
192
+ break;
193
+ }
194
+ this.updateManuelTriggerButton(this.alarm_triggered);
195
+ }
196
+ /**
197
+ * Convert a HomeKit mode number to its corresponding Eufy mode number.
198
+ * Searches the `this.modes` array to find a matching HomeKit mode.
199
+ * Throws an error if a matching mode is not found.
200
+ *
201
+ * @param {number} hkMode - The HomeKit mode to convert
202
+ * @returns {number} The corresponding Eufy mode
203
+ * @throws {Error} If a matching mode is not found
204
+ */
205
+ convertHKtoEufy(hkMode) {
206
+ const modeObj = this.modes.find((m) => m.hk === hkMode);
207
+ if (!modeObj) {
208
+ throw new Error(`${this.accessory.displayName} No matching Eufy mode found for HomeKit mode ${hkMode}`);
209
+ }
210
+ return modeObj.eufy;
211
+ }
212
+ /**
213
+ * Convert a Eufy mode number to its corresponding HomeKit mode number.
214
+ * Searches the `this.modes` array to find a matching Eufy mode.
215
+ * Throws an error if a matching mode is not found.
216
+ *
217
+ * @param {number} eufyMode - The Eufy mode to convert
218
+ * @returns {number} The corresponding HomeKit mode
219
+ * @throws {Error} If a matching mode is not found
220
+ */
221
+ convertEufytoHK(eufyMode) {
222
+ const modeObj = this.modes.find((m) => m.eufy === eufyMode);
223
+ if (!modeObj) {
224
+ throw new Error(`${this.accessory.displayName} No matching HomeKit mode found for Eufy mode ${eufyMode}`);
225
+ }
226
+ return modeObj.hk;
227
+ }
228
+ /**
229
+ * Handle requests to get the current value of the 'Security System Current State' characteristic
230
+ */
231
+ handleSecuritySystemCurrentStateGet() {
232
+ if (this.alarm_triggered) {
233
+ return CHAR.SecuritySystemCurrentState.ALARM_TRIGGERED;
234
+ }
235
+ return this.handleSecuritySystemTargetStateGet('handleSecuritySystemCurrentStateGets');
236
+ }
237
+ /**
238
+ * Handle requests to get the current value of the 'Security System Target State' characteristic
239
+ */
240
+ handleSecuritySystemTargetStateGet(stateCharacteristic = 'handleSecuritySystemTargetStateGet') {
241
+ try {
242
+ const currentValue = this.device.getPropertyValue(PropertyName.StationCurrentMode);
243
+ if (currentValue === -1) {
244
+ this.log.warn(`${stateCharacteristic}: Device state not initialized, returning safe default (DISARM)`);
245
+ return CHAR.SecuritySystemTargetState.DISARM;
246
+ }
247
+ this.log.debug(`GET StationCurrentMode: ${currentValue}`);
248
+ return this.convertEufytoHK(currentValue);
249
+ }
250
+ catch (error) {
251
+ this.log.error(`${stateCharacteristic}: Failed to retrieve security system state`, error);
252
+ return CHAR.SecuritySystemTargetState.DISARM;
253
+ }
254
+ }
255
+ /**
256
+ * Handle requests to set the 'Security System Target State' characteristic
257
+ */
258
+ handleSecuritySystemTargetStateSet(value) {
259
+ try {
260
+ this.alarm_triggered = false;
261
+ const NameMode = this.getGuardModeName(value);
262
+ this.log.debug(`SET StationGuardMode HomeKit: ${NameMode}`);
263
+ const mode = this.convertHKtoEufy(value);
264
+ if (isNaN(mode)) {
265
+ throw new Error(`${this.accessory.displayName}:
266
+ Could not convert guard mode value to valid number. Aborting guard mode change...'`);
267
+ }
268
+ this.log.debug(`SET StationGuardMode Eufy: ${GuardMode[mode]}(${mode})`);
269
+ this.log.info(`Request to change station guard mode to: ${NameMode}`);
270
+ // Call the device's setGuardMode method to initiate the action
271
+ this.device.setGuardMode(mode);
272
+ // Set a new timeout
273
+ this.guardModeChangeTimeout.timeout = setTimeout(() => {
274
+ // This code is executed when the timeout elapses, indicating that the action may not have completed yet.
275
+ // You can include a message indicating that the action is being retried.
276
+ this.log.warn(`Changing guard mode to ${NameMode} did not complete. Retry...'`);
277
+ // Call the device's setGuardMode method to initiate the action
278
+ this.device.setGuardMode(mode);
279
+ // Set a secondary timeout for retry, if needed
280
+ const retryTimeout = setTimeout(() => {
281
+ // This code is executed if the retry also times out, indicating a failure.
282
+ this.log.error(`Changing guard mode to ${NameMode} timed out!`);
283
+ }, this.guardModeChangeTimeout.delay);
284
+ // Store the retry timeout as part of guardModeChangeTimeout
285
+ this.guardModeChangeTimeout.timeout = retryTimeout;
286
+ }, this.guardModeChangeTimeout.delay);
287
+ this.updateManuelTriggerButton(false);
288
+ }
289
+ catch (error) {
290
+ this.log.error(`Error Setting security mode! ${error}`);
291
+ }
292
+ }
293
+ handleManualTriggerSwitchStateGet() {
294
+ return this.alarm_triggered;
295
+ }
296
+ async handleManualTriggerSwitchStateSet(value) {
297
+ if (value) { // trigger alarm
298
+ try {
299
+ const currentValue = this.device.getPropertyValue(PropertyName.StationCurrentMode);
300
+ if (currentValue === -1) {
301
+ throw 'Something wrong with this device';
302
+ }
303
+ // check if alarm is allowed for this guard mode
304
+ // and alarm is not delayed
305
+ if (this.stationConfig.manualTriggerModes.indexOf(this.convertEufytoHK(currentValue)) !== -1 && !this.alarm_delayed) {
306
+ this.device.triggerStationAlarmSound(this.stationConfig.manualAlarmSeconds)
307
+ .then(() => log.debug(this.accessory.displayName, 'alarm manually triggered for ' + this.stationConfig.manualAlarmSeconds + ' seconds.'))
308
+ .catch(error => this.log.error(`alarm could not be manually triggered: ${error}`));
309
+ }
310
+ else {
311
+ const message = this.alarm_delayed ?
312
+ 'tried to trigger alarm, but the alarm delayed event was triggered beforehand.' :
313
+ 'tried to trigger alarm, but the current station mode prevents the alarm from being triggered. ' +
314
+ 'Please look in in the configuration if you want to change this behaviour.';
315
+ setTimeout(() => {
316
+ this.log.info(`${message}`);
317
+ this.updateManuelTriggerButton(false);
318
+ }, 1000);
319
+ }
320
+ }
321
+ catch {
322
+ this.log.error(`handleSecuritySystemTargetStateGet: ${value}`);
323
+ return;
324
+ }
325
+ }
326
+ else { // reset alarm
327
+ const resetPromise = this.device.resetStationAlarmSound();
328
+ if (resetPromise) {
329
+ resetPromise
330
+ .then(() => this.log.debug(`alarm manually reset`))
331
+ .catch(error => this.log.error(`alarm could not be reset: ${error}`));
332
+ }
333
+ else {
334
+ this.log.warn(`resetStationAlarmSound returned undefined`);
335
+ }
336
+ }
337
+ }
338
+ onStationAlarmDelayedEvent(station, armDelay) {
339
+ this.log.debug(`alarm for this station will be delayed by ${armDelay} seconds.`);
340
+ this.alarm_delayed = true;
341
+ if (this.alarm_delay_timeout) {
342
+ clearTimeout(this.alarm_delay_timeout);
343
+ }
344
+ this.alarm_delay_timeout = setTimeout(() => {
345
+ this.log.debug(`alarm for this station is armed now (due to timeout).`);
346
+ this.alarm_delayed = false;
347
+ }, (armDelay + 1) * 1000);
348
+ }
349
+ onStationAlarmArmedEvent() {
350
+ this.log.debug(`alarm for this station is armed now.`);
351
+ this.alarm_delayed = false;
352
+ if (this.alarm_delay_timeout) {
353
+ clearTimeout(this.alarm_delay_timeout);
354
+ }
355
+ }
356
+ getGuardModeName(value) {
357
+ try {
358
+ return `${HKGuardMode[value]}(${value})`;
359
+ }
360
+ catch (error) {
361
+ this.log.error(`Error getting guard mode name! ${error}`);
362
+ return 'Unknown';
363
+ }
364
+ }
365
+ updateManuelTriggerButton(state) {
366
+ this.getService(SERV.Switch, this.accessory.displayName + ' Siren')
367
+ .getCharacteristic(CHAR.On)
368
+ .updateValue(state);
369
+ }
370
+ }
371
+ //# sourceMappingURL=StationAccessory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StationAccessory.js","sourceRoot":"","sources":["../../src/accessories/StationAccessory.ts"],"names":[],"mappings":"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"}
package/dist/config.js ADDED
@@ -0,0 +1,25 @@
1
+ export const DEFAULT_CONFIG_VALUES = {
2
+ platform: 'EufySecurity',
3
+ name: 'EufySecurity',
4
+ username: '',
5
+ password: '',
6
+ deviceName: 'MyPhone',
7
+ enableDetailedLogging: false,
8
+ omitLogFiles: false,
9
+ CameraMaxLivestreamDuration: 30,
10
+ pollingIntervalMinutes: 10,
11
+ hkHome: 1,
12
+ hkAway: 0,
13
+ hkNight: 3,
14
+ hkOff: 63,
15
+ ignoreStations: [],
16
+ ignoreDevices: [],
17
+ country: 'US',
18
+ stations: [],
19
+ cameras: [],
20
+ cleanCache: true,
21
+ ignoreMultipleDevicesWarning: false,
22
+ autoSyncStation: false,
23
+ enableEmbeddedPKCS1Support: false,
24
+ };
25
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAgCA,MAAM,CAAC,MAAM,qBAAqB,GAA+B;IAC/D,QAAQ,EAAE,cAAc;IACxB,IAAI,EAAE,cAAc;IACpB,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,SAAS;IACrB,qBAAqB,EAAE,KAAK;IAC5B,YAAY,EAAE,KAAK;IACnB,2BAA2B,EAAE,EAAE;IAC/B,sBAAsB,EAAE,EAAE;IAC1B,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,KAAK,EAAE,EAAE;IACT,cAAc,EAAE,EAAE;IAClB,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,EAAE;IACZ,OAAO,EAAE,EAAE;IACX,UAAU,EAAE,IAAI;IAChB,4BAA4B,EAAE,KAAK;IACnC,eAAe,EAAE,KAAK;IACtB,0BAA0B,EAAE,KAAK;CAClC,CAAC"}
@@ -0,0 +1,116 @@
1
+ import { Deferred } from '../utils/utils.js';
2
+ const P2P_TIMEOUT_MS = 15_000;
3
+ const DUPLICATE_STREAM_GUARD_S = 5;
4
+ export class LocalLivestreamManager {
5
+ stationStream = null;
6
+ pending = null;
7
+ eufyClient;
8
+ log;
9
+ serialNumber;
10
+ constructor(camera) {
11
+ this.eufyClient = camera.platform.eufyClient;
12
+ this.serialNumber = camera.device.getSerial();
13
+ this.log = camera.log;
14
+ this.log.debug(`LocalLivestreamManager initialized for ${camera.device.getName()} (serial: ${this.serialNumber})`);
15
+ this.eufyClient.on('station livestream start', this.onStationLivestreamStart);
16
+ this.eufyClient.on('station livestream stop', this.onStationLivestreamStop);
17
+ }
18
+ /** Destroy active streams and reset state. */
19
+ destroyStreams() {
20
+ if (this.stationStream) {
21
+ this.stationStream.audiostream.unpipe();
22
+ this.stationStream.audiostream.destroy();
23
+ this.stationStream.videostream.unpipe();
24
+ this.stationStream.videostream.destroy();
25
+ this.stationStream = null;
26
+ }
27
+ }
28
+ /** Return the active livestream, or start a new one. Concurrent callers share the same pending request. */
29
+ async getLocalLiveStream() {
30
+ if (this.stationStream) {
31
+ const runtime = ((Date.now() - this.stationStream.createdAt) / 1000).toFixed(1);
32
+ this.log.debug(`Reusing livestream started ${runtime}s ago.`);
33
+ return this.stationStream;
34
+ }
35
+ return this.startLocalLiveStream();
36
+ }
37
+ /** True when a P2P livestream is currently active. */
38
+ isStreamActive() {
39
+ return this.stationStream !== null;
40
+ }
41
+ /**
42
+ * Requests a P2P livestream from the eufy station and waits for the
43
+ * 'station livestream start' event. If a start is already in progress,
44
+ * the caller piggy-backs on the existing promise instead of issuing a
45
+ * duplicate request.
46
+ */
47
+ startLocalLiveStream() {
48
+ if (this.pending) {
49
+ this.log.debug('Livestream already starting — waiting on existing request.');
50
+ return this.pending.deferred.promise;
51
+ }
52
+ this.log.debug(`Starting station livestream for serial: ${this.serialNumber}...`);
53
+ const deferred = new Deferred();
54
+ const timer = setTimeout(() => {
55
+ this.log.error(`Livestream timeout: no P2P stream event received within ${P2P_TIMEOUT_MS / 1000}s for serial ${this.serialNumber}.`);
56
+ this.log.warn('If using a recent Node.js version, try enabling "Embedded PKCS1 Support" in the plugin settings.');
57
+ this.settlePending('reject', 'Livestream timeout — try enabling Embedded PKCS1 Support in settings.');
58
+ }, P2P_TIMEOUT_MS);
59
+ this.pending = { deferred, timer };
60
+ this.eufyClient.startStationLivestream(this.serialNumber).catch((err) => {
61
+ this.log.error(`startStationLivestream failed: ${err}`);
62
+ this.settlePending('reject', err);
63
+ });
64
+ return deferred.promise;
65
+ }
66
+ settlePending(action, payload) {
67
+ const p = this.pending;
68
+ if (!p)
69
+ return;
70
+ clearTimeout(p.timer);
71
+ this.pending = null;
72
+ if (action === 'resolve') {
73
+ p.deferred.resolve(payload);
74
+ }
75
+ else {
76
+ p.deferred.reject(payload instanceof Error ? payload : new Error(String(payload)));
77
+ this.stopLocalLiveStream();
78
+ }
79
+ }
80
+ stopLocalLiveStream() {
81
+ this.log.debug('Stopping station livestream.');
82
+ this.eufyClient.stopStationLivestream(this.serialNumber).catch((err) => {
83
+ this.log.warn(`stopStationLivestream failed: ${err}`);
84
+ });
85
+ this.destroyStreams();
86
+ }
87
+ /** True when the event belongs to this camera instance. */
88
+ isOwnDevice(device) {
89
+ return device.getSerial() === this.serialNumber;
90
+ }
91
+ onStationLivestreamStop = (_station, device) => {
92
+ if (!this.isOwnDevice(device))
93
+ return;
94
+ this.log.debug(`Station livestream for ${device.getName()} has stopped.`);
95
+ this.destroyStreams();
96
+ };
97
+ onStationLivestreamStart = (station, device, metadata, videostream, audiostream) => {
98
+ if (!this.isOwnDevice(device))
99
+ return;
100
+ // Guard against duplicate events fired in quick succession.
101
+ if (this.stationStream) {
102
+ const elapsed = (Date.now() - this.stationStream.createdAt) / 1000;
103
+ if (elapsed < DUPLICATE_STREAM_GUARD_S) {
104
+ this.log.warn('Duplicate livestream event received — ignoring.');
105
+ return;
106
+ }
107
+ }
108
+ // Tear down any prior stream before storing the new one.
109
+ this.destroyStreams();
110
+ this.log.debug(`${station.getName()} P2P livestream for ${device.getName()} started.`);
111
+ this.log.debug('Stream metadata:', JSON.stringify(metadata));
112
+ this.stationStream = { videostream, audiostream, createdAt: Date.now() };
113
+ this.settlePending('resolve', this.stationStream);
114
+ };
115
+ }
116
+ //# sourceMappingURL=LocalLivestreamManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalLivestreamManager.js","sourceRoot":"","sources":["../../src/controller/LocalLivestreamManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAa7C,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAEnC,MAAM,OAAO,sBAAsB;IACzB,aAAa,GAAwB,IAAI,CAAC;IAC1C,OAAO,GAAyE,IAAI,CAAC;IAE5E,UAAU,CAAe;IACzB,GAAG,CAAkB;IACrB,YAAY,CAAS;IAEtC,YAAY,MAAuB;QACjC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC7C,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAC9C,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QAEtB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,0CAA0C,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QAEnH,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,0BAA0B,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;QAC9E,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,yBAAyB,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAC9E,CAAC;IAED,8CAA8C;IACtC,cAAc;QACpB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YACxC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YACxC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,2GAA2G;IACpG,KAAK,CAAC,kBAAkB;QAC7B,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAChF,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,8BAA8B,OAAO,QAAQ,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,aAAa,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC,oBAAoB,EAAE,CAAC;IACrC,CAAC;IAED,sDAAsD;IAC/C,cAAc;QACnB,OAAO,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACK,oBAAoB;QAC1B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,2CAA2C,IAAI,CAAC,YAAY,KAAK,CAAC,CAAC;QAElF,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAkB,CAAC;QAChD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,2DAA2D,cAAc,GAAG,IAAI,gBAAgB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACrI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kGAAkG,CAAC,CAAC;YAClH,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,uEAAuE,CAAC,CAAC;QACxG,CAAC,EAAE,cAAc,CAAC,CAAC;QAEnB,IAAI,CAAC,OAAO,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAEnC,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACtE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,kCAAkC,GAAG,EAAE,CAAC,CAAC;YACxD,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC1B,CAAC;IAQO,aAAa,CAAC,MAA4B,EAAE,OAAgB;QAClE,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACvB,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAyB,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACnF,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;IAEM,mBAAmB;QACxB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACrE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAiC,GAAG,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,2DAA2D;IACnD,WAAW,CAAC,MAAc;QAChC,OAAO,MAAM,CAAC,SAAS,EAAE,KAAK,IAAI,CAAC,YAAY,CAAC;IAClD,CAAC;IAEO,uBAAuB,GAAG,CAAC,QAAiB,EAAE,MAAc,EAAQ,EAAE;QAC5E,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YAAE,OAAO;QACtC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAC1E,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC,CAAC;IAEM,wBAAwB,GAAG,CACjC,OAAgB,EAChB,MAAc,EACd,QAAwB,EACxB,WAAqB,EACrB,WAAqB,EACf,EAAE;QACR,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YAAE,OAAO;QAEtC,4DAA4D;QAC5D,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;YACnE,IAAI,OAAO,GAAG,wBAAwB,EAAE,CAAC;gBACvC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;gBACjE,OAAO;YACT,CAAC;QACH,CAAC;QAED,yDAAyD;QACzD,IAAI,CAAC,cAAc,EAAE,CAAC;QAEtB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,uBAAuB,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACvF,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAE7D,IAAI,CAAC,aAAa,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACzE,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC,CAAC;CACH"}