Improved buzz timing and rendering

pull/218/head
msdeibel 2020-04-04 08:50:55 +02:00
parent a55efc5740
commit 8fa7fd0e43
2 changed files with 326 additions and 329 deletions

View File

@ -1,3 +1,4 @@
0.05: Improved buzz timing and rendering
0.04: Only buzz on high confidence (>85%) 0.04: Only buzz on high confidence (>85%)
0.03: Optimized rendering for the background 0.03: Optimized rendering for the background
0.02: Adapted to new App code layout 0.02: Adapted to new App code layout

View File

@ -1,329 +1,325 @@
/* eslint-disable no-undef */ /* eslint-disable no-undef */
const Setter = { const Setter = {
NONE: "none", NONE: "none",
UPPER: 'upper', UPPER: 'upper',
LOWER: 'lower' LOWER: 'lower'
}; };
const shortBuzzTimeInMs = 50; const shortBuzzTimeInMs = 80;
const longBuzzTimeInMs = 200; const longBuzzTimeInMs = 400;
let upperLimit = 90; let upperLimit = 130;
let upperLimitChanged = true; let upperLimitChanged = true;
let lowerLimit = 50; let lowerLimit = 100;
let lowerLimitChanged = true; let lowerLimitChanged = true;
let limitSetter = Setter.NONE; let limitSetter = Setter.NONE;
let currentHeartRate = 0; let currentHeartRate = 0;
let hrConfidence = -1; let hrConfidence = -1;
let hrChanged = true; let hrChanged = true;
let confidenceChanged = true; let confidenceChanged = true;
let setterHighlightTimeout; let setterHighlightTimeout;
function renderUpperLimitBackground() { function renderUpperLimitBackground() {
g.setColor(1,0,0); g.setColor(1,0,0);
g.fillRect(125,40, 210, 70); g.fillRect(125,40, 210, 70);
g.fillRect(180,70, 210, 200); g.fillRect(180,70, 210, 200);
//Round top left corner //Round top left corner
g.fillEllipse(115,40,135,70); g.fillEllipse(115,40,135,70);
//Round top right corner //Round top right corner
g.setColor(0,0,0); g.setColor(0,0,0);
g.fillRect(205,40, 210, 45); g.fillRect(205,40, 210, 45);
g.setColor(1,0,0); g.setColor(1,0,0);
g.fillEllipse(190,40,210,50); g.fillEllipse(190,40,210,50);
//Round inner corner //Round inner corner
g.fillRect(174,71, 179, 76); g.fillRect(174,71, 179, 76);
g.setColor(0,0,0); g.setColor(0,0,0);
g.fillEllipse(160,71,179,82); g.fillEllipse(160,71,179,82);
//Round bottom //Round bottom
g.setColor(1,0,0); g.setColor(1,0,0);
g.fillEllipse(180,190, 210, 210); g.fillEllipse(180,190, 210, 210);
} }
function renderLowerLimitBackground() { function renderLowerLimitBackground() {
g.setColor(0,0,1); g.setColor(0,0,1);
g.fillRect(10, 180, 100, 210); g.fillRect(10, 180, 100, 210);
g.fillRect(10, 50, 40, 180); g.fillRect(10, 50, 40, 180);
//Rounded top //Rounded top
g.setColor(0,0,1); g.setColor(0,0,1);
g.fillEllipse(10,40, 40, 60); g.fillEllipse(10,40, 40, 60);
//Round bottom right corner //Round bottom right corner
g.setColor(0,0,1); g.setColor(0,0,1);
g.fillEllipse(90,180,110,210); g.fillEllipse(90,180,110,210);
//Round inner corner //Round inner corner
g.setColor(0,0,1); g.setColor(0,0,1);
g.fillRect(40,175,45,180); g.fillRect(40,175,45,180);
g.setColor(0,0,0); g.setColor(0,0,0);
g.fillEllipse(41,170,60,179); g.fillEllipse(41,170,60,179);
//Round bottom left corner //Round bottom left corner
g.setColor(0,0,0); g.setColor(0,0,0);
g.fillRect(10,205, 15, 210); g.fillRect(10,205, 15, 210);
g.setColor(0,0,1); g.setColor(0,0,1);
g.fillEllipse(10,200,30,210); g.fillEllipse(10,200,30,210);
} }
function drawTrainingHeartRate() { function drawTrainingHeartRate() {
//Only redraw if the display is on //Only redraw if the display is on
if (Bangle.isLCDOn()) { if (Bangle.isLCDOn()) {
renderUpperLimit();
renderUpperLimit(); renderCurrentHeartRate();
renderCurrentHeartRate(); renderLowerLimit();
renderLowerLimit(); renderConfidenceBars();
}
renderConfidenceBars();
} buzz();
}
buzz();
} function renderUpperLimit() {
if(!upperLimitChanged) { return; }
function renderUpperLimit() {
if(!upperLimitChanged) { return; } g.setColor(1,0,0);
g.fillRect(125,40, 210, 70);
g.setColor(1,0,0);
g.fillRect(125,40, 210, 70); if(limitSetter === Setter.UPPER){
g.setColor(255,255, 0);
if(limitSetter === Setter.UPPER){ } else {
g.setColor(255,255, 0); g.setColor(255,255,255);
} else { }
g.setColor(255,255,255); g.setFontVector(13);
} g.drawString("Upper : " + upperLimit, 130,50);
g.setFontVector(13);
g.drawString("Upper : " + upperLimit, 130,50); upperLimitChanged = false;
}
upperLimitChanged = false;
} function renderCurrentHeartRate() {
if(!hrChanged) { return; }
function renderCurrentHeartRate() {
if(!hrChanged) { return; } g.setColor(255,255,255);
g.fillRect(55, 110, 165, 150);
g.setColor(255,255,255);
g.fillRect(45, 110, 165, 150); g.setColor(0,0,0);
g.setFontVector(24);
g.setColor(0,0,0); g.setFontAlign(1, -1, 0);
g.setFontVector(24); g.drawString(currentHeartRate, 130, 117);
g.setFontAlign(1, -1, 0);
g.drawString(currentHeartRate, 130, 117); //Reset alignment to defaults
g.setFontAlign(-1, -1, 0);
//Reset alignment to defaults
g.setFontAlign(-1, -1, 0); hrChanged = false;
}
hrChanged = false;
} function renderLowerLimit() {
if(!lowerLimitChanged) { return; }
function renderLowerLimit() {
if(!lowerLimitChanged) { return; } g.setColor(0,0,1);
g.fillRect(10, 180, 100, 210);
g.setColor(0,0,1);
g.fillRect(10, 180, 100, 210); if(limitSetter === Setter.LOWER){
g.setColor(255,255, 0);
if(limitSetter === Setter.LOWER){ } else {
g.setColor(255,255, 0); g.setColor(255,255,255);
} else { }
g.setColor(255,255,255); g.setFontVector(13);
} g.drawString("Lower : " + lowerLimit, 20,190);
g.setFontVector(13);
g.drawString("Lower : " + lowerLimit, 20,190); lowerLimitChanged = false;
}
lowerLimitChanged = false;
} function renderConfidenceBars(){
if(!confidenceChanged) { return; }
function renderConfidenceBars(){
if(!confidenceChanged) { return; } if(hrConfidence >= 85){
g.setColor(0, 255, 0);
if(hrConfidence >= 85){ } else if (hrConfidence >= 50) {
g.setColor(0, 255, 0); g.setColor(255, 255, 0);
} else if (hrConfidence >= 50) { } else if(hrConfidence >= 0){
g.setColor(255, 255, 0); g.setColor(255, 0, 0);
} else if(hrConfidence >= 0){ } else {
g.setColor(255, 0, 0); g.setColor(255, 255, 255);
} else { }
g.setColor(255, 255, 255);
} g.fillRect(45, 110, 55, 150);
g.fillRect(165, 110, 175, 150);
g.fillRect(45, 110, 55, 150);
g.fillRect(165, 110, 175, 150); confidenceChanged = false;
}
confidenceChanged = false;
} function renderButtonIcons() {
g.setColor(255,255,255);
function renderButtonIcons() { g.setFontVector(14);
g.setColor(255,255,255);
g.setFontVector(14); //+ for Btn1
g.drawString("+", 222,50);
//+ for Btn1
g.drawString("+", 222,50); //Home for Btn2
g.drawLine(220, 118, 227, 110);
//Home for Btn2 g.drawLine(227, 110, 234, 118);
g.drawLine(220, 118, 227, 110);
g.drawLine(227, 110, 234, 118); g.drawPoly([222,117,222,125,232,125,232,117], false);
g.drawRect(226,120,229,125);
g.drawPoly([222,117,222,125,232,125,232,117], false);
g.drawRect(226,120,229,125); //- for Btn3
g.drawString("-", 222,165);
//- for Btn3 }
g.drawString("-", 222,165);
} function buzz()
{
function buzz() // Do not buzz if not confident
{ if(hrConfidence < 85) { return; }
// Do not buzz if not confident
if(hrConfidence < 85) { return; } if(currentHeartRate > upperLimit)
{
if(currentHeartRate > upperLimit) Bangle.buzz(shortBuzzTimeInMs);
{ setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2);
Bangle.buzz(shortBuzzTimeInMs); }
setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs+10);
setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs+10); if(currentHeartRate < lowerLimit)
} {
Bangle.buzz(longBuzzTimeInMs);
if(currentHeartRate < lowerLimit) }
{ }
Bangle.buzz(longBuzzTimeInMs);
setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs+10); function onHrm(hrm){
} if(currentHeartRate !== hrm.bpm){
} currentHeartRate = hrm.bpm;
hrChanged = true;
function onHrm(hrm){ }
if(currentHeartRate !== hrm.bpm){
currentHeartRate = hrm.bpm; if(hrConfidence !== hrm.confidence) {
hrChanged = true; hrConfidence = hrm.confidence;
} confidenceChanged = true;
}
if(hrConfidence !== hrm.confidence) { }
hrConfidence = hrm.confidence;
confidenceChanged = true; function setLimitSetterToLower() {
} resetHighlightTimeout();
}
limitSetter = Setter.LOWER;
function setLimitSetterToLower() { console.log("Limit setter is lower");
resetHighlightTimeout();
upperLimitChanged = true;
limitSetter = Setter.LOWER; lowerLimitChanged = true;
console.log("Limit setter is lower");
renderUpperLimit();
upperLimitChanged = true; renderLowerLimit();
lowerLimitChanged = true; }
renderUpperLimit(); function setLimitSetterToUpper() {
renderLowerLimit(); resetHighlightTimeout();
}
limitSetter = Setter.UPPER;
function setLimitSetterToUpper() { console.log("Limit setter is upper");
resetHighlightTimeout();
upperLimitChanged = true;
limitSetter = Setter.UPPER; lowerLimitChanged = true;
console.log("Limit setter is upper");
renderLowerLimit();
upperLimitChanged = true; renderUpperLimit();
lowerLimitChanged = true; }
renderLowerLimit(); function setLimitSetterToNone() {
renderUpperLimit(); limitSetter = Setter.NONE;
} console.log("Limit setter is none");
function setLimitSetterToNone() { upperLimitChanged = true;
limitSetter = Setter.NONE; lowerLimitChanged = true;
console.log("Limit setter is none");
renderLowerLimit();
upperLimitChanged = true; renderUpperLimit();
lowerLimitChanged = true; }
renderLowerLimit(); function incrementLimit(){
renderUpperLimit(); resetHighlightTimeout();
}
if (limitSetter === Setter.UPPER) {
function incrementLimit(){ upperLimit++;
resetHighlightTimeout(); renderUpperLimit();
console.log("Upper limit: " + upperLimit);
if (limitSetter === Setter.UPPER) { upperLimitChanged = true;
upperLimit++; } else if(limitSetter === Setter.LOWER) {
renderUpperLimit(); lowerLimit++;
console.log("Upper limit: " + upperLimit); renderLowerLimit();
upperLimitChanged = true; console.log("Lower limit: " + lowerLimit);
} else if(limitSetter === Setter.LOWER) { lowerLimitChanged = true;
lowerLimit++; }
renderLowerLimit(); }
console.log("Lower limit: " + lowerLimit);
lowerLimitChanged = true; function decrementLimit(){
} resetHighlightTimeout();
}
if (limitSetter === Setter.UPPER) {
function decrementLimit(){ upperLimit--;
resetHighlightTimeout(); renderUpperLimit();
console.log("Upper limit: " + upperLimit);
if (limitSetter === Setter.UPPER) { upperLimitChanged = true;
upperLimit--; } else if(limitSetter === Setter.LOWER) {
renderUpperLimit(); lowerLimit--;
console.log("Upper limit: " + upperLimit); renderLowerLimit();
upperLimitChanged = true; console.log("Lower limit: " + lowerLimit);
} else if(limitSetter === Setter.LOWER) { lowerLimitChanged = true;
lowerLimit--; }
renderLowerLimit(); }
console.log("Lower limit: " + lowerLimit);
lowerLimitChanged = true; function resetHighlightTimeout() {
} if (setterHighlightTimeout) {
} clearTimeout(setterHighlightTimeout);
}
function resetHighlightTimeout() {
if (setterHighlightTimeout) { setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000);
clearTimeout(setterHighlightTimeout); }
}
// Show launcher when middle button pressed
setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); function switchOffApp(){
} Bangle.setHRMPower(0);
Bangle.showLauncher();
// Show launcher when middle button pressed }
function switchOffApp(){
Bangle.setHRMPower(0); // special function to handle display switch on
Bangle.showLauncher(); Bangle.on('lcdPower', (on) => {
} g.clear();
if (on) {
// special function to handle display switch on Bangle.drawWidgets();
Bangle.on('lcdPower', (on) => { renderButtonIcons();
g.clear(); // call your app function here
if (on) { renderLowerLimitBackground();
Bangle.drawWidgets(); renderUpperLimitBackground();
renderButtonIcons(); lowerLimitChanged = true;
// call your app function here upperLimitChanged = true;
renderLowerLimitBackground(); drawTrainingHeartRate();
renderUpperLimitBackground(); }
lowerLimitChanged = true; });
upperLimitChanged = true;
drawTrainingHeartRate(); Bangle.setHRMPower(1);
} Bangle.on('HRM', onHrm);
});
setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true});
Bangle.setHRMPower(1); setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true});
Bangle.on('HRM', onHrm); setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true});
setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true});
setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true });
setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true});
setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); g.clear();
setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); Bangle.loadWidgets();
setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); Bangle.drawWidgets();
//drawTrainingHeartRate();
g.clear();
Bangle.loadWidgets(); renderButtonIcons();
Bangle.drawWidgets(); renderLowerLimitBackground();
//drawTrainingHeartRate(); renderUpperLimitBackground();
renderButtonIcons(); // refesh every sec
renderLowerLimitBackground(); setInterval(drawTrainingHeartRate, 1000);
renderUpperLimitBackground();
// refesh every sec
setInterval(drawTrainingHeartRate, 1000);