Fixed device timeline.

Ylian Saint-Hilaire committed Mar 20, 2019 at 12:40 UTC 9b214361cc551092a6c72560025b68c447865360
4 files changed +60 -15
meshuser.js
+10 -13
@@ -342,33 +342,30 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
342 var timeline = [], time = null, previousPower;
343 for (i in docs) {
344 var doc = docs[i];
345 +
346 + // Skip all starting power 0 events.
347 + if ((time == null) && (doc.power == 0) && ((doc.oldPower == null) || (doc.oldPower == 0))) { continue; }
348 +
349 doc.time = Date.parse(doc.time);
350 if (time == null) {
351 // First element
352 time = doc.time;
353 if (doc.oldPower) { timeline.push(doc.oldPower); } else { timeline.push(0); }
350 - timeline.push(time);
354 + timeline.push(time / 1000);
355 timeline.push(doc.power);
356 previousPower = doc.power;
357 } else {
358 // Delta element
355 - if ((previousPower != doc.power) && ((doc.time - time) > 60000)) { // To boost speed, any blocks less than a minute get approximated.
359 + if ((previousPower != doc.power) && ((doc.time - time) > 60000)) { // To boost speed, small blocks get approximated.
360 // Create a new timeline
357 - timeline.push(doc.time - time);
361 + timeline.push((doc.time - time) / 1000);
362 timeline.push(doc.power);
363 time = doc.time;
364 previousPower = doc.power;
365 } else {
362 - // Extend the previous timeline
363 - if ((timeline.length >= 6) && (timeline[timeline.length - 3] == doc.power)) { // We can merge the block with the previous block
364 - timeline[timeline.length - 4] += (timeline[timeline.length - 2] + (doc.time - time));
365 - timeline.pop();
366 - timeline.pop();
367 - } else { // Extend the last block in the timeline
368 - timeline[timeline.length - 2] += (doc.time - time);
369 - timeline[timeline.length - 1] = doc.power;
370 - }
371 - time = doc.time;
366 + // Merge with previous timeline
367 + timeline[timeline.length - 2] += ((doc.time - time) / 1000);
368 + timeline[timeline.length - 1] = doc.power;
369 previousPower = doc.power;
370 }
371 }
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.3.0-r",
3 + "version": "0.3.0-s",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
views/default.handlebars
+8 -1
@@ -1279,6 +1279,7 @@
1279 powerTimelineNode = message.nodeid;
1280 powerTimeline = message.timeline;
1281 powerTimelineUpdate = Date.now() + 300000; // Update every 5 minutes
1282 + for (var i in powerTimeline) { if (i % 2 == 1) { powerTimeline[i] = powerTimeline[i] * 1000; } } // Decompress time
1283 if (currentNode._id == message.nodeid) { masterUpdate(256); }
1284 break;
1285 }
@@ -3867,7 +3868,13 @@
3868 ++count;
3869 date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
3870 }
3870 - QH('p10html2', '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:center;width:150px>Day</th><th scope=col style=text-align:center>7 Day Power State</th></tr>' + x + '</tbody></table>');
3871 + QH('p10html2', '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:center;width:150px>Day</th><th scope=col style=text-align:center><img style=float:right;cursor:pointer;padding:3px onclick=p10downloadPowerEvents() title="Download power events" src="images/link4.png" />7 Day Power State</th></tr>' + x + '</tbody></table>');
3872 + }
3873 +
3874 + // Download the power events for the current device
3875 + function p10downloadPowerEvents() {
3876 + console.log("devicepowerevents?id=" + currentNode._id);
3877 + fileDownload("devicepowerevents.ashx?id=" + currentNode._id, "powerevents-" + currentNode.name + ".csv");
3878 }
3879
3880 // Return a color for the given power state
webserver.js
+41
@@ -2284,6 +2284,46 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2284 res.send(meshsettings);
2285 };
2286
2287 + // Handle a request for power events
2288 + obj.handleDevicePowerEvents = function (req, res) {
2289 + const domain = checkUserIpAddress(req, res);
2290 + if (domain == null) return;
2291 + if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid) || (req.query.id == null) || (typeof req.query.id != 'string')) { res.sendStatus(401); return; }
2292 + var x = req.query.id.split('/');
2293 + var user = obj.users[req.session.userid];
2294 + if ((x.length != 3) || (x[0] != 'node') || (x[1] != domain.id) || (user == null) || (user.links == null)) { res.sendStatus(401); return; }
2295 +
2296 + obj.db.Get(req.query.id, function (err, docs) {
2297 + if (docs.length != 1) {
2298 + res.sendStatus(401);
2299 + } else {
2300 + var node = docs[0];
2301 +
2302 + // Check if we have right to this node
2303 + var rights = 0;
2304 + for (var i in user.links) { if (i == node.meshid) { rights = user.links[i].rights; } }
2305 + if (rights == 0) { res.sendStatus(401); return; }
2306 +
2307 + // Get the list of power events and send them
2308 + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename=powerevents.csv' });
2309 + obj.db.getPowerTimeline(node._id, function (err, docs) {
2310 + var xevents = [ 'Time, State, Previous State' ], prevState = 0;
2311 + for (var i in docs) {
2312 + if (docs[i].power != prevState) {
2313 + prevState = docs[i].power;
2314 + if (docs[i].oldPower != null) {
2315 + xevents.push(docs[i].time.toString() + ',' + docs[i].power + ',' + docs[i].oldPower);
2316 + } else {
2317 + xevents.push(docs[i].time.toString() + ',' + docs[i].power);
2318 + }
2319 + }
2320 + }
2321 + res.send(xevents.join('\r\n'));
2322 + });
2323 + }
2324 + });
2325 + }
2326 +
2327 // Starts the HTTPS server, this should be called after the user/mesh tables are loaded
2328 function serverStart() {
2329 // Start the server, only after users and meshes are loaded from the database.
@@ -2368,6 +2408,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2408 obj.app.get(url + 'messenger', handleMessengerRequest);
2409 obj.app.get(url + 'meshosxagent', obj.handleMeshOsxAgentRequest);
2410 obj.app.get(url + 'meshsettings', obj.handleMeshSettingsRequest);
2411 + obj.app.get(url + 'devicepowerevents.ashx', obj.handleDevicePowerEvents);
2412 obj.app.get(url + 'downloadfile.ashx', handleDownloadFile);
2413 obj.app.post(url + 'uploadfile.ashx', handleUploadFile);
2414 obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);