BangleApps/apps/bthrv/app.js

156 lines
3.5 KiB
JavaScript
Raw Normal View History

var btm = g.getHeight()-1;
var ui = false;
function clear(y){
g.reset();
g.clearRect(0,y,g.getWidth(),g.getHeight());
}
var startingTime;
var currentSlot = 0;
var hrvSlots = [10,20,30,60,120,300];
var hrvValues = {};
var rrRmsProgress;
var rrNumberOfValues = 0;
var rrSquared = 0;
var rrLastValue;
var rrMax;
var rrMin;
function calcHrv(rr){
//Calculate HRV with RMSSD method: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5624990/
for (var currentRr of rr){
if (!rrMax) rrMax = currentRr;
if (!rrMin) rrMin = currentRr;
rrMax = Math.max(rrMax, currentRr);
rrMin = Math.min(rrMin, currentRr);
rrNumberOfValues++;
if (!rrLastValue){
rrLastValue = currentRr;
continue;
}
rrSquared += (rrLastValue - currentRr)*(rrLastValue - currentRr);
rrLastValue = currentRr;
}
var rms = Math.sqrt(rrSquared / rrNumberOfValues);
return rms;
}
function draw(y, hrv) {
clear(y);
var px = g.getWidth()/2;
var str = hrv.toFixed(1) + "ms";
g.reset();
g.setFontAlign(0,0);
g.setFontVector(40).drawString(str,px,y+20);
for (var i = 0; i < hrvSlots.length; i++){
str = hrvSlots[i] + "s: ";
if (hrvValues[hrvSlots[i]]) str += hrvValues[hrvSlots[i]].toFixed(1) + "ms";
g.setFontVector(16).drawString(str,px,y+44+(i*17));
}
g.setRotation(3);
g.setFontVector(12).drawString("Reset",g.getHeight()/2, g.getWidth()-10);
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);
}
function onBtHrm(e) {
if (e.rr && !startingTime) Bangle.buzz(500);
if (e.rr && !startingTime) startingTime=Date.now();
var hrv = calcHrv(e.rr);
if (hrv){
if (currentSlot <= hrvSlots.length && (Date.now() - startingTime) > (hrvSlots[currentSlot] * 1000) && !hrvValues[hrvSlots[currentSlot]]){
hrvValues[hrvSlots[currentSlot]] = hrv;
currentSlot++;
if (currentSlot == hrvSlots.length){
Bangle.buzz(500)
} else {
Bangle.buzz(50);
}
}
}
if (hrv){
if (!ui){
Bangle.setUI("leftright", ()=>{
resetHrv();
clear(30);
});
ui = true;
}
draw(30, hrv);
}
}
function resetHrv(){
write();
hrvValues={};
startingTime=undefined;
currentSlot=0;
rrNumberOfValues = 0;
rrSquared = 0;
rrLastValue = undefined;
rrMax = undefined;
rrMin = undefined;
}
var settings = require('Storage').readJSON("bthrm.json", true) || {};
g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();
if (Bangle.setBTHRMPower){
Bangle.on('BTHRM', onBtHrm);
Bangle.setBTHRMPower(1,'bthrv');
if (require('Storage').list(/bthrv.csv/).length == 0){
var file = require('Storage').open("bthrv.csv", "a");
var data = "Time";
for (var c of hrvSlots){
data+="," + c + "s";
}
data+=",RR_max,RR_min,Measurements";
data+="\n";
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 {
g.reset().setFont("6x8",2).setFontAlign(0,0);
g.drawString("Missing BT HRM",g.getWidth()/2,g.getHeight()/2 - 16);
}