mirror of https://github.com/espruino/BangleApps
185 lines
4.2 KiB
JavaScript
185 lines
4.2 KiB
JavaScript
//ADVANCED SETTINGS
|
|
var lower_limit_BPM = 49;
|
|
var upper_limit_BPM = 140;
|
|
var deviation_threshold = 3;
|
|
|
|
var ISBANGLEJS1 = process.env.HWVERSION==1;
|
|
|
|
var target_heartrate = 70;
|
|
var heartrate_set;
|
|
|
|
var currentBPM;
|
|
var lastBPM;
|
|
var firstBPM = true; // first reading since sensor turned on
|
|
var HR_samples = [];
|
|
var trigger_count = 0;
|
|
var file = require("Storage").open("steel_log.csv","a");
|
|
var launchtime;
|
|
var alarm_length;
|
|
|
|
function btn1Pressed() {
|
|
if(!heartrate_set){
|
|
target_heartrate++;
|
|
update_target_HR();
|
|
}
|
|
}
|
|
|
|
function btn2Pressed() {
|
|
heartrate_set = true;
|
|
Bangle.setHRMPower(1);
|
|
launchtime = 0|getTime();
|
|
g.clear();
|
|
g.setFont("6x8",2);
|
|
g.drawString("tracking HR...", 120,120);
|
|
g.setFont("6x8",3);
|
|
}
|
|
|
|
function update_target_HR(){
|
|
g.clear();
|
|
if (process.env.HWVERSION==1) {
|
|
g.setColor("#00ff7f");
|
|
g.setFont("6x8", 4);
|
|
g.setFontAlign(0,0); // center font
|
|
|
|
g.drawString(target_heartrate, 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("target HR", 120,90);
|
|
|
|
g.setFont("6x8", 1);
|
|
g.drawString("if unsure, start with 7-10%\n less than waking average and\n adjust as required", 120,170);
|
|
} else {
|
|
g.setFont("6x8", 4);
|
|
g.setFontAlign(0,0); // center font
|
|
g.drawString(target_heartrate, 88,88);
|
|
g.setFont("6x8", 2);
|
|
g.setFontAlign(-1,-1);
|
|
g.drawString("-", 160, 160);
|
|
g.drawString("+", 160, 10);
|
|
g.drawString("GO", 150, 88);
|
|
g.setFontAlign(0,0); // center font
|
|
g.drawString("target HR", 88,65);
|
|
g.setFont("6x8", 1);
|
|
g.drawString("if unsure, start with 7-10%\n less than waking average and\n adjust as required", 88,150);
|
|
}
|
|
|
|
g.setFont("6x8",3);
|
|
g.flip();
|
|
}
|
|
|
|
function btn3Pressed(){
|
|
if(!heartrate_set){
|
|
target_heartrate--;
|
|
update_target_HR();
|
|
}
|
|
}
|
|
|
|
function alarm(){
|
|
if(alarm_length > 0){
|
|
//Bangle.beep(500,4000);
|
|
Bangle.buzz(500,1);
|
|
alarm_length--;
|
|
}
|
|
else{
|
|
clearInterval(alarm);
|
|
if(trigger_count > 1)
|
|
Bangle.setHRMPower(0);
|
|
}
|
|
}
|
|
|
|
function average(nums) {
|
|
return nums.reduce((a, b) => (a + b)) / nums.length;
|
|
}
|
|
|
|
function getStandardDeviation (array) {
|
|
const n = array.length;
|
|
const mean = array.reduce((a, b) => a + b) / n;
|
|
return Math.sqrt(array.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n);
|
|
}
|
|
|
|
function checkHR() {
|
|
var bpm = currentBPM, isCurrent = true;
|
|
if (bpm===undefined) {
|
|
bpm = lastBPM;
|
|
isCurrent = false;
|
|
}
|
|
if (bpm===undefined || bpm < lower_limit_BPM || bpm > upper_limit_BPM)
|
|
bpm = "--";
|
|
if (bpm != "--"){
|
|
HR_samples.push(bpm);
|
|
// Terminal.println(bpm);
|
|
}
|
|
|
|
if(HR_samples.length == 5){
|
|
g.clear();
|
|
average_HR = average(HR_samples).toFixed(0);
|
|
stdev_HR = getStandardDeviation (HR_samples).toFixed(1);
|
|
|
|
if (ISBANGLEJS1) {
|
|
g.drawString("HR: " + average_HR, 120,100);
|
|
g.drawString("STDEV: " + stdev_HR, 120,160);
|
|
} else {
|
|
g.drawString("HR: " + average_HR, 88,60);
|
|
g.drawString("STDEV: " + stdev_HR, 88,90);
|
|
}
|
|
HR_samples = [];
|
|
if(average_HR < target_heartrate && stdev_HR < deviation_threshold){
|
|
|
|
Bangle.setHRMPower(0);
|
|
alarm_length = 4;
|
|
setInterval(alarm, 2000);
|
|
|
|
trigger_count++;
|
|
var csv = [
|
|
0|getTime(),
|
|
launchtime,
|
|
average_HR,
|
|
stdev_HR
|
|
];
|
|
file.write(csv.join(",")+"\n");
|
|
|
|
heartrate_set = false;
|
|
update_target_HR();
|
|
}
|
|
}
|
|
}
|
|
|
|
update_target_HR();
|
|
|
|
if (ISBANGLEJS1) {
|
|
// Bangle 1
|
|
setWatch(btn1Pressed, BTN1, {repeat:true});
|
|
setWatch(btn2Pressed, BTN2, {repeat:true});
|
|
setWatch(btn3Pressed, BTN3, {repeat:true});
|
|
} else {
|
|
// Bangle 2
|
|
setWatch(btn2Pressed, BTN1, { repeat: true });
|
|
Bangle.on('touch', function(zone, e) {
|
|
if (e.y < g.getHeight() / 2) {
|
|
btn1Pressed();
|
|
}
|
|
if (e.y > g.getHeight() / 2) {
|
|
btn3Pressed();
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
Bangle.on('HRM',function(hrm) {
|
|
if(trigger_count < 2){
|
|
if (firstBPM)
|
|
firstBPM=false; // ignore the first one as it's usually rubbish
|
|
else {
|
|
currentBPM = hrm.bpm;
|
|
lastBPM = currentBPM;
|
|
}
|
|
checkHR();
|
|
}
|
|
});
|