UNPKG

@hov3rcraft/homebridge-eufy-robovac

Version:
248 lines 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EufyRobovacAccessory = void 0; const robovac_api_1 = require("./robovac-api"); class EufyRobovacAccessory { constructor(platform, accessory, config, log) { this.callbackTimeout = 3000; this.cachingDuration = 60000; this.lowBatteryThreshold = 10; log.debug('Initializing EufyRobovacAccessory...'); this.platform = platform; this.accessory = accessory; this.log = log; this.name = accessory.displayName; this.connectionConfig = { deviceId: config.deviceId, localKey: config.localKey, deviceIp: config.deviceIp }; this.findButtonEnabled = config.findButtonEnabled; this.batteryInformationEnabled = config.batteryInformationEnabled; this.errorSensorEnabled = config.errorSensorEnabled; // set accessory information this.informationService = this.accessory.getService(this.platform.Service.AccessoryInformation); this.informationService.getCharacteristic(this.platform.Characteristic.Identify).onSet(this.setIdentify.bind(this)); this.informationService.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Eufy'); this.informationService.setCharacteristic(this.platform.Characteristic.Model, 'RoboVac'); this.informationService.setCharacteristic(this.platform.Characteristic.Name, this.name); this.informationService.setCharacteristic(this.platform.Characteristic.SerialNumber, config.deviceId); this.informationService.setCharacteristic(this.platform.Characteristic.FirmwareRevision, "unknown"); // create main service for the vacuum cleaner if (config.useSwitchService) { this.vacuumService = this.accessory.getService("Vacuum") || this.accessory.addService(this.platform.Service.Switch, "Vacuum", "VACUUM"); } else { this.vacuumService = this.accessory.getService("Vacuum") || this.accessory.addService(this.platform.Service.Fan, "Vacuum"); } this.vacuumService.getCharacteristic(this.platform.Characteristic.On) .onGet(this.getRunning.bind(this)) .onSet(this.setRunning.bind(this)); // create find robot service if (this.findButtonEnabled) { this.findRobotService = this.accessory.getService("FindRobot") || this.accessory.addService(this.platform.Service.Switch, "FindRobot", "FIND_ROBOT"); this.findRobotService.getCharacteristic(this.platform.Characteristic.On) .onGet(this.getFindRobot.bind(this)) .onSet(this.setFindRobot.bind(this)); } // create battery service if (this.batteryInformationEnabled) { this.batteryService = this.accessory.getService("Battery") || this.accessory.addService(this.platform.Service.Battery, "Battery", "BATTERY"); this.batteryService.getCharacteristic(this.platform.Characteristic.StatusLowBattery) .onGet(this.getLowBattery.bind(this)); this.batteryService.getCharacteristic(this.platform.Characteristic.BatteryLevel) .onGet(this.getBatteryLevel.bind(this)); this.batteryService.getCharacteristic(this.platform.Characteristic.ChargingState) .onGet(this.getCharging.bind(this)); } // create error sensor service if (this.errorSensorEnabled) { this.errorSensorService = this.accessory.getService("ErrorSensor") || this.accessory.addService(this.platform.Service.MotionSensor, "ErrorSensor", "ERROR_SENSOR"); this.errorSensorService.getCharacteristic(this.platform.Characteristic.MotionDetected) .onGet(this.getErrorStatus.bind(this)); } this.roboVac = new robovac_api_1.RoboVac(this.connectionConfig, this.updateCharacteristics.bind(this), this.cachingDuration, this.log); this.log.info('Finished initializing accessory:', this.name); } /** * Handle the "GET" requests from HomeKit * These are sent when HomeKit wants to know the current state of the accessory, for example, checking if a Light bulb is on. */ async getRunning() { this.log.debug(`getRunning for ${this.name}`); try { return await Promise.race([ this.roboVac.getRunning(), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } async getFindRobot() { this.log.debug(`getFindRobot for ${this.name}`); try { return await Promise.race([ this.roboVac.getFindRobot(), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } async getLowBattery() { this.log.debug(`getLowBattery for ${this.name}`); try { const battery_level = await Promise.race([ this.roboVac.getBatteryLevel(), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); return battery_level <= this.lowBatteryThreshold; } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } async getBatteryLevel() { this.log.debug(`getBatteryLevel for ${this.name}`); try { return await Promise.race([ this.roboVac.getBatteryLevel(), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } async getCharging() { this.log.debug(`getCharging for ${this.name}`); try { const work_status = await Promise.race([ this.roboVac.getWorkStatus(), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); return this.workStatusToChargingState(work_status); } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } async getErrorStatus() { this.log.debug(`getErrorStatus for ${this.name}`); try { const error_code = await Promise.race([ this.roboVac.getErrorCode(), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); return error_code !== robovac_api_1.ErrorCode.NO_ERROR; } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } /** * Handle "SET" requests from HomeKit * These are sent when the user changes the state of an accessory, for example, turning on a Light bulb. */ async setRunning(state) { this.log.debug(`setRunning for ${this.name} set to ${state}`); if (!state && this.roboVac.getRunningCached() == false) { // don't send additional "GO HOME" command when already off this.log.debug(`setRunning for ${this.name} set to ${state} received, but not sending GO HOME command because according to cache the device is already off`); return; } try { return await Promise.race([ (state) ? this.roboVac.setPlayPause(true) : this.roboVac.setGoHome(true), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } async setFindRobot(state) { this.log.debug(`setFindRobot for ${this.name} set to ${state}`); try { return await Promise.race([ this.roboVac.setFindRobot(state), new Promise((resolve, reject) => { setTimeout(() => reject(new Error("Request timed out")), this.callbackTimeout); }) ]); } catch (_a) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } /** * Handle requests to set the "Identify" characteristic */ setIdentify(value) { this.log.info('Triggered SET Identify:', value); } updateCharacteristics(statusResponse) { this.log.debug(`updateCharacteristics for ${this.name}`); let counter = 0; if (statusResponse.dps[robovac_api_1.StatusDps.RUNNING] !== undefined) { this.log.debug(`updating ${robovac_api_1.statusDpsFriendlyNames.get(robovac_api_1.StatusDps.RUNNING)} for ${this.name} to ${statusResponse.dps[robovac_api_1.StatusDps.RUNNING]}`); this.vacuumService.updateCharacteristic(this.platform.Characteristic.On, statusResponse.dps[robovac_api_1.StatusDps.RUNNING]); counter++; } if (this.findRobotService && statusResponse.dps[robovac_api_1.StatusDps.FIND_ROBOT] !== undefined) { this.log.debug(`updating ${robovac_api_1.statusDpsFriendlyNames.get(robovac_api_1.StatusDps.FIND_ROBOT)} for ${this.name} to ${statusResponse.dps[robovac_api_1.StatusDps.FIND_ROBOT]}`); this.findRobotService.updateCharacteristic(this.platform.Characteristic.On, statusResponse.dps[robovac_api_1.StatusDps.FIND_ROBOT]); counter++; } if (this.batteryService) { if (statusResponse.dps[robovac_api_1.StatusDps.BATTERY_LEVEL] !== undefined) { this.log.debug(`updating ${robovac_api_1.statusDpsFriendlyNames.get(robovac_api_1.StatusDps.BATTERY_LEVEL)} for ${this.name} to ${statusResponse.dps[robovac_api_1.StatusDps.BATTERY_LEVEL]}`); this.batteryService.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, statusResponse.dps[robovac_api_1.StatusDps.BATTERY_LEVEL] <= this.lowBatteryThreshold); this.batteryService.updateCharacteristic(this.platform.Characteristic.BatteryLevel, statusResponse.dps[robovac_api_1.StatusDps.BATTERY_LEVEL]); counter++; } if (statusResponse.dps[robovac_api_1.StatusDps.WORK_STATUS] !== undefined) { this.log.debug(`updating ${robovac_api_1.statusDpsFriendlyNames.get(robovac_api_1.StatusDps.WORK_STATUS)} for ${this.name} to ${statusResponse.dps[robovac_api_1.StatusDps.WORK_STATUS]}`); this.batteryService.updateCharacteristic(this.platform.Characteristic.ChargingState, this.workStatusToChargingState(statusResponse.dps[robovac_api_1.StatusDps.WORK_STATUS])); counter++; } } if (this.errorSensorService && statusResponse.dps[robovac_api_1.StatusDps.ERROR_CODE] !== undefined) { const is_error = (statusResponse.dps[robovac_api_1.StatusDps.ERROR_CODE] !== robovac_api_1.ErrorCode.NO_ERROR); this.log.debug(`updating Error Sensor status for ${this.name} to ${is_error}`); this.errorSensorService.updateCharacteristic(this.platform.Characteristic.MotionDetected, is_error); if (is_error) this.log.info(`${this.name} reported a device error: ${(0, robovac_api_1.getErrorCodeFriendlyName)(statusResponse.dps[robovac_api_1.StatusDps.ERROR_CODE])}`); counter++; } this.log.debug(`updateCharacteristics for ${this.name} complete - updated ${counter} characteristics.`); } workStatusToChargingState(workStatus) { switch (workStatus) { case robovac_api_1.WorkStatus.CHARGING: case robovac_api_1.WorkStatus.CHARGING_COMPLETED: return this.platform.Characteristic.ChargingState.CHARGING; default: return this.platform.Characteristic.ChargingState.NOT_CHARGING; } } } exports.EufyRobovacAccessory = EufyRobovacAccessory; //# sourceMappingURL=accessory.js.map