From cc64bfdd6adbc30eb9a03042c405b527ff641ce4 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sat, 22 Jan 2022 08:43:44 +0100 Subject: [PATCH] Refactoring + added timer which can easily be started / stopped. --- apps/notanalog/README.md | 10 +- apps/notanalog/notanalog.app.js | 266 ++++++++++++++++++++++++-------- apps/notanalog/screenshot_1.png | Bin 3518 -> 3488 bytes apps/notanalog/screenshot_2.png | Bin 3520 -> 3438 bytes apps/notanalog/screenshot_3.png | Bin 0 -> 3528 bytes 5 files changed, 211 insertions(+), 65 deletions(-) create mode 100644 apps/notanalog/screenshot_3.png diff --git a/apps/notanalog/README.md b/apps/notanalog/README.md index 0cc494c10..5ad3d3b24 100644 --- a/apps/notanalog/README.md +++ b/apps/notanalog/README.md @@ -6,17 +6,19 @@ It looks like an analog clock, but its not! It shows the time digital - check th The red hand shows the number of steps (0 = 0°, 2.5k = 90°, 5k = 180°, ...) and the black one the battery level (100% = 0°, 75% = 270°, 50% = 180°, ...). The selected theme is also respected. Note that this watch face is in fullscreen -mode - widgets are still loaded in background... +mode, but widgets are still loaded in background. ## Other features -- If you have done more than 10k steps, the red hand and icon will turn green. +- Set a timer - simply touch top (+5min.) or bottom (-5 min.). +- If the weather is available through the weather app, the outside temp. will be shown. - If the battery is charged, the icons will change. -- Shows outside temperature if gadgetbridge is connected with weather. -- Shows current lock status of your bangle. +- If you have done more than 10k steps, the red hand and icon will turn green. +- Shows current lock status of your bangle va a colored dot in the middle. ## Screenshots ![](screenshot_1.png) ![](screenshot_2.png) +![](screenshot_3.png) # Thanks diff --git a/apps/notanalog/notanalog.app.js b/apps/notanalog/notanalog.app.js index 8c86b1f60..b641bc9ec 100644 --- a/apps/notanalog/notanalog.app.js +++ b/apps/notanalog/notanalog.app.js @@ -1,5 +1,17 @@ -const locale = require('locale'); +/** + * NOT ANALOG CLOCK + */ +const locale = require('locale'); +const storage = require('Storage') +const SETTINGS_FILE = "notanalog.setting.json"; +let settings = { + alarm: -1, +}; +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +for (const key in saved_settings) { + settings[key] = saved_settings[key] +} /* * Set some important constants such as width, height and center @@ -10,10 +22,31 @@ var cx = W/2; var cy = H/2; var drawTimeout; +var state = { + color: "#ff0000", + steps: 0, + maxSteps: 10000, + bat: 0, + has_weather: false, + temp: "-" +} + var chargeImg = { width : 32, height : 32, bpp : 1, transparent : 0, - buffer : require("heatshrink").decompress(atob("AAMMAYUeAYUzAYVjAYXGAQMPxwDBj8cAYM73ADBuPwEAPg8E+gHAuFzgOAnHjAYMd40BwOPxkBwfHjEBw1j2ADBsPgBYPAAYIYBsEDFoPgg+AgPAg/AgeAhgJBgEYuf+AYM//BhBnAYBh1wKQXAAYM5wADBBQQoBAYQOCgA=")) + buffer : E.toArrayBuffer(atob("AAAMAAAAHgAAADMAAABjAAAAxgAAD44AAB8cAAA7uAAAcfAMAODgPgDAcHMBgDjjAYAdxgGBj4wBg8cYAYZjsAGGYeABg8DgAQGAYAMAAOAHgAHAB8ADgAzgBwAYc/4AGD/4AAw4AAAOcAAAH8AAADmAAABwAAAA4AAAAMAAAAA=")) +}; + +var alarmImg = { + width : 32, height : 32, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AA/wAAAP8AAAD/AAAAGAAAABgAAAA8AABh/4YAd//uAH+B/gA+AHwAOAAcAHAPDgDgD4cA4A/HAcAP44HAD+OBwA/zgYAP8YGAD/GBj//xgc//84HH/+OBx//jgOP/xwDh/4cAcP8OAHg8HgA8ADwAHwD4AA//8AAD/8AAAP8AA=")) +}; + +var stepsImg = { + width : 32, height : 32, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("AcAAAAPwAAAH8AAAB/gAAAf4AAAH/AAAD/wAAAf8AAAH/AfAB/wP4Af8H+AH/B/gB/wf4AP8P+AD+D/gAfg/4AGAP+AAPD/gAPw/4AD+P+AAfj/AAH4/wAB+H8AAPAeAAAAwAAAAPgAAAH8AAAB/AAAAfgAAAH4AAAA8AAAAOAA=")) }; @@ -83,6 +116,23 @@ function drawBackground() { } +function drawState(){ + g.setColor(state.color); + g.setFontAlign(1,0,0); + + // Draw alarm + var highPrioImg = isAlarmEnabled() ? alarmImg : + Bangle.isCharging() ? chargeImg : undefined; + + // As default, we draw weather if available, otherwise the steps symbol is shown. + if(!highPrioImg && state.has_weather){ + g.setColor(g.theme.fg); + g.drawString(state.temp, cx+cx/2+15, cy+cy/2+10); + } else { + var img = highPrioImg ? highPrioImg : stepsImg; + g.drawImage(img, cx+cx/2 - img.width/2, cy+cy/2 - img.height/2+5); + } +} function drawData() { g.setFontAlign(0,0,0); @@ -90,41 +140,23 @@ function drawData() { // Set hand functions var drawBatteryHand = g.drawRotRect.bind(g,6,12,R-38); - var drawStepsHand = g.drawRotRect.bind(g,5,12,R-24); - - // Draw state - g.setColor(g.theme.fg); - if(Bangle.isCharging()){ - g.drawImage(chargeImg, cx+cx/2 - chargeImg.width/2, cy+cy/2 - chargeImg.height/2+5); - } else { - dataStr = "B-JS"; - try { - weather = require('weather').get(); - if (weather === undefined){ - dataStr = "-"; - } else { - dataStr = locale.temp(Math.round(weather.temp-273.15)); - } - } catch(ex) { - - } - g.setFontAlign(1,0,0); - g.drawString(dataStr, cx+cx/2+15, cy+cy/2+10); - } - + var drawDataHand = g.drawRotRect.bind(g,5,12,R-24); // Draw battery hand + g.setColor(g.theme.fg); g.setFontAlign(0,0,0); - var bat = E.getBattery(); - var maxBat = 100; - drawBatteryHand(parseInt(bat*360/maxBat)); + drawBatteryHand(parseInt(state.bat*360/100)); - // Draw step hand and icon - var steps = getSteps(); - var maxSteps = 10000; - var stepsColor = steps > 10000 ? "#00ff00" : "#ff0000"; - g.setColor(stepsColor); - drawStepsHand(parseInt(steps*360/maxSteps)); + // Draw data hand - depending on state + g.setColor(state.color); + if(isAlarmEnabled()){ + var alrm = getAlarmMinutes(); + drawDataHand(parseInt(alrm*360/60)); + return; + } + + // Default are the steps + drawDataHand(parseInt(state.steps*360/state.maxSteps)); } @@ -150,15 +182,6 @@ function drawTime(){ var m2 = m < 10 ? m : m - m1*10; g.drawString(m2, cx, H-posY); g.drawString(m1, posX-1, cy+5); - - // Connect - var rP = 24; - var w = 4; - g.setColor(1,0,0); - for(var dy=-w;dy <= w; dy += 1){ - g.drawLine(cx+rP, posY+rP/2+dy+5, W-posX-rP, cy-rP); - g.drawLine(posX-2+rP, cy+rP/2+dy+5, cx-rP, H-posY+2-rP); - } } @@ -179,28 +202,62 @@ function drawLock(){ g.setColor(g.theme.fg); g.fillCircle(cx, cy, 7); - var c = Bangle.isLocked() ? "#ff0000" : g.theme.bg; + var c = Bangle.isLocked() ? state.color : g.theme.bg; g.setColor(c); g.fillCircle(cx, cy, 4); } +function handleState(){ + // Set battery + state.bat = E.getBattery(); + + // Set steps + state.steps = getSteps(); + state.maxSteps = 10000; + + // Set theme color + state.color = isAlarmEnabled() ? "#FF6A00" : + state.steps > state.maxSteps ? "#00ff00" : + "#ff0000"; + + // Set weather + state.has_weather = true; + try { + weather = require('weather').get(); + if (weather === undefined){ + state.temp = "-"; + } else { + state.temp = locale.temp(Math.round(weather.temp-273.15)); + } + } catch(ex) { + state.has_weather = false; + } + +} + + function draw(){ - // Clear watch face - g.reset(); - g.clearRect(0, 0, g.getWidth(), g.getHeight()); + // Execute handlers + handleState(); + handleAlarm(); - // Draw again - g.setColor(1,1,1); + // Clear watch face + g.reset(); + g.clearRect(0, 0, g.getWidth(), g.getHeight()); - drawBackground(); - drawLock(); - drawDate(); - drawData(); - drawTime(); + // Draw again + g.setColor(1,1,1); - // Queue draw in one minute - queueDraw(); + drawBackground(); + drawLock(); + drawDate(); + drawState(); + drawData(); + drawTime(); + + // Queue draw in one minute + queueDraw(); } @@ -208,12 +265,12 @@ function draw(){ * Listeners */ Bangle.on('lcdPower',on=>{ - if (on) { - draw(); - } else { // stop draw timer - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - } + if (on) { + draw(); + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } }); Bangle.on('charging',function(charging) { @@ -224,6 +281,25 @@ Bangle.on('lock', function(isLocked) { drawLock(); }); +Bangle.on('touch', function(btn, e){ + var upper = parseInt(g.getHeight() * 0.2); + var lower = g.getHeight() - upper; + + var is_upper = e.y < upper; + var is_lower = e.y > lower; + + if(is_upper){ + feedback(); + increaseAlarm(); + draw(); + } + + if(is_lower){ + feedback(); + decreaseAlarm(); + draw(); + } +}); /* @@ -238,6 +314,74 @@ function queueDraw() { } +/* + * Handle alarm + */ +function getCurrentTimeInMinutes(){ + return Math.floor(Date.now() / (1000*60)); +} + +function isAlarmEnabled(){ + return settings.alarm >= 0; +} + +function getAlarmMinutes(){ + var currentTime = getCurrentTimeInMinutes(); + return settings.alarm - currentTime; +} + +function handleAlarm(){ + if(!isAlarmEnabled()){ + return; + } + + if(getAlarmMinutes() > 0){ + return; + } + + // Alarm + var t = 300; + Bangle.buzz(t, 1) + .then(() => new Promise(resolve => setTimeout(resolve, t))) + .then(() => Bangle.buzz(t, 1)) + .then(() => new Promise(resolve => setTimeout(resolve, t))) + .then(() => Bangle.buzz(t, 1)) + .then(() => new Promise(resolve => setTimeout(resolve, t))) + .then(() => Bangle.buzz(t, 1)) + .then(() => new Promise(resolve => setTimeout(resolve, 5E3))) + .then(() => { + // Update alarm state to disabled + settings.alarm = -1; + storage.writeJSON(SETTINGS_FILE, settings); + }); +} + + +function increaseAlarm(){ + if(isAlarmEnabled()){ + settings.alarm += 5; + } else { + settings.alarm = getCurrentTimeInMinutes() + 5; + } + + storage.writeJSON(SETTINGS_FILE, settings); +} + + +function decreaseAlarm(){ + if(isAlarmEnabled() && (settings.alarm-5 > getCurrentTimeInMinutes())){ + settings.alarm -= 5; + } else { + settings.alarm = -1; + } + + storage.writeJSON(SETTINGS_FILE, settings); +} + +function feedback(){ + Bangle.buzz(40, 0.3); +} + /* * Lets start widgets, listen for btn etc. */ diff --git a/apps/notanalog/screenshot_1.png b/apps/notanalog/screenshot_1.png index 00138fc821b27d6c3c3413628c8cedd07bcca0a1..de7d9e61f28dac445867043433cd7c734fe96f68 100644 GIT binary patch delta 3473 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 A*Z=?k delta 3505 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 diff --git a/apps/notanalog/screenshot_3.png b/apps/notanalog/screenshot_3.png new file mode 100644 index 0000000000000000000000000000000000000000..b638862afdb77d1b972b5aa7290ff01a170a1906 GIT binary patch literal 3528 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