Version 0.3.0
* Added periodic refresh of robot state * Improved go to dock switch to be enabled as soon as possible without manual refresh * Improved switches to indicate the time an action lasts * Improved eco mode to not be overwritten by robot state
This commit is contained in:
parent
b2ddecc827
commit
36e8496108
@ -14,3 +14,10 @@
|
|||||||
## 0.2.1
|
## 0.2.1
|
||||||
|
|
||||||
* Improved the go to dock command
|
* Improved the go to dock command
|
||||||
|
|
||||||
|
## 0.3.0
|
||||||
|
|
||||||
|
* Added periodic refresh of robot state
|
||||||
|
* Improved go to dock switch to be enabled as soon as possible without manual refresh
|
||||||
|
* Improved switches to indicate the time an action lasts
|
||||||
|
* Improved eco mode to not be overwritten by robot state
|
@ -28,13 +28,16 @@ Feel free to leave any feedback [here](https://github.com/naofireblade/homebridg
|
|||||||
|
|
||||||
Add the following information to your config file. Change the values for name, email and password.
|
Add the following information to your config file. Change the values for name, email and password.
|
||||||
|
|
||||||
|
The parameter **refresh** is optional (default 120 seconds) and adjusts in what interval changes in the robot state will be pushed to homekit (e.g. when starting the robot with the neato app). The minimum is 60 seconds. You can disable this by entering 0.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"accessories": [
|
"accessories": [
|
||||||
{
|
{
|
||||||
"accessory": "NeatoVacuumRobot",
|
"accessory": "NeatoVacuumRobot",
|
||||||
"name": "YourRobot",
|
"name": "YourRobot",
|
||||||
"email": "YourEmail",
|
"email": "YourEmail",
|
||||||
"password": "YourPassword"
|
"password": "YourPassword",
|
||||||
|
"refresh": "120"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
@ -43,4 +46,4 @@ Add the following information to your config file. Change the values for name, e
|
|||||||
|
|
||||||
- BotVac Connected (Firmware 2.2.0)
|
- BotVac Connected (Firmware 2.2.0)
|
||||||
|
|
||||||
If you have another connected neato robot, please [tell me](https://github.com/naofireblade/homebridge-neato/issues) your experience with this plugin.
|
If you have another connected neato robot, please [tell me](https://github.com/naofireblade/homebridge-neato/issues) about your experience with this plugin.
|
256
index.js
256
index.js
@ -1,9 +1,18 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
var inherits = require('util').inherits;
|
var inherits = require('util').inherits,
|
||||||
var debug = require('debug')('homebridge-neato');
|
debug = require('debug')('homebridge-neato'),
|
||||||
var botvac = require('node-botvac');
|
botvac = require('node-botvac'),
|
||||||
|
|
||||||
var Service, Characteristic;
|
Service,
|
||||||
|
Characteristic,
|
||||||
|
vacuumRobotCleanService,
|
||||||
|
vacuumRobotGoToDockService,
|
||||||
|
vacuumRobotDockStateService,
|
||||||
|
vacuumRobotEcoService,
|
||||||
|
vacuumRobotScheduleService,
|
||||||
|
vacuumRobotBatteryService,
|
||||||
|
refresh,
|
||||||
|
timer
|
||||||
|
|
||||||
module.exports = function (homebridge) {
|
module.exports = function (homebridge) {
|
||||||
Service = homebridge.hap.Service;
|
Service = homebridge.hap.Service;
|
||||||
@ -18,8 +27,28 @@ function NeatoVacuumRobot(log, config) {
|
|||||||
this.email = config['email'];
|
this.email = config['email'];
|
||||||
this.password = config['password'];
|
this.password = config['password'];
|
||||||
|
|
||||||
|
// load refresh time
|
||||||
|
// default 120s
|
||||||
|
this.refresh = ('refresh' in config ? parseInt(config['refresh']) : 120);
|
||||||
|
// must be integer and positive
|
||||||
|
if (typeof this.refresh !=='number' || (this.refresh%1)!==0 || this.refresh < 0) {
|
||||||
|
this.refresh = 0;
|
||||||
|
}
|
||||||
|
// minimum 60s
|
||||||
|
if (this.refresh != 0 && this.refresh < 60) {
|
||||||
|
this.refresh = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.vacuumRobotScheduleService = new Service.Switch(this.name + " Schedule", "schedule");
|
||||||
|
this.vacuumRobotBatteryService = new Service.BatteryService("Battery", "battery");
|
||||||
|
|
||||||
this.lastUpdate = null;
|
this.lastUpdate = null;
|
||||||
this.robot = null;
|
this.robot = null;
|
||||||
|
this.getStateTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
NeatoVacuumRobot.prototype = {
|
NeatoVacuumRobot.prototype = {
|
||||||
@ -35,26 +64,20 @@ NeatoVacuumRobot.prototype = {
|
|||||||
.setCharacteristic(Characteristic.Model, this.name)
|
.setCharacteristic(Characteristic.Model, this.name)
|
||||||
.setCharacteristic(Characteristic.SerialNumber, this.serial);
|
.setCharacteristic(Characteristic.SerialNumber, this.serial);
|
||||||
|
|
||||||
this.vacuumRobotCleanService = new Service.Switch(this.name + " Clean", "clean");
|
this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('set', this.setClean.bind(this));
|
||||||
this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('set', this.clean.bind(this));
|
|
||||||
this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('get', this.getClean.bind(this));
|
this.vacuumRobotCleanService.getCharacteristic(Characteristic.On).on('get', this.getClean.bind(this));
|
||||||
|
|
||||||
this.vacuumRobotGoToDockService = new Service.Switch(this.name + " Go to Dock", "goToDock");
|
this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('set', this.setGoToDock.bind(this));
|
||||||
this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('set', this.dock.bind(this));
|
this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('get', this.getGoToDock.bind(this));
|
||||||
this.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).on('get', this.getCanGoToDock.bind(this));
|
|
||||||
|
|
||||||
this.vacuumRobotDockStateService = new Service.OccupancySensor(this.name + " Dock", "dockState");
|
this.vacuumRobotDockStateService.getCharacteristic(Characteristic.OccupancyDetected).on('get', this.getDock.bind(this));
|
||||||
this.vacuumRobotDockStateService.getCharacteristic(Characteristic.OccupancyDetected).on('get', this.getDockState.bind(this));
|
|
||||||
|
|
||||||
this.vacuumRobotEcoService = new Service.Switch(this.name + " Eco Mode", "eco");
|
this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('set', this.setEco.bind(this));
|
||||||
this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('set', this.eco.bind(this));
|
|
||||||
this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('get', this.getEco.bind(this));
|
this.vacuumRobotEcoService.getCharacteristic(Characteristic.On).on('get', this.getEco.bind(this));
|
||||||
|
|
||||||
this.vacuumRobotScheduleService = new Service.Switch(this.name + " Schedule", "schedule");
|
this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('set', this.setSchedule.bind(this));
|
||||||
this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('set', this.schedule.bind(this));
|
|
||||||
this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('get', this.getSchedule.bind(this));
|
this.vacuumRobotScheduleService.getCharacteristic(Characteristic.On).on('get', this.getSchedule.bind(this));
|
||||||
|
|
||||||
this.vacuumRobotBatteryService = new Service.BatteryService("Battery", "battery");
|
|
||||||
this.vacuumRobotBatteryService.getCharacteristic(Characteristic.BatteryLevel).on('get', this.getBatteryLevel.bind(this));
|
this.vacuumRobotBatteryService.getCharacteristic(Characteristic.BatteryLevel).on('get', this.getBatteryLevel.bind(this));
|
||||||
this.vacuumRobotBatteryService.getCharacteristic(Characteristic.ChargingState).on('get', this.getBatteryChargingState.bind(this));
|
this.vacuumRobotBatteryService.getCharacteristic(Characteristic.ChargingState).on('get', this.getBatteryChargingState.bind(this));
|
||||||
|
|
||||||
@ -62,92 +85,115 @@ NeatoVacuumRobot.prototype = {
|
|||||||
this.vacuumRobotScheduleService, this.vacuumRobotBatteryService];
|
this.vacuumRobotScheduleService, this.vacuumRobotBatteryService];
|
||||||
},
|
},
|
||||||
|
|
||||||
clean: function (on, callback) {
|
setClean: function (on, callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
if (on) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
this.getState(function (error, result) {
|
if (on) {
|
||||||
if (that.robot.canResume === true) {
|
if (that.robot.canResume || that.robot.canStart) {
|
||||||
debug("Resume cleaning");
|
// wait for robot to start and then disable the old timer and enable it again (with a shorter interval)
|
||||||
that.robot.resumeCleaning(function (error, result) {
|
setTimeout(function() {
|
||||||
that.log(result);
|
clearTimeout(that.timer);
|
||||||
});
|
that.getStateTimer();
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
if (that.robot.canResume) {
|
||||||
|
debug("Resume cleaning");
|
||||||
|
that.robot.resumeCleaning(callback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("Start cleaning");
|
||||||
|
that.robot.startCleaning(that.robot.eco, callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
debug("Start cleaning");
|
debug("Already cleaning");
|
||||||
that.robot.startCleaning(that.robot.eco, function (error, result) {
|
callback();
|
||||||
that.log(result);
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (that.robot.canPause) {
|
||||||
|
debug("Pause cleaning");
|
||||||
|
that.robot.pauseCleaning(callback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("Already stopped");
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setGoToDock: function (on, callback) {
|
||||||
|
let that = this;
|
||||||
|
this.getStateAndRobot(function (error, result) {
|
||||||
|
if (on) {
|
||||||
|
if (that.robot.canPause) {
|
||||||
|
debug("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)
|
||||||
}
|
{
|
||||||
else {
|
debug("Go to dock");
|
||||||
debug("Pause cleaning");
|
that.robot.sendToBase(callback);
|
||||||
this.robot.pauseCleaning(false, function (error, result) {
|
}
|
||||||
that.log(result);
|
else {
|
||||||
});
|
debug("Can't go to dock at the moment");
|
||||||
}
|
callback();
|
||||||
callback();
|
}
|
||||||
|
} else {
|
||||||
|
// dont allow manual setting the switch to off
|
||||||
|
setTimeout(function() {
|
||||||
|
that.vacuumRobotGoToDockService.setCharacteristic(Characteristic.On, true);
|
||||||
|
callback();
|
||||||
|
},1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
dock: function (on, callback) {
|
setEco: function (on, callback) {
|
||||||
let that = this;
|
|
||||||
if (on) {
|
|
||||||
debug("Pause cleaning to go to dock");
|
|
||||||
this.robot.pauseCleaning(false, function (error, result) {
|
|
||||||
that.log(result);
|
|
||||||
});
|
|
||||||
setTimeout(function() {
|
|
||||||
debug("Go to dock");
|
|
||||||
that.robot.sendToBase(false, function (error, result) {
|
|
||||||
that.log(result);
|
|
||||||
});
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
|
|
||||||
eco: function (on, callback) {
|
|
||||||
debug(on ? "Enable eco mode" : "Disable eco mode");
|
debug(on ? "Enable eco mode" : "Disable eco mode");
|
||||||
this.robot.eco = on;
|
this.robot.eco = on;
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
|
|
||||||
schedule: function (on, callback) {
|
setSchedule: function (on, callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
if (on) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
debug("Enable schedule");
|
if (on) {
|
||||||
this.robot.enableSchedule(false, function (error, result) {
|
debug("Enable schedule");
|
||||||
that.log(result);
|
that.robot.enableSchedule(callback);
|
||||||
});
|
}
|
||||||
}
|
else {
|
||||||
else {
|
debug("Disable schedule");
|
||||||
debug("Disable schedule");
|
that.robot.disableSchedule(callback);
|
||||||
this.robot.disableSchedule(false, function (error, result) {
|
}
|
||||||
that.log(result);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getClean: function(callback) {
|
getClean: function(callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.getState(function (error, result) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
debug("Is cleaning: " + that.robot.canPause);
|
debug("Is cleaning: " + that.robot.canPause);
|
||||||
callback(false, that.robot.canPause);
|
callback(false, that.robot.canPause);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getCanGoToDock: function(callback) {
|
getGoToDock: function(callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.getState(function (error, result) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
debug("Can go to dock: " + that.robot.dockHasBeenSeen);
|
debug("Can go to dock: " + that.robot.dockHasBeenSeen);
|
||||||
callback(false, !that.robot.dockHasBeenSeen);
|
callback(false, !that.robot.dockHasBeenSeen);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getDockState: function(callback) {
|
getDock: function(callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.getState(function (error, result) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
debug("Is docked: " + that.robot.isDocked);
|
debug("Is docked: " + that.robot.isDocked);
|
||||||
debug(that.robot);
|
debug(that.robot);
|
||||||
callback(false, that.robot.isDocked);
|
callback(false, that.robot.isDocked);
|
||||||
@ -155,16 +201,13 @@ NeatoVacuumRobot.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getEco: function(callback) {
|
getEco: function(callback) {
|
||||||
let that = this;
|
// dont load eco here, because we cant save the eco state on the robot
|
||||||
this.getState(function (error, result) {
|
callback(false, this.robot.eco);
|
||||||
debug("Eco mode: " + that.robot.eco);
|
|
||||||
callback(false, that.robot.eco);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getSchedule: function(callback) {
|
getSchedule: function(callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.getState(function (error, result) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
debug("Schedule: " + that.robot.isScheduleEnabled);
|
debug("Schedule: " + that.robot.isScheduleEnabled);
|
||||||
callback(false, that.robot.isScheduleEnabled);
|
callback(false, that.robot.isScheduleEnabled);
|
||||||
});
|
});
|
||||||
@ -173,7 +216,7 @@ NeatoVacuumRobot.prototype = {
|
|||||||
|
|
||||||
getBatteryLevel: function(callback) {
|
getBatteryLevel: function(callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.getState(function (error, result) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
debug("Battery: " + that.robot.charge);
|
debug("Battery: " + that.robot.charge);
|
||||||
callback(false, that.robot.charge);
|
callback(false, that.robot.charge);
|
||||||
});
|
});
|
||||||
@ -181,32 +224,32 @@ NeatoVacuumRobot.prototype = {
|
|||||||
|
|
||||||
getBatteryChargingState: function(callback) {
|
getBatteryChargingState: function(callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.getState(function (error, result) {
|
this.getStateAndRobot(function (error, result) {
|
||||||
debug("Is charging: " + that.robot.isCharging);
|
debug("Is charging: " + that.robot.isCharging);
|
||||||
callback(false, that.robot.isCharging);
|
callback(false, that.robot.isCharging);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getState: function(callback) {
|
getStateAndRobot: function(callback) {
|
||||||
let that = this;
|
let that = this;
|
||||||
if (this.robot === null)
|
if (this.robot === null)
|
||||||
{
|
{
|
||||||
this.getRobot(function (error, result) {
|
this.getRobot(function (error, result) {
|
||||||
that._getState(callback);
|
that.getState(callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
that._getState(callback);
|
that.getState(callback);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_getState: function(callback) {
|
getState: function(callback) {
|
||||||
if (this.lastUpdate !== null && new Date() - this.lastUpdate < 2000) {
|
if (this.lastUpdate !== null && new Date() - this.lastUpdate < 2000) {
|
||||||
debug("Get info (cached)");
|
debug("Get state (cached)");
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
debug("Get info (new)");
|
debug("Get state (new)");
|
||||||
let that = this;
|
let that = this;
|
||||||
this.robot.getState(function (error, result) {
|
this.robot.getState(function (error, result) {
|
||||||
that.lastUpdate = new Date();
|
that.lastUpdate = new Date();
|
||||||
@ -215,6 +258,45 @@ NeatoVacuumRobot.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getStateTimer: function() {
|
||||||
|
debug("Timer called");
|
||||||
|
let that = this;
|
||||||
|
this.getStateAndRobot(function (error, result) {
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (that.vacuumRobotGoToDockService.getCharacteristic(Characteristic.On).value !== !that.robot.dockHasBeenSeen) {
|
||||||
|
that.vacuumRobotGoToDockService.setCharacteristic(Characteristic.On, !that.robot.dockHasBeenSeen);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
that.vacuumRobotBatteryService.setCharacteristic(Characteristic.BatteryLevel, that.robot.charge);
|
||||||
|
that.vacuumRobotBatteryService.setCharacteristic(Characteristic.ChargingState, that.robot.isCharging);
|
||||||
|
|
||||||
|
// dont update eco, because we cant write that value onto the robot and dont want it to be overwritten in our plugin
|
||||||
|
|
||||||
|
if (that.robot.canPause) {
|
||||||
|
debug("Short timer set: 10s");
|
||||||
|
that.timer = setTimeout(that.getStateTimer.bind(that), 10 * 1000);
|
||||||
|
}
|
||||||
|
else if (that.refresh != 0) {
|
||||||
|
debug("Long timer set: " + that.refresh + "s");
|
||||||
|
that.timer = setTimeout(that.getStateTimer.bind(that), that.refresh * 1000);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("Disabled timer");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
getRobot: function(callback) {
|
getRobot: function(callback) {
|
||||||
debug("Get robot");
|
debug("Get robot");
|
||||||
let client = new botvac.Client();
|
let client = new botvac.Client();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "homebridge-neato",
|
"name": "homebridge-neato",
|
||||||
"version": "0.2.1",
|
"version": "0.3.0",
|
||||||
"description": "A Neato vacuum robot plugin for homebridge.",
|
"description": "A Neato vacuum robot plugin for homebridge.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
Loading…
Reference in New Issue
Block a user