diff --git a/agents/meshcore.js b/agents/meshcore.js
index 0f1dc030..b9e514eb 100644
--- a/agents/meshcore.js
+++ b/agents/meshcore.js
@@ -952,6 +952,13 @@ function createMeshCore(agent) {
p.then(function (u) { mesh.SendCommand({ action: 'msg', type: 'userSessions', sessionid: data.sessionid, data: u, tag: data.tag }); });
break;
}
+ case 'cpuinfo':
+ // CPU & memory utilization
+ var cpuuse = require('sysinfo').cpuUtilization();
+ cpuuse.sessionid = data.sessionid;
+ cpuuse.tag = data.tag;
+ cpuuse.then(function (data) { mesh.SendCommand(JSON.stringify({ action: 'msg', type: 'cpuinfo', cpu: data, memory: require('sysinfo').memUtilization(), sessionid: this.sessionid, tag: this.tag })); }, function (ex) { });
+ break;
default:
// Unknown action, ignore it.
break;
diff --git a/meshuser.js b/meshuser.js
index 812defbd..9a41c189 100644
--- a/meshuser.js
+++ b/meshuser.js
@@ -3899,6 +3899,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != SITERIGHT_ADMIN))) return;
+ // TODO: If we have peer servers, inform...
+ //if (parent.parent.multiServer != null) { parent.parent.multiServer.DispatchMessage({ action: 'uploadagentcore', sessionid: ws.sessionId }); }
+
if (command.type == 'default') {
// Send the default core to the agent
parent.parent.updateMeshCore(function () { parent.sendMeshAgentCore(user, domain, node._id, 'default'); });
diff --git a/public/images/details/graph32.png b/public/images/details/graph32.png
new file mode 100644
index 00000000..6058ee06
Binary files /dev/null and b/public/images/details/graph32.png differ
diff --git a/public/images/details/graph64.png b/public/images/details/graph64.png
new file mode 100644
index 00000000..069ca2a0
Binary files /dev/null and b/public/images/details/graph64.png differ
diff --git a/public/images/views.png b/public/images/views.png
index 00f61b26..ff655385 100644
Binary files a/public/images/views.png and b/public/images/views.png differ
diff --git a/public/styles/style.css b/public/styles/style.css
index aab00387..ed4b672d 100644
--- a/public/styles/style.css
+++ b/public/styles/style.css
@@ -692,6 +692,10 @@ body {
float: right;
}
+#devListToolbarViewIcons3 {
+ float: right;
+}
+
#devListToolbarSpan {
width: 100%;
height: 24px;
@@ -2803,6 +2807,14 @@ a {
width: 28px;
}
+.viewSelector6 {
+ margin-left: 2px;
+ margin-top: 2px;
+ background: url(../images/views.png) -336px 0px;
+ height: 28px;
+ width: 28px;
+}
+
.fulldesk .viewSelector5 {
background: url(../images/views.png) -252px 0px;
}
diff --git a/translate/translate.json b/translate/translate.json
index 6f15a354..ae624b93 100644
--- a/translate/translate.json
+++ b/translate/translate.json
@@ -11062,7 +11062,7 @@
"zh-chs": "细节 -",
"zh-cht": "細節 -",
"xloc": [
- "default.handlebars->container->column_l->p17->p17title->3"
+ "default.handlebars->container->column_l->p17->p17title->5"
]
},
{
@@ -21114,6 +21114,12 @@
"default.handlebars->29->1161"
]
},
+ {
+ "en": "Live Graph",
+ "xloc": [
+ "default.handlebars->container->column_l->p17->p17info->p17graph->1->1->0->3->1->0"
+ ]
+ },
{
"cs": "Načítání…",
"de": "Laden...",
@@ -32945,6 +32951,12 @@
"default.handlebars->29->1420"
]
},
+ {
+ "en": "Show device CPU and memory usage.",
+ "xloc": [
+ "default.handlebars->container->column_l->p17->p17title->devListToolbarViewIcons3"
+ ]
+ },
{
"cs": "Zobrazit informace o umístění zařízení",
"de": "Geräte-Standortinformationen anzeigen",
diff --git a/views/default.handlebars b/views/default.handlebars
index 8dcbab94..4bc3be1b 100644
--- a/views/default.handlebars
+++ b/views/default.handlebars
@@ -875,9 +875,27 @@
-
+
+
+
+
+
+
+ |
+
+ Live Graph
+
+
+
+ |
+
+
+
+
+
@@ -2153,7 +2171,14 @@
if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } } }
if (index != -1) {
// Node was found, dispatch the message
- if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
+ if ((message.type == 'cpuinfo') && (currentNode != null) && (currentNode._id == message.nodeid)) {
+ var now = (Date.now() / 1000), cpu = 0, memory = 0;
+ if (typeof message.cpu.total == 'number') { cpu = message.cpu.total; }
+ if (typeof message.memory.percentConsumed == 'number') { memory = message.memory.percentConsumed; }
+ console.log(message.cpu);
+ deviceDetailsStatsData.push([now, cpu, memory]);
+ deviceDetailsStatsDraw();
+ } else if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
else if (message.type == 'notify') { // This is a notification message.
var n = getstore('notifications', 0);
if (((n & 8) == 0) && (message.amtMessage != null)) { break; } // Intel AMT desktop & terminal messages should be ignored.
@@ -5583,6 +5608,7 @@
//disconnectAllKvmFunction();
var node = getNodeFromId(nodeid);
if (node == null) return;
+ if ((currentNode == null) || (currentNode._id != node._id) || ((node.conn & 1) == 0)) { deviceDetailsStatsClear(); } // Hide the list cpu/memory graph
var mesh = meshes[node.meshid];
var meshrights = GetNodeRights(node);
var deviceSwitch = ((currentNode == null) || (currentNode._id != nodeid));
@@ -5921,7 +5947,7 @@
meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
meshserver.send({ action: 'getsysinfo', nodeid: currentNode._id });
meshserver.send({ action: 'getnetworkinfo', nodeid: currentNode._id });
- QH('p17info', '');
+ QH('p17info2', '');
}
// Request device sharing
@@ -8602,6 +8628,67 @@
// DEVICE DETAILS
//
+ var deviceDetailsStats = null;
+ var deviceDetailsStatsTimer = null;
+ var deviceDetailsStatsData = [];
+ var deviceDetailsConfig = {
+ type: 'line',
+ data: {
+ labels: [],
+ datasets: [
+ { label: 'CPU', backgroundColor: 'rgba(134, 16, 158, .5)', borderColor: 'rgb(134, 16, 158)', data: [], fill: true },
+ { label: 'Memory', backgroundColor: 'rgba(255, 99, 132, .5)', borderColor: 'rgb(255, 99, 132)', data: [], fill: true }
+ ] },
+ options: {
+ animation: false,
+ responsive: true,
+ maintainAspectRatio: false,
+ tooltips: { enabled: false },
+ elements: { line: { cubicInterpolationMode: 'monotone' } },
+ scales: {
+ xAxes: [{ type: 'linear', display: true, scaleLabel: { display: false, labelString: '' }, ticks: { min: 0, max: 100 } }],
+ yAxes: [{ type: 'linear', display: true, scaleLabel: { display: false, labelString: '' }, ticks: { min: 0, max: 100 } }]
+ }
+ }
+ };
+
+ function deskToggleCpuGraph() {
+ var visible = (QS('p17graph').display == 'none');
+ if (visible) {
+ QV('p17graph', true);
+ window.deviceDetailsStatsChart = new Chart(document.getElementById('deviceDetailsStats').getContext('2d'), deviceDetailsConfig);
+ deviceDetailsStatsTimer = setInterval(deviceDetailsStatsTimerFunc, 2000);
+ deviceDetailsStatsTimerFunc();
+ } else deviceDetailsStatsClear();
+ }
+
+ function deviceDetailsStatsClear() {
+ QV('p17graph', false);
+ if (window.deviceDetailsStatsChart != null) { delete window.deviceDetailsStatsChart; }
+ if (deviceDetailsStatsTimer != null) { clearInterval(deviceDetailsStatsTimer); deviceDetailsStatsTimer = null; }
+ deviceDetailsStatsData = [];
+ }
+
+ function deviceDetailsStatsTimerFunc() {
+ if (currentNode != null) { meshserver.send({ action: 'msg', type: 'cpuinfo', nodeid: currentNode._id }); }
+ }
+
+ function deviceDetailsStatsDraw() {
+ var now = Date.now() / 1000, oldLimit = (now - 100);
+ while (deviceDetailsStatsData[0][0] < (oldLimit - 5)) { deviceDetailsStatsData.shift(); }
+
+ var cpu = [], memory = [];
+ for (var i in deviceDetailsStatsData) {
+ var d = deviceDetailsStatsData[i];
+ cpu.push({ x: 100 - (d[0] - oldLimit), y: d[1] });
+ memory.push({ x: 100 - (d[0] - oldLimit), y: d[2] });
+ }
+
+ deviceDetailsConfig.data.datasets[0].data = cpu;
+ deviceDetailsConfig.data.datasets[1].data = memory;
+ window.deviceDetailsStatsChart.update();
+ }
+
var DeviceDetailsHardware = null;
var DeviceDetailsNetwork = null;
var DeviceDetailsNodeId = null;
@@ -8842,9 +8929,9 @@
}
if (x == '') {
- QH('p17info', "No information for this device.");
+ QH('p17info2', "No information for this device.");
} else {
- QH('p17info', x);
+ QH('p17info2', x);
}
}
@@ -8932,6 +9019,7 @@
QE('p15uploadCore', false);
QV('p15outputselecttd', false);
}
+ QV('devListToolbarViewIcons3', ((consoleNode.conn & 1) != 0));
}
}