commit
57f2bd7f0c
14
apps.json
14
apps.json
|
|
@ -2536,5 +2536,19 @@
|
|||
{"name":"edisonsball.app.js","url":"app.js"},
|
||||
{"name":"edisonsball.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "hrrawexp",
|
||||
"name": "HRM Data Exporter",
|
||||
"shortName":"HRM Data Exporter",
|
||||
"icon": "app-icon.png",
|
||||
"version":"0.01",
|
||||
"description": "export raw hrm signal data to a csv file",
|
||||
"tags": "",
|
||||
"readme": "README.md",
|
||||
"interface": "interface.html",
|
||||
"storage": [
|
||||
{"name":"hrrawexp.app.js","url":"app.js"},
|
||||
{"name":"hrrawexp.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
Extract hrm raw signal data to CSV file
|
||||
=======================================
|
||||
|
||||
Simple app that will run the heart rate monitor for a defined period of time you set at the start.
|
||||
|
||||
-The app creates a csv file (it's actually just 1 column) and you can download this via My Apps in the App Loader.
|
||||
|
||||
-The max time value is 60 minutes.
|
||||
|
||||
-The first item holds the data/time when the readings were taken and the file is reset each time the app is run.
|
||||
|
||||
-The hrm sensor is sampled @50Hz and this app does not do any processing on it other than clip overly high/extreme values, the array is written as-is. There is an example Python script that can process this signal, smooth it and also extract a myriad of heart rate variability metrics using the hrvanalysis library:
|
||||
https://github.com/jabituyaben/BangleJS-HRM-Signal-Processing
|
||||
|
|
@ -0,0 +1 @@
|
|||
E.toArrayBuffer(atob("MDCBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAP4AAD/8A//AAH//D//gAP//n//gAf/////AA/////+AA/////8MA/////4cB/////w+B/////B+B////+D+B////8H+B////4P+B////w/+B/+P/h/+B/+H/D/+A/+D+H/8A//h8P/8A//w4f/8Af/4A//4Af/8B//4AP/+D//wAP//H//wAH/////gAD/////AAB////+AAA////+AAAf///8AAAP///wAAAH///gAAAD///AAAAA//+AAAAAf/4AAAAAH/gAAAAAB+AAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="))
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 826 B |
|
|
@ -0,0 +1,97 @@
|
|||
var counter = 1;
|
||||
var logging_started;
|
||||
var interval;
|
||||
var value;
|
||||
|
||||
var file = require("Storage").open("hrm_log.csv", "w");
|
||||
file.write("");
|
||||
|
||||
file = require("Storage").open("hrm_log.csv", "a");
|
||||
|
||||
function update_timer() {
|
||||
g.clear();
|
||||
g.setColor("#00ff7f");
|
||||
g.setFont("6x8", 4);
|
||||
g.setFontAlign(0, 0); // center font
|
||||
|
||||
g.drawString(counter, 120, 120);
|
||||
g.setFont("6x8", 2);
|
||||
g.setFontAlign(-1, -1);
|
||||
g.drawString("-", 220, 200);
|
||||
g.drawString("+", 220, 40);
|
||||
g.drawString("GO", 210, 120);
|
||||
|
||||
g.setColor("#ffffff");
|
||||
g.setFontAlign(0, 0); // center font
|
||||
g.drawString("Timer (minutes)", 120, 90);
|
||||
|
||||
g.setFont("6x8", 4); // bitmap font, 8x magnified
|
||||
|
||||
if (!logging_started)
|
||||
g.flip();
|
||||
}
|
||||
|
||||
function btn1Pressed() {
|
||||
if (!logging_started) {
|
||||
if (counter < 60)
|
||||
counter += 1;
|
||||
else
|
||||
counter = 1;
|
||||
update_timer();
|
||||
}
|
||||
}
|
||||
|
||||
function btn3Pressed() {
|
||||
if (!logging_started) {
|
||||
if (counter > 1)
|
||||
counter -= 1;
|
||||
else
|
||||
counter = 60;
|
||||
update_timer();
|
||||
}
|
||||
}
|
||||
|
||||
function btn2Pressed() {
|
||||
launchtime = 0 | getTime();
|
||||
file.write(launchtime + "," + "\n");
|
||||
logging_started = true;
|
||||
counter = counter * 60;
|
||||
interval = setInterval(countDown, 1000);
|
||||
Bangle.setHRMPower(1);
|
||||
}
|
||||
|
||||
function fmtMSS(e) {
|
||||
var m = Math.floor(e % 3600 / 60).toString().padStart(2, '0'),
|
||||
s = Math.floor(e % 60).toString().padStart(2, '0');
|
||||
return m + ':' + s;
|
||||
}
|
||||
|
||||
function countDown() {
|
||||
g.clear();
|
||||
counter--;
|
||||
if (counter == 0) {
|
||||
Bangle.setHRMPower(0);
|
||||
clearInterval(interval);
|
||||
g.drawString("Finished", g.getWidth() / 2, g.getHeight() / 2);
|
||||
Bangle.buzz(500, 1);
|
||||
}
|
||||
else
|
||||
g.drawString(fmtMSS(counter), g.getWidth() / 2, g.getHeight() / 2);
|
||||
}
|
||||
|
||||
update_timer();
|
||||
|
||||
setWatch(btn1Pressed, BTN1, { repeat: true });
|
||||
setWatch(btn2Pressed, BTN2, { repeat: true });
|
||||
setWatch(btn3Pressed, BTN3, { repeat: true });
|
||||
|
||||
Bangle.on('HRM', function (hrm) {
|
||||
for (let i = 0; i < hrm.raw.length; i++) {
|
||||
value = hrm.raw[i];
|
||||
if (value < -2)
|
||||
value = -2;
|
||||
if (value > 6)
|
||||
value = 6;
|
||||
file.write(value + "," + "\n");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="data"></div>
|
||||
<button class="btn btn-default" id="btnSave">Save</button>
|
||||
<button class="btn btn-default" id="btnDelete">Delete</button>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
<script>
|
||||
var dataElement = document.getElementById("data");
|
||||
var csvData = "";
|
||||
|
||||
function getData() {
|
||||
// show loading window
|
||||
Util.showModal("Loading...");
|
||||
// get the data
|
||||
dataElement.innerHTML = "";
|
||||
Util.readStorageFile(`hrm_log.csv`,data=>{
|
||||
csvData = data.trim();
|
||||
// remove window
|
||||
Util.hideModal();
|
||||
// If no data, report it and exit
|
||||
if (data.length==0) {
|
||||
dataElement.innerHTML = "<b>No data found</b>";
|
||||
return;
|
||||
}
|
||||
else{
|
||||
dataElement.innerHTML = "<b>data file found</b>";
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// You can call a utility function to save the data
|
||||
document.getElementById("btnSave").addEventListener("click", function() {
|
||||
Util.saveCSV("HRM_data", csvData);
|
||||
});
|
||||
// Or you can also delete the file
|
||||
document.getElementById("btnDelete").addEventListener("click", function() {
|
||||
Util.showModal("Deleting...");
|
||||
Util.eraseStorageFile("hrm_log.csv", function() {
|
||||
Util.hideModal();
|
||||
getData();
|
||||
});
|
||||
});
|
||||
// Called when app starts
|
||||
function onInit() {
|
||||
getData();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue