diff --git a/accessories/neatoVacuumRobot.js b/accessories/neatoVacuumRobot.js index 6c6814d..c598005 100644 --- a/accessories/neatoVacuumRobot.js +++ b/accessories/neatoVacuumRobot.js @@ -17,6 +17,9 @@ module.exports = function (_Service, _Characteristic) { Service = _Service; Characteristic = _Characteristic; + SpotWidthCharacteristic = require('../characteristics/spotWidth')(Characteristic, CustomUUID); + SpotHeightCharacteristic = require('../characteristics/spotHeight')(Characteristic, CustomUUID); + SpotRepeatCharacteristic = require('../characteristics/spotRepeat')(Characteristic, CustomUUID); return NeatoVacuumRobotAccessory; }; @@ -32,7 +35,7 @@ function NeatoVacuumRobotAccessory(platform, robotObject) this.robotObject = robotObject; this.robot = robotObject.device; this.meta = robotObject.meta; - this.availableServices = robotObject.availableServices; + this.spotPlusFeatures = ((typeof robotObject.availableServices.spotCleaning !== 'undefined') && robotObject.availableServices.spotCleaning.includes("basic")); this.boundary = (typeof robotObject.boundary === 'undefined') ? null : robotObject.boundary; if (this.boundary == null) @@ -74,23 +77,12 @@ function NeatoVacuumRobotAccessory(platform, robotObject) this.scheduleService = new Service.Switch(this.name + " Schedule", "schedule"); this.findMeService = new Service.Switch(this.name + " Find Me", "findMe"); - SpotWidthCharacteristic = require('../characteristics/spotWidth')(Characteristic, CustomUUID); - SpotHeightCharacteristic = require('../characteristics/spotHeight')(Characteristic, CustomUUID); - SpotRepeatCharacteristic = require('../characteristics/spotRepeat')(Characteristic, CustomUUID); - - // Spot cleaning with advanced options - if ((typeof this.availableServices.spotCleaning !== 'undefined') && this.availableServices.spotCleaning.includes("basic")) + this.spotCleanService = new Service.Switch(this.name + " Clean Spot", "cleanSpot"); + this.spotCleanService.addCharacteristic(SpotRepeatCharacteristic); + if (this.spotPlusFeatures) { - this.spotCleanAdvancedService = new Service.Switch(this.name + " Clean Spot", "cleanSpot"); - this.spotCleanAdvancedService.addCharacteristic(SpotRepeatCharacteristic); - this.spotCleanAdvancedService.addCharacteristic(SpotWidthCharacteristic); - this.spotCleanAdvancedService.addCharacteristic(SpotHeightCharacteristic); - } - // Spot cleaning without advanced options - else - { - this.spotCleanSimpleService = new Service.Switch(this.name + " Clean Spot", "cleanSpot"); - this.spotCleanSimpleService.addCharacteristic(SpotRepeatCharacteristic); + this.spotCleanService.addCharacteristic(SpotWidthCharacteristic); + this.spotCleanService.addCharacteristic(SpotHeightCharacteristic); } } else @@ -166,29 +158,22 @@ NeatoVacuumRobotAccessory.prototype = { this.findMeService.getCharacteristic(Characteristic.On).on('set', this.setFindMe.bind(this)); this.findMeService.getCharacteristic(Characteristic.On).on('get', this.getFindMe.bind(this)); - if (typeof this.spotCleanAdvancedService !== 'undefined') - { - this.spotCleanAdvancedService.getCharacteristic(Characteristic.On).on('set', this.setSpotClean.bind(this)); - this.spotCleanAdvancedService.getCharacteristic(Characteristic.On).on('get', this.getSpotClean.bind(this)); - this.spotCleanAdvancedService.getCharacteristic(SpotRepeatCharacteristic).on('set', this.setSpotRepeat.bind(this)); - this.spotCleanAdvancedService.getCharacteristic(SpotRepeatCharacteristic).on('get', this.getSpotRepeat.bind(this)); - this.spotCleanAdvancedService.getCharacteristic(SpotWidthCharacteristic).on('set', this.setSpotWidth.bind(this)); - this.spotCleanAdvancedService.getCharacteristic(SpotWidthCharacteristic).on('get', this.getSpotWidth.bind(this)); - this.spotCleanAdvancedService.getCharacteristic(SpotHeightCharacteristic).on('set', this.setSpotHeight.bind(this)); - this.spotCleanAdvancedService.getCharacteristic(SpotHeightCharacteristic).on('get', this.getSpotHeight.bind(this)); + this.spotCleanService.getCharacteristic(Characteristic.On).on('set', this.setSpotClean.bind(this)); + this.spotCleanService.getCharacteristic(Characteristic.On).on('get', this.getSpotClean.bind(this)); + this.spotCleanService.getCharacteristic(SpotRepeatCharacteristic).on('set', this.setSpotRepeat.bind(this)); + this.spotCleanService.getCharacteristic(SpotRepeatCharacteristic).on('get', this.getSpotRepeat.bind(this)); - if (this.hiddenServices.indexOf('spot') === -1) - this.services.push(this.spotCleanAdvancedService); + if (this.spotPlusFeatures) + { + this.spotCleanService.getCharacteristic(SpotWidthCharacteristic).on('set', this.setSpotWidth.bind(this)); + this.spotCleanService.getCharacteristic(SpotWidthCharacteristic).on('get', this.getSpotWidth.bind(this)); + this.spotCleanService.getCharacteristic(SpotHeightCharacteristic).on('set', this.setSpotHeight.bind(this)); + this.spotCleanService.getCharacteristic(SpotHeightCharacteristic).on('get', this.getSpotHeight.bind(this)); } - else - { - this.spotCleanSimpleService.getCharacteristic(Characteristic.On).on('set', this.setSpotClean.bind(this)); - this.spotCleanSimpleService.getCharacteristic(Characteristic.On).on('get', this.getSpotClean.bind(this)); - this.spotCleanSimpleService.getCharacteristic(SpotRepeatCharacteristic).on('set', this.setSpotRepeat.bind(this)); - this.spotCleanSimpleService.getCharacteristic(SpotRepeatCharacteristic).on('get', this.getSpotRepeat.bind(this)); - if (this.hiddenServices.indexOf('spot') === -1) - this.services.push(this.spotCleanSimpleService); + if (this.hiddenServices.indexOf('spot') === -1) + { + this.services.push(this.spotCleanService); } // Add optional services @@ -507,12 +492,10 @@ NeatoVacuumRobotAccessory.prototype = { setSpotClean: function (on, callback) { - let spotCleanService = (typeof this.spotCleanAdvancedService !== 'undefined') ? this.spotCleanAdvancedService : this.spotCleanSimpleService; - let spot = { - width: spotCleanService.getCharacteristic(SpotWidthCharacteristic).value, - height: spotCleanService.getCharacteristic(SpotHeightCharacteristic).value, - repeat: spotCleanService.getCharacteristic(SpotRepeatCharacteristic).value + width: this.spotPlusFeatures ? this.spotCleanService.getCharacteristic(SpotWidthCharacteristic).value : null, + height: this.spotPlusFeatures ? this.spotCleanService.getCharacteristic(SpotHeightCharacteristic).value : null, + repeat: this.spotCleanService.getCharacteristic(SpotRepeatCharacteristic).value }; this.platform.updateRobot(this.robot._serial, (error, result) => @@ -658,15 +641,12 @@ NeatoVacuumRobotAccessory.prototype = { this.noGoLinesService.setCharacteristic(Characteristic.On, this.robot.noGoLines); this.extraCareService.setCharacteristic(Characteristic.On, this.robot.navigationMode == 2 ? true : false); - if (typeof this.spotCleanAdvancedService !== 'undefined') + this.spotCleanService.setCharacteristic(SpotRepeatCharacteristic, this.robot.spotRepeat); + + if (this.spotPlusFeatures) { - this.spotCleanAdvancedService.setCharacteristic(SpotWidthCharacteristic, this.robot.spotWidth); - this.spotCleanAdvancedService.setCharacteristic(SpotHeightCharacteristic, this.robot.spotHeight); - this.spotCleanAdvancedService.setCharacteristic(SpotRepeatCharacteristic, this.robot.spotRepeat); - } - else - { - this.spotCleanSimpleService.setCharacteristic(SpotRepeatCharacteristic, this.robot.spotRepeat); + this.spotCleanService.setCharacteristic(SpotWidthCharacteristic, this.robot.spotWidth); + this.spotCleanService.setCharacteristic(SpotHeightCharacteristic, this.robot.spotHeight); } } diff --git a/index.js b/index.js index 9a1f1e1..92c18f6 100644 --- a/index.js +++ b/index.js @@ -4,12 +4,14 @@ let inherits = require('util').inherits, botvac = require('node-botvac'), Service, - Characteristic; + Characteristic, + NeatoVacuumRobotAccessory; module.exports = function (homebridge) { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; + NeatoVacuumRobotAccessory = require('./accessories/neatoVacuumRobot')(Service, Characteristic); homebridge.registerPlatform("homebridge-neato", "NeatoVacuumRobot", NeatoVacuumRobotPlatform); }; @@ -54,50 +56,70 @@ NeatoVacuumRobotPlatform.prototype = { debug("Get robots"); let accessories = []; this.boundaryNames = []; + this.getRobots(() => { - this.robots.forEach((robot, i) => - { - this.log("Found robot #" + (i + 1) + " named \"" + robot.device.name + "\" with serial \"" + robot.device._serial.substring(0,9) + "XXXXXXXXXXXX\""); + // // MOCK MULTIPLE ROBOTS START + // let client = new botvac.Client(); + // client.authorize(this.email, this.password, false, (error) => + // { + // client.getRobots((error, robs) => + // { + // let testRobot = robs[0]; + // testRobot.getState((error, result) => + // { + // testRobot.name = "Testrobot"; + // this.robots.push({device: testRobot, meta: result.meta, availableServices: result.availableServices}); + // // MOCK MULTIPLE ROBOTS END - // Start Update Intervall - this.updateRobotTimer(robot.device._serial); - - let NeatoVacuumRobotAccessory = require('./accessories/neatoVacuumRobot')(Service, Characteristic); - let mainAccessory = new NeatoVacuumRobotAccessory(this, robot); - accessories.push(mainAccessory); - - robot.mainAccessory = mainAccessory; - robot.roomAccessories = []; - - // For testing purposes only - // robot.boundary = {name: "Testroom", id: "1"}; - // let roomAccessory = new NeatoVacuumRobotAccessory(this, robot); - // accessories.push(roomAccessory); - // robot.roomAccessories.push(roomAccessory); - - if (robot.device.maps) - { - robot.device.maps.forEach((map) => - { - if (map.boundaries) + this.robots.forEach((robot, i) => { - map.boundaries.forEach((boundary) => - { - if (boundary.type === "polygon") - { - robot.boundary = boundary; - let roomAccessory = new NeatoVacuumRobotAccessory(this, robot); - accessories.push(roomAccessory); + this.log("Found robot #" + (i + 1) + " named \"" + robot.device.name + "\" with serial \"" + robot.device._serial.substring(0, 9) + "XXXXXXXXXXXX\""); - robot.roomAccessories.push(roomAccessory); - } - }) - } - }) - } - }); - callback(accessories); + let mainAccessory = new NeatoVacuumRobotAccessory(this, robot); + accessories.push(mainAccessory); + + robot.mainAccessory = mainAccessory; + robot.roomAccessories = []; + + // Start Update Intervall + this.updateRobotTimer(robot.device._serial); + + // // MOCK ZONE CLEANING START + // robot.boundary = {name: "Testroom", id: "1"}; + // let roomAccessory = new NeatoVacuumRobotAccessory(this, robot); + // accessories.push(roomAccessory); + // robot.roomAccessories.push(roomAccessory); + // // MOCK ZONE CLEANING END + + if (robot.device.maps) + { + robot.device.maps.forEach((map) => + { + if (map.boundaries) + { + map.boundaries.forEach((boundary) => + { + if (boundary.type === "polygon") + { + robot.boundary = boundary; + let roomAccessory = new NeatoVacuumRobotAccessory(this, robot); + accessories.push(roomAccessory); + + robot.roomAccessories.push(roomAccessory); + } + }) + } + }) + } + }); + callback(accessories); + + // // MOCK MULTIPLE ROBOTS START + // }); + // }); + // }); + // // MOCK MULTIPLE ROBOTS END }); }, @@ -137,46 +159,68 @@ NeatoVacuumRobotPlatform.prototype = { robots.forEach((robot) => { - // Get all maps for each robot - robot.getPersistentMaps((error, result) => + // Get additional information for the robot + robot.getState((error, state) => { if (error) { - this.log.error("Error updating persistent maps: " + error + ": " + result); + this.log.error("Error getting robot meta information: " + error + ": " + state); callback(); } - // Robot has no maps - else if (result.length === 0) - { - robot.maps = []; - this.saveRobot(robot, loadedRobots, robots.length, callback); - } - // Robot has maps else { - robot.maps = result; - let loadedMaps = 0; - robot.maps.forEach((map) => + // Get all maps for each robot + robot.getPersistentMaps((error, maps) => { - // Save zones in each map - robot.getMapBoundaries(map.id, (error, result) => + if (error) { - if (error) + this.log.error("Error updating persistent maps: " + error + ": " + maps); + callback(); + } + // Robot has no maps + else if (maps.length === 0) + { + robot.maps = []; + this.robots.push({device: robot, meta: state.meta, availableServices: state.availableServices}); + loadedRobots++; + if (loadedRobots === robots.length) { - this.log.error("Error getting boundaries: " + error + ": " + result) + callback(); } - else + } + // Robot has maps + else + { + robot.maps = maps; + let loadedMaps = 0; + robot.maps.forEach((map) => { - map.boundaries = result.boundaries; - } - loadedMaps++; + // Save zones in each map + robot.getMapBoundaries(map.id, (error, result) => + { + if (error) + { + this.log.error("Error getting boundaries: " + error + ": " + result) + } + else + { + map.boundaries = result.boundaries; + } + loadedMaps++; - // Robot is completely requested if zones for all maps are loaded - if (loadedMaps === robot.maps.length) - { - this.saveRobot(robot, loadedRobots, robots.length, callback); - } - }) + // Robot is completely requested if zones for all maps are loaded + if (loadedMaps === robot.maps.length) + { + this.robots.push({device: robot, meta: state.meta, availableServices: state.availableServices}); + loadedRobots++; + if (loadedRobots === robots.length) + { + callback(); + } + } + }) + }); + } }); } }); @@ -187,31 +231,6 @@ NeatoVacuumRobotPlatform.prototype = { }); }, - saveRobot: function (robot, loadedRobots, size, callback) - { - // Get additional information for the robot - robot.getState((error, result) => - { - if (error) - { - this.log.error("Error getting robot meta information: " + error + ": " + result); - callback(); - } - else - { - // Store the robot with his information, maps and zones - this.robots.push({device: robot, meta: result.meta, availableServices: result.availableServices}); - loadedRobots++; - - // Initial request is complete if all robots are loaded. - if (loadedRobots === size) - { - callback(); - } - } - }); - }, - updateRobot: function (serial, callback) { let robot = this.getRobot(serial); diff --git a/package.json b/package.json index 35a2ca5..4b450ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homebridge-neato", - "version": "0.7.1", + "version": "0.7.2-beta.1", "description": "A Neato vacuum robot plugin for homebridge.", "license": "MIT", "keywords": [