mirror of https://github.com/espruino/BangleApps
add acceleration logger
parent
f34fa81600
commit
55a3fb08d3
17
apps.json
17
apps.json
|
@ -2189,6 +2189,23 @@
|
|||
{"wildcard":"accelrec.?.csv" }
|
||||
]
|
||||
},
|
||||
{ "id": "accellog",
|
||||
"name": "Acceleration Logger",
|
||||
"shortName":"Accel Log",
|
||||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"interface": "interface.html",
|
||||
"description": "Logs XYZ acceleration data to a CSV file that can be downloaded to your PC",
|
||||
"tags": "outdoor",
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"accellog.app.js","url":"app.js"},
|
||||
{"name":"accellog.img","url":"app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [
|
||||
{"wildcard":"accellog.?.csv" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cprassist",
|
||||
"name":"CPR Assist",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,25 @@
|
|||
# Acceleration Logger
|
||||
|
||||
Logs XYZ acceleration data (at the normal 12.5Hz) to a CSV file that can be downloaded to your PC.
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Describe how to use it
|
||||
|
||||
## Features
|
||||
|
||||
Name the function
|
||||
|
||||
## Controls
|
||||
|
||||
Name the buttons and what they are used for
|
||||
|
||||
## Requests
|
||||
|
||||
Name who should be contacted for support/update requests
|
||||
|
||||
## Creator
|
||||
|
||||
Your name
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("oFAwhC/AH4A2xAedhGIwA+dAAI+dAAJAcEAJ/fD/4f5hAJIYSo6JIihaKxBATxAACC4YnBAAQ+TD7o/CFRJfTP5a/eb6pEOD/7JFwczAA0ybgwfUkUjD4QaDD6syiMSD4ZABCIa8JD547BCIY/ZHQQ+LD6Z/cHZYf/f6E4D6uCD4gACD6wgBkQACBAYfWABYf/D/4fPwf/ABgf/D6czABBf/P/5f/P/5f/D+WIABwfuAH4A/ADo="))
|
|
@ -0,0 +1,132 @@
|
|||
var fileNumber = 0;
|
||||
var MAXLOGS = 9;
|
||||
|
||||
function getFileName(n) {
|
||||
return "accellog."+n+".csv";
|
||||
}
|
||||
|
||||
function showMenu() {
|
||||
var menu = {
|
||||
"" : { title : "Accel Logger" },
|
||||
"File No" : {
|
||||
value : fileNumber,
|
||||
min : 0,
|
||||
max : MAXLOGS,
|
||||
onchange : v => { fileNumber=v; }
|
||||
},
|
||||
"Start" : function() {
|
||||
E.showMenu();
|
||||
startRecord();
|
||||
},
|
||||
"View Logs" : function() {
|
||||
viewLogs();
|
||||
},
|
||||
"Exit" : function() {
|
||||
load();
|
||||
},
|
||||
};
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function viewLog(n) {
|
||||
E.showMessage("Loading...");
|
||||
var f = require("Storage").open(getFileName(n), "r");
|
||||
var records = 0, l = "", ll="";
|
||||
while (l=f.readLine()) {records++;ll=l};
|
||||
var length = 0;
|
||||
if (ll) length = (ll.split(",")[0]|0)/1000;
|
||||
|
||||
var menu = {
|
||||
"" : { title : "Log "+n }
|
||||
};
|
||||
menu[records+" Records"] = "";
|
||||
menu[length+" Seconds"] = "";
|
||||
menu["DELETE"] = function() {
|
||||
E.showPrompt("Delete Log "+n).then(ok=>{
|
||||
if (ok) {
|
||||
E.showMessage("Erasing...");
|
||||
f.erase();
|
||||
viewLogs();
|
||||
} else viewLog(n);
|
||||
});
|
||||
};
|
||||
menu["< Back"] = function() {
|
||||
viewLogs();
|
||||
};
|
||||
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function viewLogs() {
|
||||
var menu = {
|
||||
"" : { title : "Logs" }
|
||||
};
|
||||
|
||||
var hadLogs = false;
|
||||
for (var i=0;i<=MAXLOGS;i++) {
|
||||
var f = require("Storage").open(getFileName(i), "r");
|
||||
if (f.readLine()!==undefined) {
|
||||
(function(i) {
|
||||
menu["Log "+i] = () => viewLog(i);
|
||||
})(i);
|
||||
hadLogs = true;
|
||||
}
|
||||
}
|
||||
if (!hadLogs)
|
||||
menu["No Logs Found"] = function(){};
|
||||
menu["< Back"] = function() { showMenu(); };
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function startRecord(force) {
|
||||
if (!force) {
|
||||
// check for existing file
|
||||
var f = require("Storage").open(getFileName(fileNumber), "r");
|
||||
if (f.readLine()!==undefined)
|
||||
return E.showPrompt("Overwrite Log "+fileNumber+"?").then(ok=>{
|
||||
if (ok) startRecord(true); else showMenu();
|
||||
});
|
||||
}
|
||||
// display
|
||||
g.clear(1);
|
||||
Bangle.drawWidgets();
|
||||
var w = g.getWidth();
|
||||
var h = g.getHeight();
|
||||
g.setColor("#ff0000").fillRect(0,h-48,w,h);
|
||||
g.setColor("#ffffff").setFont("6x8",2).setFontAlign(0,0).drawString("RECORDING", w/2,h-24);
|
||||
g.setFont("6x8").drawString("Samples:",w/2,h/3 - 20);
|
||||
g.setFont("6x8").drawString("Time:",w/2,h*2/3 - 20);
|
||||
g.setFont("6x8",2).setFontAlign(0,0,1).drawString("STOP",w-10,h/2);
|
||||
|
||||
// now start writing
|
||||
f = require("Storage").open(getFileName(fileNumber), "w");
|
||||
f.write("Time (ms),X,Y,Z\n");
|
||||
var start = getTime();
|
||||
var sampleCount = 0;
|
||||
|
||||
function accelHandler(accel) {
|
||||
var t = getTime()-start;
|
||||
f.write([
|
||||
t*1000,
|
||||
accel.x*8192,
|
||||
accel.y*8192,
|
||||
accel.z*8192].map(n=>Math.round(n)).join(",")+"\n");
|
||||
|
||||
sampleCount++;
|
||||
g.reset().setFont("6x8",2).setFontAlign(0,0);
|
||||
g.drawString(" "+sampleCount+" ",w/2,h/3,true);
|
||||
g.drawString(" "+Math.round(t)+"s ",w/2,h*2/3,true);
|
||||
}
|
||||
|
||||
Bangle.setPollInterval(80); // 12.5 Hz
|
||||
Bangle.on('accel', accelHandler);
|
||||
setWatch(()=>{
|
||||
Bangle.removeListener('accel', accelHandler);
|
||||
showMenu();
|
||||
}, BTN2);
|
||||
}
|
||||
|
||||
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
showMenu();
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,107 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="data"></div>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
<script>
|
||||
var dataElement = document.getElementById("data");
|
||||
|
||||
function getData() {
|
||||
// show loading window
|
||||
Util.showModal("Loading...");
|
||||
// get the data
|
||||
dataElement.innerHTML = "";
|
||||
var promise = Promise.resolve();
|
||||
Puck.eval('require("Storage").list(/accellog\\..\\.csv\\x01/)',files=>{
|
||||
if (files.length==0) {
|
||||
dataElement.innerHTML = "<p>No saved data</p>";
|
||||
} else {
|
||||
files.forEach(fn => {
|
||||
fn = fn.slice(0,-1);
|
||||
dataElement.innerHTML += `
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">${fn}</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button class="btn btn-primary" fn="${fn}" act="save">Save</button>
|
||||
<button class="btn" fn="${fn}" act="delete">Delete</button>
|
||||
</div>
|
||||
</div>`;
|
||||
promise = promise.then(function() {
|
||||
document.querySelector(`.btn[fn='${fn}'][act='save']`).addEventListener("click", function() {
|
||||
Util.readStorageFile(fn, function(data) {
|
||||
Util.saveCSV(fn.slice(0,-4), data);
|
||||
});
|
||||
});
|
||||
document.querySelector(`.btn[fn='${fn}'][act='delete']`).addEventListener("click", function() {
|
||||
Util.showModal("Deleting...");
|
||||
Util.eraseStorageFile(fn, function() {
|
||||
Util.hideModal();
|
||||
getData();
|
||||
});
|
||||
});
|
||||
return new Promise(resolve=>{
|
||||
Puck.eval(`require("Storage").read(${JSON.stringify(fn)})`,csv=>{
|
||||
fileData[fn] = csv.trim();
|
||||
var el = document.querySelector(`.card-body[fn='${fn}']`);
|
||||
el.innerHTML = '<canvas width="400" height="100"></canvas>';
|
||||
var c = el.firstChild;
|
||||
var ctx = c.getContext("2d");
|
||||
var lines = csv.split("\n");
|
||||
var y = 50, sx = 400/lines.length, sy = 50/8;
|
||||
function plot(n) {
|
||||
var last;
|
||||
ctx.beginPath();
|
||||
lines.map((l,x)=>{
|
||||
l = l.split(",");
|
||||
var yc = y + parseFloat(l[n])*sy;
|
||||
if (!last) {
|
||||
ctx.moveTo(0, yc);
|
||||
} else {
|
||||
ctx.lineTo(x*sx, yc);
|
||||
}
|
||||
last = l;
|
||||
});
|
||||
ctx.stroke();
|
||||
};
|
||||
ctx.strokeStyle = 'red';
|
||||
plot(0);
|
||||
ctx.strokeStyle = 'green';
|
||||
plot(1);
|
||||
ctx.strokeStyle = 'blue';
|
||||
plot(2);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
// remove window
|
||||
Util.hideModal();
|
||||
});
|
||||
}
|
||||
|
||||
// You can call a utility function to save the data
|
||||
/*document.getElementById("btnSave").addEventListener("click", function() {
|
||||
Util.saveCSV("gpsdata", csvData);
|
||||
});
|
||||
// Or you can also delete the file
|
||||
document.getElementById("btnDelete").addEventListener("click", function() {
|
||||
Util.showModal("Deleting...");
|
||||
Util.eraseStorageFile("gpspoilog.csv", function() {
|
||||
Util.hideModal();
|
||||
getData();
|
||||
});
|
||||
});*/
|
||||
// Called when app starts
|
||||
function onInit() {
|
||||
getData();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue