From e10347fff061de6df414f68ae64cf2504f79e0cf Mon Sep 17 00:00:00 2001 From: Carl Chan Date: Sun, 22 Dec 2024 18:46:31 -0500 Subject: [PATCH] initial commit of dsky_clock --- apps/dsky_clock/ChangeLog | 1 + apps/dsky_clock/README.md | 26 ++++ apps/dsky_clock/dsky_clock.app.js | 226 ++++++++++++++++++++++++++++++ apps/dsky_clock/dsky_clock.img | Bin 0 -> 1156 bytes apps/dsky_clock/metadata.json | 17 +++ apps/dsky_clock/screenshot1.png | Bin 0 -> 3169 bytes 6 files changed, 270 insertions(+) create mode 100644 apps/dsky_clock/ChangeLog create mode 100644 apps/dsky_clock/README.md create mode 100644 apps/dsky_clock/dsky_clock.app.js create mode 100644 apps/dsky_clock/dsky_clock.img create mode 100644 apps/dsky_clock/metadata.json create mode 100644 apps/dsky_clock/screenshot1.png diff --git a/apps/dsky_clock/ChangeLog b/apps/dsky_clock/ChangeLog new file mode 100644 index 000000000..d18016d21 --- /dev/null +++ b/apps/dsky_clock/ChangeLog @@ -0,0 +1 @@ +0.01: Initial commit \ No newline at end of file diff --git a/apps/dsky_clock/README.md b/apps/dsky_clock/README.md new file mode 100644 index 000000000..a710ae077 --- /dev/null +++ b/apps/dsky_clock/README.md @@ -0,0 +1,26 @@ +# DSKY Clock + +This is a clockface inspired by the Apollo DSKY interface. + +## Features +- battery level indicator (PROG indicator) +- month (VERB indicator) +- date (NOUN indicator) +- Current local time (DATA 1) +- UTC time (DATA 2) +- Step counter (DATA 3) + +Indicator lights are: +- COMP ACTY (GPS/HRM active) +- MSG (Messages waiting) +- LOCK (Screen is locked) +- BT (Bluetooth is disconnected) +- BATT (Low battery or battery charging) +- ALARM (Alarm is set) +- STEP (Reached STEP goal)) + +---- +This is my first watch face, may add features and customization later. + +## Creator +Written by Carl Chan | [github](https://github.com/carlchan) diff --git a/apps/dsky_clock/dsky_clock.app.js b/apps/dsky_clock/dsky_clock.app.js new file mode 100644 index 000000000..62003f9fa --- /dev/null +++ b/apps/dsky_clock/dsky_clock.app.js @@ -0,0 +1,226 @@ +//Init +var Layout = require("Layout"); +require("Font7x11Numeric7Seg").add(Graphics); +require("FontTeletext5x9Ascii").add(Graphics); + +borders = 1; +Light_on='#fff'; +Light_off='#554'; +Light_warn='#f90'; +Light_COMPACTY='#0F0'; +Light_width=43; +Light_height=25; +EL7_height=30; +LightFont='Teletext5x9Ascii'; +DataFont='7x11Numeric7Seg:2'; + +var layout = new Layout( + {type:"h", c:[ + {type:"",width:6}, + { type:"v", c: [ + {type:"txt", font:LightFont, col:"#000", bgCol:"#555", id:'L1', label:"UPLINK\nACTY", width:Light_width, height:Light_height}, + {type:"txt", font:LightFont, col:"#000", bgCol:"#555", id:'L2', label:"TEMP", width:Light_width, height:Light_height }, + {type:"txt", font:LightFont, col:"#000", bgCol:"#555", id:'L3', label:"GIMBAL\nLOCK", width:Light_width, height:Light_height }, + {type:"txt", font:LightFont, col:"#000", bgCol:"#555", id:'L4', label:"STBY", width:Light_width, height:Light_height }, + {type:"txt", font:LightFont, col:"#000", bgCol:"#555", id:'L5', label:"PROG", width:Light_width, height:Light_height }, + {type:"txt", font:LightFont, col:"#000", bgCol:"#eee", id:'L6', label:"OPR ERR", width:Light_width, height:Light_height }, + ]}, + { type:"", width:20}, + { type:"v", c: [ + {type:"",height:2}, + {type:"h", c: [ + {type:"", width:50},{type:"txt", font:"6x8", col:"#000",bgCol:"#0F0", label:"PROG", width:25, height:10}, + ]}, + {type:"h", c: [ + {type:"",width:10}, + {type:"txt", font:"6x8", col:"#000", bgCol:"#000", id:"COMPACTY", label:"COMP\nACTY", width:26, height:26 }, + {type:"",width:17}, + {type:"txt", font:DataFont, col:"#0F0", bgCol:"#000",label:"00", id:"PROG", fillx:1, height:EL7_height }, + ]}, + {type:"",height:1}, + {type:"h", c: [ + {type:"txt", font:"6x8", col:"#000", bgCol:"#0F0",label:"VERB", width:25, height:10}, + {type:"",width:30}, + {type:"txt", font:"6x8", col:"#000",bgCol:"#0F0",label:"NOUN", width:25, height:10}, + ]}, + {type:"h", c: [ + {type:"txt", font:DataFont, col:"#0F0", bgCol:"#000", label:"00", id:"VERB", fillx:1, height:EL7_height}, + {type:"txt", font:DataFont, col:"#0F0", bgCol:"#000", label:"00", id:"NOUN", fillx:1, height:EL7_height}, + ]}, + { type:"",bgCol:'#070', width:80, height:2 }, + {type:"txt", font:DataFont, col:"#0F0", bgCol:"#000", label:"00000", id:"R1", fillx:1, height:EL7_height}, + {type:"txt", font:DataFont, col:"#0F0", bgCol:"#000", label:"00000", id:"R2", fillx:1, height:EL7_height}, + {type:"txt", font:DataFont, col:"#0F0", bgCol:"#000", label:"00000", id:"R3", fillx:1, height:EL7_height}, + ]}, + {type:"",width:5}, + ]}, + {lazy:true}); +layout.update(); + +//support functions + +function getdatetime(){ + var datetime = []; + var d = new Date(); +// var meridian = require("locale").meridian(d); + datetime.clock = require("locale").time(d, 1); + datetime.month = d.getMonth()+1; + datetime.day = d.getDate(); + return datetime; +} + +function getSteps(){ + steps=Bangle.getHealthStatus("day").steps; + steps = typeof steps !== 'undefined' ? steps:0; + return steps; +} + +function getStepGoal(){ + let stepGoal = (require("Storage").readJSON("health.json",1)||10000).stepGoal; + stepGoal = typeof stepGoal !== 'undefined' ? stepGoal:10000; + return stepGoal; +} + +function isAlarmSet(){ + let alarmStatus = (require('Storage').readJSON('sched.json',1)||[]).some(alarm=>alarm.on); + return alarmStatus; +} + +function isMessagesNotify(){ + if (require("Storage").read("messages.json")!==undefined) { + return true; + } else { + return false; + } +} + +function getTemperature(){ + var temperature = E.getTemperature(); + temperature = typeof temperature !== 'undefined' ? temperature:99999; + return Math.round(temperature); +} + +function getHRM(){ + hrm=Bangle.getHealthStatus('10min').bpm; + hrm = typeof hrm !== 'undefined' ? hrm:0; + return hrm; +} + +function getGPS(){ + GPS=Bangle.getPressure(); + GPS = typeof GPS !== 'undefined' ? GPS:{temperature:0,pressure:0,altitude:0}; + return GPS; +} + +function isBTConnected(){ + return NRF.getSecurityStatus().connected; +} + +function getBattery(){ + battlevel = E.getBattery(); + if (Bangle.isCharging()) { + battlevel = -1; + } else if (battlevel >= 100) { + battlevel = 99; + } + battlevel=String(battlevel).padStart(2,'0'); + return battlevel; +} + +function isActive(){ + if (Bangle.isCompassOn() || Bangle.isGPSOn() || Bangle.isHRMOn() | Bangle.isBarometerOn() ) { + return true; + } else { + return false; + } +} + +function setLight(id,label,check,onColour,offColour){ + onColour = typeof onColour !== 'undefined' ? onColour:Light_on; + offColour = typeof offColour !== 'undefined' ? offColour:Light_off; + if (label !== '') { + layout[id].label=label; + } + if (check) { + layout[id].bgCol=onColour; + } else { + layout[id].bgCol=offColour; + } +} + +function draw_bg(){ + g.setColor('#666'); + g.fillRect(0,0,176,176); + g.setColor('#000'); + g.fillRect(69,2,172,174); + g.fillCircle(59,10,5); + g.fillCircle(59,166,5); +} + +// actual display +function draw(){ + datetime=getdatetime(); + var ds=new Date(); + datestring=String(String(ds.getHours()).padStart(2,'0')+String(ds.getMinutes()).padStart(2,'0')).padStart(5,'0'); + var offsets = require("Storage").readJSON("worldclock.settings.json") || []; + utchour=((ds.getHours()+(Math.round(ds.getTimezoneOffset()/60))) % 24); + utcstring=String(String(utchour).padStart(2,'0')+String(ds.getMinutes()).padStart(2,'0')).padStart(5,'0'); + + layout.R1.label=datestring; + layout.R2.label=utcstring; + layout.R3.label=String(getSteps()).padStart(5,'0'); + + layout.PROG.label=String(getBattery()).padStart(2,'0'); + layout.VERB.label=String(datetime.month).padStart(2,'0'); + layout.NOUN.label=String(datetime.day).padStart(2,'0'); + + setLight('COMPACTY','',isActive(),Light_COMPACTY); + setLight('L1','MSG',isMessagesNotify()); + setLight('L2','LOCK',Bangle.isLocked()); + setLight('L3','BT',!isBTConnected(),Light_warn); + setLight('L4','BATT',(getBattery()<=20),Light_warn); + setLight('L5','ALARM',isAlarmSet(),Light_warn); + setLight('L6','STEP',(getSteps()>=getStepGoal()),'#0a0'); + + layout.render(); + // layout.debug(); +} + +var drawTimeout; +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +//////////// Main + +// Show launcher when middle button pressed +Bangle.setUI({ + mode : "clock", + remove : function() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + require("widget_utils").show(); // re-show widgets + }}); +Bangle.loadWidgets(); +require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe + +Bangle.on('lock',on=>{ + draw(); // draw immediately + }); + +Bangle.on('GPS',draw); +Bangle.on('HRM',draw); +Bangle.on("message",draw); +Bangle.on('charging',draw); +NRF.on('connect',draw); +NRF.on('disconnect',draw); + +g.clear(); +draw_bg(); +draw(); +queueDraw(); \ No newline at end of file diff --git a/apps/dsky_clock/dsky_clock.img b/apps/dsky_clock/dsky_clock.img new file mode 100644 index 0000000000000000000000000000000000000000..9e2fb3adb55a41dd88d89048b60c5735e33e2afc GIT binary patch literal 1156 zcmZ{kJ#vFE5QP^PtCWHpzzIA#gWGgYnHg1bONB3x6K34zE_wSSB;k0OLCnYF>1h$1 z&);v0)$HSOpoL1^?)Q}@7sSf%!cXPF_adj9a{?cw@EDO?l)L|P7JVEB*W(e>D<8+$ z`S424-9L_l>%)tAd;P0C2rkp|F~2U9C}1>y&-27Rk2XMka+ill{q@xLff6T~IN>-g zzfwQaHw8LKpBqlM1dNmEFCVT~EMCeVU&W{A)xXQr`orC;pSMuz@-SA!o84>mffH}M z1q!OaJ}#D%vEYmYuTgwHubvYen+I;j_nZOxjZ^X2Ib)yUl@*_z>#|bGBX8UGPfaiL zHattrT|Yz`bl*z;#H;&92#ia9Nn|;z4*-1Nr1>ik1anbqA1Y^UoZdO)A?bovm($QQ z&!U&G{kpJ`y?Ty3h`I85%!9^ZPr<0s@bVuBwp{lyP7~s3KP^xBZ_LZA I3oobX533WW&Hw-a literal 0 HcmV?d00001 diff --git a/apps/dsky_clock/metadata.json b/apps/dsky_clock/metadata.json new file mode 100644 index 000000000..176cf48c5 --- /dev/null +++ b/apps/dsky_clock/metadata.json @@ -0,0 +1,17 @@ +{ "id": "dsky_clock", + "name": "DSKY Clock", + "shortName":"dsky_clock", + "icon": "dsky_clock.img", + "screenshots": [{"url":"screenshot1.png"}], + "version": "0.01", + "description": "A clockface inspired by the Apollo DSKY interface.", + "tags": "clock", + "type": "clock", + "supports":["BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"dsky_clock.app.js","url":"app.js"}, + {"name":"dsky_clock.img","url":"app-icon.js","evaluate":true} + ] + } diff --git a/apps/dsky_clock/screenshot1.png b/apps/dsky_clock/screenshot1.png new file mode 100644 index 0000000000000000000000000000000000000000..949199a69b8e097468a24df9bee5622bb9b8e1c8 GIT binary patch literal 3169 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 Hu0mjf27}no literal 0 HcmV?d00001