Moved update logic to platform to reduce server requests for multiple rooms

This commit is contained in:
Arne
2019-09-21 23:43:44 +02:00
parent 7594843bb3
commit 114ff70d60
3 changed files with 257 additions and 226 deletions

222
index.js
View File

@@ -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");
}
});
},
};