Moved update logic to platform to reduce server requests for multiple rooms
This commit is contained in:
222
index.js
222
index.js
@@ -21,6 +21,9 @@ function NeatoVacuumRobotPlatform(log, config)
|
||||
this.password = config['password'];
|
||||
this.hiddenServices = ('disabled' in config ? config['disabled'] : '');
|
||||
|
||||
// Array of real robots and associated robot accessories (incl rooms)
|
||||
this.robots = [];
|
||||
|
||||
if ('refresh' in config && config['refresh'] !== 'auto')
|
||||
{
|
||||
// parse config parameter
|
||||
@@ -28,52 +31,62 @@ function NeatoVacuumRobotPlatform(log, config)
|
||||
// must be integer and positive
|
||||
this.refresh = (typeof this.refresh !== 'number' || (this.refresh % 1) !== 0 || this.refresh < 0) ? 60 : this.refresh;
|
||||
// minimum 60s to save some load on the neato servers
|
||||
this.refresh = (this.refresh > 0 && this.refresh < 60) ? 60 : this.refresh;
|
||||
if (this.refresh > 0 && this.refresh < 60)
|
||||
{
|
||||
this.log.warn("Minimum refresh time is 60 seconds to not overload the neato servers");
|
||||
this.refresh = (this.refresh > 0 && this.refresh < 60) ? 60 : this.refresh;
|
||||
}
|
||||
}
|
||||
// default auto
|
||||
else
|
||||
{
|
||||
this.refresh = 'auto';
|
||||
}
|
||||
debug("Refresh is set to: " + this.refresh);
|
||||
this.log("Refresh is set to: " + this.refresh + (this.refresh !== 'auto' ? ' seconds' : ''));
|
||||
}
|
||||
|
||||
NeatoVacuumRobotPlatform.prototype = {
|
||||
accessories: function (callback)
|
||||
{
|
||||
debug("##############################################");
|
||||
debug("################# GET ROBOTS #################");
|
||||
debug("##############################################");
|
||||
let accessories = [];
|
||||
let platform = this;
|
||||
platform.boundaryNames = [];
|
||||
this.getRobots(function ()
|
||||
this.boundaryNames = [];
|
||||
this.getRobots(() =>
|
||||
{
|
||||
if (platform.robots)
|
||||
this.robots.forEach((robot, i) =>
|
||||
{
|
||||
platform.robots.forEach((robot, i) =>
|
||||
this.log("Found robot #" + (i + 1) + " named \"" + robot.device.name + "\" with serial \"" + robot.device._serial + "\"");
|
||||
this.updateRobotTimer(robot.device._serial);
|
||||
|
||||
let NeatoVacuumRobotAccessory = require('./accessories/neatoVacuumRobot')(Service, Characteristic);
|
||||
let mainAccessory = new NeatoVacuumRobotAccessory(robot, this);
|
||||
accessories.push(mainAccessory);
|
||||
|
||||
robot.mainAccessory = mainAccessory;
|
||||
robot.roomAccessories = [];
|
||||
|
||||
if (robot.device.maps)
|
||||
{
|
||||
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.device.maps.forEach((map) =>
|
||||
{
|
||||
robot.maps.forEach((map) =>
|
||||
if (map.boundaries)
|
||||
{
|
||||
if (map.boundaries)
|
||||
map.boundaries.forEach((boundary) =>
|
||||
{
|
||||
map.boundaries.forEach((boundary) =>
|
||||
if (boundary.type === "polygon")
|
||||
{
|
||||
if (boundary.type === "polygon")
|
||||
{
|
||||
accessories.push(new NeatoVacuumRobotAccessory(robot, platform, boundary))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
let roomAccessory = new NeatoVacuumRobotAccessory(robot, this, boundary);
|
||||
accessories.push(roomAccessory);
|
||||
|
||||
robot.roomAccessories.push(roomAccessory);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
callback(accessories);
|
||||
});
|
||||
},
|
||||
@@ -82,83 +95,162 @@ NeatoVacuumRobotPlatform.prototype = {
|
||||
{
|
||||
debug("Loading your robots");
|
||||
let client = new botvac.Client();
|
||||
let that = this;
|
||||
|
||||
// Login
|
||||
client.authorize(this.email, this.password, false, (error) =>
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
that.log(error);
|
||||
that.log.error("Can't log on to neato cloud. Please check your internet connection and your credentials. Try again later if the neato servers have issues.");
|
||||
this.log.error("Can't log on to neato cloud. Please check your internet connection and your credentials. Try again later if the neato servers have issues: " + error);
|
||||
callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get robots
|
||||
client.getRobots((error, robots) =>
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
that.log(error);
|
||||
that.log.error("Successful login but can't connect to your neato robot.");
|
||||
this.log.error("Successful login but can't connect to your neato robot: " + error);
|
||||
callback();
|
||||
}
|
||||
else if (robots.length === 0)
|
||||
{
|
||||
this.log.error("Successful login but no robots associated with your account.");
|
||||
this.robots = [];
|
||||
callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (robots.length === 0)
|
||||
debug("Found " + robots.length + " robots");
|
||||
let requestedRobot = 0;
|
||||
|
||||
robots.forEach((robot) =>
|
||||
{
|
||||
that.log.error("Successful login but no robots associated with your account.");
|
||||
that.robots = [];
|
||||
callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Found " + robots.length + " robots");
|
||||
let updatedRobotCount = 0;
|
||||
that.robots = robots;
|
||||
that.robots.forEach((robot) =>
|
||||
// Get Maps for each robot
|
||||
robot.getPersistentMaps((error, result) =>
|
||||
{
|
||||
robot.getPersistentMaps((error, result) =>
|
||||
if (error)
|
||||
{
|
||||
this.log.error("Error updating persistent maps: " + error + ": " + result);
|
||||
callback();
|
||||
}
|
||||
else if (result.length === 0)
|
||||
{
|
||||
robot.maps = [];
|
||||
callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
that.log("Error updating persistent maps: " + error + ": " + result);
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
robot.maps = result;
|
||||
let processedMapCount = 0;
|
||||
if (robot.maps.length === 0)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
let requestedMap = 0;
|
||||
robot.maps.forEach((map) =>
|
||||
{
|
||||
// Get Map Boundary Lines
|
||||
robot.getMapBoundaries(map.id, (error, result) =>
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
this.log("error getting boundaries: " + error + ": " + result)
|
||||
this.log.error("Error getting boundaries: " + error + ": " + result)
|
||||
}
|
||||
else
|
||||
{
|
||||
map.boundaries = result.boundaries;
|
||||
}
|
||||
processedMapCount++;
|
||||
if (processedMapCount === robot.maps.length)
|
||||
requestedMap++;
|
||||
|
||||
// Robot is completely requested if all maps are requested
|
||||
if (requestedMap === robot.maps.length)
|
||||
{
|
||||
updatedRobotCount++;
|
||||
if (updatedRobotCount === that.robots.length)
|
||||
this.robots.push({device: robot});
|
||||
requestedRobot++;
|
||||
|
||||
// Initial request is complete if all robots are requested.
|
||||
if (requestedRobot === robots.length)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
updateRobot: function (serial, callback)
|
||||
{
|
||||
let robot = this.getRobot(serial);
|
||||
|
||||
// Data is up to date
|
||||
if (typeof (robot.lastUpdate) !== 'undefined' && new Date() - robot.lastUpdate < 2000)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
debug(robot.device.name + ": ++ Updating robot state");
|
||||
robot.device.getState(function (error, result)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
this.log.error("Cannot update robot. Check if robot is online. " + error);
|
||||
}
|
||||
robot.lastUpdate = new Date();
|
||||
callback();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getRobot(serial)
|
||||
{
|
||||
let result;
|
||||
this.robots.forEach(function (robot)
|
||||
{
|
||||
if (robot.device._serial === serial)
|
||||
{
|
||||
result = robot;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
updateRobotTimer: function (serial)
|
||||
{
|
||||
this.updateRobot(serial, () =>
|
||||
{
|
||||
let robot = this.getRobot(serial);
|
||||
// Clear any other overlapping timers for this robot
|
||||
clearTimeout(robot.timer);
|
||||
|
||||
// Tell all accessories of this robot (mainAccessory and roomAccessories) that updated robot data is available
|
||||
robot.mainAccessory.updated();
|
||||
robot.roomAccessories.forEach(accessory =>
|
||||
{
|
||||
accessory.updated();
|
||||
});
|
||||
|
||||
// Periodic refresh interval set in config
|
||||
if (this.refresh !== 'auto' && this.refresh !== 0)
|
||||
{
|
||||
debug(robot.device.name + ": ++ Next background update in " + this.refresh + " seconds");
|
||||
robot.timer = setTimeout(this.updateRobotTimer.bind(this), this.refresh * 1000, serial);
|
||||
}
|
||||
// Auto refresh set in config
|
||||
else if (this.refresh === 'auto' && robot.device.canPause)
|
||||
{
|
||||
debug(robot.device.name + ": ++ Next background update in 60 seconds while cleaning (auto mode)");
|
||||
robot.timer = setTimeout(this.updateRobotTimer.bind(this), 60 * 1000, serial);
|
||||
}
|
||||
// No refresh
|
||||
else
|
||||
{
|
||||
debug(robot.device.name + ": ++ Stopped background updates");
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user