mirror of https://github.com/espruino/BangleApps
156 lines
3.5 KiB
JavaScript
156 lines
3.5 KiB
JavaScript
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);
|
|
}
|
|
|