@homebridge-eufy-security/eufy-security-client 3.7.2-dev.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 (129) hide show
  1. package/.prettierignore/342/200/216 +8 -0
  2. package/.prettierrc +11 -0
  3. package/LICENSE +21 -0
  4. package/README.md +970 -0
  5. package/build/error.d.ts +138 -0
  6. package/build/error.js +190 -0
  7. package/build/error.js.map +1 -0
  8. package/build/eufysecurity.d.ts +180 -0
  9. package/build/eufysecurity.js +3148 -0
  10. package/build/eufysecurity.js.map +1 -0
  11. package/build/http/api.d.ts +119 -0
  12. package/build/http/api.js +1877 -0
  13. package/build/http/api.js.map +1 -0
  14. package/build/http/cache.d.ts +8 -0
  15. package/build/http/cache.js +34 -0
  16. package/build/http/cache.js.map +1 -0
  17. package/build/http/const.d.ts +8 -0
  18. package/build/http/const.js +3054 -0
  19. package/build/http/const.js.map +1 -0
  20. package/build/http/device.d.ts +490 -0
  21. package/build/http/device.js +5256 -0
  22. package/build/http/device.js.map +1 -0
  23. package/build/http/error.d.ts +73 -0
  24. package/build/http/error.js +101 -0
  25. package/build/http/error.js.map +1 -0
  26. package/build/http/index.d.ts +10 -0
  27. package/build/http/index.js +30 -0
  28. package/build/http/index.js.map +1 -0
  29. package/build/http/interfaces.d.ts +248 -0
  30. package/build/http/interfaces.js +3 -0
  31. package/build/http/interfaces.js.map +1 -0
  32. package/build/http/models.d.ts +608 -0
  33. package/build/http/models.js +3 -0
  34. package/build/http/models.js.map +1 -0
  35. package/build/http/parameter.d.ts +7 -0
  36. package/build/http/parameter.js +119 -0
  37. package/build/http/parameter.js.map +1 -0
  38. package/build/http/station.d.ts +382 -0
  39. package/build/http/station.js +15735 -0
  40. package/build/http/station.js.map +1 -0
  41. package/build/http/types.d.ts +1358 -0
  42. package/build/http/types.js +10333 -0
  43. package/build/http/types.js.map +1 -0
  44. package/build/http/utils.d.ts +89 -0
  45. package/build/http/utils.js +916 -0
  46. package/build/http/utils.js.map +1 -0
  47. package/build/index.d.ts +8 -0
  48. package/build/index.js +29 -0
  49. package/build/index.js.map +1 -0
  50. package/build/interfaces.d.ts +147 -0
  51. package/build/interfaces.js +7 -0
  52. package/build/interfaces.js.map +1 -0
  53. package/build/logging.d.ts +36 -0
  54. package/build/logging.js +119 -0
  55. package/build/logging.js.map +1 -0
  56. package/build/mqtt/interface.d.ts +6 -0
  57. package/build/mqtt/interface.js +3 -0
  58. package/build/mqtt/interface.js.map +1 -0
  59. package/build/mqtt/model.d.ts +24 -0
  60. package/build/mqtt/model.js +3 -0
  61. package/build/mqtt/model.js.map +1 -0
  62. package/build/mqtt/mqtt-eufy.crt +79 -0
  63. package/build/mqtt/proto/lock.proto +33 -0
  64. package/build/mqtt/service.d.ts +28 -0
  65. package/build/mqtt/service.js +196 -0
  66. package/build/mqtt/service.js.map +1 -0
  67. package/build/p2p/ble.d.ts +59 -0
  68. package/build/p2p/ble.js +281 -0
  69. package/build/p2p/ble.js.map +1 -0
  70. package/build/p2p/error.d.ts +49 -0
  71. package/build/p2p/error.js +69 -0
  72. package/build/p2p/error.js.map +1 -0
  73. package/build/p2p/index.d.ts +8 -0
  74. package/build/p2p/index.js +28 -0
  75. package/build/p2p/index.js.map +1 -0
  76. package/build/p2p/interfaces.d.ts +423 -0
  77. package/build/p2p/interfaces.js +3 -0
  78. package/build/p2p/interfaces.js.map +1 -0
  79. package/build/p2p/models.d.ts +295 -0
  80. package/build/p2p/models.js +3 -0
  81. package/build/p2p/models.js.map +1 -0
  82. package/build/p2p/session.d.ts +186 -0
  83. package/build/p2p/session.js +3737 -0
  84. package/build/p2p/session.js.map +1 -0
  85. package/build/p2p/talkback.d.ts +8 -0
  86. package/build/p2p/talkback.js +23 -0
  87. package/build/p2p/talkback.js.map +1 -0
  88. package/build/p2p/types.d.ts +1164 -0
  89. package/build/p2p/types.js +1219 -0
  90. package/build/p2p/types.js.map +1 -0
  91. package/build/p2p/utils.d.ts +72 -0
  92. package/build/p2p/utils.js +865 -0
  93. package/build/p2p/utils.js.map +1 -0
  94. package/build/push/client.d.ts +49 -0
  95. package/build/push/client.js +344 -0
  96. package/build/push/client.js.map +1 -0
  97. package/build/push/error.d.ts +73 -0
  98. package/build/push/error.js +101 -0
  99. package/build/push/error.js.map +1 -0
  100. package/build/push/index.d.ts +6 -0
  101. package/build/push/index.js +26 -0
  102. package/build/push/index.js.map +1 -0
  103. package/build/push/interfaces.d.ts +19 -0
  104. package/build/push/interfaces.js +3 -0
  105. package/build/push/interfaces.js.map +1 -0
  106. package/build/push/models.d.ts +328 -0
  107. package/build/push/models.js +38 -0
  108. package/build/push/models.js.map +1 -0
  109. package/build/push/parser.d.ts +25 -0
  110. package/build/push/parser.js +231 -0
  111. package/build/push/parser.js.map +1 -0
  112. package/build/push/proto/checkin.proto +266 -0
  113. package/build/push/proto/mcs.proto +328 -0
  114. package/build/push/service.d.ts +46 -0
  115. package/build/push/service.js +965 -0
  116. package/build/push/service.js.map +1 -0
  117. package/build/push/types.d.ts +220 -0
  118. package/build/push/types.js +244 -0
  119. package/build/push/types.js.map +1 -0
  120. package/build/push/utils.d.ts +7 -0
  121. package/build/push/utils.js +116 -0
  122. package/build/push/utils.js.map +1 -0
  123. package/build/utils.d.ts +115 -0
  124. package/build/utils.js +438 -0
  125. package/build/utils.js.map +1 -0
  126. package/eslint.config.mts +68 -0
  127. package/jest.config.js +14 -0
  128. package/package.json +85 -0
  129. package/scripts/cut_release.sh +31 -0
@@ -0,0 +1,1877 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.HTTPApi = void 0;
37
+ const tiny_typed_emitter_1 = require("tiny-typed-emitter");
38
+ const i18n_iso_countries_1 = require("i18n-iso-countries");
39
+ const i18n_iso_languages_1 = require("@cospired/i18n-iso-languages");
40
+ const crypto_1 = require("crypto");
41
+ const schedule = __importStar(require("node-schedule"));
42
+ const types_1 = require("./types");
43
+ const parameter_1 = require("./parameter");
44
+ const utils_1 = require("./utils");
45
+ const error_1 = require("./../error");
46
+ const utils_2 = require("./../utils");
47
+ const error_2 = require("./error");
48
+ const utils_3 = require("../p2p/utils");
49
+ const logging_1 = require("../logging");
50
+ class HTTPApi extends tiny_typed_emitter_1.TypedEmitter {
51
+ static apiDomainBase = "https://extend.eufylife.com";
52
+ SERVER_PUBLIC_KEY = "04c5c00c4f8d1197cc7c3167c52bf7acb054d722f0ef08dcd7e0883236e0d72a3868d9750cb47fa4619248f3d83f0f662671dadc6e2d31c2f41db0161651c7c076";
53
+ apiBase;
54
+ username;
55
+ password;
56
+ ecdh = (0, crypto_1.createECDH)("prime256v1");
57
+ token = null;
58
+ tokenExpiration = null;
59
+ renewAuthTokenJob;
60
+ connected = false;
61
+ requestEufyCloud;
62
+ throttle;
63
+ devices = {};
64
+ hubs = {};
65
+ houses = {};
66
+ persistentData = {
67
+ user_id: "",
68
+ email: "",
69
+ nick_name: "",
70
+ device_public_keys: {},
71
+ clientPrivateKey: "",
72
+ serverPublicKey: this.SERVER_PUBLIC_KEY,
73
+ };
74
+ headers = {
75
+ "User-Agent": undefined,
76
+ App_version: "v4.6.0_1630",
77
+ Os_type: "android",
78
+ Os_version: "31",
79
+ Phone_model: "ONEPLUS A3003",
80
+ Country: "DE",
81
+ Language: "en",
82
+ Openudid: "5e4621b0152c0d00",
83
+ //uid: "",
84
+ Net_type: "wifi",
85
+ Mnc: "02",
86
+ Mcc: "262",
87
+ Sn: "75814221ee75",
88
+ Model_type: "PHONE",
89
+ Timezone: "GMT+01:00",
90
+ "Cache-Control": "no-cache",
91
+ };
92
+ apiVerifyCode = "v1/sms/send/verify_code";
93
+ apiTrustDevice = "v1/app/trust_device/add";
94
+ apiGetStations = "v2/house/station_list";
95
+ apiGetDevices = "v2/house/device_list";
96
+ apiPushCheck = "v1/app/review/app_push_check";
97
+ apiRegisterPushToken = "v1/apppush/register_push_token";
98
+ apiSetParameters = "v1/app/upload_devs_params";
99
+ apiGetCiphers = "v2/app/cipher/get_ciphers";
100
+ apiEventGetAllVideoRecord = "v2/event/app/get_all_video_record";
101
+ apiEventGetAllAlarmRecord = "v2/event/app/get_all_alarm_record";
102
+ apiEventGetAllHistoryRecord = "v2/event/app/get_all_history_record";
103
+ apiGetInvites = "v2/family/get_invites";
104
+ apiConfirmInvite = "v1/family/confirm_invite";
105
+ apiGetSensorHistory = "v1/app/get_sensor_history";
106
+ apiGetHouseDetail = "v2/house/detail";
107
+ apiGetHouseList = "v1/house/list";
108
+ apiGetHouseInvites = "v1/house/invite_list";
109
+ apiConfirmHouseInvite = "v1/house/confirm_invite";
110
+ apiAddLocalUser = "v1/app/device/local_user/add";
111
+ apiDeleteLocalUser = "v1/app/device/user/delete";
112
+ apiUpdateLocalUser = "v1/app/device/local_user/update";
113
+ apiUpdateUserPassword = "v1/app/device/password/save_or_update";
114
+ FIFTEEN_YEARS_IN_MS = 15 * 365 * 24 * 60 * 60 * 1000;
115
+ constructor(apiBase, country, username, password, persistentData) {
116
+ super();
117
+ this.username = username;
118
+ this.password = password;
119
+ this.apiBase = apiBase;
120
+ logging_1.rootHTTPLogger.debug(`Loaded API`, {
121
+ apieBase: apiBase,
122
+ country: country,
123
+ username: username,
124
+ persistentData: persistentData,
125
+ });
126
+ this.headers.timezone = (0, utils_1.getTimezoneGMTString)();
127
+ this.headers.country = country.toUpperCase();
128
+ if (persistentData) {
129
+ this.persistentData = persistentData;
130
+ }
131
+ // Generated key based on the provided one
132
+ if (this.persistentData.clientPrivateKey !== undefined && this.persistentData.clientPrivateKey !== "") {
133
+ try {
134
+ this.ecdh.setPrivateKey(Buffer.from(this.persistentData.clientPrivateKey, "hex"));
135
+ }
136
+ catch (err) {
137
+ const error = (0, error_1.ensureError)(err);
138
+ logging_1.rootHTTPLogger.debug(`Invalid client private key, generate new client private key...`, {
139
+ error: (0, utils_2.getError)(error),
140
+ });
141
+ this.generateNewKey();
142
+ }
143
+ }
144
+ else {
145
+ this.generateNewKey();
146
+ }
147
+ if (this.persistentData.serverPublicKey === undefined || this.persistentData.serverPublicKey === "") {
148
+ this.persistentData.serverPublicKey = this.SERVER_PUBLIC_KEY;
149
+ }
150
+ else {
151
+ try {
152
+ this.ecdh.computeSecret(Buffer.from(this.persistentData.serverPublicKey, "hex"));
153
+ }
154
+ catch (err) {
155
+ const error = (0, error_1.ensureError)(err);
156
+ logging_1.rootHTTPLogger.debug(`Invalid server public key, fallback to default server public key...`, {
157
+ error: (0, utils_2.getError)(error),
158
+ });
159
+ this.persistentData.serverPublicKey = this.SERVER_PUBLIC_KEY;
160
+ }
161
+ }
162
+ }
163
+ generateNewKey() {
164
+ /*
165
+ Generate a new client private key
166
+ */
167
+ this.ecdh.generateKeys();
168
+ this.persistentData.clientPrivateKey = this.ecdh.getPrivateKey().toString("hex");
169
+ }
170
+ static async getApiBaseFromCloud(country) {
171
+ /**
172
+ Query the main api with the country code ton ensure it is a valid and returns the correct api
173
+
174
+ @param country
175
+ **/
176
+ const { default: got } = await import("got");
177
+ const response = await got(`domain/${country}`, {
178
+ prefixUrl: this.apiDomainBase,
179
+ method: "GET",
180
+ responseType: "json",
181
+ retry: {
182
+ limit: 1,
183
+ methods: ["GET"],
184
+ },
185
+ });
186
+ const result = response.body;
187
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
188
+ return `https://${result.data.domain}`;
189
+ }
190
+ throw new error_2.ApiBaseLoadError("Error identifying API base from cloud", {
191
+ context: { code: result.code, message: result.msg },
192
+ });
193
+ }
194
+ async loadLibraries() {
195
+ /**
196
+ * Load library
197
+ *
198
+ */
199
+ const { default: pThrottle } = await import("p-throttle");
200
+ const { default: got } = await import("got");
201
+ this.throttle = pThrottle({
202
+ limit: 5,
203
+ interval: 1000,
204
+ });
205
+ this.requestEufyCloud = got.extend({
206
+ prefixUrl: this.apiBase,
207
+ headers: this.headers,
208
+ responseType: "json",
209
+ //throwHttpErrors: false,
210
+ retry: {
211
+ limit: 3,
212
+ methods: ["GET", "POST"],
213
+ statusCodes: [404, 408, 413, 423, 429, 500, 502, 503, 504, 521, 522, 524],
214
+ calculateDelay: ({ computedValue }) => {
215
+ return computedValue * 3;
216
+ },
217
+ },
218
+ hooks: {
219
+ afterResponse: [
220
+ async (response, retryWithMergedOptions) => {
221
+ // Unauthorized
222
+ if (response.statusCode === 401) {
223
+ const oldToken = this.token;
224
+ logging_1.rootHTTPLogger.debug("Invalidate token an get a new one...", {
225
+ requestUrl: response.requestUrl,
226
+ statusCode: response.statusCode,
227
+ statusMessage: response.statusMessage,
228
+ });
229
+ this.invalidateToken();
230
+ await this.login({ force: true });
231
+ if (oldToken !== this.token && this.token) {
232
+ // Refresh the access token
233
+ const updatedOptions = {
234
+ headers: {
235
+ "X-Auth-Token": this.token,
236
+ },
237
+ };
238
+ // Update the defaults
239
+ this.requestEufyCloud.defaults.options.merge(updatedOptions);
240
+ // Make a new retry
241
+ return retryWithMergedOptions(updatedOptions);
242
+ }
243
+ }
244
+ // No changes otherwise
245
+ return response;
246
+ },
247
+ ],
248
+ beforeRetry: [
249
+ (error) => {
250
+ // This will be called on `retryWithMergedOptions(...)`
251
+ const statusCode = error.response?.statusCode || 0;
252
+ const { method, url, prefixUrl } = error.options;
253
+ const shortUrl = (0, utils_2.getShortUrl)(typeof url === "string" ? new URL(url) : url === undefined ? new URL("") : url, typeof prefixUrl === "string" ? prefixUrl : prefixUrl.toString());
254
+ const body = error.response?.body ? error.response?.body : error.message;
255
+ logging_1.rootHTTPLogger.debug(`Retrying [${error.request?.retryCount !== undefined ? error.request?.retryCount + 1 : 1}]: ${error.code} (${error.request?.requestUrl})\n${statusCode} ${method} ${shortUrl}\n${body}`);
256
+ // Retrying [1]: ERR_NON_2XX_3XX_RESPONSE
257
+ },
258
+ ],
259
+ beforeError: [
260
+ (error) => {
261
+ const { response, options } = error;
262
+ const statusCode = response?.statusCode || 0;
263
+ const { method, url, prefixUrl } = options;
264
+ const shortUrl = (0, utils_2.getShortUrl)(typeof url === "string" ? new URL(url) : url === undefined ? new URL("") : url, typeof prefixUrl === "string" ? prefixUrl : prefixUrl.toString());
265
+ const body = response?.body ? response.body : error.message;
266
+ if (response?.body) {
267
+ error.name = "EufyApiError";
268
+ error.message = `${statusCode} ${method} ${shortUrl}\n${body}`;
269
+ }
270
+ return error;
271
+ },
272
+ ],
273
+ beforeRequest: [
274
+ async (_options) => {
275
+ await this.throttle(async () => {
276
+ return;
277
+ })();
278
+ },
279
+ ],
280
+ },
281
+ mutableDefaults: true,
282
+ });
283
+ }
284
+ static async initialize(country, username, password, persistentData) {
285
+ if ((0, i18n_iso_countries_1.isValid)(country) && country.length === 2) {
286
+ const apiBase = await this.getApiBaseFromCloud(country);
287
+ const api = new HTTPApi(apiBase, country, username, password, persistentData);
288
+ await api.loadLibraries();
289
+ return api;
290
+ }
291
+ throw new error_1.InvalidCountryCodeError("Invalid ISO 3166-1 Alpha-2 country code", { context: { countryCode: country } });
292
+ }
293
+ clearScheduleRenewAuthToken() {
294
+ /**
295
+ * Clear schedule to renew the auth token if running
296
+ *
297
+ **/
298
+ if (this.renewAuthTokenJob !== undefined) {
299
+ this.renewAuthTokenJob.cancel();
300
+ }
301
+ }
302
+ scheduleRenewAuthToken() {
303
+ this.clearScheduleRenewAuthToken();
304
+ if (this.tokenExpiration !== null) {
305
+ const scheduleDate = new Date(this.tokenExpiration.getTime() - 1000 * 60 * 60 * 24);
306
+ if (this.renewAuthTokenJob === undefined) {
307
+ this.renewAuthTokenJob = schedule.scheduleJob("renewAuthToken", scheduleDate, async () => {
308
+ logging_1.rootHTTPLogger.info("Authentication token is soon expiring, fetching a new one...");
309
+ await this.login({ force: true });
310
+ });
311
+ }
312
+ else {
313
+ this.renewAuthTokenJob.schedule(scheduleDate);
314
+ }
315
+ }
316
+ }
317
+ invalidateToken() {
318
+ this.connected = false;
319
+ this.token = null;
320
+ this.requestEufyCloud.defaults.options.merge({
321
+ headers: {
322
+ "X-Auth-Token": undefined,
323
+ },
324
+ });
325
+ this.tokenExpiration = null;
326
+ this.persistentData.serverPublicKey = this.SERVER_PUBLIC_KEY;
327
+ this.clearScheduleRenewAuthToken();
328
+ this.emit("auth token invalidated");
329
+ }
330
+ updateApiHeader() {
331
+ this.requestEufyCloud.defaults.options.merge({
332
+ headers: this.headers,
333
+ });
334
+ }
335
+ setPhoneModel(model) {
336
+ /**
337
+ *
338
+ * Set a new phone model for the http request
339
+ *
340
+ */
341
+ this.headers.phone_model = model.toUpperCase();
342
+ this.requestEufyCloud.defaults.options.merge({
343
+ headers: this.headers,
344
+ });
345
+ }
346
+ getPhoneModel() {
347
+ /**
348
+ *
349
+ * Return the current phone model used
350
+ *
351
+ */
352
+ return this.headers.phone_model;
353
+ }
354
+ getCountry() {
355
+ /**
356
+ * Return the current country
357
+ *
358
+ */
359
+ return this.headers.country;
360
+ }
361
+ setLanguage(language) {
362
+ if ((0, i18n_iso_languages_1.isValid)(language) && language.length === 2) {
363
+ this.headers.language = language;
364
+ this.updateApiHeader();
365
+ }
366
+ else
367
+ throw new error_1.InvalidLanguageCodeError("Invalid ISO 639 language code", { context: { languageCode: language } });
368
+ }
369
+ getLanguage() {
370
+ return this.headers.language;
371
+ }
372
+ loginCompleted(dataResult) {
373
+ if (dataResult.server_secret_info?.public_key)
374
+ this.persistentData.serverPublicKey = dataResult.server_secret_info.public_key;
375
+ this.persistentData.user_id = dataResult.user_id;
376
+ this.persistentData.email = this.decryptAPIData(dataResult.email, false);
377
+ this.persistentData.nick_name = dataResult.nick_name;
378
+ this.setToken(dataResult.auth_token);
379
+ this.tokenExpiration = new Date(dataResult.token_expires_at * 1000);
380
+ this.headers = {
381
+ ...this.headers,
382
+ gtoken: (0, utils_2.md5)(dataResult.user_id),
383
+ };
384
+ logging_1.rootHTTPLogger.debug("Login - Token data", {
385
+ token: this.token,
386
+ tokenExpiration: this.tokenExpiration,
387
+ serverPublicKey: this.persistentData.serverPublicKey,
388
+ });
389
+ if (!this.connected) {
390
+ this.connected = true;
391
+ this.emit("connect");
392
+ }
393
+ this.scheduleRenewAuthToken();
394
+ }
395
+ async loginVerifyCode(dataResult) {
396
+ /**
397
+ * Send verification code
398
+ */
399
+ logging_1.rootHTTPLogger.debug(`Login - Send verification code...`);
400
+ this.setToken(dataResult.auth_token);
401
+ this.tokenExpiration = new Date(dataResult.token_expires_at * 1000);
402
+ logging_1.rootHTTPLogger.debug("Token data", { token: this.token, tokenExpiration: this.tokenExpiration });
403
+ await this.sendVerifyCode(types_1.VerfyCodeTypes.TYPE_EMAIL);
404
+ logging_1.rootHTTPLogger.info("Please send required verification code to proceed with authentication");
405
+ this.emit("tfa request");
406
+ }
407
+ loginRequestCaptcha(dataResult) {
408
+ logging_1.rootHTTPLogger.debug("Login - Captcha verification received", {
409
+ captchaId: dataResult.captcha_id,
410
+ item: dataResult.item,
411
+ });
412
+ logging_1.rootHTTPLogger.info("Please send requested captcha to proceed with authentication");
413
+ this.emit("captcha request", dataResult.captcha_id, dataResult.item);
414
+ }
415
+ async login(options) {
416
+ options = (0, utils_2.mergeDeep)(options, {
417
+ force: false,
418
+ });
419
+ logging_1.rootHTTPLogger.debug("Login and get an access token", {
420
+ token: this.token,
421
+ tokenExpiration: this.tokenExpiration,
422
+ options: options,
423
+ });
424
+ const isInvalidToken = !this.token;
425
+ const isTokenExpired = this.tokenExpiration && new Date().getTime() >= this.tokenExpiration.getTime();
426
+ if (isInvalidToken || isTokenExpired || options.verifyCode || options.captcha || options.force) {
427
+ try {
428
+ const timezoneOffset = new Date().getTimezoneOffset();
429
+ const data = {
430
+ ab: this.headers.country,
431
+ client_secret_info: {
432
+ public_key: this.ecdh.getPublicKey("hex"),
433
+ },
434
+ enc: 0,
435
+ email: this.username,
436
+ password: (0, utils_1.encryptAPIData)(this.password, this.ecdh.computeSecret(Buffer.from(this.SERVER_PUBLIC_KEY, "hex"))),
437
+ time_zone: timezoneOffset !== 0 ? -timezoneOffset * 60 * 1000 : 0,
438
+ transaction: `${new Date().getTime()}`,
439
+ };
440
+ // Add verification code to the data
441
+ if (options.verifyCode) {
442
+ data.verify_code = options.verifyCode;
443
+ }
444
+ else if (options.captcha) {
445
+ // Add captcha response
446
+ data.captcha_id = options.captcha.captchaId;
447
+ data.answer = options.captcha.captchaCode;
448
+ }
449
+ const response = await this.request({
450
+ method: "post",
451
+ endpoint: "v2/passport/login_sec",
452
+ data: data,
453
+ });
454
+ if (response.status == 200) {
455
+ const result = response.data;
456
+ if (result.data !== undefined) {
457
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
458
+ this.loginCompleted(result.data);
459
+ }
460
+ else if (result.code == types_1.ResponseErrorCode.CODE_NEED_VERIFY_CODE) {
461
+ this.loginVerifyCode(result.data);
462
+ }
463
+ else if (result.code == types_1.ResponseErrorCode.LOGIN_NEED_CAPTCHA ||
464
+ result.code == types_1.ResponseErrorCode.LOGIN_CAPTCHA_ERROR) {
465
+ this.loginRequestCaptcha(result.data);
466
+ }
467
+ else {
468
+ logging_1.rootHTTPLogger.error("Login - Response code not ok", {
469
+ code: result.code,
470
+ msg: result.msg,
471
+ data: response.data,
472
+ });
473
+ this.emit("connection error", new error_2.ApiResponseCodeError("API response code not ok", {
474
+ context: { code: result.code, message: result.msg },
475
+ }));
476
+ }
477
+ }
478
+ else {
479
+ logging_1.rootHTTPLogger.error("Login - Response data is missing", {
480
+ code: result.code,
481
+ msg: result.msg,
482
+ data: result.data,
483
+ });
484
+ this.emit("connection error", new error_2.ApiInvalidResponseError("API response data is missing", {
485
+ context: { code: result.code, message: result.msg, data: result.data },
486
+ }));
487
+ }
488
+ }
489
+ else {
490
+ logging_1.rootHTTPLogger.error("Login - Status return code not 200", {
491
+ status: response.status,
492
+ statusText: response.statusText,
493
+ data: response.data,
494
+ });
495
+ this.emit("connection error", new error_2.ApiHTTPResponseCodeError("API HTTP response code not ok", {
496
+ context: { status: response.status, statusText: response.statusText },
497
+ }));
498
+ }
499
+ }
500
+ catch (err) {
501
+ const error = (0, error_1.ensureError)(err);
502
+ logging_1.rootHTTPLogger.error("Login - Generic Error:", { error: (0, utils_2.getError)(error) });
503
+ this.emit("connection error", new error_2.ApiGenericError("Generic API error", { cause: error }));
504
+ }
505
+ }
506
+ else if (!this.connected) {
507
+ try {
508
+ const profile = await this.getPassportProfile();
509
+ if (profile !== null) {
510
+ if (!this.connected) {
511
+ this.connected = true;
512
+ this.emit("connect");
513
+ this.scheduleRenewAuthToken();
514
+ }
515
+ }
516
+ else {
517
+ this.emit("connection error", new error_2.ApiInvalidResponseError(`Invalid passport profile response`));
518
+ }
519
+ }
520
+ catch (err) {
521
+ const error = (0, error_1.ensureError)(err);
522
+ logging_1.rootHTTPLogger.error("Login - getPassportProfile Error", { error: (0, utils_2.getError)(error) });
523
+ this.emit("connection error", new error_2.ApiGenericError("API get passport profile error", { cause: error }));
524
+ }
525
+ }
526
+ }
527
+ async makePostRequest(endPoint, data, forceConnect = false) {
528
+ if (this.connected || forceConnect) {
529
+ try {
530
+ const response = await this.request({
531
+ method: "post",
532
+ endpoint: endPoint,
533
+ data: data,
534
+ });
535
+ if (response.status == 200) {
536
+ return response;
537
+ }
538
+ else {
539
+ logging_1.rootHTTPLogger.error(`Post to ${endPoint} - Status return code not 200`, {
540
+ status: response.status,
541
+ statusText: response.statusText,
542
+ data: response.data,
543
+ });
544
+ }
545
+ }
546
+ catch (err) {
547
+ const error = (0, error_1.ensureError)(err);
548
+ logging_1.rootHTTPLogger.error("Send verify code - Generic Error", { error: (0, utils_2.getError)(error) });
549
+ }
550
+ }
551
+ return undefined;
552
+ }
553
+ async sendVerifyCode(type) {
554
+ if (!type)
555
+ type = types_1.VerfyCodeTypes.TYPE_EMAIL;
556
+ const data = {
557
+ message_type: type,
558
+ transaction: `${new Date().getTime()}`,
559
+ };
560
+ const response = await this.makePostRequest(this.apiVerifyCode, data, true);
561
+ if (response != undefined) {
562
+ if (response.status == 200) {
563
+ const result = response.data;
564
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
565
+ logging_1.rootHTTPLogger.info(`Requested verification code for 2FA`);
566
+ return true;
567
+ }
568
+ else {
569
+ logging_1.rootHTTPLogger.error("Send verify code - Response code not ok", {
570
+ code: result.code,
571
+ msg: result.msg,
572
+ data: response.data,
573
+ });
574
+ }
575
+ }
576
+ else {
577
+ logging_1.rootHTTPLogger.error("Send verify code - Status return code not 200", {
578
+ status: response.status,
579
+ statusText: response.statusText,
580
+ data: response.data,
581
+ });
582
+ }
583
+ }
584
+ return false;
585
+ }
586
+ async listTrustDevice() {
587
+ if (this.connected) {
588
+ try {
589
+ const response = await this.request({
590
+ method: "get",
591
+ endpoint: "v1/app/trust_device/list",
592
+ });
593
+ if (response.status == 200) {
594
+ const result = response.data;
595
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
596
+ if (result.data && result.data.list) {
597
+ return result.data.list;
598
+ }
599
+ }
600
+ else {
601
+ logging_1.rootHTTPLogger.error("List trust device - Response code not ok", {
602
+ code: result.code,
603
+ msg: result.msg,
604
+ data: response.data,
605
+ });
606
+ }
607
+ }
608
+ else {
609
+ logging_1.rootHTTPLogger.error("List trust device - Status return code not 200", {
610
+ status: response.status,
611
+ statusText: response.statusText,
612
+ data: response.data,
613
+ });
614
+ }
615
+ }
616
+ catch (err) {
617
+ const error = (0, error_1.ensureError)(err);
618
+ logging_1.rootHTTPLogger.error("List trust device - Generic Error", { error: (0, utils_2.getError)(error) });
619
+ }
620
+ }
621
+ return [];
622
+ }
623
+ async addTrustDevice(verifyCode) {
624
+ const data = {
625
+ verify_code: verifyCode,
626
+ transaction: `${new Date().getTime()}`,
627
+ };
628
+ const response = await this.makePostRequest(this.apiTrustDevice, data);
629
+ if (response != undefined) {
630
+ logging_1.rootHTTPLogger.debug("Add trust device - Response trust device", { verifyCode: verifyCode, data: response.data });
631
+ if (response.status == 200) {
632
+ const result = response.data;
633
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
634
+ logging_1.rootHTTPLogger.info(`2FA authentication successfully done. Device trusted.`);
635
+ const trusted_devices = await this.listTrustDevice();
636
+ trusted_devices.forEach((trusted_device) => {
637
+ if (trusted_device.is_current_device === 1) {
638
+ logging_1.rootHTTPLogger.debug("Add trust device - This device is trusted. Token expiration extended:", {
639
+ trustDevice: { phoneModel: trusted_device.phone_model, openUdid: trusted_device.open_udid },
640
+ tokenExpiration: this.tokenExpiration,
641
+ });
642
+ }
643
+ });
644
+ return true;
645
+ }
646
+ else {
647
+ logging_1.rootHTTPLogger.error("Add trust device - Response code not ok", {
648
+ code: result.code,
649
+ msg: result.msg,
650
+ verifyCode: verifyCode,
651
+ data: response.data,
652
+ });
653
+ }
654
+ }
655
+ else {
656
+ logging_1.rootHTTPLogger.error("Add trust device - Status return code not 200", {
657
+ status: response.status,
658
+ statusText: response.statusText,
659
+ verifyCode: verifyCode,
660
+ data: response.data,
661
+ });
662
+ }
663
+ }
664
+ return false;
665
+ }
666
+ async getStationList() {
667
+ const data = {
668
+ device_sn: "",
669
+ num: 1000,
670
+ orderby: "",
671
+ page: 0,
672
+ station_sn: "",
673
+ time_zone: new Date().getTimezoneOffset() !== 0 ? -new Date().getTimezoneOffset() * 60 * 1000 : 0,
674
+ transaction: `${new Date().getTime()}`,
675
+ };
676
+ const response = await this.makePostRequest(this.apiGetStations, data);
677
+ if (response != undefined) {
678
+ if (response.status == 200) {
679
+ const result = response.data;
680
+ if (result.code == 0) {
681
+ if (result.data) {
682
+ const stationList = this.decryptAPIData(result.data);
683
+ logging_1.rootHTTPLogger.debug("Decrypted station list data", stationList);
684
+ return stationList;
685
+ }
686
+ }
687
+ else {
688
+ logging_1.rootHTTPLogger.error("Station list - Response code not ok", {
689
+ code: result.code,
690
+ msg: result.msg,
691
+ data: response.data,
692
+ });
693
+ }
694
+ }
695
+ else {
696
+ logging_1.rootHTTPLogger.error("Station list - Status return code not 200", {
697
+ status: response.status,
698
+ statusText: response.statusText,
699
+ data: response.data,
700
+ });
701
+ }
702
+ }
703
+ return [];
704
+ }
705
+ async getDeviceList() {
706
+ const data = {
707
+ device_sn: "",
708
+ num: 1000,
709
+ orderby: "",
710
+ page: 0,
711
+ station_sn: "",
712
+ time_zone: new Date().getTimezoneOffset() !== 0 ? -new Date().getTimezoneOffset() * 60 * 1000 : 0,
713
+ transaction: `${new Date().getTime()}`,
714
+ };
715
+ const response = await this.makePostRequest(this.apiGetDevices, data);
716
+ if (response != undefined) {
717
+ if (response.status == 200) {
718
+ const result = response.data;
719
+ if (result.code == 0) {
720
+ if (result.data) {
721
+ const deviceList = this.decryptAPIData(result.data);
722
+ logging_1.rootHTTPLogger.debug("Decrypted device list data: %s", JSON.stringify(deviceList, null, 2));
723
+ return deviceList;
724
+ }
725
+ }
726
+ else {
727
+ logging_1.rootHTTPLogger.error("Device list - Response code not ok", {
728
+ code: result.code,
729
+ msg: result.msg,
730
+ data: response.data,
731
+ });
732
+ }
733
+ }
734
+ else {
735
+ logging_1.rootHTTPLogger.error("Device list - Status return code not 200", {
736
+ status: response.status,
737
+ statusText: response.statusText,
738
+ data: response.data,
739
+ });
740
+ }
741
+ }
742
+ return [];
743
+ }
744
+ async refreshHouseData() {
745
+ //Get Houses
746
+ const houses = await this.getHouseList();
747
+ if (houses && houses.length > 0) {
748
+ houses.forEach((element) => {
749
+ this.houses[element.house_id] = element;
750
+ });
751
+ }
752
+ else {
753
+ logging_1.rootHTTPLogger.info("No houses found.");
754
+ }
755
+ this.emit("houses", this.houses);
756
+ }
757
+ async refreshStationData() {
758
+ //Get Stations
759
+ const stations = await this.getStationList();
760
+ if (stations && stations.length > 0) {
761
+ stations.forEach((element) => {
762
+ this.hubs[element.station_sn] = element;
763
+ });
764
+ }
765
+ else {
766
+ logging_1.rootHTTPLogger.info("No stations found.");
767
+ }
768
+ this.emit("hubs", this.hubs);
769
+ }
770
+ async refreshDeviceData() {
771
+ //Get Devices
772
+ const devices = await this.getDeviceList();
773
+ if (devices && devices.length > 0) {
774
+ devices.forEach((element) => {
775
+ this.devices[element.device_sn] = element;
776
+ });
777
+ }
778
+ else {
779
+ logging_1.rootHTTPLogger.info("No devices found.");
780
+ }
781
+ this.emit("devices", this.devices);
782
+ }
783
+ async refreshAllData() {
784
+ //Get the latest info
785
+ //Get Houses
786
+ await this.refreshHouseData();
787
+ //Get Stations
788
+ await this.refreshStationData();
789
+ //Get Devices
790
+ await this.refreshDeviceData();
791
+ }
792
+ async request(request, withoutUrlPrefix = false) {
793
+ logging_1.rootHTTPLogger.debug("Api request", {
794
+ method: request.method,
795
+ endpoint: request.endpoint,
796
+ responseType: request.responseType,
797
+ token: this.token,
798
+ data: request.data,
799
+ });
800
+ try {
801
+ let options;
802
+ switch (request.responseType) {
803
+ case undefined:
804
+ case "json":
805
+ options = {
806
+ method: request.method,
807
+ json: request.data,
808
+ responseType: "json",
809
+ };
810
+ break;
811
+ case "text":
812
+ options = {
813
+ method: request.method,
814
+ json: request.data,
815
+ responseType: request.responseType,
816
+ };
817
+ break;
818
+ case "buffer":
819
+ options = {
820
+ method: request.method,
821
+ json: request.data,
822
+ responseType: request.responseType,
823
+ };
824
+ break;
825
+ }
826
+ if (withoutUrlPrefix)
827
+ options.prefixUrl = "";
828
+ const internalResponse = await this.requestEufyCloud(request.endpoint, options);
829
+ const response = {
830
+ status: internalResponse.statusCode,
831
+ statusText: internalResponse.statusMessage ? internalResponse.statusMessage : "",
832
+ headers: internalResponse.headers,
833
+ data: internalResponse.body,
834
+ };
835
+ logging_1.rootHTTPLogger.debug("Api request - Response", { token: this.token, request: request, response: response.data });
836
+ return response;
837
+ }
838
+ catch (err) {
839
+ const error = (0, error_1.ensureError)(err);
840
+ if (error instanceof (await import("got")).HTTPError) {
841
+ if (error.response.statusCode === 401) {
842
+ this.invalidateToken();
843
+ logging_1.rootHTTPLogger.error("Status return code 401, invalidate token", {
844
+ status: error.response.statusCode,
845
+ statusText: error.response.statusMessage,
846
+ });
847
+ this.emit("close");
848
+ }
849
+ }
850
+ throw new error_2.ApiRequestError("API request error", {
851
+ cause: error,
852
+ context: {
853
+ method: request.method,
854
+ endpoint: request.endpoint,
855
+ responseType: request.responseType,
856
+ token: this.token,
857
+ data: request.data,
858
+ },
859
+ });
860
+ }
861
+ }
862
+ async checkPushToken() {
863
+ //Check push notification token
864
+ const data = {
865
+ app_type: "eufySecurity",
866
+ transaction: `${new Date().getTime()}`,
867
+ };
868
+ const response = await this.makePostRequest(this.apiPushCheck, data);
869
+ if (response !== undefined) {
870
+ if (response.status == 200) {
871
+ const result = response.data;
872
+ if (result.code == 0) {
873
+ logging_1.rootHTTPLogger.debug(`Check push token - Push token OK`);
874
+ return true;
875
+ }
876
+ else {
877
+ logging_1.rootHTTPLogger.error("Check push token - Response code not ok", {
878
+ code: result.code,
879
+ msg: result.msg,
880
+ data: response.data,
881
+ });
882
+ }
883
+ }
884
+ else {
885
+ logging_1.rootHTTPLogger.error("Check push token - Status return code not 200", {
886
+ status: response.status,
887
+ statusText: response.statusText,
888
+ data: response.data,
889
+ });
890
+ }
891
+ }
892
+ return false;
893
+ }
894
+ async registerPushToken(token) {
895
+ //Register push notification token
896
+ const data = {
897
+ is_notification_enable: true,
898
+ token: token,
899
+ transaction: `${new Date().getTime().toString()}`,
900
+ };
901
+ const response = await this.makePostRequest(this.apiRegisterPushToken, data);
902
+ if (response !== undefined) {
903
+ if (response.status == 200) {
904
+ const result = response.data;
905
+ if (result.code == 0) {
906
+ logging_1.rootHTTPLogger.debug(`Register push token - Push token registered successfully`);
907
+ return true;
908
+ }
909
+ else {
910
+ logging_1.rootHTTPLogger.error("Register push token - Response code not ok", {
911
+ code: result.code,
912
+ msg: result.msg,
913
+ data: response.data,
914
+ token: token,
915
+ });
916
+ }
917
+ }
918
+ else {
919
+ logging_1.rootHTTPLogger.error("Register push token - Status return code not 200", {
920
+ status: response.status,
921
+ statusText: response.statusText,
922
+ data: response.data,
923
+ token: token,
924
+ });
925
+ }
926
+ }
927
+ return false;
928
+ }
929
+ async setParameters(stationSN, deviceSN, params) {
930
+ const tmp_params = [];
931
+ params.forEach((param) => {
932
+ tmp_params.push({
933
+ param_type: param.paramType,
934
+ param_value: parameter_1.ParameterHelper.writeValue(param.paramType, param.paramValue),
935
+ });
936
+ });
937
+ const data = {
938
+ device_sn: deviceSN,
939
+ station_sn: stationSN,
940
+ params: tmp_params,
941
+ transaction: `${new Date().getTime().toString()}`,
942
+ };
943
+ const response = await this.makePostRequest(this.apiSetParameters, data);
944
+ if (response !== undefined) {
945
+ logging_1.rootHTTPLogger.debug("Set parameter - Response:", {
946
+ stationSN: stationSN,
947
+ deviceSN: deviceSN,
948
+ params: tmp_params,
949
+ response: response.data,
950
+ });
951
+ if (response.status == 200) {
952
+ const result = response.data;
953
+ if (result.code == 0) {
954
+ const dataresult = result.data;
955
+ logging_1.rootHTTPLogger.debug("Set parameter - New parameters set", { params: tmp_params, response: dataresult });
956
+ return true;
957
+ }
958
+ else {
959
+ logging_1.rootHTTPLogger.error("Set parameter - Response code not ok", {
960
+ code: result.code,
961
+ msg: result.msg,
962
+ data: response.data,
963
+ stationSN: stationSN,
964
+ deviceSN: deviceSN,
965
+ params: params,
966
+ });
967
+ }
968
+ }
969
+ else {
970
+ logging_1.rootHTTPLogger.error("Set parameter - Status return code not 200", {
971
+ status: response.status,
972
+ statusText: response.statusText,
973
+ data: response.data,
974
+ stationSN: stationSN,
975
+ deviceSN: deviceSN,
976
+ params: params,
977
+ });
978
+ }
979
+ }
980
+ return false;
981
+ }
982
+ async getCiphers(/*stationSN: string, */ cipherIDs, userID) {
983
+ const data = {
984
+ cipher_ids: cipherIDs,
985
+ user_id: userID,
986
+ //sn: stationSN
987
+ transaction: `${new Date().getTime().toString()}`,
988
+ };
989
+ const response = await this.makePostRequest(this.apiGetCiphers, data);
990
+ if (response !== undefined) {
991
+ if (response.status == 200) {
992
+ const result = response.data;
993
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
994
+ if (result.data) {
995
+ const ciphers = {};
996
+ const decrypted = this.decryptAPIData(result.data);
997
+ logging_1.rootHTTPLogger.debug("Get ciphers - Decrypted ciphers data", { ciphers: decrypted });
998
+ if (Array.isArray(decrypted)) {
999
+ decrypted.forEach((cipher) => {
1000
+ ciphers[cipher.cipher_id] = cipher;
1001
+ });
1002
+ }
1003
+ return ciphers;
1004
+ }
1005
+ }
1006
+ else {
1007
+ logging_1.rootHTTPLogger.error("Get ciphers - Response code not ok", {
1008
+ code: result.code,
1009
+ msg: result.msg,
1010
+ data: response.data,
1011
+ cipherIDs: cipherIDs,
1012
+ userID: userID,
1013
+ });
1014
+ }
1015
+ }
1016
+ else {
1017
+ logging_1.rootHTTPLogger.error("Get ciphers - Status return code not 200", {
1018
+ status: response.status,
1019
+ statusText: response.statusText,
1020
+ data: response.data,
1021
+ cipherIDs: cipherIDs,
1022
+ userID: userID,
1023
+ });
1024
+ }
1025
+ }
1026
+ return {};
1027
+ }
1028
+ async getVoices(deviceSN) {
1029
+ if (this.connected) {
1030
+ try {
1031
+ const response = await this.request({
1032
+ method: "get",
1033
+ endpoint: `v1/voice/response/lists/${deviceSN}`,
1034
+ });
1035
+ if (response.status == 200) {
1036
+ const result = response.data;
1037
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1038
+ if (result.data) {
1039
+ const voices = {};
1040
+ result.data.forEach((voice) => {
1041
+ voices[voice.voice_id] = voice;
1042
+ });
1043
+ return voices;
1044
+ }
1045
+ }
1046
+ else {
1047
+ logging_1.rootHTTPLogger.error("Get Voices - Response code not ok", {
1048
+ code: result.code,
1049
+ msg: result.msg,
1050
+ data: response.data,
1051
+ deviceSN: deviceSN,
1052
+ });
1053
+ }
1054
+ }
1055
+ else {
1056
+ logging_1.rootHTTPLogger.error("Get Voices - Status return code not 200", {
1057
+ status: response.status,
1058
+ statusText: response.statusText,
1059
+ data: response.data,
1060
+ deviceSN: deviceSN,
1061
+ });
1062
+ }
1063
+ }
1064
+ catch (err) {
1065
+ const error = (0, error_1.ensureError)(err);
1066
+ logging_1.rootHTTPLogger.error("Get Voices - Generic Error", { error: (0, utils_2.getError)(error), deviceSN: deviceSN });
1067
+ }
1068
+ }
1069
+ return {};
1070
+ }
1071
+ async getCipher(/*stationSN: string, */ cipherID, userID) {
1072
+ return (await this.getCiphers(/*stationSN, */ [cipherID], userID))[cipherID];
1073
+ }
1074
+ getDevices() {
1075
+ return this.devices;
1076
+ }
1077
+ getHubs() {
1078
+ return this.hubs;
1079
+ }
1080
+ getToken() {
1081
+ return this.token;
1082
+ }
1083
+ getTokenExpiration() {
1084
+ return this.tokenExpiration;
1085
+ }
1086
+ setToken(token) {
1087
+ this.token = token;
1088
+ this.requestEufyCloud.defaults.options.merge({
1089
+ headers: {
1090
+ "X-Auth-Token": token,
1091
+ },
1092
+ });
1093
+ }
1094
+ setTokenExpiration(tokenExpiration) {
1095
+ this.tokenExpiration = tokenExpiration;
1096
+ }
1097
+ getAPIBase() {
1098
+ return typeof this.requestEufyCloud.defaults.options.prefixUrl === "string"
1099
+ ? this.requestEufyCloud.defaults.options.prefixUrl
1100
+ : this.requestEufyCloud.defaults.options.prefixUrl.toString();
1101
+ }
1102
+ setOpenUDID(openudid) {
1103
+ this.headers.openudid = openudid;
1104
+ this.updateApiHeader();
1105
+ }
1106
+ setSerialNumber(serialnumber) {
1107
+ this.headers.sn = serialnumber;
1108
+ this.updateApiHeader();
1109
+ }
1110
+ async _getEvents(functionName, endpoint, startTime, endTime, filter, maxResults) {
1111
+ const records = [];
1112
+ if (filter === undefined)
1113
+ filter = { deviceSN: "", stationSN: "", storageType: types_1.StorageType.NONE };
1114
+ if (maxResults === undefined)
1115
+ maxResults = 1000;
1116
+ const data = {
1117
+ device_sn: filter.deviceSN !== undefined ? filter.deviceSN : "",
1118
+ end_time: Math.trunc(endTime.getTime() / 1000),
1119
+ exclude_guest: false,
1120
+ house_id: "HOUSEID_ALL_DEVICE",
1121
+ id: 0,
1122
+ id_type: 1,
1123
+ is_favorite: false,
1124
+ num: maxResults,
1125
+ pullup: true,
1126
+ shared: true,
1127
+ start_time: Math.trunc(startTime.getTime() / 1000),
1128
+ station_sn: filter.stationSN !== undefined ? filter.stationSN : "",
1129
+ storage: filter.storageType !== undefined ? filter.storageType : types_1.StorageType.NONE,
1130
+ transaction: `${new Date().getTime().toString()}`,
1131
+ };
1132
+ const response = await this.makePostRequest(endpoint, data);
1133
+ if (response !== undefined) {
1134
+ logging_1.rootHTTPLogger.debug(`${functionName} - Response:`, response.data);
1135
+ if (response.status == 200) {
1136
+ const result = response.data;
1137
+ if (result.code == 0) {
1138
+ if (result.data) {
1139
+ const dataresult = this.decryptAPIData(result.data);
1140
+ logging_1.rootHTTPLogger.debug(`${functionName} - Decrypted data:`, dataresult);
1141
+ if (dataresult) {
1142
+ dataresult.forEach((record) => {
1143
+ logging_1.rootHTTPLogger.debug(`${functionName} - Record:`, record);
1144
+ records.push(record);
1145
+ });
1146
+ }
1147
+ }
1148
+ else {
1149
+ logging_1.rootHTTPLogger.error(`${functionName} - Response data is missing`, {
1150
+ code: result.code,
1151
+ msg: result.msg,
1152
+ data: response.data,
1153
+ endpoint: endpoint,
1154
+ startTime: startTime,
1155
+ endTime: endTime,
1156
+ filter: filter,
1157
+ maxResults: maxResults,
1158
+ });
1159
+ }
1160
+ }
1161
+ else {
1162
+ logging_1.rootHTTPLogger.error(`${functionName} - Response code not ok`, {
1163
+ code: result.code,
1164
+ msg: result.msg,
1165
+ data: response.data,
1166
+ endpoint: endpoint,
1167
+ startTime: startTime,
1168
+ endTime: endTime,
1169
+ filter: filter,
1170
+ maxResults: maxResults,
1171
+ });
1172
+ }
1173
+ }
1174
+ else {
1175
+ logging_1.rootHTTPLogger.error(`${functionName} - Status return code not 200`, {
1176
+ status: response.status,
1177
+ statusText: response.statusText,
1178
+ data: response.data,
1179
+ endpoint: endpoint,
1180
+ startTime: startTime,
1181
+ endTime: endTime,
1182
+ filter: filter,
1183
+ maxResults: maxResults,
1184
+ });
1185
+ }
1186
+ }
1187
+ return records;
1188
+ }
1189
+ async getVideoEvents(startTime, endTime, filter, maxResults) {
1190
+ return this._getEvents("getVideoEvents", this.apiEventGetAllVideoRecord, startTime, endTime, filter, maxResults);
1191
+ }
1192
+ async getAlarmEvents(startTime, endTime, filter, maxResults) {
1193
+ return this._getEvents("getAlarmEvents", this.apiEventGetAllAlarmRecord, startTime, endTime, filter, maxResults);
1194
+ }
1195
+ async getHistoryEvents(startTime, endTime, filter, maxResults) {
1196
+ return this._getEvents("getHistoryEvents", this.apiEventGetAllHistoryRecord, startTime, endTime, filter, maxResults);
1197
+ }
1198
+ async getAllVideoEvents(filter, maxResults) {
1199
+ return this.getVideoEvents(new Date(new Date().getTime() - this.FIFTEEN_YEARS_IN_MS), new Date(), filter, maxResults);
1200
+ }
1201
+ async getAllAlarmEvents(filter, maxResults) {
1202
+ return this.getAlarmEvents(new Date(new Date().getTime() - this.FIFTEEN_YEARS_IN_MS), new Date(), filter, maxResults);
1203
+ }
1204
+ async getAllHistoryEvents(filter, maxResults) {
1205
+ return this.getHistoryEvents(new Date(new Date().getTime() - this.FIFTEEN_YEARS_IN_MS), new Date(), filter, maxResults);
1206
+ }
1207
+ isConnected() {
1208
+ return this.connected;
1209
+ }
1210
+ async getInvites() {
1211
+ const data = {
1212
+ num: 100,
1213
+ orderby: "",
1214
+ own: false,
1215
+ page: 0,
1216
+ transaction: `${new Date().getTime().toString()}`,
1217
+ };
1218
+ const response = await this.makePostRequest(this.apiGetInvites, data);
1219
+ if (response !== undefined) {
1220
+ if (response.status == 200) {
1221
+ const result = response.data;
1222
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1223
+ if (result.data) {
1224
+ const invites = {};
1225
+ const decrypted = this.decryptAPIData(result.data);
1226
+ logging_1.rootHTTPLogger.debug("Get invites - Decrypted invites data", { invites: decrypted });
1227
+ if (Array.isArray(decrypted)) {
1228
+ decrypted.forEach((invite) => {
1229
+ invites[invite.invite_id] = invite;
1230
+ let data = (0, utils_2.parseJSON)(invites[invite.invite_id].devices, logging_1.rootHTTPLogger);
1231
+ if (data === undefined)
1232
+ data = [];
1233
+ invites[invite.invite_id].devices = data;
1234
+ });
1235
+ }
1236
+ return invites;
1237
+ }
1238
+ }
1239
+ else {
1240
+ logging_1.rootHTTPLogger.error("Get invites - Response code not ok", {
1241
+ code: result.code,
1242
+ msg: result.msg,
1243
+ data: response.data,
1244
+ });
1245
+ }
1246
+ }
1247
+ else {
1248
+ logging_1.rootHTTPLogger.error("Get invites - Status return code not 200", {
1249
+ status: response.status,
1250
+ statusText: response.statusText,
1251
+ data: response.data,
1252
+ });
1253
+ }
1254
+ }
1255
+ return {};
1256
+ }
1257
+ async confirmInvites(confirmInvites) {
1258
+ const data = {
1259
+ invites: confirmInvites,
1260
+ transaction: `${new Date().getTime().toString()}`,
1261
+ };
1262
+ const response = await this.makePostRequest(this.apiConfirmInvite, data);
1263
+ if (response !== undefined) {
1264
+ if (response.status == 200) {
1265
+ const result = response.data;
1266
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1267
+ return true;
1268
+ }
1269
+ else {
1270
+ logging_1.rootHTTPLogger.error("Confirm invites - Response code not ok", {
1271
+ code: result.code,
1272
+ msg: result.msg,
1273
+ data: response.data,
1274
+ confirmInvites: confirmInvites,
1275
+ });
1276
+ }
1277
+ }
1278
+ else {
1279
+ logging_1.rootHTTPLogger.error("Confirm invites - Status return code not 200", {
1280
+ status: response.status,
1281
+ statusText: response.statusText,
1282
+ data: response.data,
1283
+ confirmInvites: confirmInvites,
1284
+ });
1285
+ }
1286
+ }
1287
+ return false;
1288
+ }
1289
+ async getPublicKey(deviceSN, type) {
1290
+ if (this.connected) {
1291
+ try {
1292
+ if (this.persistentData.device_public_keys[deviceSN] !== undefined && type === types_1.PublicKeyType.LOCK) {
1293
+ logging_1.rootHTTPLogger.debug("return cached public key", this.persistentData.device_public_keys[deviceSN]);
1294
+ return this.persistentData.device_public_keys[deviceSN];
1295
+ }
1296
+ else {
1297
+ const response = await this.request({
1298
+ method: "get",
1299
+ endpoint: `v1/app/public_key/query?device_sn=${deviceSN}&type=${type}`,
1300
+ });
1301
+ if (response.status == 200) {
1302
+ const result = response.data;
1303
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1304
+ if (result.data) {
1305
+ if (type === types_1.PublicKeyType.LOCK)
1306
+ this.persistentData.device_public_keys[deviceSN] = result.data.public_key;
1307
+ return result.data.public_key;
1308
+ }
1309
+ }
1310
+ else {
1311
+ logging_1.rootHTTPLogger.error("Get public key - Response code not ok", {
1312
+ code: result.code,
1313
+ msg: result.msg,
1314
+ data: response.data,
1315
+ deviceSN: deviceSN,
1316
+ type: type,
1317
+ });
1318
+ }
1319
+ }
1320
+ else {
1321
+ logging_1.rootHTTPLogger.error("Get public key - Status return code not 200", {
1322
+ status: response.status,
1323
+ statusText: response.statusText,
1324
+ data: response.data,
1325
+ deviceSN: deviceSN,
1326
+ type: type,
1327
+ });
1328
+ }
1329
+ }
1330
+ }
1331
+ catch (err) {
1332
+ const error = (0, error_1.ensureError)(err);
1333
+ logging_1.rootHTTPLogger.error("Get public key - Generic Error", {
1334
+ error: (0, utils_2.getError)(error),
1335
+ deviceSN: deviceSN,
1336
+ type: type,
1337
+ });
1338
+ }
1339
+ }
1340
+ return "";
1341
+ }
1342
+ decryptAPIData(data, json = true) {
1343
+ if (data) {
1344
+ let decryptedData;
1345
+ try {
1346
+ decryptedData = (0, utils_1.decryptAPIData)(data, this.ecdh.computeSecret(Buffer.from(this.persistentData.serverPublicKey, "hex")));
1347
+ }
1348
+ catch (err) {
1349
+ const error = (0, error_1.ensureError)(err);
1350
+ logging_1.rootHTTPLogger.error("Data decryption error, invalidating session data and reconnecting...", {
1351
+ error: (0, utils_2.getError)(error),
1352
+ serverPublicKey: this.persistentData.serverPublicKey,
1353
+ });
1354
+ this.persistentData.serverPublicKey = this.SERVER_PUBLIC_KEY;
1355
+ this.invalidateToken();
1356
+ this.emit("close");
1357
+ }
1358
+ if (decryptedData) {
1359
+ const str = (0, utils_3.getNullTerminatedString)(decryptedData, "utf-8");
1360
+ if (json)
1361
+ return (0, utils_2.parseJSON)(str, logging_1.rootHTTPLogger);
1362
+ return str;
1363
+ }
1364
+ if (json)
1365
+ return {};
1366
+ }
1367
+ return undefined;
1368
+ }
1369
+ async getSensorHistory(stationSN, deviceSN) {
1370
+ const data = {
1371
+ devicse_sn: deviceSN,
1372
+ max_time: 0, //TODO: Finish implementation
1373
+ num: 500, //TODO: Finish implementation
1374
+ page: 0, //TODO: Finish implementation
1375
+ station_sn: stationSN,
1376
+ transaction: `${new Date().getTime().toString()}`,
1377
+ };
1378
+ const response = await this.makePostRequest(this.apiGetSensorHistory, data);
1379
+ if (response !== undefined) {
1380
+ if (response.status == 200) {
1381
+ const result = response.data;
1382
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1383
+ if (result.data) {
1384
+ const entries = result.data;
1385
+ return entries;
1386
+ }
1387
+ }
1388
+ else {
1389
+ logging_1.rootHTTPLogger.error("Get sensor history - Response code not ok", {
1390
+ code: result.code,
1391
+ msg: result.msg,
1392
+ data: response.data,
1393
+ stationSN: stationSN,
1394
+ deviceSN: deviceSN,
1395
+ });
1396
+ }
1397
+ }
1398
+ else {
1399
+ logging_1.rootHTTPLogger.error("Get sensor history - Status return code not 200", {
1400
+ status: response.status,
1401
+ statusText: response.statusText,
1402
+ data: response.data,
1403
+ stationSN: stationSN,
1404
+ deviceSN: deviceSN,
1405
+ });
1406
+ }
1407
+ }
1408
+ return [];
1409
+ }
1410
+ async getHouseDetail(houseID) {
1411
+ const data = {
1412
+ house_id: houseID,
1413
+ transaction: `${new Date().getTime().toString()}`,
1414
+ };
1415
+ const response = await this.makePostRequest(this.apiGetHouseDetail, data);
1416
+ if (response !== undefined) {
1417
+ if (response.status == 200) {
1418
+ const result = response.data;
1419
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1420
+ if (result.data) {
1421
+ const houseDetail = this.decryptAPIData(result.data);
1422
+ logging_1.rootHTTPLogger.debug("Get house detail - Decrypted house detail data", { details: houseDetail });
1423
+ return houseDetail;
1424
+ }
1425
+ }
1426
+ else {
1427
+ logging_1.rootHTTPLogger.error("Get house detail - Response code not ok", {
1428
+ code: result.code,
1429
+ msg: result.msg,
1430
+ data: response.data,
1431
+ houseID: houseID,
1432
+ });
1433
+ }
1434
+ }
1435
+ else {
1436
+ logging_1.rootHTTPLogger.error("Get house detail - Status return code not 200", {
1437
+ status: response.status,
1438
+ statusText: response.statusText,
1439
+ data: response.data,
1440
+ houseID: houseID,
1441
+ });
1442
+ }
1443
+ }
1444
+ return null;
1445
+ }
1446
+ async getHouseList() {
1447
+ const data = {
1448
+ transaction: `${new Date().getTime().toString()}`,
1449
+ };
1450
+ const response = await this.makePostRequest(this.apiGetHouseList, data);
1451
+ if (response !== undefined) {
1452
+ if (response.status == 200) {
1453
+ const result = response.data;
1454
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1455
+ if (result.data) {
1456
+ logging_1.rootHTTPLogger.debug("Get house list - houses", { houses: result.data });
1457
+ return result.data;
1458
+ }
1459
+ }
1460
+ else {
1461
+ logging_1.rootHTTPLogger.error("Get house list - Response code not ok", {
1462
+ code: result.code,
1463
+ msg: result.msg,
1464
+ data: response.data,
1465
+ });
1466
+ }
1467
+ }
1468
+ else {
1469
+ logging_1.rootHTTPLogger.error("Get house list - Status return code not 200", {
1470
+ status: response.status,
1471
+ statusText: response.statusText,
1472
+ data: response.data,
1473
+ });
1474
+ }
1475
+ }
1476
+ return [];
1477
+ }
1478
+ async getHouseInviteList(isInviter = 1) {
1479
+ //TODO: Understand the other values of isInviter and document it
1480
+ const data = {
1481
+ is_inviter: isInviter,
1482
+ transaction: `${new Date().getTime().toString()}`,
1483
+ };
1484
+ const response = await this.makePostRequest(this.apiGetHouseInvites, data);
1485
+ if (response !== undefined) {
1486
+ if (response.status == 200) {
1487
+ const result = response.data;
1488
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1489
+ if (result.data) {
1490
+ //const houseInviteList = this.decryptAPIData(result.data) as Array<HouseInviteListResponse>; // No more encrypted!?
1491
+ //rootHTTPLogger.debug("Get house invite list - Decrypted house invite list data", houseInviteList);
1492
+ const houseInviteList = result.data;
1493
+ logging_1.rootHTTPLogger.debug("Get house invite list - House invite list data", houseInviteList);
1494
+ return houseInviteList;
1495
+ }
1496
+ }
1497
+ else {
1498
+ logging_1.rootHTTPLogger.error("Get house invite list - Response code not ok", {
1499
+ code: result.code,
1500
+ msg: result.msg,
1501
+ data: response.data,
1502
+ isInviter: isInviter,
1503
+ });
1504
+ }
1505
+ }
1506
+ else {
1507
+ logging_1.rootHTTPLogger.error("Get house invite list - Status return code not 200", {
1508
+ status: response.status,
1509
+ statusText: response.statusText,
1510
+ data: response.data,
1511
+ isInviter: isInviter,
1512
+ });
1513
+ }
1514
+ }
1515
+ return [];
1516
+ }
1517
+ async confirmHouseInvite(houseID, inviteID) {
1518
+ const data = {
1519
+ house_id: houseID,
1520
+ invite_id: inviteID,
1521
+ is_inviter: 1, // 1 = true, 0 = false
1522
+ //user_id: "",
1523
+ transaction: `${new Date().getTime().toString()}`,
1524
+ };
1525
+ const response = await this.makePostRequest(this.apiConfirmHouseInvite, data);
1526
+ if (response !== undefined) {
1527
+ if (response.status == 200) {
1528
+ const result = response.data;
1529
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1530
+ return true;
1531
+ }
1532
+ else {
1533
+ logging_1.rootHTTPLogger.error("Confirm house invite - Response code not ok", {
1534
+ code: result.code,
1535
+ msg: result.msg,
1536
+ data: response.data,
1537
+ houseID: houseID,
1538
+ inviteID: inviteID,
1539
+ });
1540
+ }
1541
+ }
1542
+ else {
1543
+ logging_1.rootHTTPLogger.error("Confirm house invite - Status return code not 200", {
1544
+ status: response.status,
1545
+ statusText: response.statusText,
1546
+ data: response.data,
1547
+ houseID: houseID,
1548
+ inviteID: inviteID,
1549
+ });
1550
+ }
1551
+ }
1552
+ return false;
1553
+ }
1554
+ getPersistentData() {
1555
+ return this.persistentData;
1556
+ }
1557
+ async getPassportProfile() {
1558
+ try {
1559
+ const response = await this.request({
1560
+ method: "get",
1561
+ endpoint: "v2/passport/profile",
1562
+ });
1563
+ if (response.status == 200) {
1564
+ const result = response.data;
1565
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1566
+ if (result.data) {
1567
+ const profile = this.decryptAPIData(result.data);
1568
+ logging_1.rootHTTPLogger.debug("Get passport profile - Decrypted passport profile data", { profile: profile });
1569
+ this.persistentData.user_id = profile.user_id;
1570
+ this.persistentData.nick_name = profile.nick_name;
1571
+ this.persistentData.email = profile.email;
1572
+ return profile;
1573
+ }
1574
+ }
1575
+ else {
1576
+ logging_1.rootHTTPLogger.error("Get passport profile - Response code not ok", {
1577
+ code: result.code,
1578
+ msg: result.msg,
1579
+ data: response.data,
1580
+ });
1581
+ }
1582
+ }
1583
+ else {
1584
+ logging_1.rootHTTPLogger.error("Get passport profile - Status return code not 200", {
1585
+ status: response.status,
1586
+ statusText: response.statusText,
1587
+ data: response.data,
1588
+ });
1589
+ }
1590
+ }
1591
+ catch (err) {
1592
+ const error = (0, error_1.ensureError)(err);
1593
+ logging_1.rootHTTPLogger.error("Get passport profile - Generic Error", { error: (0, utils_2.getError)(error) });
1594
+ }
1595
+ return null;
1596
+ }
1597
+ async addUser(deviceSN, nickname, stationSN = "") {
1598
+ const data = {
1599
+ device_sn: deviceSN,
1600
+ nick_name: nickname,
1601
+ station_sn: stationSN === deviceSN ? "" : stationSN,
1602
+ transaction: `${new Date().getTime().toString()}`,
1603
+ };
1604
+ const response = await this.makePostRequest(this.apiAddLocalUser, data);
1605
+ if (response !== undefined) {
1606
+ if (response.status == 200) {
1607
+ const result = response.data;
1608
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1609
+ if (result.data)
1610
+ return result.data;
1611
+ }
1612
+ else {
1613
+ logging_1.rootHTTPLogger.error("Add user - Response code not ok", {
1614
+ code: result.code,
1615
+ msg: result.msg,
1616
+ data: response.data,
1617
+ deviceSN: deviceSN,
1618
+ nickname: nickname,
1619
+ stationSN: stationSN,
1620
+ });
1621
+ }
1622
+ }
1623
+ else {
1624
+ logging_1.rootHTTPLogger.error("Add user - Status return code not 200", {
1625
+ status: response.status,
1626
+ statusText: response.statusText,
1627
+ data: response.data,
1628
+ deviceSN: deviceSN,
1629
+ nickname: nickname,
1630
+ stationSN: stationSN,
1631
+ });
1632
+ }
1633
+ }
1634
+ return null;
1635
+ }
1636
+ async deleteUser(deviceSN, shortUserId, stationSN = "") {
1637
+ const data = {
1638
+ device_sn: deviceSN,
1639
+ short_user_ids: [shortUserId],
1640
+ station_sn: stationSN === deviceSN ? "" : stationSN,
1641
+ transaction: `${new Date().getTime().toString()}`,
1642
+ };
1643
+ const response = await this.makePostRequest(this.apiDeleteLocalUser, data);
1644
+ if (response !== undefined) {
1645
+ if (response.status == 200) {
1646
+ const result = response.data;
1647
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1648
+ return true;
1649
+ }
1650
+ else {
1651
+ logging_1.rootHTTPLogger.error("Delete user - Response code not ok", {
1652
+ code: result.code,
1653
+ msg: result.msg,
1654
+ data: response.data,
1655
+ deviceSN: deviceSN,
1656
+ shortUserId: shortUserId,
1657
+ stationSN: stationSN,
1658
+ });
1659
+ }
1660
+ }
1661
+ else {
1662
+ logging_1.rootHTTPLogger.error("Delete user - Status return code not 200", {
1663
+ status: response.status,
1664
+ statusText: response.statusText,
1665
+ data: response.data,
1666
+ deviceSN: deviceSN,
1667
+ shortUserId: shortUserId,
1668
+ stationSN: stationSN,
1669
+ });
1670
+ }
1671
+ }
1672
+ return false;
1673
+ }
1674
+ async getUsers(deviceSN, stationSN) {
1675
+ try {
1676
+ const response = await this.request({
1677
+ method: "get",
1678
+ endpoint: `v1/app/device/user/list?device_sn=${deviceSN}&station_sn=${stationSN}`,
1679
+ });
1680
+ if (response.status == 200) {
1681
+ const result = response.data;
1682
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1683
+ if (result.data) {
1684
+ const usersResponse = result.data;
1685
+ return usersResponse.user_list;
1686
+ }
1687
+ }
1688
+ else {
1689
+ logging_1.rootHTTPLogger.error("Get users - Response code not ok", {
1690
+ code: result.code,
1691
+ msg: result.msg,
1692
+ data: response.data,
1693
+ deviceSN: deviceSN,
1694
+ stationSN: stationSN,
1695
+ });
1696
+ }
1697
+ }
1698
+ else {
1699
+ logging_1.rootHTTPLogger.error("Get users - Status return code not 200", {
1700
+ status: response.status,
1701
+ statusText: response.statusText,
1702
+ data: response.data,
1703
+ deviceSN: deviceSN,
1704
+ stationSN: stationSN,
1705
+ });
1706
+ }
1707
+ }
1708
+ catch (err) {
1709
+ const error = (0, error_1.ensureError)(err);
1710
+ logging_1.rootHTTPLogger.error("Get users - Generic Error", {
1711
+ error: (0, utils_2.getError)(error),
1712
+ deviceSN: deviceSN,
1713
+ stationSN: stationSN,
1714
+ });
1715
+ }
1716
+ return null;
1717
+ }
1718
+ async getUser(deviceSN, stationSN, shortUserId) {
1719
+ try {
1720
+ const users = await this.getUsers(deviceSN, stationSN);
1721
+ if (users !== null) {
1722
+ for (const user of users) {
1723
+ if (user.short_user_id === shortUserId) {
1724
+ return user;
1725
+ }
1726
+ }
1727
+ }
1728
+ }
1729
+ catch (err) {
1730
+ const error = (0, error_1.ensureError)(err);
1731
+ logging_1.rootHTTPLogger.error("Get user - Generic Error", {
1732
+ error: (0, utils_2.getError)(error),
1733
+ deviceSN: deviceSN,
1734
+ stationSN: stationSN,
1735
+ shortUserId: shortUserId,
1736
+ });
1737
+ }
1738
+ return null;
1739
+ }
1740
+ async updateUser(deviceSN, stationSN, shortUserId, nickname) {
1741
+ const user = await this.getUser(deviceSN, stationSN, shortUserId);
1742
+ if (user !== null) {
1743
+ const data = {
1744
+ device_sn: deviceSN,
1745
+ nick_name: nickname,
1746
+ password_list: user.password_list,
1747
+ short_user_id: shortUserId,
1748
+ station_sn: stationSN === deviceSN ? "" : stationSN,
1749
+ user_type: user.user_type,
1750
+ transaction: `${new Date().getTime().toString()}`,
1751
+ };
1752
+ const response = await this.makePostRequest(this.apiUpdateLocalUser, data);
1753
+ if (response !== undefined) {
1754
+ if (response.status == 200) {
1755
+ const result = response.data;
1756
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1757
+ return true;
1758
+ }
1759
+ else {
1760
+ logging_1.rootHTTPLogger.error("Update user - Response code not ok", {
1761
+ code: result.code,
1762
+ msg: result.msg,
1763
+ data: response.data,
1764
+ deviceSN: deviceSN,
1765
+ stationSN: stationSN,
1766
+ shortUserId: shortUserId,
1767
+ nickname: nickname,
1768
+ });
1769
+ }
1770
+ }
1771
+ else {
1772
+ logging_1.rootHTTPLogger.error("Update user - Status return code not 200", {
1773
+ status: response.status,
1774
+ statusText: response.statusText,
1775
+ data: response.data,
1776
+ deviceSN: deviceSN,
1777
+ stationSN: stationSN,
1778
+ shortUserId: shortUserId,
1779
+ nickname: nickname,
1780
+ });
1781
+ }
1782
+ }
1783
+ }
1784
+ return false;
1785
+ }
1786
+ async getImage(deviceSN, url) {
1787
+ if (this.connected) {
1788
+ try {
1789
+ const device = this.devices[deviceSN];
1790
+ if (device) {
1791
+ const station = this.hubs[device.station_sn];
1792
+ if (station) {
1793
+ const response = await this.request({
1794
+ method: "GET",
1795
+ endpoint: url,
1796
+ responseType: "buffer",
1797
+ }, true);
1798
+ if (response.status == 200) {
1799
+ return (0, utils_1.decodeImage)(station.p2p_did, response.data);
1800
+ }
1801
+ else {
1802
+ logging_1.rootHTTPLogger.error("Get Image - Status return code not 200", {
1803
+ status: response.status,
1804
+ statusText: response.statusText,
1805
+ data: response.data,
1806
+ deviceSN: deviceSN,
1807
+ url: url,
1808
+ });
1809
+ }
1810
+ }
1811
+ }
1812
+ }
1813
+ catch (err) {
1814
+ const error = (0, error_1.ensureError)(err);
1815
+ logging_1.rootHTTPLogger.error("Get Image - Generic Error", { error: (0, utils_2.getError)(error), deviceSN: deviceSN, url: url });
1816
+ }
1817
+ }
1818
+ return Buffer.alloc(0);
1819
+ }
1820
+ async updateUserPassword(deviceSN, shortUserId, passwordId, schedule, stationSN = "") {
1821
+ const data = {
1822
+ device_sn: deviceSN,
1823
+ password_list: [
1824
+ {
1825
+ password_id: passwordId,
1826
+ password_type: types_1.UserPasswordType.PIN,
1827
+ schedule: JSON.stringify({
1828
+ endDay: schedule !== undefined && schedule.endDateTime !== undefined ? (0, utils_1.hexDate)(schedule.endDateTime) : "ffffffff",
1829
+ endTime: schedule !== undefined && schedule.endDateTime !== undefined ? (0, utils_1.hexTime)(schedule.endDateTime) : "ffff",
1830
+ startDay: schedule !== undefined && schedule.startDateTime !== undefined
1831
+ ? (0, utils_1.hexDate)(schedule.startDateTime)
1832
+ : "00000000",
1833
+ startTime: schedule !== undefined && schedule.startDateTime !== undefined ? (0, utils_1.hexTime)(schedule.startDateTime) : "0000",
1834
+ week: schedule !== undefined && schedule.week !== undefined ? (0, utils_1.hexWeek)(schedule) : "ff",
1835
+ }),
1836
+ },
1837
+ ],
1838
+ short_user_id: shortUserId,
1839
+ station_sn: stationSN === deviceSN ? "" : stationSN,
1840
+ transaction: `${new Date().getTime().toString()}`,
1841
+ };
1842
+ const response = await this.makePostRequest(this.apiUpdateUserPassword, data);
1843
+ if (response !== undefined) {
1844
+ if (response.status == 200) {
1845
+ const result = response.data;
1846
+ if (result.code == types_1.ResponseErrorCode.CODE_OK) {
1847
+ return true;
1848
+ }
1849
+ else {
1850
+ logging_1.rootHTTPLogger.error("Add user - Response code not ok", {
1851
+ code: result.code,
1852
+ msg: result.msg,
1853
+ data: response.data,
1854
+ deviceSN: deviceSN,
1855
+ shortUserId: shortUserId,
1856
+ schedule: schedule,
1857
+ stationSN: stationSN,
1858
+ });
1859
+ }
1860
+ }
1861
+ else {
1862
+ logging_1.rootHTTPLogger.error("Add user - Status return code not 200", {
1863
+ status: response.status,
1864
+ statusText: response.statusText,
1865
+ data: response.data,
1866
+ deviceSN: deviceSN,
1867
+ shortUserId: shortUserId,
1868
+ schedule: schedule,
1869
+ stationSN: stationSN,
1870
+ });
1871
+ }
1872
+ }
1873
+ return false;
1874
+ }
1875
+ }
1876
+ exports.HTTPApi = HTTPApi;
1877
+ //# sourceMappingURL=api.js.map