From 03a295a4ff40d9c664f155324d139ffb007e76eb Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 12:00:43 +0100 Subject: [PATCH 01/21] wohrm: prepare porting to Bangle.js2 --- apps.json | 4 ++-- apps/wohrm/README.md | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index e5e9f8f02..07c773725 100644 --- a/apps.json +++ b/apps.json @@ -1714,12 +1714,12 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.08", + "version": "0.09-rc1", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", "tags": "hrm,workout", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "allow_emulator": true, "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], diff --git a/apps/wohrm/README.md b/apps/wohrm/README.md index ad9e82525..87b1a65da 100644 --- a/apps/wohrm/README.md +++ b/apps/wohrm/README.md @@ -8,6 +8,9 @@ and will notify you with a buzz whenever your heart rate falls below or jumps ab [Try it out](https://www.espruino.com/ide/emulator.html?codeurl=https://raw.githubusercontent.com/msdeibel/BangleApps/master/apps/wohrm/app.js&upload) using the [online Espruino emulator](https://www.espruino.com/ide/emulator.html). ## Setting the limits + +Use the settings menu to set the limits. On the Bangle.js1 these can in addition be set with the buttons: + For setting the lower limit press button 4 (left part of the watch's touch screen). Then adjust the value with the buttons 1 (top) and 3 (bottom) of the watch. @@ -22,7 +25,7 @@ the received value: For 85% and above the bars are green, between 84% and 50% th and below 50% they turn red. ## Closing the app -Pressing button 2 (middle) will switch off the HRM of the watch and return you to the launcher. +Pressing middle button will switch off the HRM of the watch and return you to the launcher. # HRM usage The HRM is switched on when the app is started. It stays switch on while the app is running, even From e91324c16bc9b10dde21e14468933a5500979d05 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 12:11:27 +0100 Subject: [PATCH 02/21] wohrm: Prevent crash on BangleJs2 --- apps/wohrm/app.js | 655 +++++++++++++++++++++++----------------------- 1 file changed, 328 insertions(+), 327 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index c9c060e99..01fcca63e 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -1,327 +1,328 @@ -/* eslint-disable no-undef */ -const Setter = { - NONE: "none", - UPPER: 'upper', - LOWER: 'lower' -}; - -const shortBuzzTimeInMs = 80; -const longBuzzTimeInMs = 400; - -let upperLimit = 130; -let upperLimitChanged = true; - -let lowerLimit = 100; -let lowerLimitChanged = true; - -let limitSetter = Setter.NONE; - -let currentHeartRate = 0; -let hrConfidence = -1; -let hrChanged = true; -let confidenceChanged = true; - -let setterHighlightTimeout; - -function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); - - //Round top left corner - g.fillEllipse(115,40,135,70); - - //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); - - //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); - - //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); -} - -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); -} - -function drawTrainingHeartRate() { - //Only redraw if the display is on - if (Bangle.isLCDOn()) { - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - } - - buzz(); -} - -function renderUpperLimit() { - if(!upperLimitChanged) { return; } - - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Upper: " + upperLimit, 125, 50); - - upperLimitChanged = false; -} - -function renderCurrentHeartRate() { - if(!hrChanged) { return; } - - g.setColor(255,255,255); - g.fillRect(55, 110, 165, 150); - - g.setColor(0,0,0); - g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); - - //Reset alignment to defaults - g.setFontAlign(-1, -1, 0); - - hrChanged = false; -} - -function renderLowerLimit() { - if(!lowerLimitChanged) { return; } - - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - - if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Lower: " + lowerLimit, 20,190); - - lowerLimitChanged = false; -} - -function renderConfidenceBars(){ - if(!confidenceChanged) { return; } - - if(hrConfidence >= 85){ - g.setColor(0, 255, 0); - } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); - } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); - } else { - g.setColor(255, 255, 255); - } - - g.fillRect(45, 110, 55, 150); - g.fillRect(165, 110, 175, 150); - - confidenceChanged = false; -} - -function renderPlusMinusIcons() { - if (limitSetter === Setter.NONE) { - g.setColor(0, 0, 0); - } else { - g.setColor(1, 1, 1); - } - - g.setFontVector(14); - - //+ for Btn1 - g.drawString("+", 222, 50); - - //- for Btn3 - g.drawString("-", 222,165); - - return; -} - -function renderHomeIcon() { - //Home for Btn2 - g.setColor(1, 1, 1); - 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); -} - -function buzz() { - // Do not buzz if not confident - if(hrConfidence < 85) { return; } - - if(currentHeartRate > upperLimit) - { - Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); - } - - if(currentHeartRate < lowerLimit) - { - Bangle.buzz(longBuzzTimeInMs); - } -} - -function onHrm(hrm){ - if(currentHeartRate !== hrm.bpm){ - currentHeartRate = hrm.bpm; - hrChanged = true; - } - - if(hrConfidence !== hrm.confidence) { - hrConfidence = hrm.confidence; - confidenceChanged = true; - } -} - -function setLimitSetterToLower() { - resetHighlightTimeout(); - - limitSetter = Setter.LOWER; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderUpperLimit(); - renderLowerLimit(); - renderPlusMinusIcons(); -} - -function setLimitSetterToUpper() { - resetHighlightTimeout(); - - limitSetter = Setter.UPPER; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderLowerLimit(); - renderUpperLimit(); - renderPlusMinusIcons(); -} - -function setLimitSetterToNone() { - limitSetter = Setter.NONE; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderLowerLimit(); - renderUpperLimit(); - renderPlusMinusIcons(); -} - -function incrementLimit() { - resetHighlightTimeout(); - - if (limitSetter === Setter.UPPER) { - upperLimit++; - renderUpperLimit(); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit++; - renderLowerLimit(); - lowerLimitChanged = true; - } -} - -function decrementLimit(){ - resetHighlightTimeout(); - - if (limitSetter === Setter.UPPER) { - upperLimit--; - renderUpperLimit(); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit--; - renderLowerLimit(); - lowerLimitChanged = true; - } -} - -function resetHighlightTimeout() { - if (setterHighlightTimeout) { - clearTimeout(setterHighlightTimeout); - } - - setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); -} - -function switchOffApp(){ - Bangle.setHRMPower(0,"wohrm"); - Bangle.showLauncher(); -} - -Bangle.on('lcdPower', (on) => { - g.clear(); - if (on) { - Bangle.drawWidgets(); - - renderHomeIcon(); - renderLowerLimitBackground(); - renderUpperLimitBackground(); - lowerLimitChanged = true; - upperLimitChanged = true; - drawTrainingHeartRate(); - } -}); - -Bangle.setHRMPower(1,"wohrm"); -Bangle.on('HRM', onHrm); - -setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); -setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); -setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); - -setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); - -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); - -renderHomeIcon(); -renderLowerLimitBackground(); -renderUpperLimitBackground(); - -setInterval(drawTrainingHeartRate, 1000); +/* eslint-disable no-undef */ +const Setter = { + NONE: "none", + UPPER: 'upper', + LOWER: 'lower' +}; + +const shortBuzzTimeInMs = 80; +const longBuzzTimeInMs = 400; + +let upperLimit = 130; +let upperLimitChanged = true; + +let lowerLimit = 100; +let lowerLimitChanged = true; + +let limitSetter = Setter.NONE; + +let currentHeartRate = 0; +let hrConfidence = -1; +let hrChanged = true; +let confidenceChanged = true; + +let setterHighlightTimeout; + +function renderUpperLimitBackground() { + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); + + //Round top left corner + g.fillEllipse(115,40,135,70); + + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(1,0,0); + g.fillEllipse(190,40,210,50); + + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); + + //Round bottom + g.setColor(1,0,0); + g.fillEllipse(180,190, 210, 210); +} + +function renderLowerLimitBackground() { + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,1); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,1); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,1); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,1); + g.fillEllipse(10,200,30,210); +} + +function drawTrainingHeartRate() { + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + } + + buzz(); +} + +function renderUpperLimit() { + if(!upperLimitChanged) { return; } + + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Upper: " + upperLimit, 125, 50); + + upperLimitChanged = false; +} + +function renderCurrentHeartRate() { + if(!hrChanged) { return; } + + g.setColor(255,255,255); + g.fillRect(55, 110, 165, 150); + + g.setColor(0,0,0); + g.setFontVector(24); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 130, 117); + + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); + + hrChanged = false; +} + +function renderLowerLimit() { + if(!lowerLimitChanged) { return; } + + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + + if(limitSetter === Setter.LOWER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Lower: " + lowerLimit, 20,190); + + lowerLimitChanged = false; +} + +function renderConfidenceBars(){ + if(!confidenceChanged) { return; } + + if(hrConfidence >= 85){ + g.setColor(0, 255, 0); + } else if (hrConfidence >= 50) { + g.setColor(255, 255, 0); + } else if(hrConfidence >= 0){ + g.setColor(255, 0, 0); + } else { + g.setColor(255, 255, 255); + } + + g.fillRect(45, 110, 55, 150); + g.fillRect(165, 110, 175, 150); + + confidenceChanged = false; +} + +function renderPlusMinusIcons() { + if (limitSetter === Setter.NONE) { + g.setColor(0, 0, 0); + } else { + g.setColor(1, 1, 1); + } + + g.setFontVector(14); + + //+ for Btn1 + g.drawString("+", 222, 50); + + //- for Btn3 + g.drawString("-", 222,165); + + return; +} + +function renderHomeIcon() { + //Home for Btn2 + g.setColor(1, 1, 1); + 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); +} + +function buzz() { + // Do not buzz if not confident + if(hrConfidence < 85) { return; } + + if(currentHeartRate > upperLimit) + { + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); + } + + if(currentHeartRate < lowerLimit) + { + Bangle.buzz(longBuzzTimeInMs); + } +} + +function onHrm(hrm){ + if(currentHeartRate !== hrm.bpm){ + currentHeartRate = hrm.bpm; + hrChanged = true; + } + + if(hrConfidence !== hrm.confidence) { + hrConfidence = hrm.confidence; + confidenceChanged = true; + } +} + +function setLimitSetterToLower() { + resetHighlightTimeout(); + + limitSetter = Setter.LOWER; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderUpperLimit(); + renderLowerLimit(); + renderPlusMinusIcons(); +} + +function setLimitSetterToUpper() { + resetHighlightTimeout(); + + limitSetter = Setter.UPPER; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderLowerLimit(); + renderUpperLimit(); + renderPlusMinusIcons(); +} + +function setLimitSetterToNone() { + limitSetter = Setter.NONE; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderLowerLimit(); + renderUpperLimit(); + renderPlusMinusIcons(); +} + +function incrementLimit() { + resetHighlightTimeout(); + + if (limitSetter === Setter.UPPER) { + upperLimit++; + renderUpperLimit(); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit++; + renderLowerLimit(); + lowerLimitChanged = true; + } +} + +function decrementLimit(){ + resetHighlightTimeout(); + + if (limitSetter === Setter.UPPER) { + upperLimit--; + renderUpperLimit(); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit--; + renderLowerLimit(); + lowerLimitChanged = true; + } +} + +function resetHighlightTimeout() { + if (setterHighlightTimeout) { + clearTimeout(setterHighlightTimeout); + } + + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); +} + +function switchOffApp(){ + Bangle.setHRMPower(0,"wohrm"); + Bangle.showLauncher(); +} + +Bangle.on('lcdPower', (on) => { + g.clear(); + if (on) { + Bangle.drawWidgets(); + + renderHomeIcon(); + renderLowerLimitBackground(); + renderUpperLimitBackground(); + lowerLimitChanged = true; + upperLimitChanged = true; + drawTrainingHeartRate(); + } +}); + +Bangle.setHRMPower(1,"wohrm"); +Bangle.on('HRM', onHrm); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +renderLowerLimitBackground(); +renderUpperLimitBackground(); + +if (typeof(BTN5) !== typeof(undefined)) { + renderHomeIcon(); + setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); + setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); + setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); + setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); + + setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); +} + +setInterval(drawTrainingHeartRate, 1000); From e98690a8533eefd23d23cd017b65c3b2def73aa1 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 14:10:08 +0100 Subject: [PATCH 03/21] wohrm: parameterized renderUpperLimitBackground() --- apps/wohrm/app.js | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 01fcca63e..ba037fc7c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -24,27 +24,45 @@ let confidenceChanged = true; let setterHighlightTimeout; function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); + var minX=125; + var maxX=210; + var minY=40; + var maxY=210; + var rectWidth=30; + var cornerRoundness=5; + var bgColor = 0; + var fgColor = '#f00'; + g.setColor(fgColor); + + g.fillRect(minX,minY, maxX, minY+rectWidth); + g.fillRect(maxX-rectWidth, minY+rectWidth, maxX, maxY-cornerRoundness*2); //Round top left corner - g.fillEllipse(115,40,135,70); + g.fillEllipse(minX-cornerRoundness*2, + minY, + minX+cornerRoundness*2, + minY+rectWidth); //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); + g.setColor(bgColor); + g.fillRect(maxX-cornerRoundness,minY, maxX, minY+cornerRoundness); + g.setColor(fgColor); + g.fillEllipse(maxX-cornerRoundness*4,minY,maxX,minY+cornerRoundness*2); //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); + g.fillRect(maxX-rectWidth-cornerRoundness-1, + minY+rectWidth+1, + maxX-rectWidth-1, + minY+rectWidth+cornerRoundness-1); + g.setColor(bgColor); + g.fillEllipse(maxX-rectWidth-cornerRoundness*4, + minY+rectWidth+1, + maxX-rectWidth-1, + minY+rectWidth+cornerRoundness*3-1); //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); + g.setColor(fgColor); + g.fillEllipse(maxX-rectWidth,maxY-cornerRoundness*4, maxX, maxY); } function renderLowerLimitBackground() { From 8c4f37e991fc3ab17ea6c24b7d15d813dc343b53 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 14:30:12 +0100 Subject: [PATCH 04/21] wohrm: renderLshape() from renderUpperLimitBackground() --- apps/wohrm/app.js | 69 ++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ba037fc7c..e73307773 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,46 +23,49 @@ let confidenceChanged = true; let setterHighlightTimeout; -function renderUpperLimitBackground() { - var minX=125; - var maxX=210; - var minY=40; - var maxY=210; - var rectWidth=30; - var cornerRoundness=5; - var bgColor = 0; - var fgColor = '#f00'; - g.setColor(fgColor); +const upperLshape = { + minX: 125, + maxX: 210, + minY: 40, + maxY: 210, + rectWidth: 30, + cornerRoundness: 5, + bgColor: 0, + fgColor: '#f00' +}; - g.fillRect(minX,minY, maxX, minY+rectWidth); - g.fillRect(maxX-rectWidth, minY+rectWidth, maxX, maxY-cornerRoundness*2); +function renderLshape(p) { + g.setColor(p.fgColor); + + g.fillRect(p.minX,p.minY, p.maxX, p.minY+p.rectWidth); + g.fillRect(p.maxX-p.rectWidth, p.minY+p.rectWidth, p.maxX, p.maxY-p.cornerRoundness*2); //Round top left corner - g.fillEllipse(minX-cornerRoundness*2, - minY, - minX+cornerRoundness*2, - minY+rectWidth); + g.fillEllipse(p.minX-p.cornerRoundness*2, + p.minY, + p.minX+p.cornerRoundness*2, + p.minY+p.rectWidth); //Round top right corner - g.setColor(bgColor); - g.fillRect(maxX-cornerRoundness,minY, maxX, minY+cornerRoundness); - g.setColor(fgColor); - g.fillEllipse(maxX-cornerRoundness*4,minY,maxX,minY+cornerRoundness*2); + g.setColor(p.bgColor); + g.fillRect(p.maxX-p.cornerRoundness,p.minY, p.maxX, p.minY+p.cornerRoundness); + g.setColor(p.fgColor); + g.fillEllipse(p.maxX-p.cornerRoundness*4,p.minY,p.maxX,p.minY+p.cornerRoundness*2); //Round inner corner - g.fillRect(maxX-rectWidth-cornerRoundness-1, - minY+rectWidth+1, - maxX-rectWidth-1, - minY+rectWidth+cornerRoundness-1); - g.setColor(bgColor); - g.fillEllipse(maxX-rectWidth-cornerRoundness*4, - minY+rectWidth+1, - maxX-rectWidth-1, - minY+rectWidth+cornerRoundness*3-1); + g.fillRect(p.maxX-p.rectWidth-p.cornerRoundness-1, + p.minY+p.rectWidth+1, + p.maxX-p.rectWidth-1, + p.minY+p.rectWidth+p.cornerRoundness-1); + g.setColor(p.bgColor); + g.fillEllipse(p.maxX-p.rectWidth-p.cornerRoundness*4, + p.minY+p.rectWidth+1, + p.maxX-p.rectWidth-1, + p.minY+p.rectWidth+p.cornerRoundness*3-1); //Round bottom - g.setColor(fgColor); - g.fillEllipse(maxX-rectWidth,maxY-cornerRoundness*4, maxX, maxY); + g.setColor(p.fgColor); + g.fillEllipse(p.maxX-p.rectWidth,p.maxY-p.cornerRoundness*4, p.maxX, p.maxY); } function renderLowerLimitBackground() { @@ -317,7 +320,7 @@ Bangle.on('lcdPower', (on) => { renderHomeIcon(); renderLowerLimitBackground(); - renderUpperLimitBackground(); + renderLshape(upperLshape); lowerLimitChanged = true; upperLimitChanged = true; drawTrainingHeartRate(); @@ -331,7 +334,7 @@ g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); renderLowerLimitBackground(); -renderUpperLimitBackground(); +renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { renderHomeIcon(); From f4a7a4f77e78a24cb26490f100e29bdf75e02676 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:28:26 +0100 Subject: [PATCH 05/21] wohrt: removed renderLowerLimitBackground() --- apps/wohrm/app.js | 102 ++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index e73307773..638627e17 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -30,68 +30,74 @@ const upperLshape = { maxY: 210, rectWidth: 30, cornerRoundness: 5, + orientation: -1, bgColor: 0, fgColor: '#f00' }; +const lowerLshape = { + maxX: 10, + minX: 100, + minY: 210, + maxY: 40, + rectWidth: 30, + cornerRoundness: 5, + orientation: 1, + bgColor: 0, + fgColor: '#00f' +}; + +function fillEllipse(x, y, x2, y2) { + g.fillEllipse(Math.min(x, x2), + Math.min(y, y2), + Math.max(x, x2), + Math.max(y, y2)); +} + function renderLshape(p) { g.setColor(p.fgColor); - g.fillRect(p.minX,p.minY, p.maxX, p.minY+p.rectWidth); - g.fillRect(p.maxX-p.rectWidth, p.minY+p.rectWidth, p.maxX, p.maxY-p.cornerRoundness*2); + g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); + g.fillRect(p.maxX+p.orientation*p.rectWidth, + p.minY-p.orientation*p.rectWidth, + p.maxX, + p.maxY+p.orientation*p.cornerRoundness*2); - //Round top left corner - g.fillEllipse(p.minX-p.cornerRoundness*2, - p.minY, - p.minX+p.cornerRoundness*2, - p.minY+p.rectWidth); + //Round end of small line + fillEllipse(p.minX+p.orientation*p.cornerRoundness*2, + p.minY, + p.minX-p.orientation*p.cornerRoundness*2, + p.minY-p.orientation*p.rectWidth); - //Round top right corner + //Round outer corner g.setColor(p.bgColor); - g.fillRect(p.maxX-p.cornerRoundness,p.minY, p.maxX, p.minY+p.cornerRoundness); + g.fillRect(p.maxX+p.orientation*p.cornerRoundness, + p.minY, + p.maxX, + p.minY-p.orientation*p.cornerRoundness); g.setColor(p.fgColor); - g.fillEllipse(p.maxX-p.cornerRoundness*4,p.minY,p.maxX,p.minY+p.cornerRoundness*2); + fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, + p.minY, + p.maxX, + p.minY-p.orientation*p.cornerRoundness*2); //Round inner corner - g.fillRect(p.maxX-p.rectWidth-p.cornerRoundness-1, - p.minY+p.rectWidth+1, - p.maxX-p.rectWidth-1, - p.minY+p.rectWidth+p.cornerRoundness-1); + g.fillRect(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness+1), + p.minY-p.orientation*(p.rectWidth+1), + p.maxX+p.orientation*(p.rectWidth+1), + p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); g.setColor(p.bgColor); - g.fillEllipse(p.maxX-p.rectWidth-p.cornerRoundness*4, - p.minY+p.rectWidth+1, - p.maxX-p.rectWidth-1, - p.minY+p.rectWidth+p.cornerRoundness*3-1); + fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), + p.minY-p.orientation*(p.rectWidth+1), + p.maxX+p.orientation*(p.rectWidth+1), + p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); - //Round bottom + //Round end of long line g.setColor(p.fgColor); - g.fillEllipse(p.maxX-p.rectWidth,p.maxY-p.cornerRoundness*4, p.maxX, p.maxY); -} - -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); + fillEllipse(p.maxX+p.orientation*p.rectWidth, + p.maxY+p.orientation*p.cornerRoundness*4, + p.maxX, + p.maxY); } function drawTrainingHeartRate() { @@ -319,7 +325,7 @@ Bangle.on('lcdPower', (on) => { Bangle.drawWidgets(); renderHomeIcon(); - renderLowerLimitBackground(); + renderLshape(lowerLshape); renderLshape(upperLshape); lowerLimitChanged = true; upperLimitChanged = true; @@ -333,7 +339,7 @@ Bangle.on('HRM', onHrm); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLowerLimitBackground(); +renderLshape(lowerLshape); renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { From 3e0e590b86a3a2282fd22ca03c37232410a35d94 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:41:06 +0100 Subject: [PATCH 06/21] Add home buttom for Bangle.js2 --- apps/wohrm/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 638627e17..de3db14e2 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -350,6 +350,8 @@ if (typeof(BTN5) !== typeof(undefined)) { setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); +} else { + setWatch(switchOffApp, BTN1, {edge:"falling", debounce:50, repeat:true}); } setInterval(drawTrainingHeartRate, 1000); From 616f1f784f8780adce5f586ecc51e54b0c8a1a2a Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:46:56 +0100 Subject: [PATCH 07/21] wohrm: Don't draw home-icon on Banglejs2 --- apps/wohrm/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index de3db14e2..8e041fa98 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -320,11 +320,13 @@ function switchOffApp(){ } Bangle.on('lcdPower', (on) => { - g.clear(); if (on) { + g.clear(); Bangle.drawWidgets(); - renderHomeIcon(); + if (typeof(BTN5) !== typeof(undefined)) { + renderHomeIcon(); + } renderLshape(lowerLshape); renderLshape(upperLshape); lowerLimitChanged = true; From 9f33ded981cb117537350698292509eac4f4e24b Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:56:03 +0100 Subject: [PATCH 08/21] wohrm: Fixed rounding of outer corner --- apps/wohrm/app.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 8e041fa98..0681a3b33 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -118,8 +118,7 @@ function drawTrainingHeartRate() { function renderUpperLimit() { if(!upperLimitChanged) { return; } - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); + renderLshape(upperLshape); if(limitSetter === Setter.UPPER){ g.setColor(255,255, 0); @@ -152,8 +151,7 @@ function renderCurrentHeartRate() { function renderLowerLimit() { if(!lowerLimitChanged) { return; } - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); + renderLshape(lowerLshape); if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); @@ -341,8 +339,6 @@ Bangle.on('HRM', onHrm); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLshape(lowerLshape); -renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { renderHomeIcon(); From 0d172f1db04b957f6b9520b61affde4f6952e92c Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 16:23:56 +0100 Subject: [PATCH 09/21] wohrm: place Upper/Lower relative to "L" --- apps/wohrm/app.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 0681a3b33..f761c421e 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -125,8 +125,10 @@ function renderUpperLimit() { } else { g.setColor(255,255,255); } - g.setFontVector(13); - g.drawString("Upper: " + upperLimit, 125, 50); + g.setFontVector(13).setFontAlign(-1, 0, 0); + g.drawString("Upper: " + upperLimit, + upperLshape.minX, + upperLshape.minY+upperLshape.rectWidth/2); upperLimitChanged = false; } @@ -158,8 +160,10 @@ function renderLowerLimit() { } else { g.setColor(255,255,255); } - g.setFontVector(13); - g.drawString("Lower: " + lowerLimit, 20,190); + g.setFontVector(13).setFontAlign(-1, 0, 0); + g.drawString("Lower: " + lowerLimit, + lowerLshape.maxX + lowerLshape.rectWidth/2, + lowerLshape.minY - lowerLshape.rectWidth/2); lowerLimitChanged = false; } From 09e7330ae0547eaa5270e2a175756167e04ccb2d Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:25:05 +0100 Subject: [PATCH 10/21] wohrm: parameterized centerBar --- apps/wohrm/app.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f761c421e..ef4a3013d 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -47,6 +47,14 @@ const lowerLshape = { fgColor: '#00f' }; +const centerBar = { + minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, + maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, + confidenceWidth: 10, + minX: 55, + maxX: 165 +}; + function fillEllipse(x, y, x2, y2) { g.fillEllipse(Math.min(x, x2), Math.min(y, y2), @@ -136,13 +144,16 @@ function renderUpperLimit() { function renderCurrentHeartRate() { if(!hrChanged) { return; } - g.setColor(255,255,255); - g.fillRect(55, 110, 165, 150); + g.setColor(1, 1, 1); + g.fillRect(centerBar.minX, centerBar.minY, + centerBar.maxX, centerBar.maxY); g.setColor(0,0,0); g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); + g.setFontAlign(1, 0, 0); + g.drawString(currentHeartRate, + upperLshape.minX+upperLshape.cornerRoundness, + (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults g.setFontAlign(-1, -1, 0); @@ -181,8 +192,8 @@ function renderConfidenceBars(){ g.setColor(255, 255, 255); } - g.fillRect(45, 110, 55, 150); - g.fillRect(165, 110, 175, 150); + g.fillRect(centerBar.minX-centerBar.confidenceWidth, centerBar.minY, centerBar.minX, centerBar.maxY); + g.fillRect(centerBar.maxX, centerBar.minY, centerBar.maxX+centerBar.confidenceWidth, centerBar.maxY); confidenceChanged = false; } From 0456843385231a1e817100386adf24026065204a Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:45:38 +0100 Subject: [PATCH 11/21] wohrm: Use theme colors --- apps/wohrm/app.js | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ef4a3013d..63194f390 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -31,8 +31,7 @@ const upperLshape = { rectWidth: 30, cornerRoundness: 5, orientation: -1, - bgColor: 0, - fgColor: '#f00' + color: '#f00' }; const lowerLshape = { @@ -43,8 +42,7 @@ const lowerLshape = { rectWidth: 30, cornerRoundness: 5, orientation: 1, - bgColor: 0, - fgColor: '#00f' + color: '#00f' }; const centerBar = { @@ -63,7 +61,7 @@ function fillEllipse(x, y, x2, y2) { } function renderLshape(p) { - g.setColor(p.fgColor); + g.setColor(p.color); g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); g.fillRect(p.maxX+p.orientation*p.rectWidth, @@ -78,12 +76,12 @@ function renderLshape(p) { p.minY-p.orientation*p.rectWidth); //Round outer corner - g.setColor(p.bgColor); + g.setColor(g.theme.bg); g.fillRect(p.maxX+p.orientation*p.cornerRoundness, p.minY, p.maxX, p.minY-p.orientation*p.cornerRoundness); - g.setColor(p.fgColor); + g.setColor(p.color); fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, p.minY, p.maxX, @@ -94,14 +92,14 @@ function renderLshape(p) { p.minY-p.orientation*(p.rectWidth+1), p.maxX+p.orientation*(p.rectWidth+1), p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); - g.setColor(p.bgColor); + g.setColor(g.theme.bg); fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), p.minY-p.orientation*(p.rectWidth+1), p.maxX+p.orientation*(p.rectWidth+1), p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); //Round end of long line - g.setColor(p.fgColor); + g.setColor(p.color); fillEllipse(p.maxX+p.orientation*p.rectWidth, p.maxY+p.orientation*p.cornerRoundness*4, p.maxX, @@ -129,9 +127,9 @@ function renderUpperLimit() { renderLshape(upperLshape); if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); + g.setColor(1,1,0); } else { - g.setColor(255,255,255); + g.setColor(g.theme.fg); } g.setFontVector(13).setFontAlign(-1, 0, 0); g.drawString("Upper: " + upperLimit, @@ -144,11 +142,11 @@ function renderUpperLimit() { function renderCurrentHeartRate() { if(!hrChanged) { return; } - g.setColor(1, 1, 1); + g.setColor(g.theme.fg); g.fillRect(centerBar.minX, centerBar.minY, centerBar.maxX, centerBar.maxY); - g.setColor(0,0,0); + g.setColor(g.theme.bg); g.setFontVector(24); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, @@ -167,9 +165,9 @@ function renderLowerLimit() { renderLshape(lowerLshape); if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 0); + g.setColor(1,1,0); } else { - g.setColor(255,255,255); + g.setColor(g.theme.fg); } g.setFontVector(13).setFontAlign(-1, 0, 0); g.drawString("Lower: " + lowerLimit, @@ -183,13 +181,13 @@ function renderConfidenceBars(){ if(!confidenceChanged) { return; } if(hrConfidence >= 85){ - g.setColor(0, 255, 0); + g.setColor(0, 1, 0); } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); + g.setColor(1, 1, 0); } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); + g.setColor(1, 0, 0); } else { - g.setColor(255, 255, 255); + g.setColor(g.theme.fg); } g.fillRect(centerBar.minX-centerBar.confidenceWidth, centerBar.minY, centerBar.minX, centerBar.maxY); @@ -200,9 +198,9 @@ function renderConfidenceBars(){ function renderPlusMinusIcons() { if (limitSetter === Setter.NONE) { - g.setColor(0, 0, 0); + g.setColor(g.theme.bg); } else { - g.setColor(1, 1, 1); + g.setColor(g.theme.fg); } g.setFontVector(14); From b513772692f129ad676b8f1dac15ecdf1419ce8f Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:51:55 +0100 Subject: [PATCH 12/21] wohrm: parameterized font sizes --- apps/wohrm/app.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 63194f390..bb21b5d59 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -53,6 +53,11 @@ const centerBar = { maxX: 165 }; +const fontSizes = { + limits: 13, + heartRate: 24 +}; + function fillEllipse(x, y, x2, y2) { g.fillEllipse(Math.min(x, x2), Math.min(y, y2), @@ -131,7 +136,7 @@ function renderUpperLimit() { } else { g.setColor(g.theme.fg); } - g.setFontVector(13).setFontAlign(-1, 0, 0); + g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Upper: " + upperLimit, upperLshape.minX, upperLshape.minY+upperLshape.rectWidth/2); @@ -147,7 +152,7 @@ function renderCurrentHeartRate() { centerBar.maxX, centerBar.maxY); g.setColor(g.theme.bg); - g.setFontVector(24); + g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, upperLshape.minX+upperLshape.cornerRoundness, @@ -169,7 +174,7 @@ function renderLowerLimit() { } else { g.setColor(g.theme.fg); } - g.setFontVector(13).setFontAlign(-1, 0, 0); + g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Lower: " + lowerLimit, lowerLshape.maxX + lowerLshape.rectWidth/2, lowerLshape.minY - lowerLshape.rectWidth/2); From d5e08477e1692a7867f0c715070e58f0b7fddffd Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:59:57 +0100 Subject: [PATCH 13/21] wohrm: deduplicate --- apps/wohrm/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index bb21b5d59..6ebcdabc3 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -37,10 +37,10 @@ const upperLshape = { const lowerLshape = { maxX: 10, minX: 100, - minY: 210, - maxY: 40, - rectWidth: 30, - cornerRoundness: 5, + minY: upperLshape.maxY, + maxY: upperLshape.minY, + rectWidth: upperLshape.rectWidth, + cornerRoundness: upperLshape.cornerRoundness, orientation: 1, color: '#00f' }; From b120f7572f454426ab8bb912830e758f177134dd Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 19:32:19 +0100 Subject: [PATCH 14/21] wohrm: resize on Bangls.js2 --- apps/wohrm/app.js | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 6ebcdabc3..75d48c7ff 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,7 +23,8 @@ let confidenceChanged = true; let setterHighlightTimeout; -const upperLshape = { +const isB1 = process.env.HWVERSION==1; +const upperLshape = isB1 ? { minX: 125, maxX: 210, minY: 40, @@ -32,10 +33,19 @@ const upperLshape = { cornerRoundness: 5, orientation: -1, color: '#f00' +} : { + minX: Bangle.appRect.x2-100, + maxX: Bangle.appRect.x2, + minY: Bangle.appRect.y, + maxY: Bangle.appRect.y2, + rectWidth: 26, + cornerRoundness: 4, + orientation: -1, + color: '#f00' }; const lowerLshape = { - maxX: 10, + maxX: isB1 ? 10 : Bangle.appRect.x, minX: 100, minY: upperLshape.maxY, maxY: upperLshape.minY, @@ -48,14 +58,17 @@ const lowerLshape = { const centerBar = { minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, - confidenceWidth: 10, - minX: 55, - maxX: 165 + confidenceWidth: isB1 ? 10 : 8, + minX: isB1 ? 55 : upperLshape.rectWidth + 14, + maxX: isB1 ? 165 : Bangle.appRect.x2 - upperLshape.rectWidth - 14 }; -const fontSizes = { - limits: 13, - heartRate: 24 +const fontSizes = isB1 ? { + limits: 13, + heartRate: 24 +} : { + limits: 12, + heartRate: 20 }; function fillEllipse(x, y, x2, y2) { @@ -155,7 +168,8 @@ function renderCurrentHeartRate() { g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, - upperLshape.minX+upperLshape.cornerRoundness, + Math.max(upperLshape.minX+upperLshape.cornerRoundness, + lowerLshape.minX-lowerLshape.cornerRoundness), (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults From 3ae35376fcd3db363c33030b01d88e254a0781d5 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 20:45:11 +0100 Subject: [PATCH 15/21] wohrm: fixes after running on Bangle.js2 - set to dark theme as doesn't look good with white in the corners) - leave space for widgets --- apps.json | 2 +- apps/wohrm/app.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 07c773725..2acd3b981 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc1", + "version": "0.09-rc2", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 75d48c7ff..429b9f565 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -36,7 +36,7 @@ const upperLshape = isB1 ? { } : { minX: Bangle.appRect.x2-100, maxX: Bangle.appRect.x2, - minY: Bangle.appRect.y, + minY: 24, maxY: Bangle.appRect.y2, rectWidth: 26, cornerRoundness: 4, @@ -368,7 +368,7 @@ Bangle.on('lcdPower', (on) => { Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); -g.clear(); +g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From 9e1dd8eda39fb1bc76b9c52e1851072158cb4982 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:01:47 +0100 Subject: [PATCH 16/21] wohrm: Fix bgcolor --- apps.json | 2 +- apps/wohrm/app.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 2acd3b981..ed616c952 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc2", + "version": "0.09-rc3", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 429b9f565..115849fa6 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -351,7 +351,6 @@ function switchOffApp(){ Bangle.on('lcdPower', (on) => { if (on) { - g.clear(); Bangle.drawWidgets(); if (typeof(BTN5) !== typeof(undefined)) { @@ -368,7 +367,9 @@ Bangle.on('lcdPower', (on) => { Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); -g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); +g.setTheme({bg:"#000",fg:"#fff",dark:true}); +g.reset() +g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From 288a204b9d608d90bb33cf82ec005f8a980df01e Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:13:39 +0100 Subject: [PATCH 17/21] wohrm: Add ChangeLog entry --- apps/wohrm/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 084ca6ed5..156d32740 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -5,4 +5,5 @@ 0.05: Improved buzz timing and rendering 0.06: Removed debug outputs, fixed rendering for upper limit, improved rendering for +/- icons, changelog version order fixed 0.07: Home button fixed and README added -0.08: tag HRM power requests to allow this ot work alongside other widgets/apps (fix #799) +0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) +0.09: Ported to Bangle.js2 From 15df1205060eaf866fb3b2eb0c4db861a0d7bc90 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:29:16 +0100 Subject: [PATCH 18/21] wohrm: Home returns to clock, instead of menu --- apps.json | 2 +- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index ed616c952..4d98ce731 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc3", + "version": "0.09-rc4", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 156d32740..b177c1902 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -7,3 +7,4 @@ 0.07: Home button fixed and README added 0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) 0.09: Ported to Bangle.js2 + Home returns to clock, instead of menu diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 115849fa6..646dab58f 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -346,7 +346,7 @@ function resetHighlightTimeout() { function switchOffApp(){ Bangle.setHRMPower(0,"wohrm"); - Bangle.showLauncher(); + load(); } Bangle.on('lcdPower', (on) => { From 0caa10b7052a639ba80d2f35d061b6026cef6bf7 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 22:01:08 +0100 Subject: [PATCH 19/21] wohrm: Add settings --- apps.json | 3 ++- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 26 ++++++++++++++------------ apps/wohrm/settings.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 apps/wohrm/settings.js diff --git a/apps.json b/apps.json index 4d98ce731..1d4f98c1e 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc4", + "version": "0.09-rc7", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", @@ -1725,6 +1725,7 @@ "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], "storage": [ {"name":"wohrm.app.js","url":"app.js"}, + {"name":"wohrm.settings.js","url":"settings.js"}, {"name":"wohrm.img","url":"app-icon.js","evaluate":true} ] }, diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index b177c1902..2ca405365 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -8,3 +8,4 @@ 0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) 0.09: Ported to Bangle.js2 Home returns to clock, instead of menu + Add settings diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 646dab58f..26e7b7eae 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -4,14 +4,16 @@ const Setter = { UPPER: 'upper', LOWER: 'lower' }; +const SETTINGS_FILE = "wohrm.setting.json"; +var settings = require('Storage').readJSON(SETTINGS_FILE, 1) || { + upperLimit: 130, + lowerLimit: 100 +}; const shortBuzzTimeInMs = 80; const longBuzzTimeInMs = 400; -let upperLimit = 130; let upperLimitChanged = true; - -let lowerLimit = 100; let lowerLimitChanged = true; let limitSetter = Setter.NONE; @@ -150,7 +152,7 @@ function renderUpperLimit() { g.setColor(g.theme.fg); } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); - g.drawString("Upper: " + upperLimit, + g.drawString("Upper: " + settings.upperLimit, upperLshape.minX, upperLshape.minY+upperLshape.rectWidth/2); @@ -189,7 +191,7 @@ function renderLowerLimit() { g.setColor(g.theme.fg); } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); - g.drawString("Lower: " + lowerLimit, + g.drawString("Lower: " + settings.lowerLimit, lowerLshape.maxX + lowerLshape.rectWidth/2, lowerLshape.minY - lowerLshape.rectWidth/2); @@ -247,13 +249,13 @@ function buzz() { // Do not buzz if not confident if(hrConfidence < 85) { return; } - if(currentHeartRate > upperLimit) + if(currentHeartRate > settings.upperLimit) { Bangle.buzz(shortBuzzTimeInMs); setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); } - if(currentHeartRate < lowerLimit) + if(currentHeartRate < settings.lowerLimit) { Bangle.buzz(longBuzzTimeInMs); } @@ -312,11 +314,11 @@ function incrementLimit() { resetHighlightTimeout(); if (limitSetter === Setter.UPPER) { - upperLimit++; + settings.upperLimit++; renderUpperLimit(); upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { - lowerLimit++; + settings.lowerLimit++; renderLowerLimit(); lowerLimitChanged = true; } @@ -326,11 +328,11 @@ function decrementLimit(){ resetHighlightTimeout(); if (limitSetter === Setter.UPPER) { - upperLimit--; + settings.upperLimit--; renderUpperLimit(); upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { - lowerLimit--; + settings.lowerLimit--; renderLowerLimit(); lowerLimitChanged = true; } @@ -368,7 +370,7 @@ Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); g.setTheme({bg:"#000",fg:"#fff",dark:true}); -g.reset() +g.reset(); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); diff --git a/apps/wohrm/settings.js b/apps/wohrm/settings.js new file mode 100644 index 000000000..6d31688f4 --- /dev/null +++ b/apps/wohrm/settings.js @@ -0,0 +1,35 @@ +(function menu(back) { + const SETTINGS_FILE = "wohrm.setting.json"; + + // initialize with default settings... + const storage = require('Storage'); + var settings = storage.readJSON(SETTINGS_FILE, 1) || { + upperLimit: 130, + lowerLimit: 100 + }; + + function save() { + storage.write(SETTINGS_FILE, settings); + } + + E.showMenu({ + '': { 'title': 'Workout HRM' }, + '< Back': back, + 'Upper limit': { + value: settings.upperLimit, + min: 100, max: 200, + onchange: v => { + settings.upperLimit = v; + save(); + } + }, + 'Lower limit': { + value: settings.lowerLimit, + min: 50, max: 150, + onchange: v => { + settings.lowerLimit = v; + save(); + } + } + }); +}) From 4f16d6ce35cfc3ea49075a5fa0c4d9cda9c67754 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Mon, 20 Dec 2021 11:08:08 +0100 Subject: [PATCH 20/21] wohrm: Refactor renderLshape() rename variables and document renderLshape() --- apps.json | 2 +- apps/wohrm/app.js | 110 +++++++++++++++++++++++++--------------------- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/apps.json b/apps.json index 1d4f98c1e..7898ba786 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc7", + "version": "0.09-rc10", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 26e7b7eae..ab579463c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -27,30 +27,30 @@ let setterHighlightTimeout; const isB1 = process.env.HWVERSION==1; const upperLshape = isB1 ? { - minX: 125, - maxX: 210, - minY: 40, - maxY: 210, + right: 125, + left: 210, + bottom: 40, + top: 210, rectWidth: 30, cornerRoundness: 5, orientation: -1, color: '#f00' } : { - minX: Bangle.appRect.x2-100, - maxX: Bangle.appRect.x2, - minY: 24, - maxY: Bangle.appRect.y2, + right: Bangle.appRect.x2-100, + left: Bangle.appRect.x2, + bottom: 24, + top: Bangle.appRect.y2, rectWidth: 26, cornerRoundness: 4, - orientation: -1, + orientation: -1, // rotated 180° color: '#f00' }; const lowerLshape = { - maxX: isB1 ? 10 : Bangle.appRect.x, - minX: 100, - minY: upperLshape.maxY, - maxY: upperLshape.minY, + left: isB1 ? 10 : Bangle.appRect.x, + right: 100, + bottom: upperLshape.top, + top: upperLshape.bottom, rectWidth: upperLshape.rectWidth, cornerRoundness: upperLshape.cornerRoundness, orientation: 1, @@ -58,8 +58,8 @@ const lowerLshape = { }; const centerBar = { - minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, - maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, + minY: (upperLshape.bottom + upperLshape.top - upperLshape.rectWidth)/2, + maxY: (upperLshape.bottom + upperLshape.top + upperLshape.rectWidth)/2, confidenceWidth: isB1 ? 10 : 8, minX: isB1 ? 55 : upperLshape.rectWidth + 14, maxX: isB1 ? 165 : Bangle.appRect.x2 - upperLshape.rectWidth - 14 @@ -80,50 +80,60 @@ function fillEllipse(x, y, x2, y2) { Math.max(y, y2)); } +/** + * @param p.left: the X coordinate of the left side of the L in its orientation + * @param p.right: the X coordinate of the right side of the L in its orientation + * @param p.top: the Y coordinate of the top side of the L in its orientation + * @param p.bottom: the Y coordinate of the bottom side of the L in its orientation + * @param p.strokeWidth: how thick we draw the letter. + * @param p.cornerRoundness: how much the corners should be rounded + * @param p.orientation: 1 == turned 0°; -1 == turned 180° + * @param p.color: the color to draw the shape + */ function renderLshape(p) { g.setColor(p.color); - g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); - g.fillRect(p.maxX+p.orientation*p.rectWidth, - p.minY-p.orientation*p.rectWidth, - p.maxX, - p.maxY+p.orientation*p.cornerRoundness*2); + g.fillRect(p.right, p.bottom, p.left, p.bottom-p.orientation*p.rectWidth); + g.fillRect(p.left+p.orientation*p.rectWidth, + p.bottom-p.orientation*p.rectWidth, + p.left, + p.top+p.orientation*p.cornerRoundness*2); //Round end of small line - fillEllipse(p.minX+p.orientation*p.cornerRoundness*2, - p.minY, - p.minX-p.orientation*p.cornerRoundness*2, - p.minY-p.orientation*p.rectWidth); + fillEllipse(p.right+p.orientation*p.cornerRoundness*2, + p.bottom, + p.right-p.orientation*p.cornerRoundness*2, + p.bottom-p.orientation*p.rectWidth); //Round outer corner g.setColor(g.theme.bg); - g.fillRect(p.maxX+p.orientation*p.cornerRoundness, - p.minY, - p.maxX, - p.minY-p.orientation*p.cornerRoundness); + g.fillRect(p.left+p.orientation*p.cornerRoundness, + p.bottom, + p.left, + p.bottom-p.orientation*p.cornerRoundness); g.setColor(p.color); - fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, - p.minY, - p.maxX, - p.minY-p.orientation*p.cornerRoundness*2); + fillEllipse(p.left+p.orientation*p.cornerRoundness*4, + p.bottom, + p.left, + p.bottom-p.orientation*p.cornerRoundness*2); //Round inner corner - g.fillRect(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness+1), - p.minY-p.orientation*(p.rectWidth+1), - p.maxX+p.orientation*(p.rectWidth+1), - p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); + g.fillRect(p.left+p.orientation*(p.rectWidth+p.cornerRoundness+1), + p.bottom-p.orientation*(p.rectWidth+1), + p.left+p.orientation*(p.rectWidth+1), + p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness-1)); g.setColor(g.theme.bg); - fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), - p.minY-p.orientation*(p.rectWidth+1), - p.maxX+p.orientation*(p.rectWidth+1), - p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); + fillEllipse(p.left+p.orientation*(p.rectWidth+p.cornerRoundness*4), + p.bottom-p.orientation*(p.rectWidth+1), + p.left+p.orientation*(p.rectWidth+1), + p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); //Round end of long line g.setColor(p.color); - fillEllipse(p.maxX+p.orientation*p.rectWidth, - p.maxY+p.orientation*p.cornerRoundness*4, - p.maxX, - p.maxY); + fillEllipse(p.left+p.orientation*p.rectWidth, + p.top+p.orientation*p.cornerRoundness*4, + p.left, + p.top); } function drawTrainingHeartRate() { @@ -153,8 +163,8 @@ function renderUpperLimit() { } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Upper: " + settings.upperLimit, - upperLshape.minX, - upperLshape.minY+upperLshape.rectWidth/2); + upperLshape.right, + upperLshape.bottom+upperLshape.rectWidth/2); upperLimitChanged = false; } @@ -170,8 +180,8 @@ function renderCurrentHeartRate() { g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, - Math.max(upperLshape.minX+upperLshape.cornerRoundness, - lowerLshape.minX-lowerLshape.cornerRoundness), + Math.max(upperLshape.right+upperLshape.cornerRoundness, + lowerLshape.right-lowerLshape.cornerRoundness), (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults @@ -192,8 +202,8 @@ function renderLowerLimit() { } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Lower: " + settings.lowerLimit, - lowerLshape.maxX + lowerLshape.rectWidth/2, - lowerLshape.minY - lowerLshape.rectWidth/2); + lowerLshape.left + lowerLshape.rectWidth/2, + lowerLshape.bottom - lowerLshape.rectWidth/2); lowerLimitChanged = false; } From 992b1e6564777d5d4e3bb012594ee5c030953393 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 9 Jan 2022 18:55:33 +0100 Subject: [PATCH 21/21] Bumped wohrm version number --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ebe193f3a..c155f9262 100644 --- a/apps.json +++ b/apps.json @@ -1717,7 +1717,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc10", + "version": "0.09", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app",