From 23cb4ea18ed9deab5c502fe7fdbe9b1a02646fbc Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Sep 2020 08:44:58 +0100 Subject: [PATCH] Added vibrate clock --- apps.json | 13 ++++ apps/vibrclock/ChangeLog | 1 + apps/vibrclock/app-icon.js | 1 + apps/vibrclock/app.js | 125 +++++++++++++++++++++++++++++++++++++ apps/vibrclock/app.png | Bin 0 -> 2850 bytes 5 files changed, 140 insertions(+) create mode 100644 apps/vibrclock/ChangeLog create mode 100644 apps/vibrclock/app-icon.js create mode 100644 apps/vibrclock/app.js create mode 100644 apps/vibrclock/app.png diff --git a/apps.json b/apps.json index 104609ae6..7f97b6f84 100644 --- a/apps.json +++ b/apps.json @@ -692,6 +692,19 @@ {"name":"sclock.img","url":"clock-simple-icon.js","evaluate":true} ] }, + { "id": "vibrclock", + "name": "Vibrate Clock", + "icon": "app.png", + "version":"0.01", + "description": "When BTN1 is pressed, vibrate out the time as a series of buzzes, one digit at a time. Hours, then Minutes. Zero is signified by one long buzz. Otherwise a simple digital clock.", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"vibrclock.app.js","url":"app.js"}, + {"name":"vibrclock.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "svclock", "name": "Simple V-Clock", "icon": "vclock-simple.png", diff --git a/apps/vibrclock/ChangeLog b/apps/vibrclock/ChangeLog new file mode 100644 index 000000000..b4d1ae593 --- /dev/null +++ b/apps/vibrclock/ChangeLog @@ -0,0 +1 @@ +0.01: First commit diff --git a/apps/vibrclock/app-icon.js b/apps/vibrclock/app-icon.js new file mode 100644 index 000000000..c41aa0f9c --- /dev/null +++ b/apps/vibrclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATlgAGFlgylEQUyq1WwOB1msAYIHBmQxeDwQrB1nXABA0BqwxaP4eBFhIAFwIwYLgYtPAAZiWCgMrLhS7BMRUrGCQuN1gvBYxQwCF6S6LF5rEDFyC7MF5zDDF50rD5gvP1iRORpovRSJ6NNF6SRCLzQvSMBksmQdOF6OsmQvLRxwvSSBZqBF5+BmUyUJwvCGBC+QwMrCQMrCZ4vZxErLoJhBGAOsAAgvTwR6OH4QfBmTEBAAYwGwQv7R5uCR8DbOrrvSOoIuHF4VWDZ2CQwOICR3XFxAwCF54ATF5cyUo4vmYB4AM63P53O5/Q6wvKSDfW52j44AC0YFBMEnPFgYAGGBcrYKvWFAnP64wPMAKRV5wuE63W6HIMB6RU6y7E5HO6BfF0aRMGCS9D54EBF4I3BTIhgMGCSOCXYIwBSAICC6ySCF5QwCYYL0PF4fW53OAYjzDF5ZiTR4g0BR4OiR4LxDF5piEwJjLW4QACLgLvBFobvMGJEyqwzBwOCwQ3E6wvFXYLtEF6QxEAAtWBoYmEeYReERx4yNBYowFAAouWABouuAATDE0a7TAH4ASA")) diff --git a/apps/vibrclock/app.js b/apps/vibrclock/app.js new file mode 100644 index 000000000..817a69815 --- /dev/null +++ b/apps/vibrclock/app.js @@ -0,0 +1,125 @@ +/* jshint esversion: 6 */ +const timeFontSize = 6; +const dateFontSize = 3; +const gmtFontSize = 2; +const font = "6x8"; + +const xyCenter = g.getWidth() / 2; +const yposTime = 75; +const yposDate = 130; +const yposYear = 175; + +// Check settings for what type our clock should be +var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; +var d, da, time, hours, minutes, meridian = ""; + +function drawSimpleClock() { + // get date + var d = new Date(); + var da = d.toString().split(" "); + + g.reset(); // default draw styles + // drawSting centered + g.setFontAlign(0, 0); + + // draw time + var time = da[4].substr(0, 5).split(":"); + var hours = time[0], + minutes = time[1]; + var meridian = ""; + if (is12Hour) { + hours = parseInt(hours,10); + meridian = "AM"; + if (hours == 0) { + hours = 12; + meridian = "AM"; + } else if (hours >= 12) { + meridian = "PM"; + if (hours>12) hours -= 12; + } + hours = (" "+hours).substr(-2); + } + + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, true); + g.setFont(font, gmtFontSize); + g.drawString(meridian, xyCenter + 102, yposTime + 10, true); + + // draw Day, name of month, Date + var date = [da[0], da[1], da[2]].join(" "); + g.setFont(font, dateFontSize); + + g.drawString(date, xyCenter, yposDate, true); + + // draw year + g.setFont(font, dateFontSize); + g.drawString(d.getFullYear(), xyCenter, yposYear, true); + + // draw gmt + var gmt = da[5]; + g.setFont(font, gmtFontSize); + g.drawString(gmt, xyCenter, yposGMT, true); +} + +// handle switch display on by pressing BTN1 +Bangle.on('lcdPower', function(on) { + if (on) drawSimpleClock(); +}); + +// clean app screen +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// refesh every 15 sec +setInterval(drawSimpleClock, 15E3); + +// draw now +drawSimpleClock(); + +// vibrate 0..9 +function vibrateDigit(num) { + if (num==0) return Bangle.buzz(500); + return new Promise(function f(resolve){ + if (num--<=0) return resolve(); + Bangle.buzz(100).then(()=>{ + setTimeout(()=>f(resolve), 200); + }); + }); +} +// vibrate multiple digits (num must be a string) +function vibrateNumber(num) { + return new Promise(function f(resolve){ + if (!num.length) return resolve(); + var digit = num[0]; + num = num.substr(1); + vibrateDigit(digit).then(()=>{ + setTimeout(()=>f(resolve),500); + }); + }); +} + +var vibrateBusy; +function vibrateTime() { + if (vibrateBusy) return; + vibrateBusy = true; + + var d = new Date(); + var hours = d.getHours(), minutes = d.getMinutes(); + if (is12Hour) { + if (hours == 0) hours = 12; + else if (hours>12) hours -= 12; + } + + vibrateNumber(hours.toString()). + then(() => new Promise(resolve=>setTimeout(resolve,500))). + then(() => vibrateNumber(minutes.toString())). + then(() => vibrateBusy=false); +} + + + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// when BTN1 pressed, vibrate +setWatch(vibrateTime, BTN1, {repeat:true,edge:"rising"}); diff --git a/apps/vibrclock/app.png b/apps/vibrclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..79ff0b9922dd1c5310ea7d737df3079bb231f27d GIT binary patch literal 2850 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