From 7df753a0f75df09f24a05b781e41334b59b336be Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 13:29:17 +0100 Subject: [PATCH 1/9] New clock: CLI complete --- apps/clicompleteclk/app.js | 183 +++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 apps/clicompleteclk/app.js diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js new file mode 100644 index 000000000..487dbfa07 --- /dev/null +++ b/apps/clicompleteclk/app.js @@ -0,0 +1,183 @@ +const storage = require('Storage'); +const locale = require("locale"); + +const font = "12x20"; +const fontsize = 1; +const fontheight = 19; + +const marginTop = 10; +const marginLeftTopic = 3; // margin of topics +const marginLeftData = 68; // margin of data values + +const topicColor = g.theme.dark ? "#fff" : "#000"; +const textColor = g.theme.dark ? "#0f0" : "#080"; + +let hrtValue; +let localTempValue; +let weatherTempString; +let lastHeartRateRowIndex; + +// timeout used to update every minute +var drawTimeout; +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + drawAll(false); + }, 60000 - (Date.now() % 60000)); +} + +function drawAll(drawInfoToo){ + let now = new Date(); + updateTime(now); + if (drawInfoToo) { + drawInfo(now); + } + queueDraw(); +} + +function updateTime(now){ + if (!Bangle.isLCDOn()) return; + writeLineTopic("TIME", 1); + writeLine(locale.time(now,1),1); + if(now.getMinutes() == 0) + drawInfo(now); +} + +function drawInfo(now) { + if (now == undefined) + now = new Date(); + + let i = 2; + + writeLineTopic("DOWK", i); + writeLine(locale.dow(now),i); + i++; + + writeLineTopic("DATE", i); + writeLine(locale.date(now,1),i); + i++; + + /* + writeLineTopic("BAT", i); + const b = E.getBattery(); + writeLine(b + "%", i); // TODO make bars + i++; + */ + + // weather + var weatherJson = getWeather(); + if(weatherJson && weatherJson.weather){ + const currentWeather = weatherJson.weather; + + const weatherTempValue = locale.temp(currentWeather.temp-273.15); + weatherTempString = weatherTempValue; + writeLineTopic("WTHR", i); + writeLine(currentWeather.txt,i); + i++; + } + + // temperatures (local & weather) + if (localTempValue != undefined || weatherTempString != undefined) { + writeLineTopic("TEMP", i); + let tempString = ""; + if (localTempValue != undefined) + tempString += "l: " + localTempValue; + if (tempString != "") + tempString += ", "; + if (weatherTempString != undefined) + tempString += weatherTempString; + writeLine(tempString,i); + i++; + } + + // steps + if (stepsWidget() != undefined) { + writeLineTopic("STEP", i); + const steps = stepsWidget().getSteps(); + writeLine(steps, i); + i++; + } + + drawHeartRate(i); +} + +function drawHeartRate(i) { + if (hrtValue != undefined) { + writeLineTopic("HRTM", i); + writeLine(hrtValue,i); + } + lastHeartRateRowIndex = i; +} + + +function writeLineTopic(str, line) { + var y = marginTop+line*fontheight; + g.setFont(font,fontsize); + g.setColor(topicColor).setFontAlign(-1,-1); + + g.clearRect(0,y,g.getWidth(),y+fontheight-1); + g.drawString("[" + str + "]",marginLeftTopic,y); +} + +function writeLine(str,line){ + var y = marginTop+line*fontheight; + g.setFont(font,fontsize); + g.setColor(textColor).setFontAlign(-1,-1); + g.drawString(str,marginLeftData,y); +} + + +Bangle.on('HRM', function(hrm) { + //if(hrm.confidence > 90){ + hrtValue = hrm.bpm + " bpm"; + if (Bangle.isLCDOn()) + drawHeartRate(lastHeartRateRowIndex); + //} else { + // hrtValue = undefined; + //} +}); + + +function getTemperature() { + if (Bangle.getPressure) { + Bangle.getPressure().then(onTemperature); + } else { + onTemperature({ + temperature : E.getTemperature() + }); + } +} +function onTemperature(p) { + localTempValue = locale.temp(p.temperature.toFixed(1)); +} + +function stepsWidget() { + if (WIDGETS.activepedom !== undefined) { + return WIDGETS.activepedom; + } else if (WIDGETS.wpedom !== undefined) { + return WIDGETS.wpedom; + } + return undefined; +} + + +function getWeather() { + let jsonWeather = storage.readJSON('weather.json'); + return jsonWeather; +} + +g.clear(); +Bangle.setUI("clock"); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawAll(true); +Bangle.on('lcdPower',function(on) { + if (on) { + drawAll(true); + } else { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); From a1599a967b0cf5223c0e96c041e14c98b6212ff7 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 13:29:54 +0100 Subject: [PATCH 2/9] Adding icons, readme and changelog --- apps/clicompleteclk/ChangeLog | 1 + apps/clicompleteclk/README.md | 18 ++++++++++++++++++ apps/clicompleteclk/app-icon.js | 1 + apps/clicompleteclk/app.png | Bin 0 -> 258 bytes 4 files changed, 20 insertions(+) create mode 100644 apps/clicompleteclk/ChangeLog create mode 100644 apps/clicompleteclk/README.md create mode 100644 apps/clicompleteclk/app-icon.js create mode 100644 apps/clicompleteclk/app.png diff --git a/apps/clicompleteclk/ChangeLog b/apps/clicompleteclk/ChangeLog new file mode 100644 index 000000000..85b5360ad --- /dev/null +++ b/apps/clicompleteclk/ChangeLog @@ -0,0 +1 @@ +0.01: New clock! diff --git a/apps/clicompleteclk/README.md b/apps/clicompleteclk/README.md new file mode 100644 index 000000000..653123187 --- /dev/null +++ b/apps/clicompleteclk/README.md @@ -0,0 +1,18 @@ +# Command line complete clock + +Command line styled clock with lots of information: + +It can show the following (depending on availability) information: +* Time +* Day of week +* Date +* Weather condition (requires weather app) +* Temperature (requires weather app) +* Steps (requires a step widget) +* Heart rate + +## Creator +Marco ([myxor](https://github.com/myxor)) + +## Icon +Icon taken from [materialdesignicons](https://materialdesignicons.com) under Apache License 2.0 diff --git a/apps/clicompleteclk/app-icon.js b/apps/clicompleteclk/app-icon.js new file mode 100644 index 000000000..b874bb6fa --- /dev/null +++ b/apps/clicompleteclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgI/8/4ACAqYv/F/PwAqgA6A==")) diff --git a/apps/clicompleteclk/app.png b/apps/clicompleteclk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..104e6124afa8fcb86f8f8c625912eb4f933ca51a GIT binary patch literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oArNM~bhqvgP;iT< zi(^Oz>)RO@xf&FBTsQB3zkKr|^Te1V)3#eU@t2n79Y5=M`cMM{ivj~9$DbJo%8qUG zuhWx16zKF+>|508S;{^=CznpCii%LyUMQej@Y|0ePyN!b*XFKsLhv}Q9i~I>c#?<+C3pmbRd)r-MrtmGC#VF{-rk^(|_VTaz zZ?kt|VedDg>Z*Uw{T&!L>L-aZSb?43aA4K}#>F$3-mEKrrVn&KgQu&X%Q~loCIB;9 BV`cyV literal 0 HcmV?d00001 From 93361297bd23d90dde7538a64a32f456cdd4614a Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 13:31:12 +0100 Subject: [PATCH 3/9] Add clicompleteclk to apps.json --- apps.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 8cbc755d0..f9d417b95 100644 --- a/apps.json +++ b/apps.json @@ -4825,5 +4825,20 @@ { "name": "ptlaunch.img", "url": "app-icon.js", "evaluate": true } ], "data": [{"name":"ptlaunch.patterns.json"}] - } + }, + { "id": "clicompleteclk", + "name": "Command line complete clock", + "shortName":"Command line complete clock", + "version":"0.01", + "description": "Command line styled clock with lots of information", + "icon": "app.png", + "type": "clock", + "tags": "clock,cli,command,bash,shell,weather,hrt", + "supports" : ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"clicompleteclk.app.js","url":"app.js"}, + {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true} + ] +} ] From 32107c668eda2e644560dd158a7b8e30a0db3f4a Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 13:34:33 +0100 Subject: [PATCH 4/9] Make shortName short --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index f9d417b95..231e40949 100644 --- a/apps.json +++ b/apps.json @@ -4828,7 +4828,7 @@ }, { "id": "clicompleteclk", "name": "Command line complete clock", - "shortName":"Command line complete clock", + "shortName":"Cli cmplt clk", "version":"0.01", "description": "Command line styled clock with lots of information", "icon": "app.png", From 0f18c5888f23af8f4c76e6372c399b89dc2d2306 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 13:38:10 +0100 Subject: [PATCH 5/9] Make names even shorter + allow emulator --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 231e40949..340fb6f13 100644 --- a/apps.json +++ b/apps.json @@ -4827,11 +4827,12 @@ "data": [{"name":"ptlaunch.patterns.json"}] }, { "id": "clicompleteclk", - "name": "Command line complete clock", - "shortName":"Cli cmplt clk", + "name": "CLI cmplt clock", + "shortName":"CLI cmplt clk", "version":"0.01", "description": "Command line styled clock with lots of information", "icon": "app.png", + "allow_emulator": true, "type": "clock", "tags": "clock,cli,command,bash,shell,weather,hrt", "supports" : ["BANGLEJS", "BANGLEJS2"], From 7ce4ada3dff0e844cc1386ca9bb5a64a20ddf834 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 13:40:33 +0100 Subject: [PATCH 6/9] Fix names (again) --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 340fb6f13..cb920f43d 100644 --- a/apps.json +++ b/apps.json @@ -4827,8 +4827,8 @@ "data": [{"name":"ptlaunch.patterns.json"}] }, { "id": "clicompleteclk", - "name": "CLI cmplt clock", - "shortName":"CLI cmplt clk", + "name": "CLI complete clock", + "shortName":"CLI cmplt clock", "version":"0.01", "description": "Command line styled clock with lots of information", "icon": "app.png", From 7b09fd9b4f7b9c998df6a4b644ce6d0b4dfb63b8 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 14:53:22 +0100 Subject: [PATCH 7/9] Add todo to README --- apps/clicompleteclk/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/clicompleteclk/README.md b/apps/clicompleteclk/README.md index 653123187..e182b55fd 100644 --- a/apps/clicompleteclk/README.md +++ b/apps/clicompleteclk/README.md @@ -9,7 +9,12 @@ It can show the following (depending on availability) information: * Weather condition (requires weather app) * Temperature (requires weather app) * Steps (requires a step widget) -* Heart rate +* Heart rate (when screen is on and unlocked) + +## TODO +* Make time font bigger +* Show progress of steps (if any goal is set) +* Show trend of HRM out of history data ## Creator Marco ([myxor](https://github.com/myxor)) From 5903aed3e437f8a5bbc76bff49d12720ffe19940 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 14:53:51 +0100 Subject: [PATCH 8/9] Turn on HRM when screen is on and unlocked --- apps/clicompleteclk/app.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js index 487dbfa07..cc7fd5e41 100644 --- a/apps/clicompleteclk/app.js +++ b/apps/clicompleteclk/app.js @@ -104,9 +104,11 @@ function drawInfo(now) { } function drawHeartRate(i) { + writeLineTopic("HRTM", i); if (hrtValue != undefined) { - writeLineTopic("HRTM", i); writeLine(hrtValue,i); + } else { + writeLine("-",i); } lastHeartRateRowIndex = i; } @@ -129,6 +131,15 @@ function writeLine(str,line){ } +// turn on HRM when the LCD is unlocked +Bangle.on('lock', function(isLocked) { + if (!isLocked) { + Bangle.setHRMPower(1,"clicompleteclk"); + hrtValue = undefined; + } else { + Bangle.setHRMPower(0,"clicompleteclk"); + } +}); Bangle.on('HRM', function(hrm) { //if(hrm.confidence > 90){ hrtValue = hrm.bpm + " bpm"; @@ -173,6 +184,7 @@ Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); drawAll(true); + Bangle.on('lcdPower',function(on) { if (on) { drawAll(true); From 0a67d177bbf44f8ff2e8fc9a65e63222930eacb3 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 9 Dec 2021 15:35:17 +0100 Subject: [PATCH 9/9] Update app.js * Remove local temperature * Draw heart rate value in grey if the value is not up to date --- apps/clicompleteclk/app.js | 75 +++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js index cc7fd5e41..89dbce919 100644 --- a/apps/clicompleteclk/app.js +++ b/apps/clicompleteclk/app.js @@ -13,6 +13,7 @@ const topicColor = g.theme.dark ? "#fff" : "#000"; const textColor = g.theme.dark ? "#0f0" : "#080"; let hrtValue; +let hrtValueIsOld = false; let localTempValue; let weatherTempString; let lastHeartRateRowIndex; @@ -76,19 +77,9 @@ function drawInfo(now) { writeLineTopic("WTHR", i); writeLine(currentWeather.txt,i); i++; - } - // temperatures (local & weather) - if (localTempValue != undefined || weatherTempString != undefined) { writeLineTopic("TEMP", i); - let tempString = ""; - if (localTempValue != undefined) - tempString += "l: " + localTempValue; - if (tempString != "") - tempString += ", "; - if (weatherTempString != undefined) - tempString += weatherTempString; - writeLine(tempString,i); + writeLine(weatherTempValue,i); i++; } @@ -104,11 +95,16 @@ function drawInfo(now) { } function drawHeartRate(i) { + if (i == undefined) + i = lastHeartRateRowIndex; writeLineTopic("HRTM", i); if (hrtValue != undefined) { - writeLine(hrtValue,i); + if (!hrtValueIsOld) + writeLine(hrtValue,i); + else + writeLine(hrtValue,i, topicColor); } else { - writeLine("-",i); + writeLine("...",i); } lastHeartRateRowIndex = i; } @@ -123,47 +119,54 @@ function writeLineTopic(str, line) { g.drawString("[" + str + "]",marginLeftTopic,y); } -function writeLine(str,line){ +function writeLine(str,line,pColor){ + if (pColor == undefined) + pColor = textColor; var y = marginTop+line*fontheight; g.setFont(font,fontsize); - g.setColor(textColor).setFontAlign(-1,-1); + g.setColor(pColor).setFontAlign(-1,-1); g.drawString(str,marginLeftData,y); } +// EVENTS: // turn on HRM when the LCD is unlocked Bangle.on('lock', function(isLocked) { if (!isLocked) { Bangle.setHRMPower(1,"clicompleteclk"); - hrtValue = undefined; + if (hrtValue == undefined) + hrtValue = "..."; + else + hrtValueIsOld = true; + drawHeartRate(); } else { + hrtValueIsOld = true; Bangle.setHRMPower(0,"clicompleteclk"); } }); + +Bangle.on('lcdPower',function(on) { + if (on) { + drawAll(true); + } else { + hrtValueIsOld = true; + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + Bangle.on('HRM', function(hrm) { //if(hrm.confidence > 90){ - hrtValue = hrm.bpm + " bpm"; + hrtValueIsOld = false; + hrtValue = hrm.bpm; if (Bangle.isLCDOn()) - drawHeartRate(lastHeartRateRowIndex); + drawHeartRate(); //} else { // hrtValue = undefined; //} }); -function getTemperature() { - if (Bangle.getPressure) { - Bangle.getPressure().then(onTemperature); - } else { - onTemperature({ - temperature : E.getTemperature() - }); - } -} -function onTemperature(p) { - localTempValue = locale.temp(p.temperature.toFixed(1)); -} - function stepsWidget() { if (WIDGETS.activepedom !== undefined) { return WIDGETS.activepedom; @@ -173,7 +176,6 @@ function stepsWidget() { return undefined; } - function getWeather() { let jsonWeather = storage.readJSON('weather.json'); return jsonWeather; @@ -184,12 +186,3 @@ Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); drawAll(true); - -Bangle.on('lcdPower',function(on) { - if (on) { - drawAll(true); - } else { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - } -});