diff --git a/accessories/neatVacuumRobot.js b/accessories/neatVacuumRobot.js new file mode 100644 index 0000000..ff5e649 --- /dev/null +++ b/accessories/neatVacuumRobot.js @@ -0,0 +1,552 @@ +const debug = require('debug')('homebridge-neato'); + +let Service, + Characteristic; + +module.exports = function (_Service, _Characteristic) +{ + Service = _Service; + Characteristic = _Characteristic; + + return NeatoVacuumRobotAccessory; +}; + +function NeatoVacuumRobotAccessory(robot, platform, boundary = undefined) +{ + this.platform = platform; + this.boundary = boundary; + this.log = platform.log; + this.refresh = platform.refresh; + this.hiddenServices = platform.hiddenServices; + this.robot = robot; + + if (typeof boundary === 'undefined') + { + this.name = robot.name; + } + else + { + // if boundary name already exists + if (platform.boundaryNames.includes(this.boundary.name)) + { + let lastChar = this.boundary.name.slice(-1); + // boundary name already contains a count number + if (!isNaN(lastChar)) + { + // Increment existing count number + this.boundary.name = this.boundary.name.slice(0, -1) + (parseInt(lastChar) + 1); + } + else + { + // Add a new count number + this.boundary.name = this.boundary.name + " 2"; + } + } + platform.boundaryNames.push(this.boundary.name); + this.name = this.robot.name + ' - ' + this.boundary.name; + } + this.lastUpdate = null; + + this.vacuumRobotBatteryService = new Service.BatteryService("Battery", "battery"); + + if (typeof boundary === 'undefined') + { + this.vacuumRobotCleanService = new Service.Switch("Clean", "clean"); + this.vacuumRobotGoToDockService = new Service.Switch(this.name + " Go to Dock", "goToDock"); + this.vacuumRobotDockStateService = new Service.OccupancySensor(this.name + " Dock", "dockState"); + this.vacuumRobotEcoService = new Service.Switch(this.name + " Eco Mode", "eco"); + this.vacuumRobotNoGoLinesService = new Service.Switch(this.name + " NoGo Lines", "noGoLines"); + this.vacuumRobotExtraCareService = new Service.Switch(this.name + " Extra Care", "extraCare"); + this.vacuumRobotScheduleService = new Service.Switch(this.name + " Schedule", "schedule"); + } + else + { + const splitName = boundary.name.split(' '); + let serviceName = "Clean the " + boundary.name; + if (splitName.length >= 2 && splitName[splitName.length - 2].match(/[']s$/g)) + { + serviceName = "Clean " + boundary.name; + } + this.vacuumRobotCleanBoundaryService = + new Service.Switch(serviceName, "cleanBoundary:" + boundary.id); + this.log("Adding zone cleaning for: " + boundary.name); + } + + this.updateRobotTimer(); +} + +NeatoVacuumRobotAccessory.prototype = { + identify: function (callback) + { + let that = this; + this.updateRobot(function () + { + // hide serial and secret in log + let _serial = that.robot._serial; + let _secret = that.robot._secret; + that.robot._serial = "*****"; + that.robot._secret = "*****"; + that.log(that.robot); + that.robot._serial = _serial; + that.robot._secret = _secret; + }); + }, + + getServices: function () + { + this.informationService = new Service.AccessoryInformation(); + this.informationService + .setCharacteristic(Characteristic.Manufacturer, "Neato Robotics") + .setCharacteristic(Characteristic.Model, "Coming soon") + .setCharacteristic(Characteristic.SerialNumber, this.robot._serial); + if (!this.boundary) + { + this.informationService + .setCharacteristic(Characteristic.Name, this.robot.name) + } + else + { + this.informationService + .setCharacteristic(Characteristic.Name, this.robot.name + ' - ' + this.boundary.name) + } + + this.vacuumRobotBatteryService.getCharacteristic(Characteristic.BatteryLevel).on('get', this.getBatteryLevel.bind(this)); + this.vacuumRobotBatteryService.getCharacteristic(Characteristic.ChargingState).on('get', this.getBatteryChargingState.bind(this)); + + this.services = [this.informationService, this.vacuumRobotBatteryService]; + + if (!this.boundary) + { + this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('set', this.setClean.bind(this)); + this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('get', this.getClean.bind(this)); + + this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('set', this.setGoToDock.bind(this)); + this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('get', this.getGoToDock.bind(this)); + + this.vacuumRobotDockStateService.getCharacteristic(Characteristic.OccupancyDetected).on('get', this.getDock.bind(this)); + + this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('set', this.setEco.bind(this)); + this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('get', this.getEco.bind(this)); + + this.vacuumRobotNoGoLinesService.getCharacteristic(Characteristic.On).on('set', this.setNoGoLines.bind(this)); + this.vacuumRobotNoGoLinesService.getCharacteristic(Characteristic.On).on('get', this.getNoGoLines.bind(this)); + + this.vacuumRobotExtraCareService.getCharacteristic(Characteristic.On).on('set', this.setExtraCare.bind(this)); + this.vacuumRobotExtraCareService.getCharacteristic(Characteristic.On).on('get', this.getExtraCare.bind(this)); + + this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('set', this.setSchedule.bind(this)); + this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('get', this.getSchedule.bind(this)); + + this.services.push(this.vacuumRobotCleanService); + + if (this.hiddenServices.indexOf('dock') === -1) + this.services.push(this.vacuumRobotGoToDockService); + if (this.hiddenServices.indexOf('dockstate') === -1) + this.services.push(this.vacuumRobotDockStateService); + if (this.hiddenServices.indexOf('eco') === -1) + this.services.push(this.vacuumRobotEcoService); + if (this.hiddenServices.indexOf('nogolines') === -1) + this.services.push(this.vacuumRobotNoGoLinesService); + if (this.hiddenServices.indexOf('extracare') === -1) + this.services.push(this.vacuumRobotExtraCareService); + if (this.hiddenServices.indexOf('schedule') === -1) + this.services.push(this.vacuumRobotScheduleService); + } + + if (this.boundary) + { + this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).on('set', (on, serviceCallback) => + { + this.setClean(on, serviceCallback, this.boundary) + }); + this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).on('get', (serviceCallback) => + { + this.getClean(serviceCallback, this.boundary); + }); + this.services.push(this.vacuumRobotCleanBoundaryService); + } + + return this.services; + }, + + + getClean: function (callback, boundary) + { + this.updateRobot((error, result) => + { + let cleaning; + if (typeof boundary === 'undefined') + { + cleaning = this.robot.canPause; + } + else + { + cleaning = this.robot.canPause && (this.robot.cleaningBoundaryId === boundary.id) + } + + debug(this.name + ": Is cleaning: " + cleaning); + callback(false, cleaning); + }); + }, + + setClean: function (on, callback, boundary) + { + this.updateRobot((error, result) => + { + // Start + if (on) + { + // No room given or same room + if (typeof boundary === 'undefined' || this.robot.cleaningBoundaryId === boundary.id) + { + // Resume cleaning + if (this.robot.canResume) + { + debug(this.name + ": Resume cleaning"); + this.robot.resumeCleaning(callback); + } + // Start cleaning + else if (this.robot.canStart) + { + this.clean(callback, boundary); + } + // Cannot start + else + { + debug(this.name + ": Cannot start, maybe already cleaning"); + callback(); + } + } + // Different room given + else + { + // Stop current (running or paused) cleaning of old room + if (this.robot.canPause || this.robot.canResume) + { + debug(this.name + ": Stop cleaning to start cleaning of new room"); + this.robot.stopCleaning((error, result) => + { + setTimeout(() => + { + this.clean(callback, boundary); + }, 1000); + }); + } + // Start new cleaning of new room + else + { + this.clean(callback, boundary); + } + } + } + // Stop + else + { + if (this.robot.canPause) + { + debug(this.name + ": Pause cleaning"); + this.robot.pauseCleaning(callback); + } + else + { + debug(this.name + ": Already stopped"); + callback(); + } + } + }); + }, + + clean: function (callback, boundaryId) + { + // Start automatic update while cleaning + if (this.refresh === 'auto') + { + setTimeout(() => + { + clearTimeout(this.timer); + this.updateRobotTimer(); + }, 60 * 1000); + } + + + let eco = this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).value; + let extraCare = this.vacuumRobotExtraCareService.getCharacteristic(Characteristic.On).value; + let nogoLines = this.vacuumRobotNoGoLinesService.getCharacteristic(Characteristic.On).value; + let room = typeof boundary === 'undefined' ? '' : boundary.name; + debug(that.name + ": Start cleaning (" + room + " eco: " + eco + ", extraCare: " + extraCare + ", nogoLines: " + nogoLines + ")"); + + // Normal cleaning + if (typeof boundary === 'undefined') + { + this.robot.startCleaning( + eco, + extraCare ? 2 : 1, + nogoLines, + (error, result) => + { + if (error) + { + this.log.error("Cannot start cleaning. " + error + ": " + JSON.stringify(result)); + callback(true); + } + else + { + callback(); + } + }); + } + // Room cleaning + else + { + this.robot.startCleaningBoundary(eco, extraCare, boundary.id, (error, result) => + { + if (error) + { + this.log.error("Cannot start room cleaning. " + error + ": " + JSON.stringify(result)); + callback(true); + } + else + { + callback(); + } + }); + } + }, + + getGoToDock: function (callback) + { + callback(false, false); + }, + + setGoToDock: function (on, callback) + { + let that = this; + this.updateRobot(function (error, result) + { + if (on) + { + if (that.robot.canPause) + { + debug(that.name + ": Pause cleaning to go to dock"); + that.robot.pauseCleaning(function (error, result) + { + setTimeout(function () + { + debug(that.name + ": Go to dock"); + that.robot.sendToBase(callback); + }, 1000); + }); + } + else if (that.robot.canGoToBase) + { + debug(that.name + ": Go to dock"); + that.robot.sendToBase(callback); + } + else + { + that.log.warn(that.name + ": Can't go to dock at the moment"); + callback(); + } + } + else + { + callback(); + } + }); + }, + + getEco: function (callback) + { + let that = this; + this.updateRobot(function () + { + debug(that.name + ": Eco mode is " + (that.robot.eco ? 'ON' : 'OFF')); + callback(false, that.robot.eco); + }); + }, + + setEco: function (on, callback) + { + this.robot.eco = on; + debug(this.name + ": " + (on ? "Enabled" : "Disabled") + " Eco mode "); + callback(); + }, + + getNoGoLines: function (callback) + { + let that = this; + this.updateRobot(function () + { + debug(that.name + ": Nogo Lines are " + (that.robot.eco ? 'ON' : 'OFF')); + callback(false, that.robot.noGoLines ? 1 : 0); + }); + }, + + setNoGoLines: function (on, callback) + { + this.robot.noGoLines = on; + debug(this.name + ": " + (on ? "Enabled" : "Disabled") + " Nogo lines "); + callback(); + }, + + getExtraCare: function (callback) + { + let that = this; + this.updateRobot(function () + { + debug(that.name + ": Extra Care Navigation is " + (that.robot.navigationMode == 2 ? 'ON' : 'OFF')); + callback(false, that.robot.navigationMode == 2 ? 1 : 0); + }); + }, + + setExtraCare: function (on, callback) + { + this.robot.navigationMode = on ? 2 : 1; + debug(this.name + ": " + (on ? "Enabled" : "Disabled") + " Extra Care Navigation "); + callback(); + }, + + getSchedule: function (callback) + { + let that = this; + this.updateRobot(function () + { + debug(that.name + ": Schedule is " + (that.robot.eco ? 'ON' : 'OFF')); + callback(false, that.robot.isScheduleEnabled); + }); + }, + + setSchedule: function (on, callback) + { + let that = this; + this.updateRobot(function (error, result) + { + if (on) + { + debug(that.name + ": Enabled Schedule"); + that.robot.enableSchedule(callback); + } + else + { + debug(that.name + ": Disabled Schedule"); + that.robot.disableSchedule(callback); + } + }); + }, + + getDock: function (callback) + { + let that = this; + this.updateRobot(function () + { + debug(that.name + ": Is " + (that.robot.isDocked ? '' : 'not ') + "docked"); + callback(false, that.robot.isDocked ? 1 : 0); + }); + }, + + getBatteryLevel: function (callback) + { + let that = this; + this.updateRobot(function () + { + debug(that.name + ": Battery is at " + that.robot.charge + "%"); + callback(false, that.robot.charge); + }); + }, + + getBatteryChargingState: function (callback) + { + let that = this; + this.updateRobot(function () + { + debug(that.name + ": Is " + (that.robot.isCharging ? '' : 'not ') + "charging"); + callback(false, that.robot.isCharging); + }); + }, + + updateRobot: function (callback) + { + let that = this; + if (this.lastUpdate !== null && new Date() - this.lastUpdate < 2000) + { + callback(); + } + else + { + debug(this.name + ": Updating robot state"); + this.robot.getState(function (error, result) + { + if (error) + { + that.log.error("Cannot update robot. Check if robot is online. " + error); + } + that.lastUpdate = new Date(); + callback(); + }); + } + }, + + updateRobotTimer: function () + { + let that = this; + this.updateRobot((error, result) => + { + + if (!this.boundary) + { + // only update these values if the state is different from the current one, otherwise we might accidentally start an action + if (that.vacuumRobotCleanService.getCharacteristic(Characteristic.On).value !== that.robot.canPause) + { + that.vacuumRobotCleanService.setCharacteristic(Characteristic.On, that.robot.canPause); + } + + // dock switch is on (dock not seen before) and dock has just been seen -> turn switch off + if (that.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).value == true && that.robot.dockHasBeenSeen) + { + that.vacuumRobotGoToDockService.setCharacteristic(Characteristic.On, false); + } + + if (that.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).value !== that.robot.isScheduleEnabled) + { + that.vacuumRobotScheduleService.setCharacteristic(Characteristic.On, that.robot.isScheduleEnabled); + } + + // no commands here, values can be updated without problems + that.vacuumRobotDockStateService.setCharacteristic(Characteristic.OccupancyDetected, that.robot.isDocked ? 1 : 0); + that.vacuumRobotEcoService.setCharacteristic(Characteristic.On, that.robot.eco); + that.vacuumRobotNoGoLinesService.setCharacteristic(Characteristic.On, that.robot.noGoLines); + that.vacuumRobotExtraCareService.setCharacteristic(Characteristic.On, that.robot.navigationMode == 2 ? true : false); + + } + else + { + if (this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).value !== that.robot.canPause) + { + this.vacuumRobotCleanBoundaryService.setCharacteristic(Characteristic.On, that.robot.canPause); + } + } + + that.vacuumRobotBatteryService.setCharacteristic(Characteristic.BatteryLevel, that.robot.charge); + that.vacuumRobotBatteryService.setCharacteristic(Characteristic.ChargingState, that.robot.isCharging); + + // robot is currently cleaning, refresh is set to auto or specific interval -> continue updating + if (that.robot.canPause && that.refresh !== 0) + { + let refreshTime = that.refresh === 'auto' ? 60 : that.refresh; + debug(that.name + ": Updating state in background every " + refreshTime + " seconds while cleaning"); + that.timer = setTimeout(that.updateRobotTimer.bind(that), refreshTime * 1000); + } + // robot is not cleaning, but a specific refresh interval is set -> continue updating + else if (that.refresh !== 'auto' && that.refresh !== 0) + { + debug(that.name + ": Updating state in background every " + that.refresh + " seconds (user setting)"); + that.timer = setTimeout(that.updateRobotTimer.bind(that), that.refresh * 1000); + } + // robot is not cleaning, no specific refresh interval is set -> stop updating + else + { + debug(that.name + ": Disabled background updates"); + } + }); + }, +}; \ No newline at end of file diff --git a/index.js b/index.js index 3740344..bc5a3a9 100644 --- a/index.js +++ b/index.js @@ -42,17 +42,20 @@ NeatoVacuumRobotPlatform.prototype = { accessories: function (callback) { let accessories = []; - let that = this; - that.boundaryNames = []; + let platform = this; + platform.boundaryNames = []; this.getRobots(function () { - if (that.robots) + if (platform.robots) { - that.robots.forEach((robot, i) => + platform.robots.forEach((robot, i) => { - that.log("Found robot #" + (i + 1) + " named \"" + robot.name + "\" with serial \"" + robot._serial + "\""); - let robotAccessory = new NeatoVacuumRobotAccessory(robot, that); + platform.log("Found robot #" + (i + 1) + " named \"" + robot.name + "\" with serial \"" + robot._serial + "\""); + + let NeatoVacuumRobotAccessory = require('./accessories/neatVacuumRobot')(Service, Characteristic); + let robotAccessory = new NeatoVacuumRobotAccessory(robot, platform); accessories.push(robotAccessory); + if (robot.maps) { robot.maps.forEach((map) => @@ -63,7 +66,7 @@ NeatoVacuumRobotPlatform.prototype = { { if (boundary.type === "polygon") { - accessories.push(new NeatoVacuumRobotAccessory(robot, that, boundary)) + accessories.push(new NeatoVacuumRobotAccessory(robot, platform, boundary)) } }) } @@ -158,530 +161,4 @@ NeatoVacuumRobotPlatform.prototype = { } }); } -}; - -function NeatoVacuumRobotAccessory(robot, platform, boundary) -{ - this.platform = platform; - this.boundary = boundary; - this.log = platform.log; - this.refresh = platform.refresh; - this.hiddenServices = platform.hiddenServices; - this.robot = robot; - if (!this.boundary) - { - this.name = robot.name; - } - else - { - // if boundary name already exists - if (platform.boundaryNames.includes(this.boundary.name)) - { - let lastChar = this.boundary.name.slice(-1); - // boundary name already contains a count number - if (!isNaN(lastChar)) - { - // Increment existing count number - this.boundary.name = this.boundary.name.slice(0, -1) + (parseInt(lastChar) + 1); - } - else - { - // Add a new count number - this.boundary.name = this.boundary.name + " 2"; - } - } - platform.boundaryNames.push(this.boundary.name); - this.name = this.robot.name + ' - ' + this.boundary.name; - } - this.lastUpdate = null; - - this.vacuumRobotBatteryService = new Service.BatteryService("Battery", "battery"); - - if (!this.boundary) - { - this.vacuumRobotCleanService = new Service.Switch("Clean", "clean"); - this.vacuumRobotGoToDockService = new Service.Switch(this.name + " Go to Dock", "goToDock"); - this.vacuumRobotDockStateService = new Service.OccupancySensor(this.name + " Dock", "dockState"); - this.vacuumRobotEcoService = new Service.Switch(this.name + " Eco Mode", "eco"); - this.vacuumRobotNoGoLinesService = new Service.Switch(this.name + " NoGo Lines", "noGoLines"); - this.vacuumRobotExtraCareService = new Service.Switch(this.name + " Extra Care", "extraCare"); - this.vacuumRobotScheduleService = new Service.Switch(this.name + " Schedule", "schedule"); - } - else - { - const splitName = boundary.name.split(' '); - let serviceName = "Clean the " + boundary.name; - if (splitName.length >= 2 && splitName[splitName.length - 2].match(/[']s$/g)) - { - serviceName = "Clean " + boundary.name; - } - this.vacuumRobotCleanBoundaryService = - new Service.Switch(serviceName, "cleanBoundary:" + boundary.id); - this.log("Adding zone cleaning for: " + boundary.name); - } - - this.updateRobotTimer(); -} - - -NeatoVacuumRobotAccessory.prototype = { - identify: function (callback) - { - let that = this; - this.updateRobot(function () - { - // hide serial and secret in log - let _serial = that.robot._serial; - let _secret = that.robot._secret; - that.robot._serial = "*****"; - that.robot._secret = "*****"; - that.log(that.robot); - that.robot._serial = _serial; - that.robot._secret = _secret; - }); - }, - - getServices: function () - { - this.informationService = new Service.AccessoryInformation(); - this.informationService - .setCharacteristic(Characteristic.Manufacturer, "Neato Robotics") - .setCharacteristic(Characteristic.Model, "Coming soon") - .setCharacteristic(Characteristic.SerialNumber, this.robot._serial); - if (!this.boundary) - { - this.informationService - .setCharacteristic(Characteristic.Name, this.robot.name) - } - else - { - this.informationService - .setCharacteristic(Characteristic.Name, this.robot.name + ' - ' + this.boundary.name) - } - - this.vacuumRobotBatteryService.getCharacteristic(Characteristic.BatteryLevel).on('get', this.getBatteryLevel.bind(this)); - this.vacuumRobotBatteryService.getCharacteristic(Characteristic.ChargingState).on('get', this.getBatteryChargingState.bind(this)); - - this.services = [this.informationService, this.vacuumRobotBatteryService]; - - if (!this.boundary) - { - this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('set', this.setClean.bind(this)); - this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('get', this.getClean.bind(this)); - - this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('set', this.setGoToDock.bind(this)); - this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('get', this.getGoToDock.bind(this)); - - this.vacuumRobotDockStateService.getCharacteristic(Characteristic.OccupancyDetected).on('get', this.getDock.bind(this)); - - this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('set', this.setEco.bind(this)); - this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('get', this.getEco.bind(this)); - - this.vacuumRobotNoGoLinesService.getCharacteristic(Characteristic.On).on('set', this.setNoGoLines.bind(this)); - this.vacuumRobotNoGoLinesService.getCharacteristic(Characteristic.On).on('get', this.getNoGoLines.bind(this)); - - this.vacuumRobotExtraCareService.getCharacteristic(Characteristic.On).on('set', this.setExtraCare.bind(this)); - this.vacuumRobotExtraCareService.getCharacteristic(Characteristic.On).on('get', this.getExtraCare.bind(this)); - - this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('set', this.setSchedule.bind(this)); - this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('get', this.getSchedule.bind(this)); - - this.services.push(this.vacuumRobotCleanService); - - if (this.hiddenServices.indexOf('dock') === -1) - this.services.push(this.vacuumRobotGoToDockService); - if (this.hiddenServices.indexOf('dockstate') === -1) - this.services.push(this.vacuumRobotDockStateService); - if (this.hiddenServices.indexOf('eco') === -1) - this.services.push(this.vacuumRobotEcoService); - if (this.hiddenServices.indexOf('nogolines') === -1) - this.services.push(this.vacuumRobotNoGoLinesService); - if (this.hiddenServices.indexOf('extracare') === -1) - this.services.push(this.vacuumRobotExtraCareService); - if (this.hiddenServices.indexOf('schedule') === -1) - this.services.push(this.vacuumRobotScheduleService); - } - - if (this.boundary) - { - this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).on('set', (on, serviceCallback) => - { - this.setCleanBoundary(this.boundary.id, on, serviceCallback) - }); - this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).on('get', (serviceCallback) => - { - this.getCleanBoundary(this.boundary.id, serviceCallback); - }); - this.services.push(this.vacuumRobotCleanBoundaryService); - } - - return this.services; - }, - - setCleanBoundary: function (boundaryId, on, callback) - { - this.updateRobot((error, result) => - { - if (on) - { - if (this.robot.canStart) - { - this.log("Starting to clean: " + boundaryId); - this.robot.startCleaningBoundary(this.eco, this.extraCare, boundaryId, (error, result) => - { - if (error) - { - this.log(error + ": " + JSON.stringify(result)); - } - callback(); - }); - return - } - else - { - this.log("Error, robot is already cleaning"); - } - } - else - { - if (this.robot.canPause) - { - debug(this.name + ": Pause cleaning"); - this.robot.pauseCleaning(callback); - return; - } - else - { - debug(this.name + ": Already stopped"); - } - } - callback(); - }); - }, - - getCleanBoundary: function (boundaryId, callback) - { - this.updateRobot((error, result) => - { - callback(false, this.robot.canPause && (this.robot.cleaningBoundaryId == boundaryId)); - }); - }, - - setClean: function (on, callback) - { - let that = this; - this.updateRobot(function (error, result) - { - if (on) - { - if (that.robot.canResume || that.robot.canStart) - { - - // start extra update robot timer if refresh is set to "auto" - if (that.refresh === 'auto') - { - setTimeout(function () - { - clearTimeout(that.timer); - that.updateRobotTimer(); - }, 60 * 1000); - } - - if (that.robot.canResume) - { - debug(that.name + ": Resume cleaning"); - that.robot.resumeCleaning(callback); - } - else - { - let eco = that.vacuumRobotEcoService.getCharacteristic(Characteristic.On).value; - let extraCare = that.vacuumRobotExtraCareService.getCharacteristic(Characteristic.On).value; - let nogoLines = that.vacuumRobotNoGoLinesService.getCharacteristic(Characteristic.On).value; - debug(that.name + ": Start cleaning (eco: " + eco + ", extraCare: " + extraCare + ", nogoLines: " + nogoLines + ")"); - that.robot.startCleaning( - eco, - extraCare ? 2 : 1, - nogoLines, - function (error, result) - { - if (error) - { - that.log.error("Cannot start cleaning. " + error + ": " + result); - callback(true); - } - else - { - callback(); - } - }); - } - } - else - { - debug(that.name + ": Cannot start, maybe already cleaning"); - callback(); - } - } - else - { - if (that.robot.canPause) - { - debug(that.name + ": Pause cleaning"); - that.robot.pauseCleaning(callback); - } - else - { - debug(that.name + ": Already stopped"); - callback(); - } - } - }); - }, - - setGoToDock: function (on, callback) - { - let that = this; - this.updateRobot(function (error, result) - { - if (on) - { - if (that.robot.canPause) - { - debug(that.name + ": Pause cleaning to go to dock"); - that.robot.pauseCleaning(function (error, result) - { - setTimeout(function () - { - debug("Go to dock"); - that.robot.sendToBase(callback); - }, 1000); - }); - } - else if (that.robot.canGoToBase) - { - debug(that.name + ": Go to dock"); - that.robot.sendToBase(callback); - } - else - { - that.log.warn(that.name + ": Can't go to dock at the moment"); - callback(); - } - } - else - { - callback(); - } - }); - }, - - setEco: function (on, callback) - { - debug(this.name + ": " + (on ? "Enable eco mode" : "Disable eco mode")); - this.robot.eco = on; - callback(); - }, - - setNoGoLines: function (on, callback) - { - debug(this.name + ": " + (on ? "Enable nogo lines" : "Disable nogo lines")); - this.robot.noGoLines = on; - callback(); - }, - - setExtraCare: function (on, callback) - { - debug(this.name + ": " + (on ? "Enable extra care navigation" : "Disable extra care navigation")); - this.robot.navigationMode = on ? 2 : 1; - callback(); - }, - - setSchedule: function (on, callback) - { - let that = this; - this.updateRobot(function (error, result) - { - if (on) - { - debug(that.name + ": Enable schedule"); - that.robot.enableSchedule(callback); - } - else - { - debug(that.name + ": Disable schedule"); - that.robot.disableSchedule(callback); - } - }); - }, - - getClean: function (callback) - { - let that = this; - this.updateRobot(function (error, result) - { - debug(that.name + ": Is cleaning: " + that.robot.canPause); - callback(false, that.robot.canPause); - }); - }, - - getGoToDock: function (callback) - { - callback(false, false); - }, - - getDock: function (callback) - { - let that = this; - this.updateRobot(function () - { - debug(that.name + ": Is docked: " + that.robot.isDocked); - callback(false, that.robot.isDocked ? 1 : 0); - }); - }, - - getEco: function (callback) - { - let that = this; - this.updateRobot(function () - { - debug(that.name + ": Is eco: " + that.robot.eco); - callback(false, that.robot.eco); - }); - }, - - getNoGoLines: function (callback) - { - let that = this; - this.updateRobot(function () - { - debug(that.name + ": Is nogo lines: " + that.robot.noGoLines); - callback(false, that.robot.noGoLines ? 1 : 0); - }); - }, - - getExtraCare: function (callback) - { - let that = this; - this.updateRobot(function () - { - debug(that.name + ": Is extra care navigation: " + (that.robot.navigationMode == 2 ? true : false)); - callback(false, that.robot.navigationMode == 2 ? 1 : 0); - }); - }, - - getSchedule: function (callback) - { - let that = this; - this.updateRobot(function () - { - debug(that.name + ": Is schedule: " + that.robot.isScheduleEnabled); - callback(false, that.robot.isScheduleEnabled); - }); - }, - - - getBatteryLevel: function (callback) - { - let that = this; - this.updateRobot(function () - { - debug(that.name + ": Battery: " + that.robot.charge + "%"); - callback(false, that.robot.charge); - }); - }, - - getBatteryChargingState: function (callback) - { - let that = this; - this.updateRobot(function () - { - debug(that.name + ": Is charging: " + that.robot.isCharging); - callback(false, that.robot.isCharging); - }); - }, - - updateRobot: function (callback) - { - let that = this; - if (this.lastUpdate !== null && new Date() - this.lastUpdate < 2000) - { - callback(); - } - else - { - debug(this.name + ": Updating robot state"); - this.robot.getState(function (error, result) - { - if (error) - { - that.log.error("Cannot update robot. Check if robot is online. " + error); - } - that.lastUpdate = new Date(); - callback(); - }); - } - }, - - updateRobotTimer: function () - { - let that = this; - this.updateRobot((error, result) => - { - - if (!this.boundary) - { - // only update these values if the state is different from the current one, otherwise we might accidentally start an action - if (that.vacuumRobotCleanService.getCharacteristic(Characteristic.On).value !== that.robot.canPause) - { - that.vacuumRobotCleanService.setCharacteristic(Characteristic.On, that.robot.canPause); - } - - // dock switch is on (dock not seen before) and dock has just been seen -> turn switch off - if (that.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).value == true && that.robot.dockHasBeenSeen) - { - that.vacuumRobotGoToDockService.setCharacteristic(Characteristic.On, false); - } - - if (that.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).value !== that.robot.isScheduleEnabled) - { - that.vacuumRobotScheduleService.setCharacteristic(Characteristic.On, that.robot.isScheduleEnabled); - } - - // no commands here, values can be updated without problems - that.vacuumRobotDockStateService.setCharacteristic(Characteristic.OccupancyDetected, that.robot.isDocked ? 1 : 0); - that.vacuumRobotEcoService.setCharacteristic(Characteristic.On, that.robot.eco); - that.vacuumRobotNoGoLinesService.setCharacteristic(Characteristic.On, that.robot.noGoLines); - that.vacuumRobotExtraCareService.setCharacteristic(Characteristic.On, that.robot.navigationMode == 2 ? true : false); - - } - else - { - if (this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).value !== that.robot.canPause) - { - this.vacuumRobotCleanBoundaryService.setCharacteristic(Characteristic.On, that.robot.canPause); - } - } - - that.vacuumRobotBatteryService.setCharacteristic(Characteristic.BatteryLevel, that.robot.charge); - that.vacuumRobotBatteryService.setCharacteristic(Characteristic.ChargingState, that.robot.isCharging); - - // robot is currently cleaning, update if refresh is set to auto or a specific interval - if (that.robot.canPause && that.refresh !== 0) - { - let refreshTime = that.refresh === 'auto' ? 60 : that.refresh; - debug("Updating state in background every " + refreshTime + " seconds while cleaning"); - that.timer = setTimeout(that.updateRobotTimer.bind(that), refreshTime * 1000); - } - // robot is not cleaning, but a specific refresh interval is set - else if (that.refresh !== 'auto' && that.refresh !== 0) - { - debug("Updating state in background every " + that.refresh + " seconds (user setting)"); - that.timer = setTimeout(that.updateRobotTimer.bind(that), that.refresh * 1000); - } - else - { - debug("Updating state in background disabled"); - } - }); - }, -}; +}; \ No newline at end of file