UNPKG

eufy-security-client-fork

Version:

Client to comunicate with Eufy-Security devices

1,155 lines 49.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HTTPApi = void 0; const got_1 = require("got"); const tiny_typed_emitter_1 = require("tiny-typed-emitter"); const ts_log_1 = require("ts-log"); const i18n_iso_countries_1 = require("i18n-iso-countries"); const i18n_iso_languages_1 = require("@cospired/i18n-iso-languages"); const crypto_1 = require("crypto"); const schedule = require("node-schedule"); const pThrottle = require("p-throttle"); const types_1 = require("./types"); const parameter_1 = require("./parameter"); const utils_1 = require("./utils"); const error_1 = require("./../error"); const utils_2 = require("./../utils"); const error_2 = require("./error"); class HTTPApi extends tiny_typed_emitter_1.TypedEmitter { constructor(apiBase, country, username, password, log = ts_log_1.dummyLogger, persistentData) { super(); this.ecdh = (0, crypto_1.createECDH)("prime256v1"); this.serverPublicKey = "04c5c00c4f8d1197cc7c3167c52bf7acb054d722f0ef08dcd7e0883236e0d72a3868d9750cb47fa4619248f3d83f0f662671dadc6e2d31c2f41db0161651c7c076"; this.token = null; this.tokenExpiration = null; this.connected = false; this.throttle = pThrottle({ limit: 6, interval: 10000, }); this.devices = {}; this.hubs = {}; this.houses = {}; this.persistentData = { user_id: "", email: "", nick_name: "", device_public_keys: {} }; this.headers = { app_version: "v4.2.1_1280", os_type: "android", os_version: "31", phone_model: "ONEPLUS A3003", country: "DE", language: "en", openudid: "5e4621b0152c0d00", uid: "", net_type: "wifi", mnc: "02", mcc: "262", sn: "75814221ee75", Model_type: "PHONE", timezone: "GMT+01:00", "Cache-Control": "no-cache", }; this.username = username; this.password = password; this.log = log; this.apiBase = apiBase; this.log.debug(`Loaded API_BASE: ${apiBase}`); this.headers.timezone = (0, utils_1.getTimezoneGMTString)(); this.headers.country = country.toUpperCase(); if (persistentData) this.persistentData = persistentData; this.requestEufyCloud = got_1.default.extend({ prefixUrl: this.apiBase, headers: this.headers, responseType: "json", //throwHttpErrors: false, retry: { limit: 3, methods: ["GET", "POST"], statusCodes: [ 408, 413, 423, 429, 500, 502, 503, 504, 521, 522, 524 ], calculateDelay: ({ computedValue }) => { return computedValue * 3; } }, hooks: { afterResponse: [ async (response, retryWithMergedOptions) => { // Unauthorized if (response.statusCode === 401) { const oldToken = this.token; this.log.debug("Invalidate token an get a new one...", { requestUrl: response.requestUrl, statusCode: response.statusCode, statusMessage: response.statusMessage }); this.invalidateToken(); await this.login({ force: true }); if (oldToken !== this.token && this.token) { // Refresh the access token const updatedOptions = { headers: { "X-Auth-Token": this.token } }; // Update the defaults this.requestEufyCloud.defaults.options = this.requestEufyCloud.mergeOptions(this.requestEufyCloud.defaults.options, updatedOptions); // Make a new retry return retryWithMergedOptions(updatedOptions); } } // No changes otherwise return response; } ], beforeRetry: [ (options, error, retryCount) => { var _a; // This will be called on `retryWithMergedOptions(...)` this.log.debug(`Retrying [${retryCount}]: ${error === null || error === void 0 ? void 0 : error.code} (${(_a = error === null || error === void 0 ? void 0 : error.request) === null || _a === void 0 ? void 0 : _a.requestUrl})`, { options: options }); // Retrying [1]: ERR_NON_2XX_3XX_RESPONSE } ], beforeError: [ error => { var _a; const { response } = error; if (response && response.body) { const result = response.body; error.name = "EufyError"; error.message = `Code: ${result.code} Message: ${result.msg} (HTTP Code: ${response.statusCode})`; this.log.error(`${error.name} - ${error.message} - requestUrl: ${(_a = error.request) === null || _a === void 0 ? void 0 : _a.requestUrl}`); } return error; } ], beforeRequest: [ async (_options) => { await this.throttle(async () => { return; })(); } ] }, mutableDefaults: true }); } static async getApiBaseFromCloud(country) { const response = await (0, got_1.default)(`domain/${country}`, { prefixUrl: this.apiDomainBase, method: "GET", responseType: "json", retry: { limit: 1, methods: ["GET"] } }); const result = response.body; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { return `https://${result.data.domain}`; } throw new error_2.ApiBaseLoadError(result.code, result.msg); } static async initialize(country, username, password, log = ts_log_1.dummyLogger, persistentData) { if ((0, i18n_iso_countries_1.isValid)(country) && country.length === 2) { const apiBase = await this.getApiBaseFromCloud(country); return new HTTPApi(apiBase, country, username, password, log, persistentData); } throw new error_1.InvalidCountryCodeError("Invalid ISO 3166-1 Alpha-2 country code"); } clearScheduleRenewAuthToken() { if (this.renewAuthTokenJob !== undefined) { this.renewAuthTokenJob.cancel(); } } scheduleRenewAuthToken() { this.clearScheduleRenewAuthToken(); if (this.tokenExpiration !== null) { const scheduleDate = new Date(this.tokenExpiration.getTime() - (1000 * 60 * 60 * 24)); if (this.renewAuthTokenJob === undefined) { this.renewAuthTokenJob = schedule.scheduleJob("renewAuthToken", scheduleDate, async () => { this.log.info("Authentication token is soon expiring, fetching a new one..."); await this.login({ force: true }); }); } else { this.renewAuthTokenJob.schedule(scheduleDate); } } } invalidateToken() { this.token = null; this.requestEufyCloud.defaults.options.headers["X-Auth-Token"] = undefined; this.tokenExpiration = null; this.clearScheduleRenewAuthToken(); this.emit("auth token invalidated"); } setPhoneModel(model) { this.headers.phone_model = model.toUpperCase(); this.requestEufyCloud.defaults.options.headers = this.headers; } getPhoneModel() { return this.headers.phone_model; } getCountry() { return this.headers.country; } setLanguage(language) { if ((0, i18n_iso_languages_1.isValid)(language) && language.length === 2) { this.headers.language = language; this.requestEufyCloud.defaults.options.headers = this.headers; } else throw new error_1.InvalidLanguageCodeError("Invalid ISO 639 language code"); } getLanguage() { return this.headers.language; } async login(options) { options = (0, utils_2.mergeDeep)(options, { force: false }); this.log.debug("Login and get an access token", { token: this.token, tokenExpiration: this.tokenExpiration }); if (!this.token || (this.tokenExpiration && (new Date()).getTime() >= this.tokenExpiration.getTime()) || options.verifyCode || options.captcha || options.force) { try { this.ecdh.generateKeys(); const data = { client_secret_info: { public_key: this.ecdh.getPublicKey("hex") }, enc: 0, email: this.username, password: (0, utils_1.encryptPassword)(this.password, this.ecdh.computeSecret(Buffer.from(this.serverPublicKey, "hex"))), time_zone: new Date().getTimezoneOffset() !== 0 ? -new Date().getTimezoneOffset() * 60 * 1000 : 0, transaction: `${new Date().getTime()}` }; if (options.verifyCode) { data.verify_code = options.verifyCode; } else if (options.captcha) { data.captcha_id = options.captcha.captchaId; data.answer = options.captcha.captchaCode; } const response = await this.request({ method: "post", endpoint: "v2/passport/login", data: data }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { const dataresult = result.data; this.persistentData.user_id = dataresult.user_id; this.persistentData.email = dataresult.email; this.persistentData.nick_name = dataresult.nick_name; this.setToken(dataresult.auth_token); this.tokenExpiration = new Date(dataresult.token_expires_at * 1000); this.headers = { ...this.headers, gtoken: (0, utils_2.md5)(dataresult.user_id) }; /*if (dataresult.server_secret_info?.public_key) this.serverPublicKey = dataresult.server_secret_info.public_key;*/ this.log.debug("Token data", { token: this.token, tokenExpiration: this.tokenExpiration }); if (!this.connected) this.emit("connect"); this.connected = true; this.scheduleRenewAuthToken(); } else if (result.code == types_1.ResponseErrorCode.CODE_NEED_VERIFY_CODE) { this.log.debug(`Send verification code...`); const dataresult = result.data; this.setToken(dataresult.auth_token); this.tokenExpiration = new Date(dataresult.token_expires_at * 1000); this.log.debug("Token data", { token: this.token, tokenExpiration: this.tokenExpiration }); await this.sendVerifyCode(types_1.VerfyCodeTypes.TYPE_EMAIL); this.emit("tfa request"); } else if (result.code == types_1.ResponseErrorCode.LOGIN_NEED_CAPTCHA || result.code == types_1.ResponseErrorCode.LOGIN_CAPTCHA_ERROR) { const dataresult = result.data; this.log.debug("Captcha verification received", { captchaId: dataresult.captcha_id, item: dataresult.item }); this.emit("captcha request", dataresult.captcha_id, dataresult.item); } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } else if (!this.connected) { try { const profile = await this.getPassportProfile(); if (profile !== null) { this.emit("connect"); this.connected = true; this.scheduleRenewAuthToken(); } } catch (error) { this.log.error("getPassportProfile Error", error); } } } async sendVerifyCode(type) { try { if (!type) type = types_1.VerfyCodeTypes.TYPE_EMAIL; const response = await this.request({ method: "post", endpoint: "v1/sms/send/verify_code", data: { message_type: type, transaction: `${new Date().getTime()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { this.log.info(`Requested verification code for 2FA`); return true; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } return false; } async listTrustDevice() { if (this.connected) { try { const response = await this.request({ method: "get", endpoint: "v1/app/trust_device/list" }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data && result.data.list) { return result.data.list; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return []; } async addTrustDevice(verifyCode) { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/app/trust_device/add", data: { verify_code: verifyCode, transaction: `${new Date().getTime()}` } }); this.log.debug("Response trust device:", response.data); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { this.log.info(`2FA authentication successfully done. Device trusted.`); const trusted_devices = await this.listTrustDevice(); trusted_devices.forEach((trusted_device) => { if (trusted_device.is_current_device === 1) { this.log.debug("This device is trusted. Token expiration extended:", { tokenExpiration: this.tokenExpiration }); } }); return true; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return false; } async getStationList() { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/house/station_list", data: { device_sn: "", num: 1000, orderby: "", page: 0, station_sn: "", time_zone: new Date().getTimezoneOffset() !== 0 ? -new Date().getTimezoneOffset() * 60 * 1000 : 0, transaction: `${new Date().getTime()}` } }); this.log.debug("Stations - Response:", response.data); if (response.status == 200) { const result = response.data; if (result.code == 0) { return result.data; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Stations - Generic Error:", error); } } return []; } async getDeviceList() { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/house/device_list", data: { device_sn: "", num: 1000, orderby: "", page: 0, station_sn: "", time_zone: new Date().getTimezoneOffset() !== 0 ? -new Date().getTimezoneOffset() * 60 * 1000 : 0, transaction: `${new Date().getTime()}` } }); this.log.debug("Devices - Response:", response.data); if (response.status == 200) { const result = response.data; if (result.code == 0) { return result.data; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Devices - Generic Error:", error); } } return []; } async refreshHouseData() { //Get Houses const houses = await this.getHouseList(); if (houses && houses.length > 0) { houses.forEach(element => { this.log.debug(`Houses - element: ${JSON.stringify(element)}`); this.log.debug(`Houses - house name: ${element.house_name}`); this.houses[element.house_id] = element; }); if (Object.keys(this.houses).length > 0) this.emit("houses", this.houses); } else { this.log.info("No houses found."); } } async refreshStationData() { //Get Stations const stations = await this.getStationList(); if (stations && stations.length > 0) { stations.forEach(element => { this.log.debug(`Stations - element: ${JSON.stringify(element)}`); this.log.debug(`Stations - device_type: ${element.device_type}`); this.hubs[element.station_sn] = element; }); if (Object.keys(this.hubs).length > 0) this.emit("hubs", this.hubs); } else { this.log.info("No stations found."); } } async refreshDeviceData() { //Get Devices const devices = await this.getDeviceList(); if (devices && devices.length > 0) { devices.forEach(element => { this.devices[element.device_sn] = element; }); if (Object.keys(this.devices).length > 0) this.emit("devices", this.devices); } else { this.log.info("No devices found."); } } async refreshAllData() { //Get the latest info //Get Houses await this.refreshHouseData(); //Get Stations await this.refreshStationData(); //Get Devices await this.refreshDeviceData(); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types async request(request) { this.log.debug("Request:", { method: request.method, endpoint: request.endpoint, token: this.token, data: request.data }); try { const internalResponse = await this.requestEufyCloud(request.endpoint, { method: request.method, json: request.data, }); const response = { status: internalResponse.statusCode, statusText: internalResponse.statusMessage ? internalResponse.statusMessage : "", headers: internalResponse.headers, data: internalResponse.body, }; this.log.debug("Response:", { response: response.data }); return response; } catch (error) { if (error instanceof got_1.HTTPError) { if (error.response.statusCode === 401) { this.invalidateToken(); this.log.error("Status return code 401, invalidate token", { status: error.response.statusCode, statusText: error.response.statusMessage }); this.emit("close"); this.connected = false; } } throw error; } } async checkPushToken() { //Check push notification token if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/app/review/app_push_check", data: { app_type: "eufySecurity", transaction: `${new Date().getTime()}` } }); if (response.status == 200) { const result = response.data; if (result.code == 0) { this.log.debug(`Push token OK`); return true; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return false; } async registerPushToken(token) { //Register push notification token if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/apppush/register_push_token", data: { is_notification_enable: true, token: token, transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == 0) { this.log.debug(`Push token registered successfully`); return true; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return false; } async setParameters(stationSN, deviceSN, params) { if (this.connected) { const tmp_params = []; params.forEach(param => { tmp_params.push({ param_type: param.paramType, param_value: parameter_1.ParameterHelper.writeValue(param.paramType, param.paramValue) }); }); try { const response = await this.request({ method: "post", endpoint: "v1/app/upload_devs_params", data: { device_sn: deviceSN, station_sn: stationSN, params: tmp_params } }); this.log.debug("Response:", { stationSN: stationSN, deviceSN: deviceSN, params: tmp_params, response: response.data }); if (response.status == 200) { const result = response.data; if (result.code == 0) { const dataresult = result.data; this.log.debug("New parameters set", { params: tmp_params, response: dataresult }); return true; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return false; } async getCiphers(cipherIDs, userID) { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/app/cipher/get_ciphers", data: { cipher_ids: cipherIDs, user_id: userID, transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { const ciphers = {}; result.data.forEach((cipher) => { ciphers[cipher.cipher_id] = cipher; }); return ciphers; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return {}; } async getVoices(deviceSN) { if (this.connected) { try { const response = await this.request({ method: "get", endpoint: `v1/voice/response/lists/${deviceSN}` }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { const voices = {}; result.data.forEach((voice) => { voices[voice.voice_id] = voice; }); return voices; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return {}; } async getCipher(cipherID, userID) { return (await this.getCiphers([cipherID], userID))[cipherID]; } getLog() { return this.log; } getDevices() { return this.devices; } getHubs() { return this.hubs; } getToken() { return this.token; } getTokenExpiration() { return this.tokenExpiration; } setToken(token) { this.token = token; this.requestEufyCloud.defaults.options.headers["X-Auth-Token"] = token; } setTokenExpiration(tokenExpiration) { this.tokenExpiration = tokenExpiration; } getAPIBase() { return this.requestEufyCloud.defaults.options.prefixUrl; } setOpenUDID(openudid) { this.headers.openudid = openudid; this.requestEufyCloud.defaults.options.headers = this.headers; } setSerialNumber(serialnumber) { this.headers.sn = serialnumber; this.requestEufyCloud.defaults.options.headers = this.headers; } async _getEvents(functionName, endpoint, startTime, endTime, filter, maxResults) { const records = []; if (this.connected) { try { if (filter === undefined) filter = { deviceSN: "", stationSN: "", storageType: types_1.StorageType.NONE }; if (maxResults === undefined) maxResults = 1000; const response = await this.request({ method: "post", endpoint: endpoint, data: { device_sn: filter.deviceSN !== undefined ? filter.deviceSN : "", end_time: Math.trunc(endTime.getTime() / 1000), exclude_guest: false, house_id: "HOUSEID_ALL_DEVICE", id: 0, id_type: 1, is_favorite: false, num: maxResults, pullup: true, shared: true, start_time: Math.trunc(startTime.getTime() / 1000), station_sn: filter.stationSN !== undefined ? filter.stationSN : "", storage: filter.storageType !== undefined ? filter.storageType : types_1.StorageType.NONE, transaction: `${new Date().getTime().toString()}` } }); this.log.debug(`${functionName} - Response:`, response.data); if (response.status == 200) { const result = response.data; if (result.code == 0) { const dataresult = result.data; if (dataresult) { dataresult.forEach(record => { this.log.debug(`${functionName} - Record:`, record); records.push(record); }); } } else { this.log.error(`${functionName} - Response code not ok`, { code: result.code, msg: result.msg }); } } else { this.log.error(`${functionName} - Status return code not 200`, { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error(`${functionName} - Generic Error:`, error); } } return records; } async getVideoEvents(startTime, endTime, filter, maxResults) { return this._getEvents("getVideoEvents", "v1/event/app/get_all_video_record", startTime, endTime, filter, maxResults); } async getAlarmEvents(startTime, endTime, filter, maxResults) { return this._getEvents("getAlarmEvents", "v1/event/app/get_all_alarm_record", startTime, endTime, filter, maxResults); } async getHistoryEvents(startTime, endTime, filter, maxResults) { return this._getEvents("getHistoryEvents", "v1/event/app/get_all_history_record", startTime, endTime, filter, maxResults); } async getAllVideoEvents(filter, maxResults) { const fifthyYearsInMilliseconds = 15 * 365 * 24 * 60 * 60 * 1000; return this.getVideoEvents(new Date(new Date().getTime() - fifthyYearsInMilliseconds), new Date(), filter, maxResults); } async getAllAlarmEvents(filter, maxResults) { const fifthyYearsInMilliseconds = 15 * 365 * 24 * 60 * 60 * 1000; return this.getAlarmEvents(new Date(new Date().getTime() - fifthyYearsInMilliseconds), new Date(), filter, maxResults); } async getAllHistoryEvents(filter, maxResults) { const fifthyYearsInMilliseconds = 15 * 365 * 24 * 60 * 60 * 1000; return this.getHistoryEvents(new Date(new Date().getTime() - fifthyYearsInMilliseconds), new Date(), filter, maxResults); } isConnected() { return this.connected; } async getInvites() { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/family/get_invites", data: { num: 100, orderby: "", own: false, page: 0, transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { const invites = {}; result.data.forEach((invite) => { invites[invite.invite_id] = invite; invites[invite.invite_id].devices = JSON.parse(invites[invite.invite_id].devices); }); return invites; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return {}; } async confirmInvites(confirmInvites) { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/family/confirm_invite", data: { invites: confirmInvites, transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { return true; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return false; } async getPublicKey(deviceSN, type) { if (this.connected) { try { if (this.persistentData.device_public_keys[deviceSN] !== undefined && type === types_1.PublicKeyType.LOCK) { this.log.debug("return cached public key", this.persistentData.device_public_keys[deviceSN]); return this.persistentData.device_public_keys[deviceSN]; } else { const response = await this.request({ method: "get", endpoint: `v1/app/public_key/query?device_sn=${deviceSN}&type=${type}` }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { if (type === types_1.PublicKeyType.LOCK) this.persistentData.device_public_keys[deviceSN] = result.data.public_key; return result.data.public_key; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } } catch (error) { this.log.error("Generic Error:", error); } } return ""; } async getSensorHistory(stationSN, deviceSN) { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/app/get_sensor_history", data: { devicse_sn: deviceSN, max_time: 0, num: 500, page: 0, station_sn: stationSN, transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { const entries = result.data; return entries; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return []; } async getHouseDetail(houseID) { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/house/detail", data: { house_id: houseID, transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { return result.data; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return null; } async getHouseList() { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/house/list", data: { transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { return result.data; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return []; } async getHouseInviteList(isInviter = 1) { //TODO: Understand the other values of isInviter and document it if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/house/invite_list", data: { is_inviter: isInviter, transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { return result.data; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return []; } async confirmHouseInvite(houseID, inviteID) { if (this.connected) { try { const response = await this.request({ method: "post", endpoint: "v1/house/confirm_invite", data: { house_id: houseID, invite_id: inviteID, is_inviter: 1, //user_id: "", transaction: `${new Date().getTime().toString()}` } }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { return true; } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } } return false; } getPersistentData() { return this.persistentData; } async getPassportProfile() { try { const response = await this.request({ method: "get", endpoint: "v1/passport/profile" }); if (response.status == 200) { const result = response.data; if (result.code == types_1.ResponseErrorCode.CODE_WHATEVER_ERROR) { if (result.data) { const profile = result.data; this.persistentData.user_id = profile.user_id; this.persistentData.nick_name = profile.nick_name; this.persistentData.email = profile.email; return profile; } } else { this.log.error("Response code not ok", { code: result.code, msg: result.msg }); } } else { this.log.error("Status return code not 200", { status: response.status, statusText: response.statusText }); } } catch (error) { this.log.error("Generic Error:", error); } return null; } } exports.HTTPApi = HTTPApi; HTTPApi.apiDomainBase = "https://extend.eufylife.com"; //# sourceMappingURL=api.js.map