BangleApps/apps/powermanager/interface.html

269 lines
9.2 KiB
HTML

<html>
<head>
<link rel="stylesheet" href="../../css/spectre.min.css">
</head>
<body>
<div id="content"></div>
<script src="../../core/lib/interface.js"></script>
<script>
var domContent = document.getElementById("content");
function download(filename, callback) {
Util.showModal("Downloading power info...");
Util.readStorage(filename, data => {
Util.hideModal();
callback(data);
});
}
function show() {
Util.showModal("Loading...");
domContent.innerHTML = "";
var htmlOverview = `<table class="table table-striped table-hover">
<div>This needs "Logging" to be enabled in power manager settings. The deferred function calls table is only updated on the bangle on reloads.</div>
<thead>
<tr>
<th>Type</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Deferred function calls</td>
<td>
<button class="btn btn-primary" filename="powermanager.def.json" task="deftable">Table</button>
<button class="btn btn-error" filename="powermanager.def.json" task="clear" style="float: right;margin-right: 5px;">Clear</button>
</td>
</tr>
<tr>
<td>Hardware</td>
<td>
<button class="btn btn-primary" filename="powermanager.hw.json" task="hardwaretable">Table</button>
<button class="btn btn-error" filename="powermanager.hw.json" task="clear" style="float: right;margin-right: 5px;">Clear</button>
</td>
</tr>
<tr>
<td>Details (Trace)</td>
<td>
<button class="btn btn-primary" filename="powermanager.log" task="detailstable">Table</button>
<button class="btn btn-error" filename="powermanager.log" task="detailsclear" style="float: right;margin-right: 5px;">Clear</button>
</td>
</tr>
</tbody>
</table>`;
domContent.innerHTML = htmlOverview;
Util.hideModal();
var buttons = domContent.querySelectorAll("button");
for (var i=0;i<buttons.length;i++) {
buttons[i].addEventListener("click",event => {
var button = event.currentTarget;
var filename = button.getAttribute("filename");
if (!filename) return;
var task = button.getAttribute("task");
if (task=="detailsclear") {
Util.showModal("Clearing...");
Util.eraseStorageFile(filename,()=>{
Util.hideModal();
show();
});
}
if (task=="clear") {
Util.showModal("Clearing...");
Util.eraseStorage(filename,()=>{
Util.hideModal();
show();
});
}
if (task=="deftable") {
viewDeferredTable(filename);
}
if (task=="hardwaretable") {
viewHardwareTable(filename);
}
if (task=="detailstable") {
viewDetailsTable(filename);
}
});
}
}
function viewDeferredTable(filename) {
Puck.eval(`require("Storage").list("powermanager.def.json").length > 0`, (f)=>{
if (f) {
Util.showModal("Reading summarized info...");
Util.readStorage(
filename, data => {
Util.hideModal();
let parsed = JSON.parse(data);
let sum = 0;
let rows = [];
for (var i in parsed.deferred) {
sum += parsed.deferred[i];
rows.push({func: i, time: parsed.deferred[i]});
}
rows.sort((a,b)=>{return b.time/sum - a.time/sum;});
let tableRows = "";
for (var i in rows) {
let c = rows[i];
tableRows += `<tr>
<td>${(c.time/1000).toFixed(2)}s</td>
<td>${(c.time/sum*100).toFixed(2)}%</td>
<td><pre>${c.func}</pre></td>`
}
let duration = parsed.saved - parsed.start;
var htmlOverview = `<h1>Deferred function calls</h1>
<button class="btn btn-primary" id="back" style="float: right;margin-right: 5px;margin-left: 10px;">Back</button>
<div>
This are functions used in timeouts and intervals and their accumulated execution times. Recorded in a time span of <b>${Math.round((duration)/1000)}s</b>. Timeouts/intervals have run for <b>${Math.round(sum/1000)}s (${(sum/duration*100).toFixed(2)}%)</b>. Percentages are calculated from summarized timeout/interval running time.
</div>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Time</th>
<th>Percentage</th>
<th>Function</th>
</tr>
</thead>
<tbody>\n`;
htmlOverview += tableRows;
htmlOverview += `</tbody></table>`;
domContent.innerHTML = htmlOverview;
domContent.querySelector("#back").addEventListener("click",event => {
show();
});
//try finding possible sources for the given function, currently does not work because function.toString() not being identical to code in the *.js files.
/*Puck.eval(`require("Storage").list(/.*.js$/)`, (f)=>{
console.log("Found files:", f, rows[1].func);
for (let file of f){
let query = `require("Storage").read('${file}').includes('${rows[1].func}')`;
console.log("Query: " + query);
Puck.eval(query, (r)=>{
if (r) domContent.querySelector("#row_1").innerHTML = file;
console.log("Found", file, r)
});
}
});*/
});
} else {
var htmlOverview = `<h1>Deferred function calls</h1>
<button class="btn btn-primary" id="back" style="float: right;margin-right: 5px;">Back</button>
<div>
No data available.
</div>`;
domContent.innerHTML = htmlOverview;
domContent.querySelector("#back").addEventListener("click",event => {
show();
});
}
});
}
function viewHardwareTable(filename) {
Puck.eval(`require("Storage").list("powermanager.hw.json").length > 0`, (f)=>{
if (f) {
Util.showModal("Reading hardware info...");
Util.readStorage(
filename, data => {
Util.hideModal();
let parsed = JSON.parse(data);
console.log("Hardware", parsed);
let duration = parsed.saved - parsed.start;
let rows = [];
for (var i in parsed.power) {
rows.push({func: i, time: parsed.power[i]});
}
rows.sort((a,b)=>{return b.time/duration - a.time/duration;});
let tableRows = "";
for (var i in rows) {
let c = rows[i];
tableRows += `<tr>
<td>${(c.time/1000).toFixed(2)}s</td>
<td>${(c.time/duration*100).toFixed(2)}%</td>
<td>${c.func}</td>`
}
var htmlOverview = `<h1>Hardware power</h1>
<button class="btn btn-primary" id="back" style="float: right;margin-right: 5px;margin-left: 10px;">Back</button>
<div>
Recorded in a time span of <b>${Math.round(duration/1000)}s</b>. Percentages are calculated from recording time.
</div>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Time</th>
<th>Percentage</th>
<th>Device</th>
</tr>
</thead>
<tbody>\n`;
htmlOverview += tableRows;
htmlOverview += `</tbody></table>`;
domContent.innerHTML = htmlOverview;
domContent.querySelector("#back").addEventListener("click",event => {
show();
});
});
} else {
var htmlOverview = `<h1>Hardware power</h1>
<button class="btn btn-primary" id="back" style="float: right;margin-right: 5px;">Back</button>
<div>
No data available.
</div>`;
domContent.innerHTML = htmlOverview;
domContent.querySelector("#back").addEventListener("click",event => {
show();
});
}
});
}
function viewDetailsTable(filename) {
Util.showModal("Reading details info...");
Util.readStorageFile(
filename, data => {
Util.hideModal();
var htmlOverview = `<h1>Detailed logging</h1>
This is a trace log of all logged power entries, first column denotes the type. p for power, i for interval and t for timeout. Power is logged with old state, new state and calling app if available. Functions are logged with execution duraion and source if available.
<button class="btn btn-primary" id="back" style="float: right;margin-right: 5px;">Back</button>
<table class="table table-striped table-hover">
<tbody>\n`;
let rows = data.trim().split("\n");
for (var row of rows) {
let cols = row.split(",");
htmlOverview += `<tr>
<td>${cols[0]}</td>
<td>${cols[1]}</td>
<td>${cols[2]}</td>
<td>${cols[3]}</td>
<td>${cols[4]}</td>
</tr>`
}
htmlOverview += `</tbody></table>`;
domContent.innerHTML = htmlOverview;
domContent.querySelector("#back").addEventListener("click",event => {
show();
});
});
}
function onInit() {
show();
}
</script>
</body>
</html>