UNPKG

homebridge-eufy-security-mikebcbc

Version:
646 lines 32.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EufySecurityPlatform = void 0; const settings_1 = require("./settings"); const StationAccessory_1 = require("./accessories/StationAccessory"); const EntrySensorAccessory_1 = require("./accessories/EntrySensorAccessory"); const MotionSensorAccessory_1 = require("./accessories/MotionSensorAccessory"); const CameraAccessory_1 = require("./accessories/CameraAccessory"); const LockAccessory_1 = require("./accessories/LockAccessory"); const eufy_security_client_1 = require("eufy-security-client"); const tslog_1 = require("tslog"); const rotating_file_stream_1 = require("rotating-file-stream"); const fs_1 = __importDefault(require("fs")); const EufyClientInteractor_1 = require("./utils/EufyClientInteractor"); const node_os_1 = __importDefault(require("node:os")); const node_process_1 = require("node:process"); const node_fs_1 = require("node:fs"); const ffmpeg_for_homebridge_1 = __importDefault(require("ffmpeg-for-homebridge")); const ffmpeg_codecs_1 = require("./utils/ffmpeg-codecs"); class EufySecurityPlatform { constructor(hblog, config, api) { this.hblog = hblog; this.api = api; this.Service = this.api.hap.Service; this.Characteristic = this.api.hap.Characteristic; // this is used to track restored cached accessories this.accessories = []; this.eufyConfig = {}; this.log = {}; this.tsLogger = {}; this.ffmpegLogger = {}; this.already_shutdown = false; this.activeAccessoryIds = []; this.STATION_INIT_DELAY = 5 * 1000; // 5 seconds this.DEVICE_INIT_DELAY = 7 * 1000; // 7 seconds; this._hostSystem = ''; this.verboseFfmpeg = true; this.blackSnapshot = this.readFileSync(settings_1.SnapshotBlackPath); this.SnapshotUnavailable = this.readFileSync(settings_1.SnapshotUnavailablePath); this.config = config; this.eufyPath = this.api.user.storagePath() + '/eufysecurity'; if (!fs_1.default.existsSync(this.eufyPath)) { fs_1.default.mkdirSync(this.eufyPath); } // Identify what we're running on so we can take advantage of hardware-specific features. this.probeHwOs(); this.configureLogger(); this.initSetup(); } configureLogger() { var _a; const plugin = require('../package.json'); const logOptions = { name: (this.config.enableDetailedLogging) ? `[EufySecurity-${plugin.version}]` : '[EufySecurity]', prettyLogTemplate: (this.config.enableDetailedLogging) // eslint-disable-next-line max-len ? '[{{mm}}/{{dd}}/{{yyyy}} {{hh}}:{{MM}}:{{ss}}]\t{{name}}\t{{logLevelName}}\t[{{fileNameWithLine}}]\t' : '[{{mm}}/{{dd}}/{{yyyy}}, {{hh}}:{{MM}}:{{ss}}]\t{{name}}\t{{logLevelName}}\t', prettyErrorTemplate: '\n{{errorName}} {{errorMessage}}\nerror stack:\n{{errorStack}}', prettyErrorStackTemplate: ' • {{fileName}}\t{{method}}\n\t{{fileNameWithLine}}', prettyErrorParentNamesSeparator: ':', prettyErrorLoggerNameDelimiter: '\t', stylePrettyLogs: true, minLevel: (this.config.enableDetailedLogging) ? 2 : 3, prettyLogTimeZone: 'local', prettyLogStyles: { logLevelName: { '*': ['bold', 'black', 'bgWhiteBright', 'dim'], SILLY: ['bold', 'white'], TRACE: ['bold', 'whiteBright'], DEBUG: ['bold', 'green'], INFO: ['bold', 'blue'], WARN: ['bold', 'yellow'], ERROR: ['bold', 'red'], FATAL: ['bold', 'redBright'], }, dateIsoStr: 'gray', filePathWithLine: 'white', name: 'green', nameWithDelimiterPrefix: ['white', 'bold'], nameWithDelimiterSuffix: ['white', 'bold'], errorName: ['bold', 'bgRedBright', 'whiteBright'], fileName: ['yellow'], }, maskValuesOfKeys: [ 'username', 'password', 'serialnumber', 'serialNumber', 'stationSerialNumber', 'data', 'ignoreStations', 'ignoreDevices', ], }; this.log = new tslog_1.Logger(logOptions); this.tsLogger = new tslog_1.Logger({ ...logOptions, type: 'hidden' }); this.ffmpegLogger = new tslog_1.Logger({ ...logOptions, type: 'hidden' }); const omitLogFiles = (_a = this.config.omitLogFiles) !== null && _a !== void 0 ? _a : false; if (omitLogFiles) { this.log.info('log file storage will be omitted.'); } if (!omitLogFiles) { // Log streams configuration const logStreams = [ { name: 'eufy-security.log', logger: this.log }, { name: 'ffmpeg.log', logger: this.ffmpegLogger }, { name: 'eufy-log.log', logger: this.tsLogger }, ]; for (const { name, logger } of logStreams) { const logStream = (0, rotating_file_stream_1.createStream)(name, { path: this.eufyPath, interval: '1d', rotate: 3, maxSize: '200M', }); logger.attachTransport((logObj) => { var _a; const meta = logObj['_meta']; const name = meta.name; const level = meta.logLevelName; const date = meta.date.toISOString(); const fileNameWithLine = ((_a = meta.path) === null || _a === void 0 ? void 0 : _a.fileNameWithLine) || 'UNKNOWN_FILE'; // Initialize the message let message = ''; // Loop through logObj from index 0 to 5 and append values to the message for (let i = 0; i <= 5; i++) { if (logObj[i]) { message += ' ' + typeof logObj[i] === 'string' ? logObj[i] : JSON.stringify(logObj[i]); } } logStream.write(date + '\t' + name + '\t' + level + '\t' + fileNameWithLine + '\t' + message + '\n'); }); } } } // Identify what hardware and operating system environment we're actually running on. probeHwOs() { // Start off with a generic identifier. this._hostSystem = 'generic'; // Take a look at the platform we're on for an initial hint of what we are. switch (node_process_1.platform) { // The beloved macOS. case 'darwin': this._hostSystem = 'macOS.' + (node_os_1.default.cpus()[0].model.includes('Apple') ? 'Apple' : 'Intel'); break; // The indomitable Linux. case 'linux': // Let's further see if we're a small, but scrappy, Raspberry Pi. try { // As of the 4.9 kernel, Raspberry Pi prefers to be identified using this method and has deprecated cpuinfo. const systemId = (0, node_fs_1.readFileSync)('/sys/firmware/devicetree/base/model', { encoding: 'utf8' }); // Is it a Pi 4? if (/Raspberry Pi (Compute Module )?4/.test(systemId)) { this._hostSystem = 'raspbian'; } } catch (error) { // We aren't especially concerned with errors here, given we're just trying to ascertain the system information through hints. } break; default: // We aren't trying to solve for every system type. break; } } // Utility to return the hardware environment we're on. get hostSystem() { return this._hostSystem; } initSetup() { var _a, _b, _c, _d, _e, _f, _g; var _h, _j, _k, _l; this.log.warn('warning: planned changes, see https://github.com/homebridge-eufy-security/plugin/issues/1'); this.log.debug('plugin data store: ' + this.eufyPath); this.log.debug('OS is', this.hostSystem); this.log.debug('Using bropats @homebridge-eufy-security/eufy-security-client library in version ' + eufy_security_client_1.libVersion); this.videoProcessor = ffmpeg_for_homebridge_1.default !== null && ffmpeg_for_homebridge_1.default !== void 0 ? ffmpeg_for_homebridge_1.default : 'ffmpeg'; this.log.info(`ffmpegPath set: ${this.videoProcessor}`); this.clean_config(); this.log.debug('The config is:', this.config); this.eufyConfig = { username: this.config.username, password: this.config.password, country: (_a = this.config.country) !== null && _a !== void 0 ? _a : 'US', trustedDeviceName: (_b = this.config.deviceName) !== null && _b !== void 0 ? _b : 'My Phone', language: 'en', persistentDir: this.eufyPath, p2pConnectionSetup: 0, pollingIntervalMinutes: (_c = this.config.pollingIntervalMinutes) !== null && _c !== void 0 ? _c : 10, eventDurationSeconds: 10, }; this.config.ignoreStations = (_d = (_h = this.config).ignoreStations) !== null && _d !== void 0 ? _d : (_h.ignoreStations = []); this.config.ignoreDevices = (_e = (_j = this.config).ignoreDevices) !== null && _e !== void 0 ? _e : (_j.ignoreDevices = []); this.config.cleanCache = (_f = (_k = this.config).cleanCache) !== null && _f !== void 0 ? _f : (_k.cleanCache = true); this.config.unbridge = (_g = (_l = this.config).unbridge) !== null && _g !== void 0 ? _g : (_l.unbridge = true); this.codecSupport = new ffmpeg_codecs_1.FfmpegCodecs(this); this.log.info(`Country set: ${this.eufyConfig.country}`); // this.log.info(`Codec set: ${JSON.stringify(this.codecSupport)}`); // This function is here to avoid any break while moving from 1.0.x to 1.1.x // moving persistent into our dedicated folder (this need to be removed after few release of 1.1.x) if (fs_1.default.existsSync(this.api.user.storagePath() + '/persistent.json')) { this.log.debug('An old persistent file have been found'); if (!fs_1.default.existsSync(this.eufyPath + '/persistent.json')) { fs_1.default.copyFileSync(this.api.user.storagePath() + '/persistent.json', this.eufyPath + '/persistent.json', fs_1.default.constants.COPYFILE_EXCL); } else { this.log.debug('but the new one is already present'); } fs_1.default.unlinkSync(this.api.user.storagePath() + '/persistent.json'); } // ******** this.api.on("didFinishLaunching" /* APIEvent.DID_FINISH_LAUNCHING */, async () => { this.clean_config_after_init(); await this.pluginSetup(); }); this.api.on("shutdown" /* APIEvent.SHUTDOWN */, async () => { await this.pluginShutdown(); }); this.log.info('Finished initializing!'); } async pluginSetup() { var _a; // First things first - ensure we've got a working video processor before we do anything else. if (!(await this.codecSupport.probe())) { return; } try { this.eufyClient = (this.config.enableDetailedLogging) ? await eufy_security_client_1.EufySecurity.initialize(this.eufyConfig, this.tsLogger) : await eufy_security_client_1.EufySecurity.initialize(this.eufyConfig); this.eufyClient.on('station added', this.stationAdded.bind(this)); this.eufyClient.on('device added', this.deviceAdded.bind(this)); this.eufyClient.on('device removed', this.deviceRemoved.bind(this)); this.eufyClient.on('push connect', () => { this.log.debug('Push Connected!'); }); this.eufyClient.on('push close', () => { this.log.debug('Push Closed!'); }); this.eufyClient.on('connect', () => { this.log.debug('Connected!'); }); this.eufyClient.on('close', () => { this.log.debug('Closed!'); }); this.eufyClient.on('connection error', async (error) => { this.log.debug(`Error: ${error}`); await this.pluginShutdown(); }); this.eufyClient.once('captcha request', async (id, captcha) => { this.log.error(` *************************** ***** WARNING MESSAGE ***** *************************** Important Notice: CAPTCHA Required Your account seems to have triggered a security measure that requires CAPTCHA verification for the next 24 hours... Please abstain from any activities until this period elapses... Should your issue persist beyond this timeframe, you may need to consider setting up a new account. For more detailed instructions, please consult: https://github.com/homebridge-eufy-security/plugin/wiki/Create-a-dedicated-admin-account-for-Homebridge-Eufy-Security-Plugin *************************** `); await this.pluginShutdown(); }); this.eufyClient.on('tfa request', async () => { this.log.error(` *************************** ***** WARNING MESSAGE ***** *************************** Attention: Two-Factor Authentication (2FA) Requested It appears that your account is currently under a temporary 24-hour flag for security reasons... Kindly refrain from making any further attempts during this period... If your concern remains unresolved after 24 hours, you may need to consider creating a new account. For additional information, refer to: https://github.com/homebridge-eufy-security/plugin/wiki/Create-a-dedicated-admin-account-for-Homebridge-Eufy-Security-Plugin *************************** `); await this.pluginShutdown(); }); } catch (e) { this.log.error(`Error while setup : ${e}`); this.log.error('Not connected can\'t continue!'); return; } try { await this.eufyClient.connect(); this.log.debug('EufyClient connected ' + this.eufyClient.isConnected()); } catch (e) { this.log.error(`Error authenticating Eufy: ${e}`); } if (!this.eufyClient.isConnected()) { this.log.error('Not connected can\'t continue!'); return; } // give the connection 45 seconds to discover all devices // clean old accessories after that time this.cleanCachedAccessoriesTimeout = setTimeout(() => { this.cleanCachedAccessories(); }, 45 * 1000); let cameraMaxLivestreamDuration = (_a = this.config.CameraMaxLivestreamDuration) !== null && _a !== void 0 ? _a : 30; if (cameraMaxLivestreamDuration > 86400) { cameraMaxLivestreamDuration = 86400; // eslint-disable-next-line max-len this.log.warn('Your maximum livestream duration value is too large. Since this can cause problems it was reset to 86400 seconds (1 day maximum).'); } this.eufyClient.setCameraMaxLivestreamDuration(cameraMaxLivestreamDuration); this.log.debug(`CameraMaxLivestreamDuration: ${this.eufyClient.getCameraMaxLivestreamDuration()}`); try { this.pluginConfigInteractor = new EufyClientInteractor_1.EufyClientInteractor(this.eufyPath, this.log, this.eufyClient); await this.pluginConfigInteractor.setupServer(); } catch (err) { this.log.warn(err); } } generateUUID(identifier, type) { const prefix = type === eufy_security_client_1.DeviceType.STATION ? '' : 's_'; return this.api.hap.uuid.generate(prefix + identifier); } async delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async addOrUpdateAccessory(deviceContainer, isStation) { try { const uuid = this.generateUUID(deviceContainer.deviceIdentifier.uniqueId, deviceContainer.deviceIdentifier.type); const cachedAccessory = this.accessories.find((accessory) => accessory.UUID === uuid); let unbridge = false; if (cachedAccessory) { this.accessories.splice(this.accessories.indexOf(cachedAccessory), 1); // Remove from the accessories array } const accessory = cachedAccessory || new this.api.platformAccessory(deviceContainer.deviceIdentifier.displayName, uuid); accessory.context['device'] = deviceContainer.deviceIdentifier; if (isStation) { this.register_station(accessory, deviceContainer); } else { unbridge = this.register_device(accessory, deviceContainer); } if (cachedAccessory) { if (!unbridge) { // Rule: if a device exists and it's not a camera this.api.updatePlatformAccessories([accessory]); this.log.info(`Updating existing accessory: ${accessory.displayName}`); } else if (this.config.unbridge) { // Rule: if a device exists, it's a camera, and unbridge is true this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]); this.log.info(`Unregistering unbridged accessory: ${accessory.displayName}`); } } else { if (!unbridge) { // Rule: if a device doesn't exist and it's not a camera this.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]); this.log.info(`Registering new accessory: ${accessory.displayName}`); } else { if (this.config.unbridge) { // Rule: if a device doesn't exist, it's a camera, and unbridge is true this.api.publishExternalAccessories(settings_1.PLUGIN_NAME, [accessory]); this.log.info(`Publishing unbridged accessory externally: ${accessory.displayName}`); } else { // Rule: if a device doesn't exist, it's a camera, and unbridge is false this.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]); this.log.info(`Registering new accessory: ${accessory.displayName}`); } } } } catch (error) { this.log.error(`Error in ${isStation ? 'stationAdded' : 'deviceAdded'}: ${error}`); } } async stationAdded(station) { try { if (this.config.ignoreStations.includes(station.getSerial())) { this.log.debug(`${station.getName()}: Station ignored`); return; } const rawStation = station.getRawStation(); if (rawStation.member.member_type !== eufy_security_client_1.UserType.ADMIN) { await this.pluginShutdown(); this.log.error(` ######################### ######### ERROR ######### ######################### You're not using a guest admin account with this plugin! You must use a guest admin account! Please look here for more details: https://github.com/homebridge-eufy-security/plugin/wiki/Create-a-dedicated-admin-account-for-Homebridge-Eufy-Security-Plugin ######################### `); return; } const deviceContainer = { deviceIdentifier: { uniqueId: station.getSerial(), displayName: station.getName(), type: station.getDeviceType(), }, eufyDevice: station, }; await this.delay(this.STATION_INIT_DELAY); this.log.debug(`${deviceContainer.deviceIdentifier.displayName} pre-caching complete`); this.addOrUpdateAccessory(deviceContainer, true); } catch (error) { this.log.error(`Error in stationAdded:, ${error}`); } } async deviceAdded(device) { try { if (this.config.ignoreDevices.includes(device.getSerial())) { this.log.debug(`${device.getName()}: Device ignored`); return; } const deviceContainer = { deviceIdentifier: { uniqueId: device.getSerial(), displayName: device.getName(), type: device.getDeviceType(), }, eufyDevice: device, }; await this.delay(this.DEVICE_INIT_DELAY); this.log.debug(`${deviceContainer.deviceIdentifier.displayName} pre-caching complete`); this.addOrUpdateAccessory(deviceContainer, false); } catch (error) { this.log.error(`Error in deviceAdded: ${error}`); } } async deviceRemoved(device) { const serial = device.getSerial(); this.log.debug(`A device has been removed: ${serial}`); if (this.config.ignoreDevices.indexOf(device.getSerial()) !== -1) { this.log.debug('Device ignored'); return; } const deviceContainer = { deviceIdentifier: { uniqueId: device.getSerial(), displayName: device.getName(), type: device.getDeviceType(), }, eufyDevice: device, }; // this.processAccessory(deviceContainer); } async pluginShutdown() { // Ensure a single shutdown to prevent corruption of the persistent file. // This also enables captcha through the GUI and prevents repeated captcha or 2FA prompts upon plugin restart. if (this.already_shutdown) { return; } this.already_shutdown = true; if (this.cleanCachedAccessoriesTimeout) { clearTimeout(this.cleanCachedAccessoriesTimeout); } if (this.pluginConfigInteractor) { this.pluginConfigInteractor.stopServer(); } try { this.eufyClient.close(); this.log.info('Finished shutdown!'); } catch (e) { this.log.error(`Error while shutdown: ${e}`); } } /** * This function is invoked when homebridge restores cached accessories from disk at startup. * It should be used to setup event handlers for characteristics and update respective values. */ configureAccessory(accessory) { this.log.debug(`Loading accessory from cache: ${accessory.displayName}`); // add the restored accessory to the accessories cache so we can track if it has already been registered this.accessories.push(accessory); } cleanCachedAccessories() { if (this.config.cleanCache) { this.log.info('Looking for old cached accessories that seem to be outdated...'); let num = 0; const staleAccessories = this.accessories.filter((item) => { return this.activeAccessoryIds.indexOf(item.UUID) === -1; }); staleAccessories.forEach((staleAccessory) => { this.log.info(`Removing cached accessory ${staleAccessory.UUID} ${staleAccessory.displayName}`); num++; this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [staleAccessory]); }); if (num > 0) { this.log.info('Removed ' + num + ' cached accessories'); } else { this.log.info('No outdated cached accessories found.'); } } } register_station(accessory, container) { this.log.debug(accessory.displayName + ' UUID:' + accessory.UUID); const type = container.deviceIdentifier.type; const station = container.eufyDevice; if (type !== eufy_security_client_1.DeviceType.STATION) { // Allowing camera but not the lock nor doorbell for now if ((type === eufy_security_client_1.DeviceType.LOCK_BLE || type === eufy_security_client_1.DeviceType.LOCK_WIFI || type === eufy_security_client_1.DeviceType.LOCK_BLE_NO_FINGER || type === eufy_security_client_1.DeviceType.LOCK_WIFI_NO_FINGER || type === eufy_security_client_1.DeviceType.DOORBELL || type === eufy_security_client_1.DeviceType.BATTERY_DOORBELL || type === eufy_security_client_1.DeviceType.BATTERY_DOORBELL_2 || type === eufy_security_client_1.DeviceType.BATTERY_DOORBELL_PLUS || type === eufy_security_client_1.DeviceType.DOORBELL_SOLO)) { this.log.warn(`${accessory.displayName} looks station but it's not could imply some errors! Type: ${type}`); return; } } new StationAccessory_1.StationAccessory(this, accessory, station); } register_device(accessory, container) { this.log.debug(accessory.displayName + ' UUID:' + accessory.UUID); const device = container.eufyDevice; if (device.isMotionSensor()) { this.log.debug(accessory.displayName + ' isMotionSensor!'); new MotionSensorAccessory_1.MotionSensorAccessory(this, accessory, device); } if (device.isEntrySensor()) { this.log.debug(accessory.displayName + ' isEntrySensor!'); new EntrySensorAccessory_1.EntrySensorAccessory(this, accessory, device); } if (device.isLock()) { this.log.debug(accessory.displayName + ' isLock!'); new LockAccessory_1.LockAccessory(this, accessory, device); } if (device.isCamera()) { this.log.debug(accessory.displayName + ' isCamera!'); new CameraAccessory_1.CameraAccessory(this, accessory, device); return true; } return false; } getStationById(id) { return this.eufyClient.getStation(id); } clean_config() { try { const currentConfig = JSON.parse(fs_1.default.readFileSync(this.api.user.configPath(), 'utf8')); // check the platforms section is an array before we do array things on it if (!Array.isArray(currentConfig.platforms)) { throw new Error('Cannot find platforms array in config'); } // find this plugins current config const pluginConfig = currentConfig.platforms.find((x) => x.platform === settings_1.PLATFORM_NAME); if (!pluginConfig) { throw new Error(`Cannot find config for ${settings_1.PLATFORM_NAME} in platforms array`); } // Cleaning space const i = ['hkHome', 'hkAway', 'hkNight', 'hkOff', 'pollingIntervalMinutes', 'CameraMaxLivestreamDuration']; Object.entries(pluginConfig).forEach(([key, value]) => { if (!i.includes(key)) { return; } pluginConfig[key] = (typeof pluginConfig[key] === 'string') ? parseInt(value) : value; }); // End of Cleaning space // Applying clean and save it this.config = pluginConfig; fs_1.default.writeFileSync(this.api.user.configPath(), JSON.stringify(currentConfig, null, 4)); } catch (e) { this.log.error('Error cleaning config: ' + e); } } // this needs to be called after api did finished launching so that cached accessories are already loaded clean_config_after_init() { var _a, _b, _c; var _d, _e, _f; try { const currentConfig = JSON.parse(fs_1.default.readFileSync(this.api.user.configPath(), 'utf8')); // check the platforms section is an array before we do array things on it if (!Array.isArray(currentConfig.platforms)) { throw new Error('Cannot find platforms array in config'); } // find this plugins current config const pluginConfig = currentConfig.platforms.find((x) => x.platform === settings_1.PLATFORM_NAME); if (!pluginConfig) { throw new Error(`Cannot find config for ${settings_1.PLATFORM_NAME} in platforms array`); } // Cleaning space // clean device specific parametes const cameras = (Array.isArray(pluginConfig.cameras)) ? pluginConfig.cameras : null; if (cameras && this.accessories.length > 0) { for (let i = 0; i < cameras.length; i++) { const camera = cameras[i]; const cachedAccessory = this.accessories.find((acc) => camera.serialNumber === acc.context['device'].uniqueId); if (cachedAccessory && eufy_security_client_1.Device.isDoorbell(cachedAccessory.context['device'].type) && !camera.enableCamera) { // eslint-disable-next-line max-len this.log.warn('Found camera ' + cachedAccessory.context['device'].displayName + ' (' + cachedAccessory.context['device'].uniqueId + ') with invalid camera configuration option enableCamera. Attempt to repair. This should only happen once per device...'); pluginConfig.cameras[i]['enableCamera'] = true; // if (camera.unbridge) { // eslint-disable-next-line max-len // this.log.warn('Camera ' + cachedAccessory.context['device'].displayName + ' (' + cachedAccessory.context['device'].uniqueId + ') had camera configuration option \'unbridge\' set to true. This will be set to false to maintain functionality. See https://github.com/homebridge-eufy-security/plugin/issues/79 for more information.'); // pluginConfig.cameras[i]['unbridge'] = false; // } } } } // End of Cleaning space // Applying clean and save it this.config = pluginConfig; this.config.ignoreStations = (_a = (_d = this.config).ignoreStations) !== null && _a !== void 0 ? _a : (_d.ignoreStations = []); this.config.ignoreDevices = (_b = (_e = this.config).ignoreDevices) !== null && _b !== void 0 ? _b : (_e.ignoreDevices = []); this.config.cleanCache = (_c = (_f = this.config).cleanCache) !== null && _c !== void 0 ? _c : (_f.cleanCache = true); fs_1.default.writeFileSync(this.api.user.configPath(), JSON.stringify(currentConfig, null, 4)); } catch (e) { this.log.error('Error cleaning config: ' + e); } } /** * Reads a file synchronously and returns its buffer. * Also lists the contents of the current directory. * @param filepath - The path to the file to read. * @returns The file buffer. * @throws An error if the file cannot be read. */ readFileSync(filepath) { try { filepath = __dirname + filepath; // Read and return the file buffer return fs_1.default.readFileSync(filepath); } catch (error) { throw new Error(`We could not cache ${filepath} file for further use: ${error}`); } } } exports.EufySecurityPlatform = EufySecurityPlatform; //# sourceMappingURL=platform.js.map