add acceleration logger

pull/658/head
Gordon Williams 2021-02-03 10:06:00 +00:00
parent f34fa81600
commit 55a3fb08d3
7 changed files with 283 additions and 0 deletions

View File

@ -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",

1
apps/accellog/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: New App!

25
apps/accellog/README.md Normal file
View File

@ -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

View File

@ -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="))

132
apps/accellog/app.js Normal file
View File

@ -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();

BIN
apps/accellog/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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>