forked from FOSS/BangleApps
bthrv - Write interval data even if values are missing
parent
405de6d6c0
commit
7c3d4c5908
|
@ -1,11 +1,2 @@
|
|||
0.01: New App!
|
||||
0.02: Make overriding the HRM event optional
|
||||
Emit BTHRM event for external sensor
|
||||
Add recorder app plugin
|
||||
0.03: Prevent readings from internal sensor mixing into BT values
|
||||
Mark events with src property
|
||||
Show actual source of event in app
|
||||
0.04: Allow reading additional data if available: HRM battery and position
|
||||
Better caching of scanned BT device properties
|
||||
New setting for not starting the BTHRM together with HRM
|
||||
Save some RAM by not definining functions if disabled in settings
|
||||
0.02: Write available data on reset or kill
|
||||
|
|
|
@ -11,22 +11,20 @@ var currentSlot = 0;
|
|||
var hrvSlots = [10,20,30,60,120,300];
|
||||
var hrvValues = {};
|
||||
var rrRmsProgress;
|
||||
var saved = false;
|
||||
|
||||
var rrNumberOfValues = 0;
|
||||
var rrSquared = 0;
|
||||
var rrLastValue
|
||||
var rrLastValue;
|
||||
var rrMax;
|
||||
var rrMin;
|
||||
|
||||
function calcHrv(rr){
|
||||
//Calculate HRV with RMSSD method: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5624990/
|
||||
for (currentRr of rr){
|
||||
for (var currentRr of rr){
|
||||
if (!rrMax) rrMax = currentRr;
|
||||
if (!rrMin) rrMin = currentRr;
|
||||
rrMax = Math.max(rrMax, currentRr);
|
||||
rrMin = Math.min(rrMin, currentRr);
|
||||
//print("Calc for: " + currentRr);
|
||||
rrNumberOfValues++;
|
||||
if (!rrLastValue){
|
||||
rrLastValue = currentRr;
|
||||
|
@ -34,11 +32,9 @@ function calcHrv(rr){
|
|||
}
|
||||
rrSquared += (rrLastValue - currentRr)*(rrLastValue - currentRr);
|
||||
|
||||
//print("rr²: " + rrSquared);
|
||||
rrLastValue = currentRr;
|
||||
}
|
||||
var rms = Math.sqrt(rrSquared / rrNumberOfValues);
|
||||
//print("rms: " + rms);
|
||||
return rms;
|
||||
}
|
||||
|
||||
|
@ -62,10 +58,29 @@ function draw(y, hrv) {
|
|||
g.setRotation(0);
|
||||
}
|
||||
|
||||
function write(){
|
||||
if (!hrvValues[hrvSlots[0]]){
|
||||
return;
|
||||
}
|
||||
|
||||
var file = require('Storage').open("bthrv.csv", "a");
|
||||
var data = new Date(startingTime).toISOString();
|
||||
for (var i = 0; i < hrvSlots.length; i++ ){
|
||||
data += ",";
|
||||
if (hrvValues[hrvSlots[i]]){
|
||||
data += hrvValues[hrvSlots[i]];
|
||||
}
|
||||
}
|
||||
|
||||
data += "," + rrMax + "," + rrMin + ","+rrNumberOfValues;
|
||||
data += "\n";
|
||||
file.write(data);
|
||||
Bangle.buzz(500);
|
||||
}
|
||||
|
||||
function onBtHrm(e) {
|
||||
if (e.rr && !startingTime) Bangle.buzz(500);
|
||||
if (e.rr && !startingTime) startingTime=Date.now();
|
||||
//print("Event:" + e.rr);
|
||||
|
||||
var hrv = calcHrv(e.rr);
|
||||
if (hrv){
|
||||
|
@ -74,18 +89,7 @@ function onBtHrm(e) {
|
|||
currentSlot++;
|
||||
}
|
||||
}
|
||||
if (!saved && currentSlot == hrvSlots.length){
|
||||
var file = require('Storage').open("bthrv.csv", "a");
|
||||
var data = new Date(startingTime).toISOString();
|
||||
for (var c of hrvSlots){
|
||||
data+=","+hrvValues[c];
|
||||
}
|
||||
data+="," + rrMax + "," + rrMin + ","+rrNumberOfValues;
|
||||
data+="\n";
|
||||
file.write(data);
|
||||
saved = true;
|
||||
Bangle.buzz(500);
|
||||
}
|
||||
|
||||
if (hrv){
|
||||
if (!ui){
|
||||
Bangle.setUI("leftright", ()=>{
|
||||
|
@ -94,15 +98,16 @@ function onBtHrm(e) {
|
|||
});
|
||||
ui = true;
|
||||
}
|
||||
|
||||
draw(30, hrv);
|
||||
}
|
||||
}
|
||||
|
||||
function resetHrv(){
|
||||
write();
|
||||
hrvValues={};
|
||||
startingTime=undefined;
|
||||
currentSlot=0;
|
||||
saved=false;
|
||||
rrNumberOfValues = 0;
|
||||
rrSquared = 0;
|
||||
rrLastValue = undefined;
|
||||
|
@ -117,7 +122,6 @@ g.clear();
|
|||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
|
||||
if (Bangle.setBTHRMPower){
|
||||
Bangle.on('BTHRM', onBtHrm);
|
||||
Bangle.setBTHRMPower(1,'bthrv');
|
||||
|
@ -133,6 +137,11 @@ if (Bangle.setBTHRMPower){
|
|||
file.write(data);
|
||||
}
|
||||
|
||||
E.on('kill', ()=>{
|
||||
write();
|
||||
Bangle.setBTHRMPower(0,'bthrv');
|
||||
});
|
||||
|
||||
g.reset().setFont("6x8",2).setFontAlign(0,0);
|
||||
g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 16);
|
||||
} else {
|
||||
|
@ -140,4 +149,3 @@ if (Bangle.setBTHRMPower){
|
|||
g.drawString("Missing BT HRM",g.getWidth()/2,g.getHeight()/2 - 16);
|
||||
}
|
||||
|
||||
E.on('kill', ()=>Bangle.setBTHRMPower(0,'bthrv'));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "bthrv",
|
||||
"name": "Bluetooth Heart Rate variance calculator",
|
||||
"shortName": "BT HRV",
|
||||
"version": "0.01",
|
||||
"version": "0.02",
|
||||
"description": "Calculates HRV from a a BT HRM with interval data",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
|
|
Loading…
Reference in New Issue