From 911c0e454c0525b83a3d3888cb6311b4de0ff6e2 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 16 Feb 2020 09:42:39 +0100 Subject: [PATCH 01/83] Initial checkin --- apps/wohrm/ChangeLog | 1 + apps/wohrm/add_to_apps.json | 13 +++ apps/wohrm/app-icon.js | 1 + apps/wohrm/wohrm.js | 166 ++++++++++++++++++++++++++++++++++++ apps/wohrm/wohrm.json | 5 ++ apps/wohrm/wohrm.png | Bin 0 -> 1925 bytes 6 files changed, 186 insertions(+) create mode 100644 apps/wohrm/ChangeLog create mode 100644 apps/wohrm/add_to_apps.json create mode 100644 apps/wohrm/app-icon.js create mode 100644 apps/wohrm/wohrm.js create mode 100644 apps/wohrm/wohrm.json create mode 100644 apps/wohrm/wohrm.png diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog new file mode 100644 index 000000000..bc13085a4 --- /dev/null +++ b/apps/wohrm/ChangeLog @@ -0,0 +1 @@ +0.01: Only tested on the emulator. diff --git a/apps/wohrm/add_to_apps.json b/apps/wohrm/add_to_apps.json new file mode 100644 index 000000000..96ffe838c --- /dev/null +++ b/apps/wohrm/add_to_apps.json @@ -0,0 +1,13 @@ +// Create an entry in apps.json as follows: +{ "id": "wohrm", + "name": "Workout Heart Rate Monitor", + "icon": "wohrm.png", + "version":"0.01", + "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", + "tags": "hrm workout app", + "storage": [ + {"name":"+wohrm","url":"wohrm.json"}, + {"name":"-wohrm","url":"wohrm.js"}, + {"name":"*wohrm","url":"wohrm-icon.js","evaluate":true} + ] +} diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js new file mode 100644 index 000000000..36663d0ed --- /dev/null +++ b/apps/wohrm/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("MDCI/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsK7u8HC/v7+/v7+/v7+/v7+/v7Cwbu7wsL+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7u7u7u7u7vI/v7+/v7+/v7Iu7u7u7u7u7u7u8n+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/ru7u7u7u7u7u7u7u7u7u7v+/v7+u7u7u7u7u7u7u7u7u7u7u/7+/v7+/v7+/v7+u7u7u7u7u7u7u7u7u7u7u7u7/v67u7u7u7u7u7u7u7u7u7u7u7v+/v7+/v7+/v67u7u7u7u7u7u7wci7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7/v7+/v7+/sm7u7u7u7u7u7u7wsm7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7yf7+/v7+/ru7u7u7u7u7u7u7ydC7u7u7u7u7u7u7u7u7u7u7u8LQ19DCu7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u70NfCu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u/7+/v7+wru7u7u7u7u7u7vC19fJu7u7u7u7u7u7u7u7u7u7u9fX19fXu7u7u7u7u8L+/v7+wru7u7u7u7u7u7vJ19fJu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u8L+/v7+u7u7u7u7u7u7u7vQ19fQu7u7u7u7u7u7u7u7u7u7u8nX19DCu7u7u7u7u7v+/v7+wbu7u7u7ybu7u7vX19DXwru7u7u7u7u7u7u7wcnQ19fX0Lu7u7u7u7u7u8H+/v7+wru7u7vC18K7u8LX0MnXybu7u7vCu7u7wc/Q19fX19fX18K7u7u7u7u7u8L+/v7+yLu7u7vJ18m7u8nXycnXybu7u7vJu7u7wtfX19DJydfX19C7u7u7u7u7u8j+/v7+/ru7u8HR19HBu9DXwsLX0Lu7u7vQu7u7wdfX0Lu70NfJ0NfJu7u7u7u7u/7+/v7+/ru7u8nX19fJwtfQu7vQ18K7u8LXu7u7u8HQ18LC19fBwtfXycm7u7u7u/7+/v7+/tDX19fXydfQydfJu7vJ18m7u8nXu7u7u7vBwrvQ18m7u9DX19e7u7u7yf7+/v7+/v7Q19fQu9DX0NfIu7vJ18m7u9DXu7u7u7u7u8HX18K7u8HJycm7u7u7/v7+/v7+/v7+u7u7u8nX19fBu7vC19C7wtfQu7u7u7u7u8nX0Lu7u7u7u7u7u7v+/v7+/v7+/v7+wru7u8HR19C7u7u70NfCz9fJu7u7wru7u9fX18nCu7u7u7u7u8L+/v7+/v7+/v7+/sG7u7vJ18m7u7u7ydfJ0dfBu8HC19C7yNfX19fX0MK7u7u7wf7+/v7+/v7+/v7+/v67u7vC18K7u7u7ydfQ19C7u7vB0NfQ0NfJws/X18G7u7u7/v7+/v7+/v7+/v7+/v7+u7u70Lu7u7u7wtfX18m7u7u7wdDX19e7u8LX18K7u7v+/v7+/v7+/v7+/v7+/v7+/ru7wbu7u7u7u9DX18G7u7u7u8HJ18m7wdDX0Lu7u/7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u8nX0Lu7u7u7u7u7wcG70NfQu7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+wbu7u7u7u8nXyLu7u7u7u7u7u7vJ19fCu7v+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sG7u7u7u8LXwbu7u7u7u7u7u8HX18K7wf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7Cu7u7u7vJu7u7u7u7u7u7u7vCybvC/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7vBu7u7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sm7u7u7u7u7u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsL+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/g==")) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js new file mode 100644 index 000000000..d5f2c1c03 --- /dev/null +++ b/apps/wohrm/wohrm.js @@ -0,0 +1,166 @@ +upperLimit = 130; +lowerLimit = 100; +limitSetter = "lower"; +currentHeartRate = 220; +hrConfidence = 49; + +function drawTrainingHeartRate() { + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + + buzz(); +} + +function renderUpperLimit() { + g.setColor(255,0,0); + g.fillRect(140,40, 230, 70); + g.fillRect(200,70, 230, 210); + + if(limitSetter === "upper"){ + g.setColor(255,255, 255); + g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); + } + + g.setColor(255,255,255); + g.setFontVector(10); + g.drawString("Upper : " + upperLimit, 150,50); +} + +function renderCurrentHeartRate() { + g.setColor(0,255,0); + g.fillRect(55, 110, 175, 140); + g.setColor(0,0,0); + g.setFontVector(13); + g.drawString("Current: " + currentHeartRate, 75,117); +} + +function renderLowerLimit() { + g.setColor(0,0,255); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 40, 40, 180); + + if(limitSetter === "lower"){ + g.setColor(255,255, 255); + g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); + } + + g.setColor(255,255,255); + g.setFontVector(10); + g.drawString("Lower : " + lowerLimit, 20,190); +} + +function renderConfidenceBars(){ + 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(0, 0, 0); + } + + g.fillRect(55, 110, 65, 140); + g.fillRect(175, 110, 185, 140); +} + +function buzz() +{ + if(currentHeartRate > upperLimit) + { + Bangle.buzz(70); + setTimeout(() => { Bangle.buzz(70); }, 70); + setTimeout(() => { Bangle.buzz(70); }, 70); + } + + if(currentHeartRate < upperLimit) + { + Bangle.buzz(140); + setTimeout(() => { Bangle.buzz(140); }, 140); + } +} + +function onHrm(hrm){ + currentHeartRate = hrm.bpm; + hrConfidence = hrm.confidence; +} + +function setLimitSetterToLower() { + limitSetter = "lower"; + console.log("Limit setter is lower"); + renderUpperLimit(); + renderLowerLimit(); +} + +function setLimitSetterToUpper() { + limitSetter = "upper"; + console.log("Limit setter is upper"); + renderLowerLimit(); + renderUpperLimit(); +} + +function incrementLimit(){ + if(limitSetter === "upper"){ + upperLimit++; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else { + lowerLimit++; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + +function decrementLimit(){ + if(limitSetter === "upper"){ + upperLimit--; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else { + lowerLimit--; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + +// Show launcher when middle button pressed +function switchOfWidget(){ + Bangle.setHRMPower(0); + Bangle.showLauncher(); +} + +// special function to handle display switch on +Bangle.on('lcdPower', (on) => { + g.clear(); + if (on) { + Bangle.drawWidgets(); + // call your app function here + drawTrainingHeartRate(); + } +}); + +Bangle.setHRMPower(1); +Bangle.on('HRM', onHrm); + +// refesh every sec +setInterval(drawTrainingHeartRate, 1000); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawTrainingHeartRate(); + +setWatch(switchOfWidget, BTN2, {repeat:false,edge:"falling"}); + +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}); \ No newline at end of file diff --git a/apps/wohrm/wohrm.json b/apps/wohrm/wohrm.json new file mode 100644 index 000000000..9b212bfd4 --- /dev/null +++ b/apps/wohrm/wohrm.json @@ -0,0 +1,5 @@ +{ + "name":"Workout HRM", + "icon":"*wohrm", + "src":"-wohrm" +} diff --git a/apps/wohrm/wohrm.png b/apps/wohrm/wohrm.png new file mode 100644 index 0000000000000000000000000000000000000000..8f9c0ea5dc9baa64f7b6586eaba4773699b33b72 GIT binary patch literal 1925 zcmeHH`8(7J82^rOrA9nbvWZeco1+|sax)m$xbKmp+!NzLmunR38dlU~SFI?Kt5gzE zVzr(X5y_FG=MIN6e<6r}(FAlZ?vs6y5G z0ZF2eX%kyoghEK5+FAhhfA3io4x(qw9nArtsc9lkQW8=ra->Vu%9awK!pR`;6N%I=mrJ3Lo^SV<_QIRL8rZ-5N|ld7Yg-- z!~NiJe>fr#jy{dVgdwqENL)A^9|0#sA_-A&Vib}TgCxZv$+1YvIpjPYxo{4-5RYC? zLQ|6w=0)VnWi%rN&A5POUPQA}k?b@ikBJmyp;yz;>~v0c1}7&I%}qyhh0NsSUP1Gi zoPumlVGgG#m-A~rT9S`mD?m#NIVCK#tcY{Hh;yTubF+k7ejUBd=2ZU1t^R{oUCFz9 zhgVa@t*zqJRrBgT6St)id(y&v`jFT5nAg#YwYT%S zo?~5|SobTe=M}H7hu7c7@B0%Ia(_QIG=RMu#72hr!^8N<2sZW}`!I@+PvDbN*z_bm zHH}Yw!l!5WGt>CYoM3hypZmg}pB2o15qw?{EG!DXF7ubZ3KmxcORIwAHU8QvzW$B> zeI4K2z+ni7VH`zp6veq*9OK~_hU2(EAQ0~Q|N2(~%Ch>B!aD&NR3|rKME~Ui+z^R_ z!g#jO$vz1HApPnG2)%LlLWQOR!`hqS78lM)3XTs0=)n=O46WEOhKin+j+TB{*3mEk z5Sg;GGIu9Cd@k|vk~5ddipd~T%rabURHZ~;XJ#DEK0LcO$z?cG@m!a@t3N$IJI%pe z=9-9@<(#qKCDu3dJcD62X`cRJ=g8Rjn?ZANYKrpou?>UU>BDgn+Z#204xK9w zlqdAI-g>kkebXl~n{Y;(`BcACt?G?Jk7hokL$kS4PVj#H-gTR7$O`Fgr)pJXnrgIC zjmdtVlA`)T(U4DCp4xejjZZEzn|jvsgP@DL1!d|Fx))qjthNGr4b1I( zb%Dsy$0Ck?-*ecC6wxL6l1+)!*4@d~Lv$ss(_lP9&QM>a&UY{$VJ3GU8th5KMBbK- zN@O-VXG>1Vb1F!;SfcljkR}U;v{Ch10-vr&%qx|2t!9r&Yo`QNqAwMS3lwR&isBtF zqcm%K7f(G>cbnTarAuLqIgg4f>8EY0u`u?pK7UAWdttpy`gqRuRBfmIY855a_U;3_ zS%F4vj(W1`&TlK%Jokj~lk1zKH0=ahg_#B_BOgq>&CG6$H;07Qp~~3muBbzDk*=6c z8vq4rS1Gj1nUerU?i$0Mx zgo8~Rtt;w8mdBnE`ygozIo9Ct)m5D`f3_IwX!Pu76Uw`~G#s37X?FJ7X|^`r7hc^= e@X?nbXb1>8u*t*8XN-v-AH>eu$*SIhmhlgSO4arN literal 0 HcmV?d00001 From e5624843605dfbf71d57d929031e3ff3ff2ea58e Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 16 Feb 2020 09:48:07 +0100 Subject: [PATCH 02/83] Adds Workout Heart Rate Monitor App --- apps.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0c47a9377..212ece336 100644 --- a/apps.json +++ b/apps.json @@ -809,6 +809,17 @@ {"name":"-flagrse","url":"app.js"}, {"name":"*flagrse","url":"app-icon.js","evaluate":true} ] + }, + { "id": "wohrm", + "name": "Workout Heart Rate Monitor", + "icon": "wohrm.png", + "version":"0.01", + "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", + "tags": "hrm workout app", + "storage": [ + {"name":"+wohrm","url":"wohrm.json"}, + {"name":"-wohrm","url":"wohrm.js"}, + {"name":"*wohrm","url":"wohrm-icon.js","evaluate":true} + ] } - ] From 18c69b9e677e22436e3263182b2c52884c54155f Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 16 Feb 2020 09:52:06 +0100 Subject: [PATCH 03/83] Fixes type and tags for wohrm --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 212ece336..cb98281fc 100644 --- a/apps.json +++ b/apps.json @@ -815,7 +815,8 @@ "icon": "wohrm.png", "version":"0.01", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", - "tags": "hrm workout app", + "tags": "hrm,workout,app", + "type": "app", "storage": [ {"name":"+wohrm","url":"wohrm.json"}, {"name":"-wohrm","url":"wohrm.js"}, From 7386330f599165378a1a0a9251f58e56c8ee9a64 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 16 Feb 2020 09:56:01 +0100 Subject: [PATCH 04/83] Allow running in the emulator for wohrm --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index cb98281fc..ca784bd37 100644 --- a/apps.json +++ b/apps.json @@ -815,8 +815,9 @@ "icon": "wohrm.png", "version":"0.01", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", - "tags": "hrm,workout,app", + "tags": "hrm,workout", "type": "app", + "allow_emulator":true, "storage": [ {"name":"+wohrm","url":"wohrm.json"}, {"name":"-wohrm","url":"wohrm.js"}, From f01133bf571abed7082679cf0f36d33be5b7bb2d Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Mon, 17 Feb 2020 21:54:12 +0100 Subject: [PATCH 05/83] Uses enum for limit setter values --- apps/wohrm/wohrm.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index d5f2c1c03..7d39f5e63 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -1,8 +1,13 @@ +const Setter = { + UPPER: 'upper', + LOWER: 'lower' +}; + upperLimit = 130; lowerLimit = 100; -limitSetter = "lower"; -currentHeartRate = 220; -hrConfidence = 49; +limitSetter = Setter.LOWER; +currentHeartRate = 0; +hrConfidence = -1; function drawTrainingHeartRate() { renderUpperLimit(); @@ -21,7 +26,7 @@ function renderUpperLimit() { g.fillRect(140,40, 230, 70); g.fillRect(200,70, 230, 210); - if(limitSetter === "upper"){ + if(limitSetter === Setter.UPPER){ g.setColor(255,255, 255); g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); } @@ -44,7 +49,7 @@ function renderLowerLimit() { g.fillRect(10, 180, 100, 210); g.fillRect(10, 40, 40, 180); - if(limitSetter === "lower"){ + if(limitSetter === Setter.LOWER){ g.setColor(255,255, 255); g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); } @@ -91,21 +96,21 @@ function onHrm(hrm){ } function setLimitSetterToLower() { - limitSetter = "lower"; + limitSetter = Setter.LOWER; console.log("Limit setter is lower"); renderUpperLimit(); renderLowerLimit(); } function setLimitSetterToUpper() { - limitSetter = "upper"; + limitSetter = Setter.UPPER; console.log("Limit setter is upper"); renderLowerLimit(); renderUpperLimit(); } function incrementLimit(){ - if(limitSetter === "upper"){ + if(limitSetter === Setter.UPPER){ upperLimit++; renderUpperLimit(); console.log("Upper limit: " + upperLimit); @@ -117,7 +122,7 @@ function incrementLimit(){ } function decrementLimit(){ - if(limitSetter === "upper"){ + if(limitSetter === Setter.UPPER){ upperLimit--; renderUpperLimit(); console.log("Upper limit: " + upperLimit); @@ -163,4 +168,4 @@ 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}); \ No newline at end of file +setWatch(setLimitSetterToUpper, BTN5, {edge:"rising", debounce:50, repeat:true}); From d3711e6ae9067777a53fb404a6c41a2bce35bd79 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 18 Feb 2020 21:47:20 +0100 Subject: [PATCH 06/83] Icon renamed. --- apps/wohrm/{app-icon.js => wohrm-icon.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/wohrm/{app-icon.js => wohrm-icon.js} (100%) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/wohrm-icon.js similarity index 100% rename from apps/wohrm/app-icon.js rename to apps/wohrm/wohrm-icon.js From 173d9a2dae7885051ff044ec6399d8aaa96f85f5 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 1 Mar 2020 12:10:17 +0100 Subject: [PATCH 07/83] Adds rounded corners for upper limit button --- apps/wohrm/.gitignore | 4 ++++ apps/wohrm/wohrm.js | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 apps/wohrm/.gitignore diff --git a/apps/wohrm/.gitignore b/apps/wohrm/.gitignore new file mode 100644 index 000000000..2060ed3f3 --- /dev/null +++ b/apps/wohrm/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.eslintrc.js +/package.json +/package-lock.json \ No newline at end of file diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 7d39f5e63..c30c62eb6 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -1,13 +1,14 @@ +/* eslint-disable no-undef */ const Setter = { UPPER: 'upper', LOWER: 'lower' }; -upperLimit = 130; -lowerLimit = 100; -limitSetter = Setter.LOWER; -currentHeartRate = 0; -hrConfidence = -1; +let upperLimit = 130; +let lowerLimit = 100; +let limitSetter = Setter.LOWER; +let currentHeartRate = 0; +let hrConfidence = -1; function drawTrainingHeartRate() { renderUpperLimit(); @@ -26,6 +27,36 @@ function renderUpperLimit() { g.fillRect(140,40, 230, 70); g.fillRect(200,70, 230, 210); + //Round top left corner + g.setColor(0,0,0); + g.fillRect(140,40, 145, 45); + g.setColor(255,0,0); + g.fillCircle(150,50, 10); + + //Round top right corner + g.setColor(0,0,0); + g.fillRect(225,40, 230, 45); + g.setColor(255,0,0); + g.fillCircle(220,50, 10); + + //Round middle left corner + g.setColor(0,0,0); + g.fillRect(140,65, 145, 70); + g.setColor(255,0,0); + g.fillCircle(150,60, 10); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(200,205, 205, 210); + g.setColor(255,0,0); + g.fillCircle(210,200, 10); + + //Round bottom right corner + g.setColor(0,0,0); + g.fillRect(225,205, 230, 210); + g.setColor(255,0,0); + g.fillCircle(220,200, 10); + if(limitSetter === Setter.UPPER){ g.setColor(255,255, 255); g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); From 73dc1d0a7306e489d3a3186ea874240b00daf064 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 1 Mar 2020 21:14:35 +0100 Subject: [PATCH 08/83] UI fixes and code cleanup --- apps/wohrm/wohrm.js | 58 ++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index c30c62eb6..2d9553473 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -1,12 +1,16 @@ /* eslint-disable no-undef */ const Setter = { - UPPER: 'upper', - LOWER: 'lower' -}; + NONE: "none", + UPPER: 'upper', + LOWER: 'lower' + }; + +const shortBuzzTimeInMs = 100; +const longBuzzTimeInMs = 200; let upperLimit = 130; let lowerLimit = 100; -let limitSetter = Setter.LOWER; +let limitSetter = Setter.NONE; let currentHeartRate = 0; let hrConfidence = -1; @@ -24,38 +28,28 @@ function drawTrainingHeartRate() { function renderUpperLimit() { g.setColor(255,0,0); - g.fillRect(140,40, 230, 70); - g.fillRect(200,70, 230, 210); + g.fillRect(145,40, 230, 70); + g.fillRect(200,70, 230, 200); - //Round top left corner - g.setColor(0,0,0); - g.fillRect(140,40, 145, 45); + //Round middle left corner g.setColor(255,0,0); - g.fillCircle(150,50, 10); + g.fillEllipse(135,40,155,70); //Round top right corner g.setColor(0,0,0); g.fillRect(225,40, 230, 45); g.setColor(255,0,0); - g.fillCircle(220,50, 10); + g.fillEllipse(210,40,230,50); - //Round middle left corner - g.setColor(0,0,0); - g.fillRect(140,65, 145, 70); + //Round inner corner g.setColor(255,0,0); - g.fillCircle(150,60, 10); - - //Round bottom left corner + g.fillRect(194,71, 199, 76); g.setColor(0,0,0); - g.fillRect(200,205, 205, 210); - g.setColor(255,0,0); - g.fillCircle(210,200, 10); + g.fillEllipse(180,71,199,82); - //Round bottom right corner - g.setColor(0,0,0); - g.fillRect(225,205, 230, 210); + //Round bottom g.setColor(255,0,0); - g.fillCircle(220,200, 10); + g.fillEllipse(200,190, 230, 210); if(limitSetter === Setter.UPPER){ g.setColor(255,255, 255); @@ -68,7 +62,7 @@ function renderUpperLimit() { } function renderCurrentHeartRate() { - g.setColor(0,255,0); + g.setColor(255,255,255); g.fillRect(55, 110, 175, 140); g.setColor(0,0,0); g.setFontVector(13); @@ -109,15 +103,15 @@ function buzz() { if(currentHeartRate > upperLimit) { - Bangle.buzz(70); - setTimeout(() => { Bangle.buzz(70); }, 70); - setTimeout(() => { Bangle.buzz(70); }, 70); + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); } if(currentHeartRate < upperLimit) { - Bangle.buzz(140); - setTimeout(() => { Bangle.buzz(140); }, 140); + Bangle.buzz(longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); } } @@ -165,7 +159,7 @@ function decrementLimit(){ } // Show launcher when middle button pressed -function switchOfWidget(){ +function switchOffApp(){ Bangle.setHRMPower(0); Bangle.showLauncher(); } @@ -191,7 +185,7 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); drawTrainingHeartRate(); -setWatch(switchOfWidget, BTN2, {repeat:false,edge:"falling"}); +setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); From 74dc9e5cbcd1ffa7d7e0435a208de8197ce68175 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sat, 7 Mar 2020 07:18:33 +0100 Subject: [PATCH 09/83] Rounds button corners and adds HW button icons --- apps/wohrm/wohrm.js | 86 +++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 2d9553473..199fe9261 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -15,6 +15,8 @@ let currentHeartRate = 0; let hrConfidence = -1; function drawTrainingHeartRate() { + renderButtonIcons(); + renderUpperLimit(); renderCurrentHeartRate(); @@ -28,56 +30,76 @@ function drawTrainingHeartRate() { function renderUpperLimit() { g.setColor(255,0,0); - g.fillRect(145,40, 230, 70); - g.fillRect(200,70, 230, 200); + g.fillRect(135,40, 220, 70); + g.fillRect(190,70, 220, 200); - //Round middle left corner + //Round top left corner g.setColor(255,0,0); - g.fillEllipse(135,40,155,70); + g.fillEllipse(125,40,145,70); //Round top right corner g.setColor(0,0,0); - g.fillRect(225,40, 230, 45); + g.fillRect(215,40, 220, 45); g.setColor(255,0,0); - g.fillEllipse(210,40,230,50); + g.fillEllipse(200,40,220,50); //Round inner corner g.setColor(255,0,0); - g.fillRect(194,71, 199, 76); + g.fillRect(184,71, 189, 76); g.setColor(0,0,0); - g.fillEllipse(180,71,199,82); + g.fillEllipse(170,71,189,82); //Round bottom g.setColor(255,0,0); - g.fillEllipse(200,190, 230, 210); + g.fillEllipse(190,190, 220, 210); - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 255); - g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], true); - } + // if(limitSetter === Setter.UPPER){ + // g.setColor(255,255, 255); + // g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], false); + // } g.setColor(255,255,255); g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 150,50); + g.drawString("Upper : " + upperLimit, 140,50); } function renderCurrentHeartRate() { g.setColor(255,255,255); - g.fillRect(55, 110, 175, 140); + g.fillRect(45, 110, 165, 140); g.setColor(0,0,0); g.setFontVector(13); - g.drawString("Current: " + currentHeartRate, 75,117); + g.drawString("Current: " + currentHeartRate, 65,117); } function renderLowerLimit() { g.setColor(0,0,255); g.fillRect(10, 180, 100, 210); - g.fillRect(10, 40, 40, 180); + g.fillRect(10, 50, 40, 180); - if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 255); - g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); - } + //Rounded top + g.setColor(0,0,255); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,255); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,255); + 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,255); + g.fillEllipse(10,200,30,210); + + // if(limitSetter === Setter.LOWER){ + // g.setColor(255,255, 255); + // g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); + // } g.setColor(255,255,255); g.setFontVector(10); @@ -95,8 +117,26 @@ function renderConfidenceBars(){ g.setColor(0, 0, 0); } - g.fillRect(55, 110, 65, 140); - g.fillRect(175, 110, 185, 140); + g.fillRect(45, 110, 55, 140); + g.fillRect(165, 110, 175, 140); +} + +function renderButtonIcons() { + g.setColor(255,255,255); + g.setFontVector(14); + + // + for Btn1 + g.drawString("+", 227,50); + + // Home for Btn2 + g.drawLine(225, 118, 232, 110); + g.drawLine(232, 110, 239, 118); + + g.drawPoly([227,117,227,125,237,125,237,117], false); + g.drawRect(231,120,234,125); + + // - for Btn3 + g.drawString("-", 227,190); } function buzz() From 3ea8201714ad166fc801bff36eedd0c4822e88a0 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sat, 7 Mar 2020 07:33:16 +0100 Subject: [PATCH 10/83] Changes button positioning --- apps/wohrm/wohrm.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 199fe9261..a32fded30 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -30,28 +30,28 @@ function drawTrainingHeartRate() { function renderUpperLimit() { g.setColor(255,0,0); - g.fillRect(135,40, 220, 70); - g.fillRect(190,70, 220, 200); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); //Round top left corner g.setColor(255,0,0); - g.fillEllipse(125,40,145,70); + g.fillEllipse(115,40,135,70); //Round top right corner g.setColor(0,0,0); - g.fillRect(215,40, 220, 45); + g.fillRect(205,40, 210, 45); g.setColor(255,0,0); - g.fillEllipse(200,40,220,50); + g.fillEllipse(190,40,210,50); //Round inner corner g.setColor(255,0,0); - g.fillRect(184,71, 189, 76); + g.fillRect(174,71, 179, 76); g.setColor(0,0,0); - g.fillEllipse(170,71,189,82); + g.fillEllipse(160,71,179,82); //Round bottom g.setColor(255,0,0); - g.fillEllipse(190,190, 220, 210); + g.fillEllipse(180,190, 210, 210); // if(limitSetter === Setter.UPPER){ // g.setColor(255,255, 255); @@ -60,7 +60,7 @@ function renderUpperLimit() { g.setColor(255,255,255); g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 140,50); + g.drawString("Upper : " + upperLimit, 130,50); } function renderCurrentHeartRate() { @@ -114,7 +114,7 @@ function renderConfidenceBars(){ } else if(hrConfidence >= 0){ g.setColor(255, 0, 0); } else { - g.setColor(0, 0, 0); + g.setColor(255, 255, 0); } g.fillRect(45, 110, 55, 140); @@ -126,17 +126,17 @@ function renderButtonIcons() { g.setFontVector(14); // + for Btn1 - g.drawString("+", 227,50); + g.drawString("+", 222,50); // Home for Btn2 - g.drawLine(225, 118, 232, 110); - g.drawLine(232, 110, 239, 118); + g.drawLine(220, 118, 227, 110); + g.drawLine(227, 110, 234, 118); - g.drawPoly([227,117,227,125,237,125,237,117], false); - g.drawRect(231,120,234,125); + g.drawPoly([222,117,222,125,232,125,232,117], false); + g.drawRect(226,120,229,125); // - for Btn3 - g.drawString("-", 227,190); + g.drawString("-", 222,165); } function buzz() From 79e70fc023d5c9f49711eed486640178f7e3c92e Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sat, 7 Mar 2020 07:35:20 +0100 Subject: [PATCH 11/83] Fixes initial color for confidence bars --- apps/wohrm/wohrm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index a32fded30..306824c79 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -114,7 +114,7 @@ function renderConfidenceBars(){ } else if(hrConfidence >= 0){ g.setColor(255, 0, 0); } else { - g.setColor(255, 255, 0); + g.setColor(255, 255, 255); } g.fillRect(45, 110, 55, 140); From f740b4f57751343500ec85fd61e5fc951d3e7e75 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 8 Mar 2020 09:32:20 +0100 Subject: [PATCH 12/83] Improves UX for highlighting the selected limit --- apps/wohrm/wohrm.js | 341 ++++++++++++++++++++++++-------------------- 1 file changed, 183 insertions(+), 158 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index 306824c79..e4d31cb27 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -3,8 +3,8 @@ const Setter = { NONE: "none", UPPER: 'upper', LOWER: 'lower' - }; - +}; + const shortBuzzTimeInMs = 100; const longBuzzTimeInMs = 200; @@ -14,223 +14,248 @@ let limitSetter = Setter.NONE; let currentHeartRate = 0; let hrConfidence = -1; +let setterHighlightTimeout; + function drawTrainingHeartRate() { - renderButtonIcons(); - - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - - buzz(); + renderButtonIcons(); + + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + + buzz(); } function renderUpperLimit() { - g.setColor(255,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); + g.setColor(255,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); - //Round top left corner - g.setColor(255,0,0); - g.fillEllipse(115,40,135,70); + //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(255,0,0); - g.fillEllipse(190,40,210,50); + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(255,0,0); + g.fillEllipse(190,40,210,50); - //Round inner corner - g.setColor(255,0,0); - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); - //Round bottom - g.setColor(255,0,0); - g.fillEllipse(180,190, 210, 210); - - // if(limitSetter === Setter.UPPER){ - // g.setColor(255,255, 255); - // g.drawPoly([140,40,230,40,230,210,200,210,200,70,140,70], false); - // } + //Round bottom + g.setColor(255,0,0); + g.fillEllipse(180,190, 210, 210); + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { g.setColor(255,255,255); - g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); + } + g.setFontVector(10); + g.drawString("Upper : " + upperLimit, 130,50); } - -function renderCurrentHeartRate() { - g.setColor(255,255,255); - g.fillRect(45, 110, 165, 140); - g.setColor(0,0,0); - g.setFontVector(13); - g.drawString("Current: " + currentHeartRate, 65,117); -} - -function renderLowerLimit() { - g.setColor(0,0,255); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,255); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,255); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,255); - 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,255); - g.fillEllipse(10,200,30,210); +function renderCurrentHeartRate() { + g.setColor(255,255,255); + g.fillRect(45, 110, 165, 140); + g.setColor(0,0,0); + g.setFontVector(13); - // if(limitSetter === Setter.LOWER){ - // g.setColor(255,255, 255); - // g.drawPoly([10,40,40,40,40,180,100,180,100,210,10,210], true); - // } + g.drawString("Current:" , 65,117); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 155, 117); + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); +} + +function renderLowerLimit() { + g.setColor(0,0,255); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,255); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,255); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,255); + 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,255); + g.fillEllipse(10,200,30,210); + + if(limitSetter === Setter.LOWER){ + g.setColor(255,255, 0); + } else { g.setColor(255,255,255); - g.setFontVector(10); - g.drawString("Lower : " + lowerLimit, 20,190); + } + g.setFontVector(10); + g.drawString("Lower : " + lowerLimit, 20,190); } - + function renderConfidenceBars(){ - 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); - } + 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, 140); - g.fillRect(165, 110, 175, 140); + g.fillRect(45, 110, 55, 140); + g.fillRect(165, 110, 175, 140); } - + function renderButtonIcons() { g.setColor(255,255,255); g.setFontVector(14); - + // + for Btn1 g.drawString("+", 222,50); - + // Home for Btn2 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); - + // - for Btn3 g.drawString("-", 222,165); } - + function buzz() { - if(currentHeartRate > upperLimit) - { - Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - } + if(currentHeartRate > upperLimit) + { + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + } - if(currentHeartRate < upperLimit) - { - Bangle.buzz(longBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); - } + if(currentHeartRate < upperLimit) + { + Bangle.buzz(longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); + } } - + function onHrm(hrm){ - currentHeartRate = hrm.bpm; - hrConfidence = hrm.confidence; + currentHeartRate = hrm.bpm; + hrConfidence = hrm.confidence; } - + function setLimitSetterToLower() { - limitSetter = Setter.LOWER; - console.log("Limit setter is lower"); - renderUpperLimit(); - renderLowerLimit(); -} + resetHighlightTimeout(); + limitSetter = Setter.LOWER; + console.log("Limit setter is lower"); + renderUpperLimit(); + renderLowerLimit(); +} + function setLimitSetterToUpper() { - limitSetter = Setter.UPPER; - console.log("Limit setter is upper"); - renderLowerLimit(); - renderUpperLimit(); -} + resetHighlightTimeout(); + limitSetter = Setter.UPPER; + console.log("Limit setter is upper"); + renderLowerLimit(); + renderUpperLimit(); +} + +function setLimitSetterToNone() { + limitSetter = Setter.NONE; + console.log("Limit setter is none"); + renderLowerLimit(); + renderUpperLimit(); +} + function incrementLimit(){ - if(limitSetter === Setter.UPPER){ - upperLimit++; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - } else { - lowerLimit++; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - } -} + resetHighlightTimeout(); + if (limitSetter === Setter.UPPER) { + upperLimit++; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else if(limitSetter === Setter.LOWER) { + lowerLimit++; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + function decrementLimit(){ - if(limitSetter === Setter.UPPER){ - upperLimit--; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - } else { - lowerLimit--; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - } -} + resetHighlightTimeout(); + if (limitSetter === Setter.UPPER) { + upperLimit--; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + } else if(limitSetter === Setter.LOWER) { + lowerLimit--; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + } +} + +function resetHighlightTimeout() { + if(setterHiglightTimeout !== undefined) + clearTimeout(setterHighlightTimeout); + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 5000); +} + // Show launcher when middle button pressed function switchOffApp(){ - Bangle.setHRMPower(0); - Bangle.showLauncher(); + Bangle.setHRMPower(0); + Bangle.showLauncher(); } - + // special function to handle display switch on Bangle.on('lcdPower', (on) => { - g.clear(); - if (on) { - Bangle.drawWidgets(); - // call your app function here - drawTrainingHeartRate(); - } + g.clear(); + if (on) { + Bangle.drawWidgets(); + // call your app function here + drawTrainingHeartRate(); + } }); - + Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); - + // refesh every sec setInterval(drawTrainingHeartRate, 1000); - + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); drawTrainingHeartRate(); - + setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); - + 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(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); From 054a0c2142c64409787625221b1ef6693df311f3 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Sun, 8 Mar 2020 09:36:19 +0100 Subject: [PATCH 13/83] Fixes resetHighlightTimeout method --- apps/wohrm/wohrm.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/wohrm.js index e4d31cb27..f37483910 100644 --- a/apps/wohrm/wohrm.js +++ b/apps/wohrm/wohrm.js @@ -218,9 +218,11 @@ function decrementLimit(){ } function resetHighlightTimeout() { - if(setterHiglightTimeout !== undefined) + if (setterHighlightTimeout) { clearTimeout(setterHighlightTimeout); - setterHighlightTimeout = setTimeout(setLimitSetterToNone, 5000); + } + + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); } // Show launcher when middle button pressed From cf64c1c2c088c29ca2f80126dbde6d87ed5d5a95 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 24 Mar 2020 17:27:13 +0100 Subject: [PATCH 14/83] Adapt to new code layout --- apps.json | 8 ++++---- apps/wohrm/ChangeLog | 1 + apps/wohrm/{wohrm-icon.js => app-icon.js} | 0 apps/wohrm/{wohrm.js => app.js} | 0 apps/wohrm/{wohrm.png => app.png} | Bin 5 files changed, 5 insertions(+), 4 deletions(-) rename apps/wohrm/{wohrm-icon.js => app-icon.js} (100%) rename apps/wohrm/{wohrm.js => app.js} (100%) rename apps/wohrm/{wohrm.png => app.png} (100%) diff --git a/apps.json b/apps.json index 3ffdbe5d4..bbc40a7fd 100644 --- a/apps.json +++ b/apps.json @@ -815,15 +815,15 @@ }, { "id": "wohrm", "name": "Workout Heart Rate Monitor", - "icon": "wohrm.png", - "version":"0.01", + "icon": "app.png", + "version":"0.02", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", "allow_emulator":true, "storage": [ - {"name":"wohrm.app.js","url":"wohrm.js"}, - {"name":"wohrm.img","url":"wohrm-icon.js","evaluate":true} + {"name":"wohrm.app.js","url":"app.js"}, + {"name":"wohrm.img","url":"app-icon.js","evaluate":true} ] }, { "id": "widid", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index bc13085a4..101ac1146 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -1 +1,2 @@ +0.02: Adapted to new App code layout 0.01: Only tested on the emulator. diff --git a/apps/wohrm/wohrm-icon.js b/apps/wohrm/app-icon.js similarity index 100% rename from apps/wohrm/wohrm-icon.js rename to apps/wohrm/app-icon.js diff --git a/apps/wohrm/wohrm.js b/apps/wohrm/app.js similarity index 100% rename from apps/wohrm/wohrm.js rename to apps/wohrm/app.js diff --git a/apps/wohrm/wohrm.png b/apps/wohrm/app.png similarity index 100% rename from apps/wohrm/wohrm.png rename to apps/wohrm/app.png From 83ffb617f26b3857d40fa8481a2b020b06b8888a Mon Sep 17 00:00:00 2001 From: msdeibel Date: Tue, 24 Mar 2020 17:34:27 +0100 Subject: [PATCH 15/83] Energy saving --- apps/wohrm/app.js | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f37483910..f6e9baba4 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -17,16 +17,19 @@ let hrConfidence = -1; let setterHighlightTimeout; function drawTrainingHeartRate() { - renderButtonIcons(); - - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderButtonIcons(); + + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + } + buzz(); } From 08cc44ce9671fd1b7afcf29fbf237a47d6bb6448 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:14:48 +0100 Subject: [PATCH 16/83] Render the background only once --- apps/wohrm/add_to_apps.json | 13 ---- apps/wohrm/app.js | 122 +++++++++++++++++++----------------- apps/wohrm/wohrm.json | 5 -- 3 files changed, 66 insertions(+), 74 deletions(-) delete mode 100644 apps/wohrm/add_to_apps.json delete mode 100644 apps/wohrm/wohrm.json diff --git a/apps/wohrm/add_to_apps.json b/apps/wohrm/add_to_apps.json deleted file mode 100644 index 96ffe838c..000000000 --- a/apps/wohrm/add_to_apps.json +++ /dev/null @@ -1,13 +0,0 @@ -// Create an entry in apps.json as follows: -{ "id": "wohrm", - "name": "Workout Heart Rate Monitor", - "icon": "wohrm.png", - "version":"0.01", - "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", - "tags": "hrm workout app", - "storage": [ - {"name":"+wohrm","url":"wohrm.json"}, - {"name":"-wohrm","url":"wohrm.js"}, - {"name":"*wohrm","url":"wohrm-icon.js","evaluate":true} - ] -} diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f6e9baba4..c80434ae7 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -16,24 +16,7 @@ let hrConfidence = -1; let setterHighlightTimeout; -function drawTrainingHeartRate() { - //Only redraw if the display is on - if (Bangle.isLCDOn()) { - renderButtonIcons(); - - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - } - - buzz(); -} - -function renderUpperLimit() { +function renderUpperLimitBackground() { g.setColor(255,0,0); g.fillRect(125,40, 210, 70); g.fillRect(180,70, 210, 200); @@ -55,31 +38,16 @@ function renderUpperLimit() { //Round bottom g.setColor(255,0,0); g.fillEllipse(180,190, 210, 210); - - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); } - -function renderCurrentHeartRate() { + +function renderCurrentHearRateBackground() { g.setColor(255,255,255); g.fillRect(45, 110, 165, 140); g.setColor(0,0,0); g.setFontVector(13); - - g.drawString("Current:" , 65,117); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 155, 117); - - //Reset alignment to defaults - g.setFontAlign(-1, -1, 0); } - -function renderLowerLimit() { + +function renderLowerLimitBackground() { g.setColor(0,0,255); g.fillRect(10, 180, 100, 210); g.fillRect(10, 50, 40, 180); @@ -103,7 +71,63 @@ function renderLowerLimit() { g.fillRect(10,205, 15, 210); g.setColor(0,0,255); g.fillEllipse(10,200,30,210); +} +function renderButtonIcons() { + g.setColor(255,255,255); + g.setFontVector(14); + + // + for Btn1 + g.drawString("+", 222,50); + + // Home for Btn2 + 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); + + // - for Btn3 + g.drawString("-", 222,165); +} + +function drawTrainingHeartRate() { + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderButtonIcons(); + + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + } + + buzz(); +} + +function renderUpperLimit() { + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(10); + g.drawString("Upper : " + upperLimit, 130,50); +} + +function renderCurrentHeartRate() { + g.drawString("Current:" , 65,117); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 155, 117); + + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); +} + +function renderLowerLimit() { if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); } else { @@ -128,24 +152,6 @@ function renderConfidenceBars(){ g.fillRect(165, 110, 175, 140); } -function renderButtonIcons() { - g.setColor(255,255,255); - g.setFontVector(14); - - // + for Btn1 - g.drawString("+", 222,50); - - // Home for Btn2 - 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); - - // - for Btn3 - g.drawString("-", 222,165); -} - function buzz() { if(currentHeartRate > upperLimit) @@ -253,7 +259,11 @@ setInterval(drawTrainingHeartRate, 1000); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -drawTrainingHeartRate(); + +renderLowerLimitBackground()); +renderCurrentHearRateBackground(); +renderUpperLimitBackground(); +renderButtonIcons(); setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); diff --git a/apps/wohrm/wohrm.json b/apps/wohrm/wohrm.json deleted file mode 100644 index 9b212bfd4..000000000 --- a/apps/wohrm/wohrm.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name":"Workout HRM", - "icon":"*wohrm", - "src":"-wohrm" -} From 1d3248882cd97deb1194febb830514e7f5e3902a Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:16:37 +0100 Subject: [PATCH 17/83] Changelog updated --- apps/wohrm/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 101ac1146..36c08b9fd 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -1,2 +1,3 @@ +0.03: Optimized rendering for the background 0.02: Adapted to new App code layout 0.01: Only tested on the emulator. From 1d339c825c443e7c0c15f28e0a82ad9c79adf5c2 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:36:45 +0100 Subject: [PATCH 18/83] Typo --- apps/wohrm/app.js | 52 +++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index c80434ae7..30f872066 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -17,7 +17,7 @@ let hrConfidence = -1; let setterHighlightTimeout; function renderUpperLimitBackground() { - g.setColor(255,0,0); + g.setColor(1,0,0); g.fillRect(125,40, 210, 70); g.fillRect(180,70, 210, 200); @@ -27,7 +27,7 @@ function renderUpperLimitBackground() { //Round top right corner g.setColor(0,0,0); g.fillRect(205,40, 210, 45); - g.setColor(255,0,0); + g.setColor(1,0,0); g.fillEllipse(190,40,210,50); //Round inner corner @@ -36,32 +36,33 @@ function renderUpperLimitBackground() { g.fillEllipse(160,71,179,82); //Round bottom - g.setColor(255,0,0); + g.setColor(1,0,0); g.fillEllipse(180,190, 210, 210); } function renderCurrentHearRateBackground() { - g.setColor(255,255,255); + g.setColor(1,1,1); g.fillRect(45, 110, 165, 140); g.setColor(0,0,0); g.setFontVector(13); + g.drawString("Current:" , 65,117); } function renderLowerLimitBackground() { - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillRect(10, 180, 100, 210); g.fillRect(10, 50, 40, 180); //Rounded top - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillEllipse(10,40, 40, 60); //Round bottom right corner - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillEllipse(90,180,110,210); //Round inner corner - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillRect(40,175,45,180); g.setColor(0,0,0); g.fillEllipse(41,170,60,179); @@ -69,12 +70,12 @@ function renderLowerLimitBackground() { //Round bottom left corner g.setColor(0,0,0); g.fillRect(10,205, 15, 210); - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillEllipse(10,200,30,210); } function renderButtonIcons() { - g.setColor(255,255,255); + g.setColor(1,1,1); g.setFontVector(14); // + for Btn1 @@ -88,14 +89,12 @@ function renderButtonIcons() { g.drawRect(226,120,229,125); // - for Btn3 - g.drawString("-", 222,165); + g.drawString("-", 222,170); } function drawTrainingHeartRate() { //Only redraw if the display is on if (Bangle.isLCDOn()) { - renderButtonIcons(); - renderUpperLimit(); renderCurrentHeartRate(); @@ -110,16 +109,17 @@ function drawTrainingHeartRate() { function renderUpperLimit() { if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); + g.setColor(1, 1, 0); } else { - g.setColor(255,255,255); + g.setColor(1, 1, 1); } + g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); + g.drawString("Upper : " + upperLimit, 130,50); } function renderCurrentHeartRate() { - g.drawString("Current:" , 65,117); + g.setFontVector(13); g.setFontAlign(1, -1, 0); g.drawString(currentHeartRate, 155, 117); @@ -246,21 +246,19 @@ Bangle.on('lcdPower', (on) => { if (on) { Bangle.drawWidgets(); // call your app function here + renderLowerLimitBackground(); + renderCurrentHearRateBackground(); + renderUpperLimitBackground(); + renderButtonIcons(); drawTrainingHeartRate(); } }); -Bangle.setHRMPower(1); -Bangle.on('HRM', onHrm); - -// refesh every sec -setInterval(drawTrainingHeartRate, 1000); - g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLowerLimitBackground()); +renderLowerLimitBackground(); renderCurrentHearRateBackground(); renderUpperLimitBackground(); renderButtonIcons(); @@ -274,3 +272,9 @@ 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 }); + +Bangle.setHRMPower(1); +Bangle.on('HRM', onHrm); + +// refesh every sec +setInterval(drawTrainingHeartRate, 1000); \ No newline at end of file From 8427b492ee05c2aae14f906f88cd3861bbde3958 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:39:42 +0100 Subject: [PATCH 19/83] Wohrm version updated --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index bbc40a7fd..28403787f 100644 --- a/apps.json +++ b/apps.json @@ -829,7 +829,7 @@ { "id": "widid", "name": "Bluetooth ID Widget", "icon": "widget.png", - "version":"0.02", + "version":"0.03", "description": "Display the last two tuple of your Bangle.js MAC address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!", "tags": "widget,address,mac", "type":"widget", From 84f56faadfd8acdbb49acb5d2085d573447db4c6 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Wed, 25 Mar 2020 18:42:43 +0100 Subject: [PATCH 20/83] Fixed version for widid after errneous edit --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 28403787f..ba72123c9 100644 --- a/apps.json +++ b/apps.json @@ -816,7 +816,7 @@ { "id": "wohrm", "name": "Workout Heart Rate Monitor", "icon": "app.png", - "version":"0.02", + "version":"0.03", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", @@ -829,7 +829,7 @@ { "id": "widid", "name": "Bluetooth ID Widget", "icon": "widget.png", - "version":"0.03", + "version":"0.02", "description": "Display the last two tuple of your Bangle.js MAC address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!", "tags": "widget,address,mac", "type":"widget", From e799dfd2061d430da73c75dc33b11a09cf830717 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Fri, 27 Mar 2020 06:23:43 +0100 Subject: [PATCH 21/83] Slight improvements to rendering --- apps/wohrm/app.js | 238 +++++++++++++++++++++++++--------------------- 1 file changed, 128 insertions(+), 110 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 30f872066..5a9264f0b 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -5,96 +5,29 @@ const Setter = { LOWER: 'lower' }; -const shortBuzzTimeInMs = 100; +const shortBuzzTimeInMs = 50; const longBuzzTimeInMs = 200; -let upperLimit = 130; -let lowerLimit = 100; +let upperLimit = 90; +let upperLimitChanged = true; + +let lowerLimit = 50; +let lowerLimitChanged = true; + let limitSetter = Setter.NONE; + let currentHeartRate = 0; let hrConfidence = -1; +let hrOrConfidenceChanged = 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 renderCurrentHearRateBackground() { - g.setColor(1,1,1); - g.fillRect(45, 110, 165, 140); - g.setColor(0,0,0); - g.setFontVector(13); - g.drawString("Current:" , 65,117); -} - -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 renderButtonIcons() { - g.setColor(1,1,1); - g.setFontVector(14); - - // + for Btn1 - g.drawString("+", 222,50); - - // Home for Btn2 - 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); - - // - for Btn3 - g.drawString("-", 222,170); -} - function drawTrainingHeartRate() { //Only redraw if the display is on if (Bangle.isLCDOn()) { + renderButtonIcons(); + renderUpperLimit(); renderCurrentHeartRate(); @@ -108,18 +41,50 @@ function drawTrainingHeartRate() { } function renderUpperLimit() { - if(limitSetter === Setter.UPPER){ - g.setColor(1, 1, 0); - } else { - g.setColor(1, 1, 1); - } + if(!upperLimitChanged) { return; } + + g.setColor(255,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(255,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(255,0,0); + g.fillEllipse(180,190, 210, 210); + + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } g.setFontVector(10); - g.drawString("Upper : " + upperLimit, 130,50); + g.drawString("Upper : " + upperLimit, 130,50); + + upperLimitChanged = false; } function renderCurrentHeartRate() { + if(!hrOrConfidenceChanged) { return; } + + g.setColor(255,255,255); + g.fillRect(45, 110, 165, 140); + g.setColor(0,0,0); g.setFontVector(13); + + g.drawString("Current:" , 65,117); g.setFontAlign(1, -1, 0); g.drawString(currentHeartRate, 155, 117); @@ -128,6 +93,32 @@ function renderCurrentHeartRate() { } function renderLowerLimit() { + if(!lowerLimitChanged) { return; } + + g.setColor(0,0,255); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,255); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,255); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,255); + 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,255); + g.fillEllipse(10,200,30,210); + if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); } else { @@ -135,9 +126,13 @@ function renderLowerLimit() { } g.setFontVector(10); g.drawString("Lower : " + lowerLimit, 20,190); + + lowerLimitChanged = false; } function renderConfidenceBars(){ + if(!hrOrConfidenceChanged) { return; } + if(hrConfidence >= 85){ g.setColor(0, 255, 0); } else if (hrConfidence >= 50) { @@ -152,6 +147,24 @@ function renderConfidenceBars(){ g.fillRect(165, 110, 175, 140); } +function renderButtonIcons() { + g.setColor(255,255,255); + g.setFontVector(14); + + // + for Btn1 + g.drawString("+", 222,50); + + // Home for Btn2 + 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); + + // - for Btn3 + g.drawString("-", 222,165); +} + function buzz() { if(currentHeartRate > upperLimit) @@ -161,7 +174,7 @@ function buzz() setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); } - if(currentHeartRate < upperLimit) + if(currentHeartRate < lowerLimit) { Bangle.buzz(longBuzzTimeInMs); setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); @@ -169,6 +182,7 @@ function buzz() } function onHrm(hrm){ + hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); currentHeartRate = hrm.bpm; hrConfidence = hrm.confidence; } @@ -178,6 +192,10 @@ function setLimitSetterToLower() { limitSetter = Setter.LOWER; console.log("Limit setter is lower"); + + upperLimitChanged = true; + lowerLimitChanged = true; + renderUpperLimit(); renderLowerLimit(); } @@ -187,6 +205,10 @@ function setLimitSetterToUpper() { limitSetter = Setter.UPPER; console.log("Limit setter is upper"); + + upperLimitChanged = true; + lowerLimitChanged = true; + renderLowerLimit(); renderUpperLimit(); } @@ -194,6 +216,10 @@ function setLimitSetterToUpper() { function setLimitSetterToNone() { limitSetter = Setter.NONE; console.log("Limit setter is none"); + + upperLimitChanged = true; + lowerLimitChanged = true; + renderLowerLimit(); renderUpperLimit(); } @@ -205,10 +231,12 @@ function incrementLimit(){ upperLimit++; renderUpperLimit(); console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { lowerLimit++; renderLowerLimit(); console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; } } @@ -219,10 +247,12 @@ function decrementLimit(){ upperLimit--; renderUpperLimit(); console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { lowerLimit--; renderLowerLimit(); console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; } } @@ -246,35 +276,23 @@ Bangle.on('lcdPower', (on) => { if (on) { Bangle.drawWidgets(); // call your app function here - renderLowerLimitBackground(); - renderCurrentHearRateBackground(); - renderUpperLimitBackground(); - renderButtonIcons(); drawTrainingHeartRate(); } }); -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); - -renderLowerLimitBackground(); -renderCurrentHearRateBackground(); -renderUpperLimitBackground(); -renderButtonIcons(); - -setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); - -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 }); - Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); +setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); +setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); +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 }); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawTrainingHeartRate(); + // refesh every sec -setInterval(drawTrainingHeartRate, 1000); \ No newline at end of file +setInterval(drawTrainingHeartRate, 1000); From 1a7fb5d2cc33d2712497ca5525ff34c0e3d94dc6 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Fri, 27 Mar 2020 06:49:16 +0100 Subject: [PATCH 22/83] Minor tweaks --- apps/wohrm/app.js | 125 ++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 55 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 5a9264f0b..75c51a578 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,6 +23,56 @@ let hrOrConfidenceChanged = 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()) { @@ -37,40 +87,21 @@ function drawTrainingHeartRate() { renderConfidenceBars(); } - buzz(); + //buzz(); } function renderUpperLimit() { if(!upperLimitChanged) { return; } - g.setColor(255,0,0); + 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(255,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(255,0,0); - g.fillEllipse(180,190, 210, 210); - + if(limitSetter === Setter.UPPER){ g.setColor(255,255, 0); } else { g.setColor(255,255,255); } - g.setFontVector(10); + g.setFontVector(13); g.drawString("Upper : " + upperLimit, 130,50); upperLimitChanged = false; @@ -80,13 +111,12 @@ function renderCurrentHeartRate() { if(!hrOrConfidenceChanged) { return; } g.setColor(255,255,255); - g.fillRect(45, 110, 165, 140); - g.setColor(0,0,0); - g.setFontVector(13); + g.fillRect(45, 110, 165, 150); - g.drawString("Current:" , 65,117); + g.setColor(0,0,0); + g.setFontVector(24); g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 155, 117); + g.drawString(currentHeartRate, 130, 117); //Reset alignment to defaults g.setFontAlign(-1, -1, 0); @@ -95,36 +125,15 @@ function renderCurrentHeartRate() { function renderLowerLimit() { if(!lowerLimitChanged) { return; } - g.setColor(0,0,255); + g.setColor(0,0,1); g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,255); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,255); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,255); - 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,255); - g.fillEllipse(10,200,30,210); - + if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); } else { g.setColor(255,255,255); } - g.setFontVector(10); + g.setFontVector(13); g.drawString("Lower : " + lowerLimit, 20,190); lowerLimitChanged = false; @@ -143,8 +152,8 @@ function renderConfidenceBars(){ g.setColor(255, 255, 255); } - g.fillRect(45, 110, 55, 140); - g.fillRect(165, 110, 175, 140); + g.fillRect(45, 110, 55, 150); + g.fillRect(165, 110, 175, 150); } function renderButtonIcons() { @@ -276,6 +285,10 @@ Bangle.on('lcdPower', (on) => { if (on) { Bangle.drawWidgets(); // call your app function here + renderLowerLimitBackground(); + renderUpperLimitBackground(); + lowerLimitChanged = true; + upperLimitChanged = true; drawTrainingHeartRate(); } }); @@ -292,7 +305,9 @@ setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: tr g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -drawTrainingHeartRate(); +//drawTrainingHeartRate(); // refesh every sec +renderLowerLimitBackground(); +renderUpperLimitBackground(); setInterval(drawTrainingHeartRate, 1000); From 0bfdb86fcb7a08edd20aeb2a3319b08a68b09b97 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:04:30 +0200 Subject: [PATCH 23/83] Fix remove unnecessary file and trim down App name --- apps.json | 2 +- apps/wohrm/.gitignore | 4 - apps/wohrm/app.js | 462 +++++++++++++++++++++--------------------- 3 files changed, 233 insertions(+), 235 deletions(-) delete mode 100644 apps/wohrm/.gitignore diff --git a/apps.json b/apps.json index 9f8b31f1d..e5b0ab15e 100644 --- a/apps.json +++ b/apps.json @@ -814,7 +814,7 @@ ] }, { "id": "wohrm", - "name": "Workout Heart Rate Monitor", + "name": "Workout HRM", "icon": "app.png", "version":"0.03", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", diff --git a/apps/wohrm/.gitignore b/apps/wohrm/.gitignore deleted file mode 100644 index 2060ed3f3..000000000 --- a/apps/wohrm/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/node_modules -/.eslintrc.js -/package.json -/package-lock.json \ No newline at end of file diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 75c51a578..8323779c9 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -1,160 +1,160 @@ -/* eslint-disable no-undef */ -const Setter = { - NONE: "none", - UPPER: 'upper', - LOWER: 'lower' -}; +// /* eslint-disable no-undef */ +// const Setter = { +// NONE: "none", +// UPPER: 'upper', +// LOWER: 'lower' +// }; -const shortBuzzTimeInMs = 50; -const longBuzzTimeInMs = 200; +// const shortBuzzTimeInMs = 50; +// const longBuzzTimeInMs = 200; -let upperLimit = 90; -let upperLimitChanged = true; +// let upperLimit = 90; +// let upperLimitChanged = true; -let lowerLimit = 50; -let lowerLimitChanged = true; +// let lowerLimit = 50; +// let lowerLimitChanged = true; -let limitSetter = Setter.NONE; +// let limitSetter = Setter.NONE; -let currentHeartRate = 0; -let hrConfidence = -1; -let hrOrConfidenceChanged = true; +// let currentHeartRate = 0; +// let hrConfidence = -1; +// let hrOrConfidenceChanged = true; -let setterHighlightTimeout; +// let setterHighlightTimeout; -function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); +// 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 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 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 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); -} +// //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); +// 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); +// //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 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 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); -} +// //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()) { - renderButtonIcons(); +// function drawTrainingHeartRate() { +// //Only redraw if the display is on +// if (Bangle.isLCDOn()) { +// renderButtonIcons(); - 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); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Upper : " + upperLimit, 130,50); +// if(limitSetter === Setter.UPPER){ +// g.setColor(255,255, 0); +// } else { +// g.setColor(255,255,255); +// } +// g.setFontVector(13); +// g.drawString("Upper : " + upperLimit, 130,50); - upperLimitChanged = false; -} +// upperLimitChanged = false; +// } -function renderCurrentHeartRate() { - if(!hrOrConfidenceChanged) { return; } +// function renderCurrentHeartRate() { +// if(!hrOrConfidenceChanged) { return; } - g.setColor(255,255,255); - g.fillRect(45, 110, 165, 150); +// g.setColor(255,255,255); +// g.fillRect(45, 110, 165, 150); - g.setColor(0,0,0); - g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); +// 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); -} +// //Reset alignment to defaults +// g.setFontAlign(-1, -1, 0); +// } -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); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Lower : " + lowerLimit, 20,190); +// 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; -} +// lowerLimitChanged = false; +// } -function renderConfidenceBars(){ - if(!hrOrConfidenceChanged) { return; } +// function renderConfidenceBars(){ +// if(!hrOrConfidenceChanged) { 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); - } +// 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); -} +// g.fillRect(45, 110, 55, 150); +// g.fillRect(165, 110, 175, 150); +// } function renderButtonIcons() { g.setColor(255,255,255); @@ -174,140 +174,142 @@ function renderButtonIcons() { g.drawString("-", 222,165); } -function buzz() -{ - if(currentHeartRate > upperLimit) - { - Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - } +// function buzz() +// { +// if(currentHeartRate > upperLimit) +// { +// Bangle.buzz(shortBuzzTimeInMs); +// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); +// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); +// } - if(currentHeartRate < lowerLimit) - { - Bangle.buzz(longBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); - } -} +// if(currentHeartRate < lowerLimit) +// { +// Bangle.buzz(longBuzzTimeInMs); +// setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); +// } +// } -function onHrm(hrm){ - hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); - currentHeartRate = hrm.bpm; - hrConfidence = hrm.confidence; -} +// function onHrm(hrm){ +// hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); +// currentHeartRate = hrm.bpm; +// hrConfidence = hrm.confidence; +// } -function setLimitSetterToLower() { - resetHighlightTimeout(); +// function setLimitSetterToLower() { +// resetHighlightTimeout(); - limitSetter = Setter.LOWER; - console.log("Limit setter is lower"); +// limitSetter = Setter.LOWER; +// console.log("Limit setter is lower"); - upperLimitChanged = true; - lowerLimitChanged = true; +// upperLimitChanged = true; +// lowerLimitChanged = true; - renderUpperLimit(); - renderLowerLimit(); -} +// renderUpperLimit(); +// renderLowerLimit(); +// } -function setLimitSetterToUpper() { - resetHighlightTimeout(); +// function setLimitSetterToUpper() { +// resetHighlightTimeout(); - limitSetter = Setter.UPPER; - console.log("Limit setter is upper"); +// limitSetter = Setter.UPPER; +// console.log("Limit setter is upper"); - upperLimitChanged = true; - lowerLimitChanged = true; +// upperLimitChanged = true; +// lowerLimitChanged = true; - renderLowerLimit(); - renderUpperLimit(); -} +// renderLowerLimit(); +// renderUpperLimit(); +// } -function setLimitSetterToNone() { - limitSetter = Setter.NONE; - console.log("Limit setter is none"); +// function setLimitSetterToNone() { +// limitSetter = Setter.NONE; +// console.log("Limit setter is none"); - upperLimitChanged = true; - lowerLimitChanged = true; +// upperLimitChanged = true; +// lowerLimitChanged = true; - renderLowerLimit(); - renderUpperLimit(); -} +// renderLowerLimit(); +// renderUpperLimit(); +// } -function incrementLimit(){ - resetHighlightTimeout(); +// function incrementLimit(){ +// resetHighlightTimeout(); - if (limitSetter === Setter.UPPER) { - upperLimit++; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit++; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - lowerLimitChanged = true; - } -} +// if (limitSetter === Setter.UPPER) { +// upperLimit++; +// renderUpperLimit(); +// console.log("Upper limit: " + upperLimit); +// upperLimitChanged = true; +// } else if(limitSetter === Setter.LOWER) { +// lowerLimit++; +// renderLowerLimit(); +// console.log("Lower limit: " + lowerLimit); +// lowerLimitChanged = true; +// } +// } -function decrementLimit(){ - resetHighlightTimeout(); +// function decrementLimit(){ +// resetHighlightTimeout(); - if (limitSetter === Setter.UPPER) { - upperLimit--; - renderUpperLimit(); - console.log("Upper limit: " + upperLimit); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit--; - renderLowerLimit(); - console.log("Lower limit: " + lowerLimit); - lowerLimitChanged = true; - } -} +// if (limitSetter === Setter.UPPER) { +// upperLimit--; +// renderUpperLimit(); +// console.log("Upper limit: " + upperLimit); +// upperLimitChanged = true; +// } else if(limitSetter === Setter.LOWER) { +// lowerLimit--; +// renderLowerLimit(); +// console.log("Lower limit: " + lowerLimit); +// lowerLimitChanged = true; +// } +// } -function resetHighlightTimeout() { - if (setterHighlightTimeout) { - clearTimeout(setterHighlightTimeout); - } +// function resetHighlightTimeout() { +// if (setterHighlightTimeout) { +// clearTimeout(setterHighlightTimeout); +// } - setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); -} +// setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); +// } -// Show launcher when middle button pressed -function switchOffApp(){ - Bangle.setHRMPower(0); - Bangle.showLauncher(); -} +// // Show launcher when middle button pressed +// function switchOffApp(){ +// Bangle.setHRMPower(0); +// Bangle.showLauncher(); +// } -// special function to handle display switch on -Bangle.on('lcdPower', (on) => { - g.clear(); - if (on) { - Bangle.drawWidgets(); - // call your app function here - renderLowerLimitBackground(); - renderUpperLimitBackground(); - lowerLimitChanged = true; - upperLimitChanged = true; - drawTrainingHeartRate(); - } -}); +// // special function to handle display switch on +// Bangle.on('lcdPower', (on) => { +// g.clear(); +// if (on) { +// Bangle.drawWidgets(); +// // call your app function here +// renderLowerLimitBackground(); +// renderUpperLimitBackground(); +// lowerLimitChanged = true; +// upperLimitChanged = true; +// drawTrainingHeartRate(); +// } +// }); -Bangle.setHRMPower(1); -Bangle.on('HRM', onHrm); +// Bangle.setHRMPower(1); +// Bangle.on('HRM', onHrm); -setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); +// setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); -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 }); -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); -//drawTrainingHeartRate(); +renderButtonIcons +// 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 }); -// refesh every sec -renderLowerLimitBackground(); -renderUpperLimitBackground(); -setInterval(drawTrainingHeartRate, 1000); +// g.clear(); +// Bangle.loadWidgets(); +// Bangle.drawWidgets(); +// //drawTrainingHeartRate(); + +// // refesh every sec +// renderLowerLimitBackground(); +// renderUpperLimitBackground(); +// setInterval(drawTrainingHeartRate, 1000); From df3935e390ed8492723e3a33d7809469799c379c Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:42:53 +0200 Subject: [PATCH 24/83] Icon file size reduced --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 36663d0ed..1bf4c808b 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("MDCI/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsK7u8HC/v7+/v7+/v7+/v7+/v7Cwbu7wsL+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7u7u7u7u7vI/v7+/v7+/v7Iu7u7u7u7u7u7u8n+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/ru7u7u7u7u7u7u7u7u7u7v+/v7+u7u7u7u7u7u7u7u7u7u7u/7+/v7+/v7+/v7+u7u7u7u7u7u7u7u7u7u7u7u7/v67u7u7u7u7u7u7u7u7u7u7u7v+/v7+/v7+/v67u7u7u7u7u7u7wci7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7/v7+/v7+/sm7u7u7u7u7u7u7wsm7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7yf7+/v7+/ru7u7u7u7u7u7u7ydC7u7u7u7u7u7u7u7u7u7u7u8LQ19DCu7u7u7u7u/7+/v7+/ru7u7u7u7u7u7u70NfCu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u/7+/v7+wru7u7u7u7u7u7vC19fJu7u7u7u7u7u7u7u7u7u7u9fX19fXu7u7u7u7u8L+/v7+wru7u7u7u7u7u7vJ19fJu7u7u7u7u7u7u7u7u7u7u9DX19fQu7u7u7u7u8L+/v7+u7u7u7u7u7u7u7vQ19fQu7u7u7u7u7u7u7u7u7u7u8nX19DCu7u7u7u7u7v+/v7+wbu7u7u7ybu7u7vX19DXwru7u7u7u7u7u7u7wcnQ19fX0Lu7u7u7u7u7u8H+/v7+wru7u7vC18K7u8LX0MnXybu7u7vCu7u7wc/Q19fX19fX18K7u7u7u7u7u8L+/v7+yLu7u7vJ18m7u8nXycnXybu7u7vJu7u7wtfX19DJydfX19C7u7u7u7u7u8j+/v7+/ru7u8HR19HBu9DXwsLX0Lu7u7vQu7u7wdfX0Lu70NfJ0NfJu7u7u7u7u/7+/v7+/ru7u8nX19fJwtfQu7vQ18K7u8LXu7u7u8HQ18LC19fBwtfXycm7u7u7u/7+/v7+/tDX19fXydfQydfJu7vJ18m7u8nXu7u7u7vBwrvQ18m7u9DX19e7u7u7yf7+/v7+/v7Q19fQu9DX0NfIu7vJ18m7u9DXu7u7u7u7u8HX18K7u8HJycm7u7u7/v7+/v7+/v7+u7u7u8nX19fBu7vC19C7wtfQu7u7u7u7u8nX0Lu7u7u7u7u7u7v+/v7+/v7+/v7+wru7u8HR19C7u7u70NfCz9fJu7u7wru7u9fX18nCu7u7u7u7u8L+/v7+/v7+/v7+/sG7u7vJ18m7u7u7ydfJ0dfBu8HC19C7yNfX19fX0MK7u7u7wf7+/v7+/v7+/v7+/v67u7vC18K7u7u7ydfQ19C7u7vB0NfQ0NfJws/X18G7u7u7/v7+/v7+/v7+/v7+/v7+u7u70Lu7u7u7wtfX18m7u7u7wdDX19e7u8LX18K7u7v+/v7+/v7+/v7+/v7+/v7+/ru7wbu7u7u7u9DX18G7u7u7u8HJ18m7wdDX0Lu7u/7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u8nX0Lu7u7u7u7u7wcG70NfQu7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+wbu7u7u7u8nXyLu7u7u7u7u7u7vJ19fCu7v+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sG7u7u7u8LXwbu7u7u7u7u7u8HX18K7wf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7Cu7u7u7vJu7u7u7u7u7u7u7vCybvC/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+ybu7u7vBu7u7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7u7u7u7u7u7u7u7u7/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u7u7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/sm7u7u7u7u7u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wru7u7u7u8L+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v67u7u7yf7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+wsL+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/g==")) +var img=require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) From de603515073b5cc3e3060f89ba0f84d5d24985aa Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:44:53 +0200 Subject: [PATCH 25/83] Image icon code --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 1bf4c808b..1b30302b4 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -var img=require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) +var img = require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) From bcce90d36df407a1b7e2c57bfae288f63cd915ce Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:47:14 +0200 Subject: [PATCH 26/83] icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 1b30302b4..84799199d 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -var img = require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) +var img = E.toArrayBuffer(atob("MDCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqAAAACqoAAAAAAqqqqAACqqqoAAAACqqqqgAKqqqqAAAAKqqqqoAqqqqqgAAAqqqqqqCqqqqqoAACqqqqqqqqqqqqqAAKqqquqqqqqqqqqgAKqqq+qqqqqr+qqgAKqqq+qqqqqv/qqgAqqqq+qqqqqv/qqoAqqqr/qqqqqv/qqoAqqqr/qqqqqr+qqoAqq6r/qqqqr/6qqoAqq6r/qqqv//6qqoAqr+v76rqv//+qqoAKr+vr6rqv6//qqgAKv/vr6rqr6+v+qgAP//vr6vqqr+v+qwAD/v+q+vqqr6r+qAAAqv+q+vqqv6qqoAAAqr+q+/qqv+qqoAAAKr+q/+q+v/6qgAAACq6qv+q//v6qAAAAAq6qv6qv+r6oAAAAAKqqv6qr+v6gAAAAACqqv6qqq/qAAAAAAAqqrqqqr+oAAAAAAAKqrqqqr6gAAAAAAACqrqqqqqAAAAAAAAA6qqqqqoAAAAAAAAACqqqqqAAAAAAAAAAAqqqqoAAAAAAAAAAAOqqqgAAAAAAAAAAAAqqoAAAAAAAAAAAAACqwAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")) From 5d98017fe7d1519a11ebfa68d2f3af031e6f87a3 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:50:15 +0200 Subject: [PATCH 27/83] Icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 84799199d..a95a3d4e0 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -var img = E.toArrayBuffer(atob("MDCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqAAAACqoAAAAAAqqqqAACqqqoAAAACqqqqgAKqqqqAAAAKqqqqoAqqqqqgAAAqqqqqqCqqqqqoAACqqqqqqqqqqqqqAAKqqquqqqqqqqqqgAKqqq+qqqqqr+qqgAKqqq+qqqqqv/qqgAqqqq+qqqqqv/qqoAqqqr/qqqqqv/qqoAqqqr/qqqqqr+qqoAqq6r/qqqqr/6qqoAqq6r/qqqv//6qqoAqr+v76rqv//+qqoAKr+vr6rqv6//qqgAKv/vr6rqr6+v+qgAP//vr6vqqr+v+qwAD/v+q+vqqr6r+qAAAqv+q+vqqv6qqoAAAqr+q+/qqv+qqoAAAKr+q/+q+v/6qgAAACq6qv+q//v6qAAAAAq6qv6qv+r6oAAAAAKqqv6qr+v6gAAAAACqqv6qqq/qAAAAAAAqqrqqqr+oAAAAAAAKqrqqqr6gAAAAAAACqrqqqqqAAAAAAAAA6qqqqqoAAAAAAAAACqqqqqAAAAAAAAAAAqqqqoAAAAAAAAAAAOqqqgAAAAAAAAAAAAqqoAAAAAAAAAAAAACqwAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")) +require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) \ No newline at end of file From 94f89db572c529f3e5f2d7e1904049085d6dd624 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:51:49 +0200 Subject: [PATCH 28/83] Icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index a95a3d4e0..5a57c6cb1 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) From e23c1ad2e508bd97c0c71ebe315a78cdf4b1dca7 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:53:33 +0200 Subject: [PATCH 29/83] Icon --- apps/wohrm/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app-icon.js b/apps/wohrm/app-icon.js index 5a57c6cb1..a7f67291e 100644 --- a/apps/wohrm/app-icon.js +++ b/apps/wohrm/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwhC/AH4AVgnd7tABJ4AClvMAAXUBIdNBIfSCw0NBgYAB6AJLAAfcBovMBIIIG5ouJ5oDC4EMC4wwFFwnSDYY4HGAkCBIlDCQ4AFkBrHmYqIn89JApUEBoJDH4f/+ZqDC4NMC4n/lgXG5///4FC4h2GEoM8F5h4CC53C/5fDC4oTB7/z/oGBBIXNkYuEC4vNCYNPmfyBgJpB6c/LoP/OAYXCAwPDEQM/mQmCGwNP/8zDII5CO4anB7//7k/7oXB5pODBIMzU4zXBEQM9B4Xc4n8YwXd//UGYLXEgZRBIoc/lnDC4PM6hTDYAUwC4MAQIPT+f05kvnnfC4RJBLoPTF4J2CMAa9BBoPfnlPXAc/Y4heCAAMEDwLVC4f9CQXdBIJpBC4VAC4bBCCQRYBSoPU+fSNgIYCIwiRD77EB4XzVISkC6YeBRoYwF4YjC/7xCCgP9A4PcFwwwC5r5Cn7nCAgKVBGwJ1EMIyJG5vdn89FxBhDAAMvMYIACWQPcLo4wG740DAoP0FxQwE4YWDJAMsFxYABLgJ7CAAfECxh6FF4YWOPQgACIpoADnoWD4QWQJIhFQDAvNmAXUglACygA/AH4AFA")) +require("heatshrink").decompress(atob("mEwwhC/AH4AWzIAByAHDhIICCpINDDAgIIFpAADBBQuKE4QIIFxgAKC7g9HABSbIBQQXWGxgXEKQxOMC5AhBC66WMC5AuBJ5h3ICoI3LeAwKBBAICBD4TmHC48ACgQCCfxC/HAgYXDL44vFA4YRDAoiOIHAgXFYRAXFBwwIIOw4OGIxKmIC5ylHGAoXIXpBIGLxxIIIx6IJFxwwNCxQwLFxYwLCxgwJFxowJCxwwHFx4wHCyAwFFyIwFCyQYDCygA/AH4AFA")) \ No newline at end of file From 01483303766627054448bb88f215e944aa44515e Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 08:56:11 +0200 Subject: [PATCH 30/83] Uncomment app code again --- apps/wohrm/app.js | 468 +++++++++++++++++++++++----------------------- 1 file changed, 233 insertions(+), 235 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 8323779c9..cc5dbc286 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -1,315 +1,313 @@ -// /* eslint-disable no-undef */ -// const Setter = { -// NONE: "none", -// UPPER: 'upper', -// LOWER: 'lower' -// }; +/* eslint-disable no-undef */ +const Setter = { + NONE: "none", + UPPER: 'upper', + LOWER: 'lower' +}; -// const shortBuzzTimeInMs = 50; -// const longBuzzTimeInMs = 200; +const shortBuzzTimeInMs = 50; +const longBuzzTimeInMs = 200; -// let upperLimit = 90; -// let upperLimitChanged = true; +let upperLimit = 90; +let upperLimitChanged = true; -// let lowerLimit = 50; -// let lowerLimitChanged = true; +let lowerLimit = 50; +let lowerLimitChanged = true; -// let limitSetter = Setter.NONE; +let limitSetter = Setter.NONE; -// let currentHeartRate = 0; -// let hrConfidence = -1; -// let hrOrConfidenceChanged = true; +let currentHeartRate = 0; +let hrConfidence = -1; +let hrOrConfidenceChanged = true; -// let setterHighlightTimeout; +let setterHighlightTimeout; -// function renderUpperLimitBackground() { -// g.setColor(1,0,0); -// g.fillRect(125,40, 210, 70); -// g.fillRect(180,70, 210, 200); +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 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 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 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); -// } + //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); +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); + //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 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 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); -// } + //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()) { -// renderButtonIcons(); +function drawTrainingHeartRate() { + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderButtonIcons(); -// 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); -// } else { -// g.setColor(255,255,255); -// } -// g.setFontVector(13); -// g.drawString("Upper : " + upperLimit, 130,50); + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Upper : " + upperLimit, 130,50); -// upperLimitChanged = false; -// } + upperLimitChanged = false; +} -// function renderCurrentHeartRate() { -// if(!hrOrConfidenceChanged) { return; } +function renderCurrentHeartRate() { + if(!hrOrConfidenceChanged) { return; } -// g.setColor(255,255,255); -// g.fillRect(45, 110, 165, 150); + g.setColor(255,255,255); + g.fillRect(45, 110, 165, 150); -// g.setColor(0,0,0); -// g.setFontVector(24); -// g.setFontAlign(1, -1, 0); -// g.drawString(currentHeartRate, 130, 117); + 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); -// } + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); +} -// 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); -// } else { -// g.setColor(255,255,255); -// } -// g.setFontVector(13); -// g.drawString("Lower : " + lowerLimit, 20,190); + 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; -// } + lowerLimitChanged = false; +} -// function renderConfidenceBars(){ -// if(!hrOrConfidenceChanged) { return; } +function renderConfidenceBars(){ + if(!hrOrConfidenceChanged) { 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); -// } + 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); -// } + g.fillRect(45, 110, 55, 150); + g.fillRect(165, 110, 175, 150); +} function renderButtonIcons() { g.setColor(255,255,255); g.setFontVector(14); - // + for Btn1 + //+ for Btn1 g.drawString("+", 222,50); - // Home for Btn2 + //Home for Btn2 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); - // - for Btn3 + //- for Btn3 g.drawString("-", 222,165); } -// function buzz() -// { -// if(currentHeartRate > upperLimit) -// { -// Bangle.buzz(shortBuzzTimeInMs); -// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); -// setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); -// } +function buzz() +{ + if(currentHeartRate > upperLimit) + { + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + } -// if(currentHeartRate < lowerLimit) -// { -// Bangle.buzz(longBuzzTimeInMs); -// setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); -// } -// } + if(currentHeartRate < lowerLimit) + { + Bangle.buzz(longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); + } +} -// function onHrm(hrm){ -// hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); -// currentHeartRate = hrm.bpm; -// hrConfidence = hrm.confidence; -// } +function onHrm(hrm){ + hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); + currentHeartRate = hrm.bpm; + hrConfidence = hrm.confidence; +} -// function setLimitSetterToLower() { -// resetHighlightTimeout(); +function setLimitSetterToLower() { + resetHighlightTimeout(); -// limitSetter = Setter.LOWER; -// console.log("Limit setter is lower"); + limitSetter = Setter.LOWER; + console.log("Limit setter is lower"); -// upperLimitChanged = true; -// lowerLimitChanged = true; + upperLimitChanged = true; + lowerLimitChanged = true; -// renderUpperLimit(); -// renderLowerLimit(); -// } + renderUpperLimit(); + renderLowerLimit(); +} -// function setLimitSetterToUpper() { -// resetHighlightTimeout(); +function setLimitSetterToUpper() { + resetHighlightTimeout(); -// limitSetter = Setter.UPPER; -// console.log("Limit setter is upper"); + limitSetter = Setter.UPPER; + console.log("Limit setter is upper"); -// upperLimitChanged = true; -// lowerLimitChanged = true; + upperLimitChanged = true; + lowerLimitChanged = true; -// renderLowerLimit(); -// renderUpperLimit(); -// } + renderLowerLimit(); + renderUpperLimit(); +} -// function setLimitSetterToNone() { -// limitSetter = Setter.NONE; -// console.log("Limit setter is none"); +function setLimitSetterToNone() { + limitSetter = Setter.NONE; + console.log("Limit setter is none"); -// upperLimitChanged = true; -// lowerLimitChanged = true; + upperLimitChanged = true; + lowerLimitChanged = true; -// renderLowerLimit(); -// renderUpperLimit(); -// } + renderLowerLimit(); + renderUpperLimit(); +} -// function incrementLimit(){ -// resetHighlightTimeout(); +function incrementLimit(){ + resetHighlightTimeout(); -// if (limitSetter === Setter.UPPER) { -// upperLimit++; -// renderUpperLimit(); -// console.log("Upper limit: " + upperLimit); -// upperLimitChanged = true; -// } else if(limitSetter === Setter.LOWER) { -// lowerLimit++; -// renderLowerLimit(); -// console.log("Lower limit: " + lowerLimit); -// lowerLimitChanged = true; -// } -// } + if (limitSetter === Setter.UPPER) { + upperLimit++; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit++; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; + } +} -// function decrementLimit(){ -// resetHighlightTimeout(); +function decrementLimit(){ + resetHighlightTimeout(); -// if (limitSetter === Setter.UPPER) { -// upperLimit--; -// renderUpperLimit(); -// console.log("Upper limit: " + upperLimit); -// upperLimitChanged = true; -// } else if(limitSetter === Setter.LOWER) { -// lowerLimit--; -// renderLowerLimit(); -// console.log("Lower limit: " + lowerLimit); -// lowerLimitChanged = true; -// } -// } + if (limitSetter === Setter.UPPER) { + upperLimit--; + renderUpperLimit(); + console.log("Upper limit: " + upperLimit); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit--; + renderLowerLimit(); + console.log("Lower limit: " + lowerLimit); + lowerLimitChanged = true; + } +} -// function resetHighlightTimeout() { -// if (setterHighlightTimeout) { -// clearTimeout(setterHighlightTimeout); -// } +function resetHighlightTimeout() { + if (setterHighlightTimeout) { + clearTimeout(setterHighlightTimeout); + } -// setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); -// } + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); +} -// // Show launcher when middle button pressed -// function switchOffApp(){ -// Bangle.setHRMPower(0); -// Bangle.showLauncher(); -// } +// Show launcher when middle button pressed +function switchOffApp(){ + Bangle.setHRMPower(0); + Bangle.showLauncher(); +} -// // special function to handle display switch on -// Bangle.on('lcdPower', (on) => { -// g.clear(); -// if (on) { -// Bangle.drawWidgets(); -// // call your app function here -// renderLowerLimitBackground(); -// renderUpperLimitBackground(); -// lowerLimitChanged = true; -// upperLimitChanged = true; -// drawTrainingHeartRate(); -// } -// }); +// special function to handle display switch on +Bangle.on('lcdPower', (on) => { + g.clear(); + if (on) { + Bangle.drawWidgets(); + // call your app function here + renderLowerLimitBackground(); + renderUpperLimitBackground(); + lowerLimitChanged = true; + upperLimitChanged = true; + drawTrainingHeartRate(); + } +}); -// Bangle.setHRMPower(1); -// Bangle.on('HRM', onHrm); +Bangle.setHRMPower(1); +Bangle.on('HRM', onHrm); -// setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); +setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); +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 }); -renderButtonIcons -// 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 }); +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +//drawTrainingHeartRate(); -// g.clear(); -// Bangle.loadWidgets(); -// Bangle.drawWidgets(); -// //drawTrainingHeartRate(); - -// // refesh every sec -// renderLowerLimitBackground(); -// renderUpperLimitBackground(); -// setInterval(drawTrainingHeartRate, 1000); +// refesh every sec +renderLowerLimitBackground(); +renderUpperLimitBackground(); +setInterval(drawTrainingHeartRate, 1000); From 21b1eaa4237d8a982f589e06373b8497023fb545 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:02:21 +0200 Subject: [PATCH 31/83] Fixes eventhandler for BTN2 --- apps/wohrm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index cc5dbc286..f077a9feb 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -297,7 +297,7 @@ Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(switchOffApp, BTN2, {repeat:false,edge:"falling"}); +setWatch(switchOffApp, BTN2, {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 }); From 7774b095b974e72ba2c979fd45352f37012f167c Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:05:23 +0200 Subject: [PATCH 32/83] BTN2 handler --- apps/wohrm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f077a9feb..ec048c8a1 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -297,7 +297,7 @@ Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true,}); +setWatch(switchOffApp, BTN2, {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 }); From 5507eb04be552a801699f388ff72a8b552e7acd0 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:20:26 +0200 Subject: [PATCH 33/83] Only buzz on high confidence --- apps.json | 2 +- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 44 ++++++++++++++++++++++++++++++++------------ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/apps.json b/apps.json index e5b0ab15e..93fa75524 100644 --- a/apps.json +++ b/apps.json @@ -816,7 +816,7 @@ { "id": "wohrm", "name": "Workout HRM", "icon": "app.png", - "version":"0.03", + "version":"0.04", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 36c08b9fd..f836f6f71 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -1,3 +1,4 @@ +0.04: Only buzz on high confidence (>85%) 0.03: Optimized rendering for the background 0.02: Adapted to new App code layout 0.01: Only tested on the emulator. diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ec048c8a1..2e147251c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -4,6 +4,10 @@ const Setter = { UPPER: 'upper', LOWER: 'lower' }; + +const Confidence = { + NONE +} const shortBuzzTimeInMs = 50; const longBuzzTimeInMs = 200; @@ -18,8 +22,8 @@ let limitSetter = Setter.NONE; let currentHeartRate = 0; let hrConfidence = -1; -let hrOrConfidenceChanged = true; - +let hrChanged = true; +let confidenceChanged = true; let setterHighlightTimeout; @@ -76,7 +80,7 @@ function renderLowerLimitBackground() { function drawTrainingHeartRate() { //Only redraw if the display is on if (Bangle.isLCDOn()) { - renderButtonIcons(); + renderUpperLimit(); @@ -108,7 +112,7 @@ function renderUpperLimit() { } function renderCurrentHeartRate() { - if(!hrOrConfidenceChanged) { return; } + if(!hrChanged) { return; } g.setColor(255,255,255); g.fillRect(45, 110, 165, 150); @@ -120,6 +124,8 @@ function renderCurrentHeartRate() { //Reset alignment to defaults g.setFontAlign(-1, -1, 0); + + hrChanged = false; } function renderLowerLimit() { @@ -140,7 +146,7 @@ function renderLowerLimit() { } function renderConfidenceBars(){ - if(!hrOrConfidenceChanged) { return; } + if(!confidenceChanged) { return; } if(hrConfidence >= 85){ g.setColor(0, 255, 0); @@ -154,6 +160,8 @@ function renderConfidenceBars(){ g.fillRect(45, 110, 55, 150); g.fillRect(165, 110, 175, 150); + + confidenceChanged = false; } function renderButtonIcons() { @@ -176,24 +184,33 @@ function renderButtonIcons() { function buzz() { + // Do not buzz if not confident + if(hrConfidence < 85) { return; } + if(currentHeartRate > upperLimit) { Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs+10); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs+10); } if(currentHeartRate < lowerLimit) { Bangle.buzz(longBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(longBuzzTimeInMs); }, longBuzzTimeInMs+10); } } function onHrm(hrm){ - hrOrConfidenceChanged = (currentHeartRate !== hrm.bpm || hrConfidence !== hrm.confidence); - currentHeartRate = hrm.bpm; - hrConfidence = hrm.confidence; + if(currentHeartRate !== hrm.bpm){ + currentHeartRate = hrm.bpm; + hrChanged = true; + } + + if(hrConfidence !== hrm.confidence) { + hrConfidence = hrm.confidence; + confidenceChanged = true; + } } function setLimitSetterToLower() { @@ -284,6 +301,7 @@ Bangle.on('lcdPower', (on) => { g.clear(); if (on) { Bangle.drawWidgets(); + renderButtonIcons(); // call your app function here renderLowerLimitBackground(); renderUpperLimitBackground(); @@ -307,7 +325,9 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); //drawTrainingHeartRate(); -// refesh every sec +renderButtonIcons(); renderLowerLimitBackground(); renderUpperLimitBackground(); + +// refesh every sec setInterval(drawTrainingHeartRate, 1000); From 18abff1d2f68ad7b78a3d189ed4c4cf258063e8d Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:22:36 +0200 Subject: [PATCH 34/83] Stupid coding error fixed --- apps/wohrm/app.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 2e147251c..979a50205 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -4,10 +4,6 @@ const Setter = { UPPER: 'upper', LOWER: 'lower' }; - -const Confidence = { - NONE -} const shortBuzzTimeInMs = 50; const longBuzzTimeInMs = 200; From d273d8860b35cacc4792bd0f64fe2e4f964cff09 Mon Sep 17 00:00:00 2001 From: Markus Deibel Date: Sun, 29 Mar 2020 09:33:52 +0200 Subject: [PATCH 35/83] Re-enable buzzing --- apps/wohrm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 979a50205..dff69d76b 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -87,7 +87,7 @@ function drawTrainingHeartRate() { renderConfidenceBars(); } - //buzz(); + buzz(); } function renderUpperLimit() { From bbc6cf35c15a5b0d7c217d5ddaccd2e265e28bc9 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 3 Apr 2020 01:41:57 +0200 Subject: [PATCH 36/83] Battery Widget with percentage: add settings (percentage/color/charger) Depends on settings 0.08 --- apps.json | 7 +++- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/settings.js | 58 +++++++++++++++++++++++++++++ apps/widbatpc/widget.js | 77 ++++++++++++++++++++++++++++++++++----- 4 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 apps/widbatpc/settings.js diff --git a/apps.json b/apps.json index 5b269e44f..58448d6f7 100644 --- a/apps.json +++ b/apps.json @@ -336,13 +336,16 @@ }, { "id": "widbatpc", "name": "Battery Level Widget (with percentage)", + "shortName": "Battery Widget", "icon": "widget.png", - "version":"0.06", + "version": "0.07", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "tags": "widget,battery", "type":"widget", "storage": [ - {"name":"widbatpc.wid.js","url":"widget.js"} + {"name":"widbatpc.wid.js","url":"widget.js"}, + {"name":"widbatpc.settings.js","url":"settings.js"}, + {"name":"widbatpc.settings.json","content": "{}"} ] }, { "id": "widbt", diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 3988729c3..245ec3af3 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -3,3 +3,4 @@ 0.04: Ensure redrawing works with variable size widget system 0.05: Change color depending on battery level, cloned from widbat 0.06: Show battery percentage as text +0.07: Add settings: percentage/color/charger icon diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/settings.js new file mode 100644 index 000000000..9ea86ed39 --- /dev/null +++ b/apps/widbatpc/settings.js @@ -0,0 +1,58 @@ +// This file should contain exactly one function, which shows the app's settings +/** + * @param {function} back Use back() to return to settings menu + */ +function settings(back) { + const SETTINGS_FILE = 'widbatpc.settings.json' + const COLORS = ['By Level', 'Green', 'Monochrome'] + + // initialize with default settings... + let s = { + 'color': COLORS[0], + 'percentage': true, + 'charger': true, + } + // ...and overwrite them with any saved values + // This way saved values are preserved if a new version adds more settings + const storage = require('Storage') + const saved = storage.readJSON(SETTINGS_FILE, 1) || {} + for (const key in saved) { + s[key] = saved[key] + } + + // creates a function to safe a specific setting, e.g. save('color')(1) + function save(key) { + return function (value) { + s[key] = value + storage.write(SETTINGS_FILE, s) + WIDGETS["batpc"].reload() + } + } + + const onOffFormat = b => (b ? 'on' : 'off') + const menu = { + '': { 'title': 'Battery Widget' }, + '< Back': back, + 'Percentage': { + value: s.percentage, + format: onOffFormat, + onchange: save('percentage'), + }, + 'Charging Icon': { + value: s.charger, + format: onOffFormat, + onchange: save('charger'), + }, + 'Color': { + format: () => s.color, + onchange: function () { + // cycles through options + const oldIndex = COLORS.indexOf(s.color) + const newIndex = (oldIndex + 1) % COLORS.length + s.color = COLORS[newIndex] + save('color')(s.color) + }, + }, + } + E.showMenu(menu) +} diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 7100dc111..a679f6721 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -1,20 +1,62 @@ (function(){ +const DEFAULTS = { + 'color': 'By Level', + 'percentage': true, + 'charger': true, +} +const COLORS = { + 'white': -1, + 'charging': 0x07E0, // "Green" + 'high': 0x05E0, // slightly darker green + 'ok': 0xFD20, // "Orange" + 'low':0xF800, // "Red" +} +const SETTINGS_FILE = 'widbatpc.settings.json' + +let settings +function loadSettings() { + settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {} +} +function setting(key) { + if (!settings) { loadSettings() } + return (key in settings) ? settings[key] : DEFAULTS[key] +} + const levelColor = (l) => { - if (Bangle.isCharging()) return 0x07E0; // "Green" - if (l >= 50) return 0x05E0; // slightly darker green - if (l >= 15) return 0xFD20; // "Orange" - return 0xF800; // "Red" + // "charging" is very bright -> percentage is hard to read, "high" is ok(ish) + const green = setting('percentage') ? COLORS.high : COLORS.charging + switch (setting('color')) { + case 'Monochrome': return COLORS.white; // no chance of reading the percentage here :-( + case 'Green': return green; + case 'By Level': // fall through + default: + if (setting('charger')) { + // charger icon -> always make percentage readable + if (Bangle.isCharging() || l >= 50) return green; + } else { + // no icon -> brightest green to indicate charging, even when showing percentage + if (Bangle.isCharging()) return COLORS.charging; + if (l >= 50) return COLORS.high; + } + if (l >= 15) return COLORS.ok; + return COLORS.low; + } +} +const chargerColor = () => { + return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging } function setWidth() { - WIDGETS["bat"].width = 40 + (Bangle.isCharging()?16:0); + WIDGETS["batpc"].width = 40; + if (Bangle.isCharging() && setting('charger')) { + WIDGETS["batpc"].width += 16; + } } function draw() { var s = 39; var x = this.x, y = this.y; - const l = E.getBattery(), c = levelColor(l); - if (Bangle.isCharging()) { - g.setColor(c).drawImage(atob( + if (Bangle.isCharging() && setting('charger')) { + g.setColor(chargerColor()).drawImage(atob( "DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y); x+=16; } @@ -22,8 +64,13 @@ function draw() { g.fillRect(x,y+2,x+s-4,y+21); g.clearRect(x+2,y+4,x+s-6,y+19); g.fillRect(x+s-3,y+10,x+s,y+14); + const l = E.getBattery(), + c = levelColor(l); g.setColor(c).fillRect(x+4,y+6,x+4+l*(s-12)/100,y+17); g.setColor(-1); + if (!setting('percentage')) { + return; + } g.setFontAlign(-1,-1); if (l >= 100) { g.setFont('4x6', 2); @@ -34,6 +81,16 @@ function draw() { g.drawString(l, x + 6, y + 4); } } +// reload widget, e.g. when settings have changed +function reload() { + loadSettings() + // need to redraw all widgets, because changing the "charger" setting + // can affect the width and mess with the whole widget layout + setWidth() + g.clear(); + Bangle.drawWidgets(); +} + Bangle.on('charging',function(charging) { if(charging) Bangle.buzz(); setWidth(); @@ -43,7 +100,7 @@ Bangle.on('charging',function(charging) { var batteryInterval; Bangle.on('lcdPower', function(on) { if (on) { - WIDGETS["bat"].draw(); + WIDGETS["batpc"].draw(); // refresh once a minute if LCD on if (!batteryInterval) batteryInterval = setInterval(draw, 60000); @@ -54,6 +111,6 @@ Bangle.on('lcdPower', function(on) { } } }); -WIDGETS["bat"]={area:"tr",width:40,draw:draw}; +WIDGETS["batpc"]={area:"tr",width:40,draw:draw,reload:reload}; setWidth(); })() From c60be707d82f9a3de6d0073afd8ba2dade9ecaa7 Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Fri, 3 Apr 2020 17:37:54 +0200 Subject: [PATCH 37/83] Added PWA and Browser Theme Support Add more favicon resolutions Add Progressive Web App Support Add Theme and Icon support for Safari Add Theme and Icon Support for Windows Metro Add Theme and Icon Support for Android Chrome Signed-off-by: OmegaRogue --- Bangle.js.svg | 478 +++++++++++++++++++++++++++++++++ browserconfig.xml | 9 + favicon.ico | Bin 1150 -> 0 bytes img/android-chrome-192x192.png | Bin 0 -> 4534 bytes img/android-chrome-512x512.png | Bin 0 -> 13713 bytes img/apple-touch-icon.png | Bin 0 -> 2905 bytes img/favicon-16x16.png | Bin 0 -> 586 bytes img/favicon-32x32.png | Bin 0 -> 860 bytes img/favicon.ico | Bin 0 -> 15086 bytes img/mstile-150x150.png | Bin 0 -> 3364 bytes img/safari-pinned-tab.svg | 100 +++++++ index.html | 13 +- site.webmanifest | 19 ++ 13 files changed, 618 insertions(+), 1 deletion(-) create mode 100644 Bangle.js.svg create mode 100644 browserconfig.xml delete mode 100644 favicon.ico create mode 100644 img/android-chrome-192x192.png create mode 100644 img/android-chrome-512x512.png create mode 100644 img/apple-touch-icon.png create mode 100644 img/favicon-16x16.png create mode 100644 img/favicon-32x32.png create mode 100644 img/favicon.ico create mode 100644 img/mstile-150x150.png create mode 100644 img/safari-pinned-tab.svg create mode 100644 site.webmanifest diff --git a/Bangle.js.svg b/Bangle.js.svg new file mode 100644 index 000000000..90c908c9b --- /dev/null +++ b/Bangle.js.svg @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browserconfig.xml b/browserconfig.xml new file mode 100644 index 000000000..0d56ca0d6 --- /dev/null +++ b/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #5755d9 + + + diff --git a/favicon.ico b/favicon.ico deleted file mode 100644 index 24ae659663f56ad85ce80aa656cd909b5977d7ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 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 COGRY> literal 0 HcmV?d00001 diff --git a/img/android-chrome-512x512.png b/img/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..6a147322241d7824b7d762c9e8d74c3c449c6769 GIT binary patch literal 13713 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 literal 0 HcmV?d00001 diff --git a/img/apple-touch-icon.png b/img/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9f5d62c1241c45e59abbca778b349fe648104d78 GIT binary patch literal 2905 zcmV-f3#RmmP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 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 JnJ45o{6FF@5n=!U literal 0 HcmV?d00001 diff --git a/img/mstile-150x150.png b/img/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..aae99969123d2a6c4fdfb081b2ff8ac17c6288cf GIT binary patch literal 3364 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 + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + + diff --git a/index.html b/index.html index efaf84a61..385e41a4b 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,17 @@ + + + + + + + + + + + Bangle.js App Loader