diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index ef4edcff0..7cc79e2cc 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -8,4 +8,5 @@ 0.08: Select the color of widgets correctly. Additional settings to hide colon. 0.09: Larger font size if colon is hidden to improve readability further. 0.10: HomeAssistant integration if HomeAssistant is installed. -0.11: Performance improvements. \ No newline at end of file +0.11: Performance improvements. +0.12: Implements a 2D menu. \ No newline at end of file diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index 190488d6b..97b282046 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -3,16 +3,39 @@ ![](screenshot.png) ## Features +A very minimalistic clock keeping date and time in focus. Nevertheless, a +2D menu allows you to display lots of different data including data from 3rd party apps and it's also possible to control things e.g. to set a timer or send a HomeAssistant trigger. + +Simply click left / right to go through the menu entries such as Bangle, Timer etc. +and click up/down to move into this sub-menu. You can then click in the middle of the screen +to e.g. send a trigger via HomeAssistant once you selected it. + +``` + Bpm ... + | | + Steps 10 min. ... ... + | | | | + Battery 5 min Temp. Trigger1 + | | | | + Bangle -- Timer[Optional] -- Weather[Optional] -- HomeAssistant [Optional] +``` + +The following list shows which apps must be installed in order to get the optional menu entries: +- Timer - Sched lib +- Weather - Weather app +- HomeAssistant - HomeAssistant app + + +## Other settings - Fullscreen on/off -- Tab left/right of screen to show steps, temperature etc. -- Enable / disable lock icon in the settings. -- If the "sched" app is installed tab top / bottom of the screen to set the timer. -- If HomeAssistant is installed, triggers are shown. Simple select the trigger and touch the middle of the screen to send the trigger to HomeAssistant. -- The design is adapted to the theme of your bangle. -- The colon (e.g. 7:35 = 735) can be hidden now in the settings. +- Enable/disable lock icon in the settings +- The colon (e.g. 7:35 = 735) can be hidden in the settings for an even larger time font +- The design of your bangle sys settings is used (e.g. you can also set a blue background) + ## Thanks to Icons created by Flaticon + ## Creator - [David Peer](https://github.com/peerdavid) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 4c4359a4f..5e2fb5eaa 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -1,10 +1,10 @@ -/* +/************ * Includes */ const locale = require('locale'); const storage = require('Storage'); -/* +/************ * Statics */ const SETTINGS_FILE = "bwclk.setting.json"; @@ -12,14 +12,15 @@ const TIMER_IDX = "bwclk"; const W = g.getWidth(); const H = g.getHeight(); -/* +/************ * Settings */ let settings = { fullscreen: false, showLock: true, hideColon: false, - showInfo: 0, + menuPosX: 0, + menuPosY: 0, }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; @@ -28,11 +29,21 @@ for (const key in saved_settings) { } -/* +/************ * Assets */ - // Manrope font +Graphics.prototype.setXLargeFont = function(scale) { + // Actual height 53 (55 - 3) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('AHM/8AIG/+AA4sD/wQGh/4EWQA/AC8YA40HNA0BRY8/RY0P/6LFgf//4iFA4IiFj4HBEQkHCAQiDHIIZGv4HCFQY5BDAo5CAAIpDDAfACA3wLYv//hsFKYxcCMgoiBOooiBQwwiBS40AHIgA/ACS/DLYjYCBAjQEBAYQDBAgHDUAbyDZQi3CegoHEVQQZFagUfW4Y0DaAgECaIJSEFYMPbIYNDv5ACGAIrBCgJ1EFYILCAAQWCj4zDGgILCegcDEQRNDHIIiCHgZ2BEQShFIqUDFYidCh5ODg4NCn40DAgd/AYR5BDILZEAAIMDAAYVCh7aHdYhKDbQg4Dv7rGBAihFCAwIDCAgA/AB3/eoa7GAAk/dgbVGDJrvCDK67DDIjaGdYpbCdYonCcQjjDEVUBEQ4A/AEMcAYV/NAUHcYUDawd/cYUPRYSmBBgaLBToP8BgYiBSgIiCj4iCg//EQSuDW4IMDVwYiCBgIiBBgrRDCATeBaIYqCv70DCgT4CEQMfIgQZBBoRnDv/3EQIvBDIffEQMHFwReBRYUfOgX/+IiDKIeHEQRRECwUHKwIuB8AiDIoJEBCwZFCv/4HIZaBIgPAEQS2CUYQiCD4SABEQcfOwIZBEQaHBO4RcEAAI/BEQQgBSIQiDTIRZBEQZuBVYQiDHoKWCEQQICFQIiDBAQeCEQQA/AANwA40BLIJ5BO4JWCBAUPAYR5En7RBUIQECN4SYCQQIiEh6CCEQk/BoQiBgYeCBoTrCAgT0CCgIfCFYQiBg4IBGgIiDj6rBg4rCBYLRDFYIiBbYIfBLgQiBIQYiD4JCCLgf/bQIWDBYV/EQV/BYXz/5FBgIiD5//IowZBD4M/NAX/BIPgDIJoC//5GgKUDn//4f/8KLE/wTBAAI8BEQPwj4HBVwYmBDgIZDN4QZCGYKJCHQP/JoSgCBATrCh5dBKITVDG4gICAAbvDAH5SCL4QADK4J5CCAiTCCAp1BCAqCDCAgiGCAIiFCAQiFeoIiFg6/FCAgiECAXnEQgQB/kfEQYQC4F/EQYQCgIiDfoIQBg4iDCAUAEQZUCcgIiDDIIQBEQhuBBoIiENoYiFDwQiECAQiFwEBPQQNCAQKDDEYMDDoMfRh4iGUwqvEESBiBaQ5oEbgr0FNAo+EEIwA+oAHGgJoFRAMHe4L0CAALNBBAT0BfwScDCAXweAL0DWgUPQYQiDwF/QYQiC/zTB+C0FBAL0CEQYIBGgMPCgIxBg4rCJIKsCh5IBBwTPCj4WBgYLBZ4V/MAIiBBQQrBEQYtCBYQiCO4QLFCwgiDIQIiGIoMHEQpFBn5FFD4JoENwRoGDgSUCAoKfBw//DgIiCT4auCFwN/T4RRET4TaCEQKoCDIQiCGgK/DAAQICdYQACHoIqCBAoQFEwIhFAH4AFQIROEj4IGXwIIGNwIACbgIhEBAiRCVwoqDTogHEW4QZFXgIZB/z9Cv49CF4MPBwI0Ca4LlB8ATCJoP4AoINDfQPAg7PBg4cBBwUfD4MfFYILCCwgOCf4QLEwEPCwILCgJaBn4WBBYQxCIQQiD+EDCYI5CBYRQBIo4fBMQIuBC4N/NAv8AoIcBSgU/FYIIBZIYrCW4hOCXIQZCgYUBv7jEh4uBZAscewZ8CgEgUYT0EEoQIBA4gICFQQIEHYQA+KQzdDAArdCAArpCEScHaIQiEvwiGe4QiFUwQiEbgIiFYIL0DEQTkBEQrJEEQc/cYYiCg4HBDIQiCfoRoEHQLaDEQQHBbQYiBCAT8Dn/BCAoXBJYP/OgZKC/6OEEARLCEQZLEEQZLEEQjKFEQI6EEQZLDEQbsGEQLjGYYYA/JIxzEg/AfgJSDAoPgfgiDC8COFAoPnaQj6CAAR+CW4TCFA4i6CDIqhCDIfwHoYHCYIN/GgKuBJ4JDBFYUf/C5CBYIZBv/Ag4ZBg4rBBYQTBAQIcBg4FBn5UBAQUfFwIfCEQeAgYfBAQUBFAKbCAQQiCGwIiE+A2BwBFNwE/AoM/EQJoIWwKCCh4cBFYKUERYV/W46uHFYIZGaJA0B/glBGYT0JIITiEMIJvCFQQAEHYQA/ABBlEOIhdGQAIRFSgQIBgQICn4IB8EAjiBCUYglCbQYeBEoQZCTwM/CYIZD/gEBUwIzBJ4UHYAU/EwIrBh4rCAoIXCn4rBCgUDAQN/FYMfBYIXBCYJnCBYXggf8HgQLCwEPEQQuBgJOECwILDCwgiLHIUHBYJFGD4IxBgYWCn4rBBwJoFDIYNBCgPADgKHBRYfDBQN/GAIrBToTLDVwYACDILiCWAb8DAAYzBYAjTCAAI9BAARNCBAoqCBAgQDFgbYCAH4AufgQACf4T8CAAT/CfgQACBwITCAAYOBCYQioh4iEAHQA=='))), + 46, + atob("FR4uHyopKyksJSssGA=="), + 70+(scale<<8)+(1<<16) + ); +}; + + Graphics.prototype.setLargeFont = function(scale) { // Actual height 48 (49 - 2) this.setFontCustom( @@ -44,15 +55,6 @@ Graphics.prototype.setLargeFont = function(scale) { return this; }; -Graphics.prototype.setXLargeFont = function(scale) { - // Actual height 53 (55 - 3) - this.setFontCustom( - E.toString(require('heatshrink').decompress(atob('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'))), - 46, - atob("FR4uHyopKyksJSssGA=="), - 70+(scale<<8)+(1<<16) - ); -}; Graphics.prototype.setMediumFont = function(scale) { // Actual height 41 (42 - 2) @@ -60,6 +62,7 @@ Graphics.prototype.setMediumFont = function(scale) { return this; }; + Graphics.prototype.setSmallFont = function(scale) { // Actual height 28 (27 - 0) this.setFontCustom( @@ -71,6 +74,7 @@ Graphics.prototype.setSmallFont = function(scale) { return this; }; + function imgLock(){ return { width : 16, height : 16, bpp : 1, @@ -111,6 +115,14 @@ function imgTemperature() { } } +function imgWeather(){ + return { + width : 24, height : 24, bpp : 1, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AAcYAQ0MgEwAQUAngLB/8AgP/wACCgf/4Fz//OAQQICCIoaCEAQpGHA4ACA=")) + } +} + function imgWind () { return { width : 24, height : 24, bpp : 1, @@ -127,14 +139,6 @@ function imgTimer() { } } -function imgCharging() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//+v///k///4AQPwBANgBoMxBoMb/P+h/w/kH8H4gfB+EBwfggHH4EAt4CBn4CBj4CBh4FCCIO/8EB//Agf/wEH/8Gh//x////fAQIA=")) - } -} - function imgWatch() { return { width : 24, height : 24, bpp : 1, @@ -143,56 +147,102 @@ function imgWatch() { } } +function imgHomeAssistant() { + return { + width : 48, height : 48, bpp : 1, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AD8BwAFDg/gAocP+AFDj4FEn/8Aod//wFD/1+FAf4j+8AoMD+EPDAUH+OPAoUP+fPAoUfBYk/C4l/EYIwC//8n//FwIFEgYFD4EH+E8nkP8BdBAonjjk44/wj/nzk58/4gAFDF4PgCIMHAoPwhkwh4FB/EEkEfIIWAHwIFC4A+BAoXgg4FDL4IFDL4IFDLIYFkAEQA==")) + } +} -/* - * INFO ENTRIES - * List of [Data, Icon, left/right, Function to execute] + +/************ + * 2D MENU with entries of: + * [name, icon, opt[customUpFun], opt[customDownFun], opt[customCenterFun]] + * + * An example is shown below: + * + * Bpm ... + * | | + * Steps 10 min. ... ... + * | | | | + * Battery 5-min Temp. Trigger1 + * | | | | + * BangleJs -- Timer -- Weather[Optional] -- HomeAssistant [Optional] */ -var infoArray = [ - function(){ return [ null, null, "left", null ] }, - function(){ return [ "Bangle", imgWatch(), "right", null ] }, - function(){ return [ E.getBattery() + "%", imgBattery(), "left", null ] }, - function(){ return [ getSteps(), imgSteps(), "left", null ] }, - function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm(), "left", null] }, - function(){ return [ getWeather().temp, imgTemperature(), "left", null ] }, - function(){ return [ getWeather().wind, imgWind(), "left", null ] }, -]; +var menu = [ + [ + function(){ return [ null, null ] }, + ], + [ + function(){ return [ "Bangle", imgWatch() ] }, + function(){ return [ E.getBattery() + (Bangle.isCharging() ? "% ++" : "%"), imgBattery() ] }, + function(){ return [ getSteps(), imgSteps() ] }, + function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm()] }, + ] +] /* - * We append the HomeAssistant integrations if HomeAssistant is available + * Timer Menu + */ +try{ + require('sched'); + menu.push([ + function(){ + var text = isAlarmEnabled() ? "T-" + getAlarmMinutes() + " min." : "Timer"; + return [text, imgTimer(), () => increaseAlarm(), () => decreaseAlarm(), null ] + }, + ]); +} catch(ex) { + // If sched is not installed, we hide this menu item +} + +/* + * WEATHER MENU + */ +if(storage.readJSON('weather.json') !== undefined){ + menu.push([ + function(){ return [ "Weather", imgWeather() ] }, + function(){ return [ getWeather().temp, imgTemperature() ] }, + function(){ return [ getWeather().wind, imgWind() ] }, + ]); +} + + +/* + * HOME ASSISTANT MENU */ try{ var triggers = require("ha.lib.js").getTriggers(); + var haMenu = [ + function(){ return [ "Home", imgHomeAssistant() ] }, + ]; + triggers.forEach(trigger => { - infoArray.push(function(){ - return [trigger.display, trigger.getIcon(), "left", function(){ + haMenu.push(function(){ + return [trigger.display, trigger.getIcon(), () => {}, () => {}, function(){ var ha = require("ha.lib.js"); ha.sendTrigger("TRIGGER_BW"); ha.sendTrigger(trigger.trigger); }] }); }) + menu.push(haMenu); } catch(ex){ - // Nothing to do if HomeAssistant is not available... -} -const NUM_INFO=infoArray.length; - - -function getInfoEntry(){ - if(isAlarmEnabled()){ - return [getAlarmMinutes() + " min.", imgTimer(), "left", null] - } else if(Bangle.isCharging()){ - return [E.getBattery() + "%", imgCharging(), "left", null] - } else{ - // In case the user removes HomeAssistant entries, showInfo - // could be larger than infoArray.length... - settings.showInfo = settings.showInfo % infoArray.length; - return infoArray[settings.showInfo](); - } + // If HomeAssistant is not installed, we hide this item } -/* +function getMenuEntry(){ + // In case the user removes HomeAssistant entries, showInfo + // could be larger than infoArray.length... + settings.menuPosX = settings.menuPosX % menu.length; + settings.menuPosY = settings.menuPosY % menu[settings.menuPosX].length; + return menu[settings.menuPosX][settings.menuPosY](); +} + + +/************ * Helper */ function getSteps() { @@ -215,38 +265,20 @@ function getSteps() { function getWeather(){ - var weatherJson; + var weatherJson = storage.readJSON('weather.json'); + var weather = weatherJson.weather; - try { - weatherJson = storage.readJSON('weather.json'); - var weather = weatherJson.weather; + weather.temp = locale.temp(weather.temp-273.15); - // Temperature - weather.temp = locale.temp(weather.temp-273.15); + weather.hum = weather.hum + "%"; - // Humidity - weather.hum = weather.hum + "%"; + var wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); + weather.wind = Math.round(wind[1]) + " km/h"; - // Wind - const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); - weather.wind = Math.round(wind[1]) + " km/h"; - - return weather - - } catch(ex) { - // Return default - } - - return { - temp: "? °C", - hum: "-", - txt: "-", - wind: "? km/h", - wdir: "-", - wrose: "-" - }; + return weather } + function isAlarmEnabled(){ try{ var alarm = require('sched'); @@ -261,6 +293,7 @@ function isAlarmEnabled(){ return false; } + function getAlarmMinutes(){ if(!isAlarmEnabled()){ return -1; @@ -271,6 +304,7 @@ function getAlarmMinutes(){ return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); } + function increaseAlarm(){ try{ var minutes = isAlarmEnabled() ? getAlarmMinutes() : 0; @@ -282,6 +316,7 @@ function increaseAlarm(){ } catch(ex){ } } + function decreaseAlarm(){ try{ var minutes = getAlarmMinutes(); @@ -301,10 +336,9 @@ function decreaseAlarm(){ } -/* - * DRAW functions +/************ + * DRAW */ - function draw() { // Queue draw again queueDraw(); @@ -338,13 +372,12 @@ function drawDate(){ var fullDateW = dateW + 10 + dayW; g.setFontAlign(-1,0); + g.drawString(dayStr, W/2 - fullDateW/2 + 10 + dateW, y-12); + g.drawString(monthStr, W/2 - fullDateW/2 + 10 + dateW, y+11); + g.setMediumFont(); g.setColor(g.theme.fg); g.drawString(dateStr, W/2 - fullDateW / 2, y+1); - - g.setSmallFont(); - g.drawString(dayStr, W/2 - fullDateW/2 + 10 + dateW, y-12); - g.drawString(monthStr, W/2 - fullDateW/2 + 10 + dateW, y+11); } @@ -368,13 +401,13 @@ function drawTime(){ // Set y coordinates correctly y += parseInt((H - y)/2) + 5; - var infoEntry = getInfoEntry(); - var infoStr = infoEntry[0]; - var infoImg = infoEntry[1]; - var printImgLeft = infoEntry[2] == "left"; + var menuEntry = getMenuEntry(); + var menuName = menuEntry[0]; + var menuImg = menuEntry[1]; + var printImgLeft = settings.menuPosY != 0; // Show large or small time depending on info entry - if(infoStr == null){ + if(menuName == null){ if(settings.hideColon){ g.setXLargeFont(); } else { @@ -386,8 +419,8 @@ function drawTime(){ } g.drawString(timeStr, W/2, y); - // Draw info if set - if(infoStr == null){ + // Draw menu if set + if(menuName == null){ return; } @@ -395,18 +428,18 @@ function drawTime(){ g.setFontAlign(0,0); g.setSmallFont(); var imgWidth = 0; - if(infoImg !== undefined){ - imgWidth = 26.0; - var strWidth = g.stringWidth(infoStr); - var scale = imgWidth / infoImg.width; + if(menuImg !== undefined){ + imgWidth = 24.0; + var strWidth = g.stringWidth(menuName); + var scale = imgWidth / menuImg.width; g.drawImage( - infoImg, + menuImg, W/2 + (printImgLeft ? -strWidth/2-2 : strWidth/2+2) - parseInt(imgWidth/2), y - parseInt(imgWidth/2), { scale: scale } ); } - g.drawString(infoStr, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); + g.drawString(menuName, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); } @@ -480,36 +513,52 @@ Bangle.on('touch', function(btn, e){ if(is_upper){ Bangle.buzz(40, 0.6); - increaseAlarm(); + settings.menuPosY = (settings.menuPosY+1) % menu[settings.menuPosX].length; + + // Handle custom menu entry function + var menuEntry = getMenuEntry(); + if(menuEntry.length > 2){ + menuEntry[2](); + } + drawTime(); } if(is_lower){ Bangle.buzz(40, 0.6); - decreaseAlarm(); + settings.menuPosY = settings.menuPosY-1; + settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].length-1 : settings.menuPosY; + + // Handle custom menu entry function + var menuEntry = getMenuEntry(); + if(menuEntry.length > 3){ + menuEntry[3](); + } + drawTime(); } if(is_right){ Bangle.buzz(40, 0.6); - settings.showInfo = (settings.showInfo+1) % NUM_INFO; + settings.menuPosX = (settings.menuPosX+1) % menu.length; + settings.menuPosY = 0; drawTime(); } if(is_left){ Bangle.buzz(40, 0.6); - settings.showInfo = settings.showInfo-1; - settings.showInfo = settings.showInfo < 0 ? NUM_INFO-1 : settings.showInfo; + settings.menuPosY = 0; + settings.menuPosX = settings.menuPosX-1; + settings.menuPosX = settings.menuPosX < 0 ? menu.length-1 : settings.menuPosX; drawTime(); } if(is_center){ - var infoEntry = getInfoEntry(); - var fun = infoEntry[3]; - if(fun != null){ + var menuEntry = getMenuEntry(); + if(menuEntry.length > 4){ Bangle.buzz(80, 0.6).then(()=>{ try{ - fun(); + menuEntry[4](); setTimeout(()=>{ Bangle.buzz(80, 0.6); }, 250); diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index 834712743..4c0335df8 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,7 +1,7 @@ { "id": "bwclk", "name": "BW Clock", - "version": "0.11", + "version": "0.12", "description": "BW Clock.", "readme": "README.md", "icon": "app.png",