From 46ba5e5f302dbdcb806b7f81677e6b5e8d771ec4 Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 23 Sep 2019 11:48:35 +0200 Subject: [PATCH] Added spot cleaning function with individual spot size (D7) --- CHANGELOG.md | 4 +- README.md | 6 +- accessories/neatoVacuumRobot.js | 352 ++++++++++++++++++++++++-------- characteristics/spotHeight.js | 21 ++ characteristics/spotRepeat.js | 17 ++ characteristics/spotWidth.js | 21 ++ index.js | 2 +- 7 files changed, 332 insertions(+), 91 deletions(-) create mode 100644 characteristics/spotHeight.js create mode 100644 characteristics/spotRepeat.js create mode 100644 characteristics/spotWidth.js diff --git a/CHANGELOG.md b/CHANGELOG.md index c6fe131..80999ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -108,4 +108,6 @@ * Fixed room switches to support pause/resume of cleaning * Added feature that enabling another room switch, returns to robot to dock and starts cleaning the new room automatically * Improved requests for multiple rooms (TODO) -* Added model and firmware information to homekit \ No newline at end of file +* Added model and firmware information to homekit +* Added find me function +* Added spot cleaning function with individual spot size and repeat option \ No newline at end of file diff --git a/README.md b/README.md index 45d14bf..619ee26 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Feel free to leave any feedback [here](https://github.com/naofireblade/homebridg - Nogo lines - Zones - Spot cleaning - - 2x2 or 4x4 + - individual spot size (only D7) - repeat - Return to dock - Find the robot @@ -61,7 +61,7 @@ The following config contains advanced optional settings. The parameter **refresh** is default set to auto and updates the robot state when the cleaning was started via homekit so that you can activate automations after the cleaning is done. If you want to get robot state updates after starting the cleaning from the neato app or a schedule, you have to set refresh to a static value in seconds e.g. `120`. You can disable background updates completely by setting this to `0`. -The parameter **disabled** accepts a list of switches/sensors that can be disabled in the neato homekit plugin (e.g. `dock`, `dockstate`, `eco`, `schedule`, `findme`, `spot`, `spotrepeat`, `spot4x4`). +The parameter **disabled** accepts a list of switches/sensors that can be disabled in the neato homekit plugin (e.g. `dock`, `dockstate`, `eco`, `schedule`, `findme`, `spot`). ```json "platforms": [ @@ -70,7 +70,7 @@ The parameter **disabled** accepts a list of switches/sensors that can be disabl "email": "YourEmail", "password": "YourPassword", "refresh": "120", - "disabled": ["dock", "dockstate", "eco", "nogolines", "extracare", "schedule", "spot"] + "disabled": ["dock", "dockstate", "eco", "nogolines", "extracare", "schedule", "findme", "spot"] } ] ``` diff --git a/accessories/neatoVacuumRobot.js b/accessories/neatoVacuumRobot.js index b16699e..a027c78 100644 --- a/accessories/neatoVacuumRobot.js +++ b/accessories/neatoVacuumRobot.js @@ -1,7 +1,16 @@ const debug = require('debug')('homebridge-neato'); +const CustomUUID = { + SpotCleanWidth: 'A7889A9A-2F27-4293-BEF8-3FE805B36F4E', + SpotCleanHeight: 'CA282DB2-62BF-4325-A1BE-F8BB5478781A', + SpotCleanRepeat: '1E79C603-63B8-4E6A-9CE1-D31D67981831' +}; + let Service, - Characteristic; + Characteristic, + SpotWidthCharacteristic, + SpotHeightCharacteristic, + SpotRepeatCharacteristic; module.exports = function (_Service, _Characteristic) { @@ -21,10 +30,15 @@ function NeatoVacuumRobotAccessory(platform, robotObject, boundary = undefined) this.robotObject = robotObject; this.robot = robotObject.device; this.meta = robotObject.meta; + this.availableServices = robotObject.availableServices; this.boundary = boundary; this.nextRoom = null; + SpotWidthCharacteristic = require('../characteristics/spotWidth')(Characteristic, CustomUUID); + SpotHeightCharacteristic = require('../characteristics/spotHeight')(Characteristic, CustomUUID); + SpotRepeatCharacteristic = require('../characteristics/spotRepeat')(Characteristic, CustomUUID); + if (typeof boundary === 'undefined') { this.name = this.robot.name; @@ -51,18 +65,33 @@ function NeatoVacuumRobotAccessory(platform, robotObject, boundary = undefined) this.name = this.robot.name + ' - ' + this.boundary.name; } - this.vacuumRobotBatteryService = new Service.BatteryService("Battery", "battery"); + this.batteryService = new Service.BatteryService("Battery", "battery"); if (typeof boundary === 'undefined') { - this.vacuumRobotCleanService = new Service.Switch(this.name + " 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"); - this.vacuumRobotFindMeService = new Service.Switch(this.name + " Find Me", "findMe"); + this.cleanService = new Service.Switch(this.name + " Clean", "clean"); + this.goToDockService = new Service.Switch(this.name + " Go to Dock", "goToDock"); + this.dockStateService = new Service.OccupancySensor(this.name + " Dock", "dockState"); + this.ecoService = new Service.Switch(this.name + " Eco Mode", "eco"); + this.noGoLinesService = new Service.Switch(this.name + " NoGo Lines", "noGoLines"); + this.extraCareService = new Service.Switch(this.name + " Extra Care", "extraCare"); + this.scheduleService = new Service.Switch(this.name + " Schedule", "schedule"); + this.findMeService = new Service.Switch(this.name + " Find Me", "findMe"); + + // Spot cleaning with advanced options + if ((typeof this.availableServices.spotCleaning !== 'undefined') && this.availableServices.spotCleaning.includes("basic")) + { + 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); + } } else { @@ -72,7 +101,7 @@ function NeatoVacuumRobotAccessory(platform, robotObject, boundary = undefined) { serviceName = "Clean " + boundary.name; } - this.vacuumRobotCleanBoundaryService = + this.cleanBoundaryService = new Service.Switch(serviceName, "cleanBoundary:" + boundary.id); this.log("Adding zone cleaning for: " + boundary.name); } @@ -81,16 +110,17 @@ function NeatoVacuumRobotAccessory(platform, robotObject, boundary = undefined) NeatoVacuumRobotAccessory.prototype = { identify: function (callback) { - this.platform.updateRobot(this.robot._serial, () => + this.robot.getState((error, result) => { - // hide serial and secret in log - let _serial = this.robot._serial; - let _secret = this.robot._secret; - this.robot._serial = "*****"; - this.robot._secret = "*****"; - this.log(this.robot); - this.robot._serial = _serial; - this.robot._secret = _secret; + if (error) + { + this.log.error("Error getting robot information: " + error + ": " + result); + } + else + { + this.log("### Robot information ###"); + this.log(result); + } callback(); }); }, @@ -118,67 +148,93 @@ NeatoVacuumRobotAccessory.prototype = { if (typeof this.boundary === "undefined") { - this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('set', (on, serviceCallback) => + this.cleanService.getCharacteristic(Characteristic.On).on('set', (on, serviceCallback) => { this.setClean(on, serviceCallback, this.boundary) }); - this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('get', (serviceCallback) => + this.cleanService.getCharacteristic(Characteristic.On).on('get', (serviceCallback) => { this.getClean(serviceCallback, this.boundary); }); - this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('set', this.setGoToDock.bind(this)); - this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('get', this.getGoToDock.bind(this)); + // Create services + this.goToDockService.getCharacteristic(Characteristic.On).on('set', this.setGoToDock.bind(this)); + this.goToDockService.getCharacteristic(Characteristic.On).on('get', this.getGoToDock.bind(this)); + this.dockStateService.getCharacteristic(Characteristic.OccupancyDetected).on('get', this.getDock.bind(this)); - this.vacuumRobotDockStateService.getCharacteristic(Characteristic.OccupancyDetected).on('get', this.getDock.bind(this)); + this.ecoService.getCharacteristic(Characteristic.On).on('set', this.setEco.bind(this)); + this.ecoService.getCharacteristic(Characteristic.On).on('get', this.getEco.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.noGoLinesService.getCharacteristic(Characteristic.On).on('set', this.setNoGoLines.bind(this)); + this.noGoLinesService.getCharacteristic(Characteristic.On).on('get', this.getNoGoLines.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.extraCareService.getCharacteristic(Characteristic.On).on('set', this.setExtraCare.bind(this)); + this.extraCareService.getCharacteristic(Characteristic.On).on('get', this.getExtraCare.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.scheduleService.getCharacteristic(Characteristic.On).on('set', this.setSchedule.bind(this)); + this.scheduleService.getCharacteristic(Characteristic.On).on('get', this.getSchedule.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.findMeService.getCharacteristic(Characteristic.On).on('set', this.setFindMe.bind(this)); + this.findMeService.getCharacteristic(Characteristic.On).on('get', this.getFindMe.bind(this)); - this.vacuumRobotFindMeService.getCharacteristic(Characteristic.On).on('set', this.setFindMe.bind(this)); - this.vacuumRobotFindMeService.getCharacteristic(Characteristic.On).on('get', this.getFindMe.bind(this)); + this.batteryService.getCharacteristic(Characteristic.BatteryLevel).on('get', this.getBatteryLevel.bind(this)); + this.batteryService.getCharacteristic(Characteristic.ChargingState).on('get', this.getBatteryChargingState.bind(this)); - this.vacuumRobotBatteryService.getCharacteristic(Characteristic.BatteryLevel).on('get', this.getBatteryLevel.bind(this)); - this.vacuumRobotBatteryService.getCharacteristic(Characteristic.ChargingState).on('get', this.getBatteryChargingState.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(SpotHeightCharacteristic).on('set', this.setSpotHeight.bind(this)); + this.spotCleanAdvancedService.getCharacteristic(SpotHeightCharacteristic).on('get', this.getSpotHeight.bind(this)); - this.services.push(this.vacuumRobotCleanService); - this.services.push(this.vacuumRobotBatteryService); + if (this.hiddenServices.indexOf('spot') === -1) + this.services.push(this.spotCleanAdvancedService); + } + 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); + } + + // Add primary services + this.services.push(this.cleanService); + this.services.push(this.batteryService); + + // Add optional services if (this.hiddenServices.indexOf('dock') === -1) - this.services.push(this.vacuumRobotGoToDockService); + this.services.push(this.goToDockService); if (this.hiddenServices.indexOf('dockstate') === -1) - this.services.push(this.vacuumRobotDockStateService); + this.services.push(this.dockStateService); if (this.hiddenServices.indexOf('eco') === -1) - this.services.push(this.vacuumRobotEcoService); + this.services.push(this.ecoService); if (this.hiddenServices.indexOf('nogolines') === -1) - this.services.push(this.vacuumRobotNoGoLinesService); + this.services.push(this.noGoLinesService); if (this.hiddenServices.indexOf('extracare') === -1) - this.services.push(this.vacuumRobotExtraCareService); + this.services.push(this.extraCareService); if (this.hiddenServices.indexOf('schedule') === -1) - this.services.push(this.vacuumRobotScheduleService); + this.services.push(this.scheduleService); // if (this.hiddenServices.indexOf('find') === -1) // this.services.push(this.vacuumRobotFindMeService); } else { - this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).on('set', (on, serviceCallback) => + this.cleanBoundaryService.getCharacteristic(Characteristic.On).on('set', (on, serviceCallback) => { this.setClean(on, serviceCallback, this.boundary) }); - this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).on('get', (serviceCallback) => + this.cleanBoundaryService.getCharacteristic(Characteristic.On).on('get', (serviceCallback) => { this.getClean(serviceCallback, this.boundary); }); - this.services.push(this.vacuumRobotCleanBoundaryService); + this.services.push(this.cleanBoundaryService); } return this.services; @@ -268,7 +324,7 @@ NeatoVacuumRobotAccessory.prototype = { }); }, - clean: function (callback, boundary) + clean: function (callback, boundary, spot) { // Start automatic update while cleaning if (this.refresh === 'auto') @@ -279,34 +335,30 @@ NeatoVacuumRobotAccessory.prototype = { }, 60 * 1000); } - let eco = this.robotObject.mainAccessory.vacuumRobotEcoService.getCharacteristic(Characteristic.On).value; - let extraCare = this.robotObject.mainAccessory.vacuumRobotExtraCareService.getCharacteristic(Characteristic.On).value; - let nogoLines = this.robotObject.mainAccessory.vacuumRobotNoGoLinesService.getCharacteristic(Characteristic.On).value; - let room = (typeof boundary === 'undefined') ? '' : boundary.name; - debug(this.name + ": ## Start cleaning (" + room + " eco: " + eco + ", extraCare: " + extraCare + ", nogoLines: " + nogoLines + ")"); + let eco = this.robotObject.mainAccessory.ecoService.getCharacteristic(Characteristic.On).value; + let extraCare = this.robotObject.mainAccessory.extraCareService.getCharacteristic(Characteristic.On).value; + let nogoLines = this.robotObject.mainAccessory.noGoLinesService.getCharacteristic(Characteristic.On).value; + let room = (typeof boundary === 'undefined' || boundary === null) ? '' : boundary.name; + debug(this.name + ": ## Start cleaning (" + (room !== '' ? room + " " : '') + "eco: " + eco + ", extraCare: " + extraCare + ", nogoLines: " + nogoLines + ", spot: " + JSON.stringify(spot) + ")"); // Normal cleaning - if (typeof boundary === 'undefined') + if (room === '' && (typeof spot === 'undefined')) { - this.robot.startCleaning( - eco, - extraCare ? 2 : 1, - nogoLines, - (error, result) => + this.robot.startCleaning(eco, extraCare ? 2 : 1, nogoLines, (error, result) => + { + if (error) { - if (error) - { - this.log.error("Cannot start cleaning. " + error + ": " + JSON.stringify(result)); - callback(true); - } - else - { - callback(); - } - }); + this.log.error("Cannot start cleaning. " + error + ": " + JSON.stringify(result)); + callback(true); + } + else + { + callback(); + } + }); } // Room cleaning - else + else if (room !== '') { this.robot.startCleaningBoundary(eco, extraCare, boundary.id, (error, result) => { @@ -321,6 +373,22 @@ NeatoVacuumRobotAccessory.prototype = { } }); } + // Spot cleaning + else + { + this.robot.startSpotCleaning(eco, spot.width, spot.height, spot.repeat, extraCare ? 2 : 1, (error, result) => + { + if (error) + { + this.log.error("Cannot start spot cleaning. " + error + ": " + JSON.stringify(result)); + callback(true); + } + else + { + callback(); + } + }); + } }, getGoToDock: function (callback) @@ -450,13 +518,114 @@ NeatoVacuumRobotAccessory.prototype = { debug(this.name + ": ## Find me"); setTimeout(() => { - this.vacuumRobotFindMeService.setCharacteristic(Characteristic.On, false); + this.findMeService.setCharacteristic(Characteristic.On, false); }, 1000); this.robot.findMe(callback); } }, + getSpotClean: function (callback) + { + callback(); + }, + + setSpotClean: function (on, callback) + { + let spot = { + width: this.spotCleanService.getCharacteristic(SpotWidthCharacteristic).value, + height: this.spotCleanService.getCharacteristic(SpotHeightCharacteristic).value, + repeat: this.spotCleanService.getCharacteristic(SpotRepeatCharacteristic).value + }; + + this.platform.updateRobot(this.robot._serial, (error, result) => + { + // Start + if (on) + { + // Resume cleaning + if (this.robot.canResume) + { + debug(this.name + ": ## Resume (spot) cleaning"); + this.robot.resumeCleaning(callback); + } + // Start cleaning + else if (this.robot.canStart) + { + this.clean(callback, null, spot); + } + // Cannot start + else + { + debug(this.name + ": Cannot start spot cleaning, maybe already cleaning"); + callback(); + } + } + // Stop + else + { + if (this.robot.canPause) + { + debug(this.name + ": ## Pause cleaning"); + this.robot.pauseCleaning(callback); + } + else + { + debug(this.name + ": Already paused"); + callback(); + } + } + }); + }, + + getSpotWidth: function (callback) + { + this.platform.updateRobot(this.robot._serial, () => + { + debug(this.name + ": S width is " + this.robot.spotWidth + "cm"); + callback(false, this.robot.spotWidth); + }); + }, + + setSpotWidth: function (width, callback) + { + this.robot.spotWidth = width; + debug(this.name + ": Set spot width to " + width + "cm"); + callback(); + }, + + getSpotHeight: function (callback) + { + this.platform.updateRobot(this.robot._serial, () => + { + debug(this.name + ": S height is " + this.robot.spotHeight + "cm"); + callback(false, this.robot.spotHeight); + }); + }, + + setSpotHeight: function (height, callback) + { + this.robot.spotHeight = height; + debug(this.name + ": Set spot height to " + height + "cm"); + callback(); + }, + + getSpotRepeat: function (callback) + { + this.platform.updateRobot(this.robot._serial, () => + { + debug(this.name + ": S repeat is " + (this.robot.spotRepeat ? 'ON' : 'OFF')); + callback(false, this.robot.spotRepeat); + }); + }, + + setSpotRepeat: function (on, callback) + { + this.robot.spotRepeat = on; + debug(this.name + ": " + (on ? "Enabled " : "Disabled") + " Spot repeat"); + callback(); + }, + getDock: function (callback) { this.platform.updateRobot(this.robot._serial, () => @@ -489,39 +658,50 @@ NeatoVacuumRobotAccessory.prototype = { if (!this.boundary) { // only update these values if the state is different from the current one, otherwise we might accidentally start an action - if (this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).value !== this.robot.canPause) + if (this.cleanService.getCharacteristic(Characteristic.On).value !== this.robot.canPause) { - this.vacuumRobotCleanService.setCharacteristic(Characteristic.On, this.robot.canPause); + this.cleanService.setCharacteristic(Characteristic.On, this.robot.canPause); } // dock switch is on (dock not seen before) and dock has just been seen -> turn switch off - if (this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).value == true && this.robot.dockHasBeenSeen) + if (this.goToDockService.getCharacteristic(Characteristic.On).value == true && this.robot.dockHasBeenSeen) { - this.vacuumRobotGoToDockService.setCharacteristic(Characteristic.On, false); + this.goToDockService.setCharacteristic(Characteristic.On, false); } - if (this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).value !== this.robot.isScheduleEnabled) + if (this.scheduleService.getCharacteristic(Characteristic.On).value !== this.robot.isScheduleEnabled) { - this.vacuumRobotScheduleService.setCharacteristic(Characteristic.On, this.robot.isScheduleEnabled); + this.scheduleService.setCharacteristic(Characteristic.On, this.robot.isScheduleEnabled); } // no commands here, values can be updated without problems - this.vacuumRobotDockStateService.setCharacteristic(Characteristic.OccupancyDetected, this.robot.isDocked ? 1 : 0); - this.vacuumRobotEcoService.setCharacteristic(Characteristic.On, this.robot.eco); - this.vacuumRobotNoGoLinesService.setCharacteristic(Characteristic.On, this.robot.noGoLines); - this.vacuumRobotExtraCareService.setCharacteristic(Characteristic.On, this.robot.navigationMode == 2 ? true : false); + this.dockStateService.setCharacteristic(Characteristic.OccupancyDetected, this.robot.isDocked ? 1 : 0); + this.ecoService.setCharacteristic(Characteristic.On, this.robot.eco); + 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.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); + } } else { - if (this.vacuumRobotCleanBoundaryService.getCharacteristic(Characteristic.On).value !== this.robot.canPause) + if (this.cleanBoundaryService.getCharacteristic(Characteristic.On).value !== this.robot.canPause) { - this.vacuumRobotCleanBoundaryService.setCharacteristic(Characteristic.On, this.robot.canPause); + this.cleanBoundaryService.setCharacteristic(Characteristic.On, this.robot.canPause); } } - this.vacuumRobotBatteryService.setCharacteristic(Characteristic.BatteryLevel, this.robot.charge); - this.vacuumRobotBatteryService.setCharacteristic(Characteristic.ChargingState, this.robot.isCharging); + this.batteryService.setCharacteristic(Characteristic.BatteryLevel, this.robot.charge); + this.batteryService.setCharacteristic(Characteristic.ChargingState, this.robot.isCharging); // Robot has a next room to clean in queue if (this.nextRoom !== null && this.robot.isDocked) diff --git a/characteristics/spotHeight.js b/characteristics/spotHeight.js new file mode 100644 index 0000000..e609595 --- /dev/null +++ b/characteristics/spotHeight.js @@ -0,0 +1,21 @@ +const inherits = require('util').inherits; + +module.exports = function (Characteristic, CustomUUID) +{ + let SpotHeight = function () + { + Characteristic.call(this, 'Spot ↕', CustomUUID.SpotCleanHeight); + this.setProps({ + format: Characteristic.Formats.INT, + unit: 'cm', + maxValue: 400, + minValue: 100, + minStep: 50, + perms: [Characteristic.Perms.READ, Characteristic.Perms.WRITE] + }); + this.value = this.getDefaultValue(); + }; + inherits(SpotHeight, Characteristic); + + return SpotHeight; +}; \ No newline at end of file diff --git a/characteristics/spotRepeat.js b/characteristics/spotRepeat.js new file mode 100644 index 0000000..568f1e1 --- /dev/null +++ b/characteristics/spotRepeat.js @@ -0,0 +1,17 @@ +const inherits = require('util').inherits; + +module.exports = function (Characteristic, CustomUUID) +{ + let SpotRepeat = function () + { + Characteristic.call(this, 'Spot ↺', CustomUUID.SpotCleanRepeat); + this.setProps({ + format: Characteristic.Formats.BOOL, + perms: [Characteristic.Perms.READ, Characteristic.Perms.WRITE] + }); + this.value = this.getDefaultValue(); + }; + inherits(SpotRepeat, Characteristic); + + return SpotRepeat; +}; \ No newline at end of file diff --git a/characteristics/spotWidth.js b/characteristics/spotWidth.js new file mode 100644 index 0000000..e3ed9cf --- /dev/null +++ b/characteristics/spotWidth.js @@ -0,0 +1,21 @@ +const inherits = require('util').inherits; + +module.exports = function (Characteristic, CustomUUID) +{ + let SpotWidth = function () + { + Characteristic.call(this, 'Spot ↔', CustomUUID.SpotCleanWidth); + this.setProps({ + format: Characteristic.Formats.INT, + unit: 'cm', + maxValue: 400, + minValue: 100, + minStep: 50, + perms: [Characteristic.Perms.READ, Characteristic.Perms.WRITE] + }); + this.value = this.getDefaultValue(); + }; + inherits(SpotWidth, Characteristic); + + return SpotWidth; +}; \ No newline at end of file diff --git a/index.js b/index.js index d6005c7..5cfb093 100644 --- a/index.js +++ b/index.js @@ -172,7 +172,7 @@ NeatoVacuumRobotPlatform.prototype = { } else { - this.robots.push({device: robot, meta: result.meta}); + this.robots.push({device: robot, meta: result.meta, availableServices: result.availableServices}); requestedRobot++; // Initial request is complete if all robots are requested.