From 212795540667dc5c609a90e0593c22f754225894 Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Thu, 28 Oct 2021 14:52:36 +0200 Subject: [PATCH 01/13] feat: add simply clock app --- apps.json | 15 ++++++ apps/gpstouch/gpstouch.app.js | 2 +- apps/simplyclock/ChangeLog | 1 + apps/simplyclock/app.js | 90 ++++++++++++++++++++++++++++++++++ apps/simplyclock/icon.js | 1 + apps/simplyclock/icon.png | Bin 0 -> 279 bytes 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 apps/simplyclock/ChangeLog create mode 100644 apps/simplyclock/app.js create mode 100644 apps/simplyclock/icon.js create mode 100644 apps/simplyclock/icon.png diff --git a/apps.json b/apps.json index f187ff3d67..7a5849281d 100644 --- a/apps.json +++ b/apps.json @@ -4101,5 +4101,20 @@ {"name":"gpstouch.app.js","url":"gpstouch.app.js"}, {"name":"gpstouch.img","url":"gpstouch.icon.js","evaluate":true} ] + }, + { + "id": "simplyclock", + "name": "Simply Clock", + "version": "0.01", + "description": "Just simply clock", + "icon": "icon.png", + "type": "clock", + "tags": "clock", + "allow_emulator": true, + "supports": ["BANGLEJS"], + "storage": [ + {"name":"simplyclock.app.js","url":"app.js"}, + {"name":"simplyclock.img","url":"icon.js","evaluate":true} + ] } ] diff --git a/apps/gpstouch/gpstouch.app.js b/apps/gpstouch/gpstouch.app.js index 0425cdc231..cac19cdef2 100644 --- a/apps/gpstouch/gpstouch.app.js +++ b/apps/gpstouch/gpstouch.app.js @@ -196,7 +196,7 @@ function prevInfo() { } Bangle.on('swipe', dir => { - if (dir == 1) prevInfo() else nextInfo(); + if (dir == 1) prevInfo(); else nextInfo(); draw(); }); diff --git a/apps/simplyclock/ChangeLog b/apps/simplyclock/ChangeLog new file mode 100644 index 0000000000..59e6934ed3 --- /dev/null +++ b/apps/simplyclock/ChangeLog @@ -0,0 +1 @@ +0.01: Init App diff --git a/apps/simplyclock/app.js b/apps/simplyclock/app.js new file mode 100644 index 0000000000..1919822a61 --- /dev/null +++ b/apps/simplyclock/app.js @@ -0,0 +1,90 @@ +function main() { + require("Font7x11Numeric7Seg").add(Graphics); + var nightMode = false; + var forceDraw = true; + var width = g.getWidth(); + var size = Math.floor(width / (7*6)); + var x = (width / 2) - size * 6, + y = (g.getHeight()/2) - size*7; + + function draw() { + var d = new Date(); + g.reset(); + if (nightMode) { + g.setColor("#ff1100"); + } + + g.setFont("7x11Numeric7Seg",size).setFontAlign(1,-1); + if ((d.getMinutes() == 0 && d.getSeconds() == 0) || forceDraw) { + g.clearRect(x - size * 9, y, x - size , y + size * 11); + g.drawString(d.getHours(), x, y); + } + + g.setFontAlign(-1,-1); + + if (d.getSeconds() % 2 == 0) g.drawString(":", x,y); + else g.clearRect(x, y, x + size *4, y + size * 12); + + if (d.getSeconds() == 0|| forceDraw) { + g.clearRect(x + size *4 , y, x + size * 17 , y + size * 11); + g.drawString(("0"+d.getMinutes()).substr(-2),x+size*4,y); + } + + // draw seconds + g.setFont("7x11Numeric7Seg",size/2); + g.clearRect(x+size*18,y + size*7,x+size*18 + size *8 ,y + size*12 ); + g.drawString(("0"+d.getSeconds()).substr(-2),x+size*18,y + size*7); + + if ((d.getHours() == 0 && d.getMinutes() == 0) || forceDraw) { + // date + var date = d.toString().split(" "); + g.setFont("6x8", size/1.5).setFontAlign(0,-1); + g.clearRect(width/4, y + size * 16, width/ 1.33 , y + size * 20); + g.drawString(date[2] + " " + date[1], width / 2 , y + size * 16); + } + + + if ((d.getMinutes() % 2 == 0 && d.getSeconds() == 0) || forceDraw) { + var bat = E.getBattery(); + var color = bat <= 20 || nightMode ? "#ff1100" : "#ffffff"; + + if (Bangle.isCharging()) { + color ="#ffc413"; + } + + g.setColor(color); + g.setFont("6x8", size/1.5).setFontAlign(0,-1); + g.clearRect(0, y - size * 10, width , y - size * 6); + g.drawString(bat + "%", width / 8 + 10, y - size * 10); + } + forceDraw = false; + } + + // Only update when display turns on + if (process.env.BOARD!="SMAQ3") // hack for Q3 which is always-on + Bangle.on('lcdPower', function(on) { + if (secondInterval) clearInterval(secondInterval); + if (on) { + forceDraw = true; + secondInterval = setInterval(draw, 1000); + } + draw(); + }); + + setWatch(() => { + nightMode = !nightMode; + if (nightMode) Bangle.setLCDBrightness(0.2); + else Bangle.setLCDBrightness(1); + forceDraw = true; + draw(); // needed for update color + }, BTN1, {edge:"rising", debounce:50, repeat:true}); + + g.clear(); + var secondInterval = setInterval(draw, 1000); + draw(); + // Show launcher when button pressed + Bangle.setUI("clock"); + Bangle.loadWidgets(); + Bangle.drawWidgets(); +} +main(); \ No newline at end of file diff --git a/apps/simplyclock/icon.js b/apps/simplyclock/icon.js new file mode 100644 index 0000000000..d5d9aaf682 --- /dev/null +++ b/apps/simplyclock/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mUygP/AC5BlH4MAn/gAwN/4EP/AFBsEMhkBwEAjEDgYJBgEGgHA4EYDwOAmEwBIIYyj/wgf+AoMH/kA/4eBJXwYLVxgAjh//AC3w")) diff --git a/apps/simplyclock/icon.png b/apps/simplyclock/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cb08aec5e1b88cbd097bd451c072ec7c04d3bea9 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-wj^(N7l!{JxM1({$v}}ao-U3d z8I5nJU*u{w5OK~wzAvjZ-u~~px328fnZ=O@Zai~1*e;N-byXs<=jBG%BflSI>;69a zbmv@K25$Di Date: Fri, 29 Oct 2021 11:31:35 +0200 Subject: [PATCH 02/13] fix: best clear hours --- apps/simplyclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/simplyclock/app.js b/apps/simplyclock/app.js index 1919822a61..47be46c3e9 100644 --- a/apps/simplyclock/app.js +++ b/apps/simplyclock/app.js @@ -16,7 +16,7 @@ function main() { g.setFont("7x11Numeric7Seg",size).setFontAlign(1,-1); if ((d.getMinutes() == 0 && d.getSeconds() == 0) || forceDraw) { - g.clearRect(x - size * 9, y, x - size , y + size * 11); + g.clearRect(x - size * 14, y, x - size , y + size * 11); g.drawString(d.getHours(), x, y); } From e1ad455544ee7d8183503d1ba5fcd90583e70798 Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Fri, 29 Oct 2021 11:34:04 +0200 Subject: [PATCH 03/13] feat: update simplyclock version --- apps.json | 2 +- apps/simplyclock/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7a5849281d..4d7b6b480c 100644 --- a/apps.json +++ b/apps.json @@ -4105,7 +4105,7 @@ { "id": "simplyclock", "name": "Simply Clock", - "version": "0.01", + "version": "0.02", "description": "Just simply clock", "icon": "icon.png", "type": "clock", diff --git a/apps/simplyclock/ChangeLog b/apps/simplyclock/ChangeLog index 59e6934ed3..579206d569 100644 --- a/apps/simplyclock/ChangeLog +++ b/apps/simplyclock/ChangeLog @@ -1 +1,2 @@ 0.01: Init App +0.02: Fix clear hours \ No newline at end of file From 5fafe97fb5494a5e497c33633cfcf2c01db02852 Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Tue, 21 Dec 2021 18:04:19 +0100 Subject: [PATCH 04/13] feat: add music management --- apps/simplyclock/app.js | 233 ++++++++++++++++++++++++++++++---------- 1 file changed, 174 insertions(+), 59 deletions(-) diff --git a/apps/simplyclock/app.js b/apps/simplyclock/app.js index 47be46c3e9..18bbaaf280 100644 --- a/apps/simplyclock/app.js +++ b/apps/simplyclock/app.js @@ -1,90 +1,205 @@ +var modeUi = "watch"; +var WIDTH = g.getWidth(); +var SIZE = Math.floor(WIDTH / (7*6)); +var watchUiState = { + nightMode: false, + forceDraw: true, + width: WIDTH, + size: SIZE, + x: (WIDTH / 2) - SIZE * 6, + y: (g.getHeight()/2) - SIZE *7 +} +var stat = "play"; +var doubleTouch = false; +var lastAction; +var actionTimeout; +var drawInterval; + function main() { require("Font7x11Numeric7Seg").add(Graphics); - var nightMode = false; - var forceDraw = true; - var width = g.getWidth(); - var size = Math.floor(width / (7*6)); - var x = (width / 2) - size * 6, - y = (g.getHeight()/2) - size*7; + + // Only update when display turns on + if (process.env.BOARD!="SMAQ3") // hack for Q3 which is always-on + + g.clear(); + drawLoop(1000); + Bangle.setUI("clock"); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + + listenEvent(); +} - function draw() { - var d = new Date(); - g.reset(); - if (nightMode) { - g.setColor("#ff1100"); - } - g.setFont("7x11Numeric7Seg",size).setFontAlign(1,-1); - if ((d.getMinutes() == 0 && d.getSeconds() == 0) || forceDraw) { +function drawWatch() { + var d = new Date(); + var x = watchUiState.x; + var y = watchUiState.y; + var size = watchUiState.size; + var width = watchUiState.width; + + g.reset(); + if (watchUiState.nightMode) { + g.setColor("#ff1100"); + } + + g.setFont("7x11Numeric7Seg",size).setFontAlign(1,-1); + if ((d.getMinutes() == 0 && d.getSeconds() == 0) || watchUiState.forceDraw) { g.clearRect(x - size * 14, y, x - size , y + size * 11); g.drawString(d.getHours(), x, y); - } - - g.setFontAlign(-1,-1); - - if (d.getSeconds() % 2 == 0) g.drawString(":", x,y); - else g.clearRect(x, y, x + size *4, y + size * 12); - - if (d.getSeconds() == 0|| forceDraw) { - g.clearRect(x + size *4 , y, x + size * 17 , y + size * 11); - g.drawString(("0"+d.getMinutes()).substr(-2),x+size*4,y); - } - - // draw seconds - g.setFont("7x11Numeric7Seg",size/2); - g.clearRect(x+size*18,y + size*7,x+size*18 + size *8 ,y + size*12 ); - g.drawString(("0"+d.getSeconds()).substr(-2),x+size*18,y + size*7); - - if ((d.getHours() == 0 && d.getMinutes() == 0) || forceDraw) { + } + + g.setFontAlign(-1,-1); + + if (d.getSeconds() % 2 == 0) g.drawString(":", x,y); + else g.clearRect(x, y, x + size *4, y + size * 12); + + if (d.getSeconds() == 0|| watchUiState.forceDraw) { + g.clearRect(x + size *4 , y, x + size * 17 , y + size * 11); + g.drawString(("0"+d.getMinutes()).substr(-2),x+size*4,y); + } + + // draw seconds + g.setFont("7x11Numeric7Seg",size/2); + g.clearRect(x+size*18,y + size*7,x+size*18 + size *8 ,y + size*12 ); + g.drawString(("0"+d.getSeconds()).substr(-2),x+size*18,y + size*7); + + if ((d.getHours() == 0 && d.getMinutes() == 0) || watchUiState.forceDraw) { // date var date = d.toString().split(" "); g.setFont("6x8", size/1.5).setFontAlign(0,-1); g.clearRect(width/4, y + size * 16, width/ 1.33 , y + size * 20); g.drawString(date[2] + " " + date[1], width / 2 , y + size * 16); - } - - - if ((d.getMinutes() % 2 == 0 && d.getSeconds() == 0) || forceDraw) { + } + + + if ((d.getMinutes() % 2 == 0 && d.getSeconds() == 0) || watchUiState.forceDraw) { var bat = E.getBattery(); - var color = bat <= 20 || nightMode ? "#ff1100" : "#ffffff"; - + var color = bat <= 20 || watchUiState.nightMode ? "#ff1100" : "#ffffff"; + if (Bangle.isCharging()) { color ="#ffc413"; } - + g.setColor(color); g.setFont("6x8", size/1.5).setFontAlign(0,-1); g.clearRect(0, y - size * 10, width , y - size * 6); g.drawString(bat + "%", width / 8 + 10, y - size * 10); + } + + g.clearRect(width * 0.30, y - size * 10 , width ,y - size * 2); + if (lastAction && !lastAction.startsWith("volume")) { + g.setFont("6x8", size/1.5).setFontAlign(0,-1); + g.drawString(lastAction, width * 0.68, y - size * 10); + } + watchUiState.forceDraw = false; +} + +function drawVolume() { + g.reset(); + g.setFont("6x8", SIZE / 1.5).setFontAlign(-1,-1); + + g.drawString("Volume", WIDTH / 4, watchUiState.y - SIZE * 5); + + g.setFont("6x8", SIZE * 1.5).setFontAlign(0,-1); + + g.drawString("-", WIDTH / 4, watchUiState.y + SIZE * 3); + g.drawString("+", WIDTH / 2 + WIDTH /4, watchUiState.y + SIZE * 3); + + g.clearRect(WIDTH/6, watchUiState.y + SIZE * 16, WIDTH , watchUiState.y + SIZE * 21); + if (lastAction) { + if (lastAction == "volumeup") { + g.setFont("6x8", SIZE / 1.5).setFontAlign(-1,-1); + g.drawString("Volume up", WIDTH / 5, watchUiState.y + SIZE * 16); + } + else if (lastAction == "volumedown") { + g.setFont("6x8", SIZE / 1.5).setFontAlign(-1,-1); + g.drawString("Volume down", WIDTH / 6, watchUiState.y + SIZE * 16); } - forceDraw = false; } +} - // Only update when display turns on - if (process.env.BOARD!="SMAQ3") // hack for Q3 which is always-on +function draw() { + if (modeUi == "volume") { + drawVolume(); + } else { + drawWatch(); + } +} + + +function listenEvent() { + setWatch(() => { + if (modeUi == "volume") { return; } + + watchUiState.nightMode = !watchUiState.nightMode; + if (watchUiState.nightMode) Bangle.setLCDBrightness(0.2); + else Bangle.setLCDBrightness(1); + + watchUiState.forceDraw = true; + drawWatch(); // needed for update color + }, BTN1, {edge:"rising", debounce:50, repeat:true}); + + setWatch(() => { + modeUi = modeUi == "watch" ? "volume" : "watch"; + watchUiState.forceDraw = true; + g.clearRect(0, watchUiState.y - SIZE * 10, WIDTH, g.getHeight()); + drawLoop(1000); + }, BTN3, {edge:"rising", debounce: 50, repeat:true}); + + setWatch(() => { + if (modeUi != "volume") { + if (BTN5.read()) { + togglePlay(); + setAction(stat); + doubleTouch = true; + setTimeout(() => doubleTouch = false, 200); + } else { + setAction("previous"); + } + } else { + setAction("volumedown"); + } + }, BTN4, {edge:"rising", debounce: 50, repeat:true}); + + setWatch(() => { + if (modeUi != "volume") { + if (doubleTouch) return; + setAction("next"); + + } else { + setAction("volumeup"); + } + }, BTN5, {edge:"rising", debounce: 50, repeat:true}); + Bangle.on('lcdPower', function(on) { - if (secondInterval) clearInterval(secondInterval); + if (drawInterval) clearInterval(drawInterval); + g.clearRect(0, watchUiState.y - SIZE * 10, WIDTH, g.getHeight()); if (on) { - forceDraw = true; - secondInterval = setInterval(draw, 1000); + modeUi = "watch"; + watchUiState.forceDraw = true; + drawLoop(1000); } - draw(); }); +} - setWatch(() => { - nightMode = !nightMode; - if (nightMode) Bangle.setLCDBrightness(0.2); - else Bangle.setLCDBrightness(1); - forceDraw = true; - draw(); // needed for update color - }, BTN1, {edge:"rising", debounce:50, repeat:true}); +function togglePlay() { + stat = (stat==="play" ? "pause" : "play"); +} - g.clear(); - var secondInterval = setInterval(draw, 1000); +function setAction(action) { + if (actionTimeout) clearTimeout(actionTimeout); + actionTimeout = setTimeout(() => lastAction = null, 1000); + lastAction = action; + + Bluetooth.println(JSON.stringify({t:"music", n: action})); draw(); - // Show launcher when button pressed - Bangle.setUI("clock"); - Bangle.loadWidgets(); - Bangle.drawWidgets(); } + +function drawLoop(time) { + if (drawInterval) clearInterval(drawInterval); + drawInterval = setInterval(draw, time); + draw(); +} + main(); \ No newline at end of file From 76172bcc3c82e5d280c6b55b93b7a73975352bd7 Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Tue, 21 Dec 2021 18:05:25 +0100 Subject: [PATCH 05/13] feat: update version --- apps.json | 2 +- apps/simplyclock/ChangeLog | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4d7b6b480c..7f4314b291 100644 --- a/apps.json +++ b/apps.json @@ -4105,7 +4105,7 @@ { "id": "simplyclock", "name": "Simply Clock", - "version": "0.02", + "version": "1.01", "description": "Just simply clock", "icon": "icon.png", "type": "clock", diff --git a/apps/simplyclock/ChangeLog b/apps/simplyclock/ChangeLog index 579206d569..7cbedbecb4 100644 --- a/apps/simplyclock/ChangeLog +++ b/apps/simplyclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: Init App -0.02: Fix clear hours \ No newline at end of file +0.02: Fix clear hours +1.01: Add music management \ No newline at end of file From 0e656faea5eef9992d3ef7f003d492634c9e8a11 Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Wed, 22 Dec 2021 15:18:36 +0100 Subject: [PATCH 06/13] init app custome gadget bridge --- apps.json | 14 ++ apps/customgadgetbridge/ChangeLog | 1 + apps/customgadgetbridge/README.md | 137 +++++++++++++++++ apps/customgadgetbridge/boot.js | 143 ++++++++++++++++++ .../customgadgetbridge/customGadgetBridge.png | Bin 0 -> 4133 bytes apps/customgadgetbridge/icon.js | 1 + apps/customgadgetbridge/settings.js | 13 ++ 7 files changed, 309 insertions(+) create mode 100644 apps/customgadgetbridge/ChangeLog create mode 100644 apps/customgadgetbridge/README.md create mode 100644 apps/customgadgetbridge/boot.js create mode 100644 apps/customgadgetbridge/customGadgetBridge.png create mode 100644 apps/customgadgetbridge/icon.js create mode 100644 apps/customgadgetbridge/settings.js diff --git a/apps.json b/apps.json index e5e9f8f027..2f4ee00962 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,19 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "cgb", + "name": "Custom Gadget Bridge", + "version": "0.01", + "description": "A custom implementation of gadget bridge", + "icon": "customgadgetbridge.png", + "type": "bootloader", + "tags": "tools, system", + "supports": ["BANGLEJS"], + "storage": [ + {"name":"customgadgetbridge.boot.js","url":"boot.js"}, + {"name":"customgadgetbridge.img","url":"icon.js","evaluate":true} + ] } ] diff --git a/apps/customgadgetbridge/ChangeLog b/apps/customgadgetbridge/ChangeLog new file mode 100644 index 0000000000..5560f00bce --- /dev/null +++ b/apps/customgadgetbridge/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/customgadgetbridge/README.md b/apps/customgadgetbridge/README.md new file mode 100644 index 0000000000..24e9b940af --- /dev/null +++ b/apps/customgadgetbridge/README.md @@ -0,0 +1,137 @@ +# Custom Gadget Bridge + +Manage event of gadget bridge (alternative to Android bangle app). +Dispatch many event in bangle and another app can listen here events + +## How to install in my app +```js +// apps.json +{ + "id": "myapp", + "name": "My app", + "shortName": "app", + "version": "0.01", + "description": "bip bip", + "dependencies": { "cgb": "app" }, +} + +// myapp/app.js +global.GadgetBridge.onEvent("notify", (event) => { + // Your code +}); +``` + +## Features + +### Api describe +```ts +global.GadgetBridge: { + onEvent(eventName: EventName, callback: Callback, option?: Option) + removeEventListener(eventName: EventName, callback: Callback) + sendEvent(message: string) + musicControl(command: string) // play/pause/next/previous/volumeup/volumedown + messageResponse(msg: Object, opened: boolean) // opened true or false, msg is the message to which you wish to reply + callResponse(call: Object, accepted: boolean) // accepted true or false, call is the call to which you wish to reply +} + +type EventName = String; // See list of events +interface Callback { + (event: any, stopPropagation: () => void): void +} +interface Option { + layer: number // default Infinity +} +``` + +List of events: +- notify +- find +- musicstate +- musicinfo +- call +- connect +- disconnect + +### Default Features + - Send Health tracking to GadgetBridge + - Send Battery status to GadgetBridge + - Vibration on find event (It can be disabled, see stop propagations part) + +## Exemples + +For listen a gadgetbridge event : +```js +// file boot.js +function boot() { + global.GadgetBridge.onEvent("notify", (event) => { + // Your code + }); +} +setTimeout(boot, 1000); // Necessary to make sure that all are well loaded +``` + +For stop listening + +```js +// file boot.js +function boot() { + var onNotify = (event) => { + // Your code + }; + global.GadgetBridge.onEvent("notify", onNotify); + global.GadgetBridge.removeEventListener("notify", onNotify); +} +setTimeout(boot, 1000); +``` + +### To Know + +Event manager sort callback by layer. If you want start your callback behind another you must add lower layer. + +For exemple: +```js +// file boot.js +function boot() { + global.GadgetBridge.onEvent("notify", (event) => { + console.log("from boot.js"); + }, { layer: 2 }); +} +setTimeout(boot, 1000); + +// file another.boot.js +function boot() { + global.GadgetBridge.onEvent("notify", (event) => { + console.log("from another.boot.js"); + }, { layer: 1 }); +} +setTimeout(boot, 1000); + +// logs +// -> "from another.boot.js" +// -> "from boot.js" +``` + +Event manager also proposes to stop the propagation (callbacks with a higher layer will not be called). This is useful if you want to disable another behavior + +For exemple: +```js +// file boot.js +function boot() { + global.GadgetBridge.onEvent("notify", (event) => { + console.log("It's never call"); + }, { layer: 2 }); +} +setTimeout(boot, 1000); + +// file another.boot.js +function boot() { + global.GadgetBridge.onEvent("notify", (event, stopPropagation) => { + console.log("from another.boot.js"); + stopPropagation(); + }, { layer: 1 }); +} +setTimeout(boot, 1000); + +// logs +// -> "from another.boot.js" +``` \ No newline at end of file diff --git a/apps/customgadgetbridge/boot.js b/apps/customgadgetbridge/boot.js new file mode 100644 index 0000000000..b3bd107efc --- /dev/null +++ b/apps/customgadgetbridge/boot.js @@ -0,0 +1,143 @@ +(function() { + var onCallbacks = {}; + + function dispatchEvent(eventName, data) { + if (!onCallbacks[eventName]) { + console.log(eventName + " not found in callbacks"); + return; + } + var stop = false; + const stopCallback = () => stop = true; + + onCallbacks[eventName].forEach(eventCallback => { + if (stop) return; + console.log(stop); + eventCallback.callback(data, stopCallback); + }); + } + + // Disposed public API + global.GadgetBridge = { + send: (message) => { + Bluetooth.println(""); + Bluetooth.println(JSON.stringify(message)); + }, + onEvent: (eventName, callback, option = {}) => { + if (!option) { + option = {}; + } + if (!onCallbacks[eventName]) { + onCallbacks[eventName] = []; + } + if (!option.layer) option.layer = Infinity; + + onCallbacks[eventName].push({callback: callback, layer: option.layer}); + onCallbacks[eventName].sort((a, b) => a.layer - b.layer); + }, + removeEventListener: (eventName, callback) => { + if (!onCallbacks[eventName]) return; + + const index = onCallbacks[eventName].findIndex(event => event.callback === callback); + if (index == -1) return; + onCallbacks[eventName].splice(index, 1); + }, + musicControl: cmd => { + // play/pause/next/previous/volumeup/volumedown + global.GadgetBridge.send({ t: "music", n:cmd }); + }, + messageResponse: (msg, response) => { + if (!isFinite(msg.id)) return; + global.GadgetBridge.send({ t: "notify", n:response ? "OPEN" : "DISMISS", id: msg.id }); + }, + + findPhone: (search) => { + global.GadgetBridge.send({ t: "findPhone", n: search}) + }, + // Call response + callResponse: (msg, response) => { + if (msg.id != "call") return; + global.GadgetBridge.send({ t: "call", n:response ? "ACCEPT" : "REJECT" }); + }, + "__private__" : { // Just for debbuging in WebIde + dispatchEvent: dispatchEvent + } + }; + + NRF.on("connect", () => dispatchEvent("connect", {})); + NRF.on("disconnect", () => dispatchEvent("disconnect", {})); + + var HANDLERS = { + // {t:"notify",id:int, src,title,subject,body,sender,tel:string} add + "notify" : function(event) { + dispatchEvent("notify", Object.assign(event, { t: "add", positive: true, negative: true })); + }, + // {t:"notify~",id:int, title:string} // modified + "notify~" : function(event) { + event.t = "modify"; + dispatchEvent("notify", event); + }, + // {t:"notify-",id:int} // remove + "notify-" : function(event) { + event.t = "remove"; + dispatchEvent("notify", event); + }, + // {t:"find", n:bool} // find my phone + "find" : (event) => dispatchEvent("find", event), + // {t:"musicstate", state:"play/pause",position,shuffle,repeat} + "musicstate" : function(event) { + dispatchEvent("musicstate", { t: "modify", id: "music", title: "Music", state: event.state }); + }, + // {t:"musicinfo", artist,album,track,dur,c(track count),n(track num} + "musicinfo" : function(event) { + dispatchEvent("musicinfo", Object.assign(event, { t: "modify", id: "music", title: "Music" })); + }, + // {"t":"call","cmd":"incoming/end","name":"Bob","number":"12421312"}) + "call" : function(event) { + dispatchEvent("call", Object.assign(event, + { + t: event.cmd == "incoming", + id:"call", + src:"Phone", + positive:true, + negative:true, + title:event.name || "Call", + body:"Incoming call\n"+event.number + } + )); + }, + }; + + var _GB = global.GB; + global.GB = (event) => { + // feed a copy to other handlers if there were any + if (_GB) setTimeout(_GB,0,Object.assign({},event)); + + var handler = HANDLERS[event.t]; + if (handler) handler(event); + else dispatchEvent(event.t, event); + }; + + /* -- Features GagdetBridge implementation -- */ + + // Battery monitor + function sendBattery() { + global.GadgetBridge.send({ t: "status", bat: E.getBattery() }); + } + setInterval(sendBattery, 10*60*1000); + global.GadgetBridge.onEvent("connect", () => setTimeout(sendBattery, 2000), { layer: 0 }); + + // Health tracking + Bangle.on('health', health=>{ + global.GadgetBridge.send({ t: "act", stp: health.steps, hrm: health.bpm }); + }); + + // Find event + global.GadgetBridge.onEvent("find", (event) => { + if (Bangle.findDeviceInterval) { + clearInterval(Bangle.findDeviceInterval); + delete Bangle.findDeviceInterval; + } + if (event.n) // Ignore quiet mode: we always want to find our watch + Bangle.findDeviceInterval = setInterval( _ => Bangle.buzz(), 1000); + }); +})(); diff --git a/apps/customgadgetbridge/customGadgetBridge.png b/apps/customgadgetbridge/customGadgetBridge.png new file mode 100644 index 0000000000000000000000000000000000000000..6618c1d2957e8b486b3509192af055963bc36297 GIT binary patch literal 4133 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 literal 0 HcmV?d00001 diff --git a/apps/customgadgetbridge/icon.js b/apps/customgadgetbridge/icon.js new file mode 100644 index 0000000000..1b71a8ddfe --- /dev/null +++ b/apps/customgadgetbridge/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("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")); \ No newline at end of file diff --git a/apps/customgadgetbridge/settings.js b/apps/customgadgetbridge/settings.js new file mode 100644 index 0000000000..c4333983a1 --- /dev/null +++ b/apps/customgadgetbridge/settings.js @@ -0,0 +1,13 @@ +(function(back) { + E.showMenu({ + "" : { "title" : "Custom GadgetBridge" }, + "< Back" : back, + "Connected" : { value : NRF.getSecurityStatus().connected? "Yes" : "No"}, + "Find Phone" : () => E.showMenu({ + "" : { "title" : "Find Phone" }, + "< Back" : ()=>E.showMenu(mainmenu), + "On" : _=> global.GadgetBridge.findPhone(true), + "Off" : _=> global.GadgetBridge.findPhone(false), + }), + }); +}) From c1b71cd0c86d61a8b705b792b5de4b04801e6f3a Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Wed, 22 Dec 2021 15:24:22 +0100 Subject: [PATCH 07/13] feat: change folder name --- apps/{customgadgetbridge => cgb}/ChangeLog | 0 apps/{customgadgetbridge => cgb}/README.md | 0 apps/{customgadgetbridge => cgb}/boot.js | 0 .../customgadgetbridge.png} | Bin apps/{customgadgetbridge => cgb}/icon.js | 0 apps/{customgadgetbridge => cgb}/settings.js | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename apps/{customgadgetbridge => cgb}/ChangeLog (100%) rename apps/{customgadgetbridge => cgb}/README.md (100%) rename apps/{customgadgetbridge => cgb}/boot.js (100%) rename apps/{customgadgetbridge/customGadgetBridge.png => cgb/customgadgetbridge.png} (100%) rename apps/{customgadgetbridge => cgb}/icon.js (100%) rename apps/{customgadgetbridge => cgb}/settings.js (100%) diff --git a/apps/customgadgetbridge/ChangeLog b/apps/cgb/ChangeLog similarity index 100% rename from apps/customgadgetbridge/ChangeLog rename to apps/cgb/ChangeLog diff --git a/apps/customgadgetbridge/README.md b/apps/cgb/README.md similarity index 100% rename from apps/customgadgetbridge/README.md rename to apps/cgb/README.md diff --git a/apps/customgadgetbridge/boot.js b/apps/cgb/boot.js similarity index 100% rename from apps/customgadgetbridge/boot.js rename to apps/cgb/boot.js diff --git a/apps/customgadgetbridge/customGadgetBridge.png b/apps/cgb/customgadgetbridge.png similarity index 100% rename from apps/customgadgetbridge/customGadgetBridge.png rename to apps/cgb/customgadgetbridge.png diff --git a/apps/customgadgetbridge/icon.js b/apps/cgb/icon.js similarity index 100% rename from apps/customgadgetbridge/icon.js rename to apps/cgb/icon.js diff --git a/apps/customgadgetbridge/settings.js b/apps/cgb/settings.js similarity index 100% rename from apps/customgadgetbridge/settings.js rename to apps/cgb/settings.js From 6bfe2a6153a982275bef2cc6a24dac4880fa6d3c Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Wed, 22 Dec 2021 15:37:53 +0100 Subject: [PATCH 08/13] feat: add readme in config --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 2f4ee00962..ded78b9a5b 100644 --- a/apps.json +++ b/apps.json @@ -5072,6 +5072,7 @@ "type": "bootloader", "tags": "tools, system", "supports": ["BANGLEJS"], + "readme": "README.md", "storage": [ {"name":"customgadgetbridge.boot.js","url":"boot.js"}, {"name":"customgadgetbridge.img","url":"icon.js","evaluate":true} From ef163fcaf3a9439d856da9430c26e8a93973da5e Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Wed, 22 Dec 2021 16:59:17 +0100 Subject: [PATCH 09/13] feat: add health battery and find app --- apps.json | 27 ++++++++++++++---- apps/cgb/settings.js | 13 --------- apps/{cgb => omgbc}/ChangeLog | 0 apps/{cgb => omgbc}/README.md | 9 ++---- apps/{cgb => omgbc}/boot.js | 24 ---------------- apps/{cgb => omgbc}/icon.js | 0 apps/omgbc/settings.js | 7 +++++ apps/omgbhbf/ChangeLog | 1 + apps/omgbhbf/README.md | 7 +++++ apps/omgbhbf/boot.js | 26 +++++++++++++++++ apps/omgbhbf/icon.js | 1 + .../omgbhbf.png} | Bin apps/omgbhbf/settings.js | 9 ++++++ 13 files changed, 74 insertions(+), 50 deletions(-) delete mode 100644 apps/cgb/settings.js rename apps/{cgb => omgbc}/ChangeLog (100%) rename apps/{cgb => omgbc}/README.md (88%) rename apps/{cgb => omgbc}/boot.js (83%) rename apps/{cgb => omgbc}/icon.js (100%) create mode 100644 apps/omgbc/settings.js create mode 100644 apps/omgbhbf/ChangeLog create mode 100644 apps/omgbhbf/README.md create mode 100644 apps/omgbhbf/boot.js create mode 100644 apps/omgbhbf/icon.js rename apps/{cgb/customgadgetbridge.png => omgbhbf/omgbhbf.png} (100%) create mode 100644 apps/omgbhbf/settings.js diff --git a/apps.json b/apps.json index ded78b9a5b..6a19ca70eb 100644 --- a/apps.json +++ b/apps.json @@ -5064,18 +5064,33 @@ ] }, { - "id": "cgb", - "name": "Custom Gadget Bridge", + "id": "omgbc", + "name": "Oh My Gadget Bridge Core", "version": "0.01", - "description": "A custom implementation of gadget bridge", - "icon": "customgadgetbridge.png", + "description": "A custom implementation of gadget bridge, expose an API for other app", "type": "bootloader", "tags": "tools, system", "supports": ["BANGLEJS"], "readme": "README.md", "storage": [ - {"name":"customgadgetbridge.boot.js","url":"boot.js"}, - {"name":"customgadgetbridge.img","url":"icon.js","evaluate":true} + {"name":"omgbc.boot.js","url":"boot.js"}, + {"name":"omgbc.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "omgbhbf", + "name": "Oh My Gadget Bridge (Health, Battery, Find)", + "version": "0.01", + "description": "Implement Health, Battery, Find", + "icon": "omgbhbf.png", + "type": "bootloader", + "tags": "tools, system", + "supports": ["BANGLEJS"], + "dependencies": {"omgbc":"app"}, + "readme": "README.md", + "storage": [ + {"name":"omgbhbf.boot.js","url":"boot.js"}, + {"name":"omgbhbf.img","url":"icon.js","evaluate":true} ] } ] diff --git a/apps/cgb/settings.js b/apps/cgb/settings.js deleted file mode 100644 index c4333983a1..0000000000 --- a/apps/cgb/settings.js +++ /dev/null @@ -1,13 +0,0 @@ -(function(back) { - E.showMenu({ - "" : { "title" : "Custom GadgetBridge" }, - "< Back" : back, - "Connected" : { value : NRF.getSecurityStatus().connected? "Yes" : "No"}, - "Find Phone" : () => E.showMenu({ - "" : { "title" : "Find Phone" }, - "< Back" : ()=>E.showMenu(mainmenu), - "On" : _=> global.GadgetBridge.findPhone(true), - "Off" : _=> global.GadgetBridge.findPhone(false), - }), - }); -}) diff --git a/apps/cgb/ChangeLog b/apps/omgbc/ChangeLog similarity index 100% rename from apps/cgb/ChangeLog rename to apps/omgbc/ChangeLog diff --git a/apps/cgb/README.md b/apps/omgbc/README.md similarity index 88% rename from apps/cgb/README.md rename to apps/omgbc/README.md index 24e9b940af..28682caf21 100644 --- a/apps/cgb/README.md +++ b/apps/omgbc/README.md @@ -1,4 +1,4 @@ -# Custom Gadget Bridge +# Oh My Gadget Bridge Core Manage event of gadget bridge (alternative to Android bangle app). Dispatch many event in bangle and another app can listen here events @@ -12,7 +12,7 @@ Dispatch many event in bangle and another app can listen here events "shortName": "app", "version": "0.01", "description": "bip bip", - "dependencies": { "cgb": "app" }, + "dependencies": { "omgbc": "app" }, } // myapp/app.js @@ -52,11 +52,6 @@ List of events: - connect - disconnect -### Default Features - - Send Health tracking to GadgetBridge - - Send Battery status to GadgetBridge - - Vibration on find event (It can be disabled, see stop propagations part) - ## Exemples For listen a gadgetbridge event : diff --git a/apps/cgb/boot.js b/apps/omgbc/boot.js similarity index 83% rename from apps/cgb/boot.js rename to apps/omgbc/boot.js index b3bd107efc..1095cad932 100644 --- a/apps/cgb/boot.js +++ b/apps/omgbc/boot.js @@ -116,28 +116,4 @@ if (handler) handler(event); else dispatchEvent(event.t, event); }; - - /* -- Features GagdetBridge implementation -- */ - - // Battery monitor - function sendBattery() { - global.GadgetBridge.send({ t: "status", bat: E.getBattery() }); - } - setInterval(sendBattery, 10*60*1000); - global.GadgetBridge.onEvent("connect", () => setTimeout(sendBattery, 2000), { layer: 0 }); - - // Health tracking - Bangle.on('health', health=>{ - global.GadgetBridge.send({ t: "act", stp: health.steps, hrm: health.bpm }); - }); - - // Find event - global.GadgetBridge.onEvent("find", (event) => { - if (Bangle.findDeviceInterval) { - clearInterval(Bangle.findDeviceInterval); - delete Bangle.findDeviceInterval; - } - if (event.n) // Ignore quiet mode: we always want to find our watch - Bangle.findDeviceInterval = setInterval( _ => Bangle.buzz(), 1000); - }); })(); diff --git a/apps/cgb/icon.js b/apps/omgbc/icon.js similarity index 100% rename from apps/cgb/icon.js rename to apps/omgbc/icon.js diff --git a/apps/omgbc/settings.js b/apps/omgbc/settings.js new file mode 100644 index 0000000000..769862233f --- /dev/null +++ b/apps/omgbc/settings.js @@ -0,0 +1,7 @@ +(function(back) { + E.showMenu({ + "" : { "title" : "Custom GadgetBridge" }, + "< Back" : back, + "Connected" : { value : NRF.getSecurityStatus().connected? "Yes" : "No"}, + }); +}) diff --git a/apps/omgbhbf/ChangeLog b/apps/omgbhbf/ChangeLog new file mode 100644 index 0000000000..5560f00bce --- /dev/null +++ b/apps/omgbhbf/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/omgbhbf/README.md b/apps/omgbhbf/README.md new file mode 100644 index 0000000000..3a10f68953 --- /dev/null +++ b/apps/omgbhbf/README.md @@ -0,0 +1,7 @@ +# Oh My Gadget Bridge (Health, Battery, Find) + +### Default Features + - Send Health tracking to GadgetBridge + - Send Battery status to GadgetBridge + - Vibration on find event (It can be disabled, see stop propagations part) + - Send Find my phone event to GadgetBridge diff --git a/apps/omgbhbf/boot.js b/apps/omgbhbf/boot.js new file mode 100644 index 0000000000..69f26a0710 --- /dev/null +++ b/apps/omgbhbf/boot.js @@ -0,0 +1,26 @@ +(function() { + function boot() { + // Battery monitor + function sendBattery() { + global.GadgetBridge.send({ t: "status", bat: E.getBattery() }); + } + setInterval(sendBattery, 10*60*1000); + global.GadgetBridge.onEvent("connect", () => setTimeout(sendBattery, 2000), { layer: 0 }); + + // Health tracking + Bangle.on('health', health => { + global.GadgetBridge.send({ t: "act", stp: health.steps, hrm: health.bpm }); + }); + + // Find event + global.GadgetBridge.onEvent("find", (event) => { + if (Bangle.findDeviceInterval) { + clearInterval(Bangle.findDeviceInterval); + delete Bangle.findDeviceInterval; + } + if (event.n) // Ignore quiet mode: we always want to find our watch + Bangle.findDeviceInterval = setInterval( _ => Bangle.buzz(), 1000); + }); + } + setTimeout(boot, 0); +})(); diff --git a/apps/omgbhbf/icon.js b/apps/omgbhbf/icon.js new file mode 100644 index 0000000000..1b71a8ddfe --- /dev/null +++ b/apps/omgbhbf/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("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")); \ No newline at end of file diff --git a/apps/cgb/customgadgetbridge.png b/apps/omgbhbf/omgbhbf.png similarity index 100% rename from apps/cgb/customgadgetbridge.png rename to apps/omgbhbf/omgbhbf.png diff --git a/apps/omgbhbf/settings.js b/apps/omgbhbf/settings.js new file mode 100644 index 0000000000..61995173d2 --- /dev/null +++ b/apps/omgbhbf/settings.js @@ -0,0 +1,9 @@ +(function(back) { + E.showMenu({ + "" : { "title" : "Find My Phone" }, + "< Back" : back, + "Phone Connected" : { value: NRF.getSecurityStatus().connected? "Yes" : "No"}, + "On" : _=> global.GadgetBridge.findPhone(true), + "Off" : _=> global.GadgetBridge.findPhone(false), + }); +}) From 9c5c1e554ce60777a0bc3289835b1fbdeb7958f1 Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Wed, 22 Dec 2021 17:01:44 +0100 Subject: [PATCH 10/13] feat: add icon for core --- apps.json | 1 + apps/omgbc/omgbc.png | Bin 0 -> 4133 bytes 2 files changed, 1 insertion(+) create mode 100644 apps/omgbc/omgbc.png diff --git a/apps.json b/apps.json index 6a19ca70eb..17cab18387 100644 --- a/apps.json +++ b/apps.json @@ -5066,6 +5066,7 @@ { "id": "omgbc", "name": "Oh My Gadget Bridge Core", + "icon": "omgbc.png", "version": "0.01", "description": "A custom implementation of gadget bridge, expose an API for other app", "type": "bootloader", diff --git a/apps/omgbc/omgbc.png b/apps/omgbc/omgbc.png new file mode 100644 index 0000000000000000000000000000000000000000..6618c1d2957e8b486b3509192af055963bc36297 GIT binary patch literal 4133 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 literal 0 HcmV?d00001 From e8b5e96bd53d6a872b768d7f9cf8726d9e051ede Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Wed, 22 Dec 2021 17:10:03 +0100 Subject: [PATCH 11/13] feat: fix icon.js size --- apps/omgbc/icon.js | 2 +- apps/omgbhbf/icon.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/omgbc/icon.js b/apps/omgbc/icon.js index 1b71a8ddfe..a5eb7845da 100644 --- a/apps/omgbc/icon.js +++ b/apps/omgbc/icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("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")); \ No newline at end of file +require("heatshrink").decompress(atob(atob("MDAB///////////////////////////////////////////////////////////////////////////////////x///////x///////hP//////iH/////+eI/////8CI/////4BQn////4BBD////xihH////wdCH////wBEP////wGkH////wACX////4ABn////4AAP////8AAP////+AAP/////AAf/////gA//////gB//////wD//////wD//////////////////////////////////////wD//////wD//////wD///////////////////////////////////////////////////////////////////////////"))); \ No newline at end of file diff --git a/apps/omgbhbf/icon.js b/apps/omgbhbf/icon.js index 1b71a8ddfe..a5eb7845da 100644 --- a/apps/omgbhbf/icon.js +++ b/apps/omgbhbf/icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("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")); \ No newline at end of file +require("heatshrink").decompress(atob(atob("MDAB///////////////////////////////////////////////////////////////////////////////////x///////x///////hP//////iH/////+eI/////8CI/////4BQn////4BBD////xihH////wdCH////wBEP////wGkH////wACX////4ABn////4AAP////8AAP////+AAP/////AAf/////gA//////gB//////wD//////wD//////////////////////////////////////wD//////wD//////wD///////////////////////////////////////////////////////////////////////////"))); \ No newline at end of file From 058d726fbf8600ad43816ce6974e6b5517075e7e Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Thu, 23 Dec 2021 15:35:21 +0100 Subject: [PATCH 12/13] feat: update apps for add settings --- apps.json | 7 ++- apps/omgbc/boot.js | 141 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 17cab18387..2810860078 100644 --- a/apps.json +++ b/apps.json @@ -5075,7 +5075,8 @@ "readme": "README.md", "storage": [ {"name":"omgbc.boot.js","url":"boot.js"}, - {"name":"omgbc.img","url":"icon.js","evaluate":true} + {"name":"omgbc.img","url":"icon.js","evaluate":true}, + {"name":"omgbc.settings.js","url":"settings.js"} ] }, { @@ -5091,7 +5092,9 @@ "readme": "README.md", "storage": [ {"name":"omgbhbf.boot.js","url":"boot.js"}, - {"name":"omgbhbf.img","url":"icon.js","evaluate":true} + {"name":"omgbhbf.img","url":"icon.js","evaluate":true}, + {"name":"omgbhbf.settings.js","url":"settings.js"} + ] } ] diff --git a/apps/omgbc/boot.js b/apps/omgbc/boot.js index 1095cad932..95895ee561 100644 --- a/apps/omgbc/boot.js +++ b/apps/omgbc/boot.js @@ -117,3 +117,144 @@ else dispatchEvent(event.t, event); }; })(); + + +/** + * + * function drawMessage(message) { + g.clearRect(0,g.getHeight() / 2 - g.getHeight() / 3, g.getWidth(), g.getHeight() / 2 + g.getHeight() / 4); + // Draw Message rect + g.setColor(1,1,1); + g.fillRect( + 0, + g.getHeight() / 2 - g.getHeight() / 3, + g.getWidth(), + g.getHeight() / 2 + g.getHeight() / 4 + ); + + drawHeader(message); + drawMessageTxt(message); + drawActionsButtons(); +} + +function drawHeader(message) { + g.setFont("6x8", 2.5).setFontAlign(-1,-1); + g.setColor(0,0,0); + + g.drawString( + message.sender.trim(), + 10, + g.getHeight() / 2 - g.getHeight() / 3 + 10 + ); + if (message.src) { + g.setFont("6x8", 1).setFontAlign(-1, 0); + g.drawString( + message.src.trim(), + g.getWidth() - g.stringWidth(message.src.trim()) - 5, + g.getHeight() / 2 - g.getHeight() / 3 + 7 + ); + } +} + +function drawMessageTxt(message) { + const width = g.getWidth() - 10;// Available width + const height = (g.getHeight() / 2 + g.getHeight() / 4) - (g.getHeight() / 2 - g.getHeight() / 3) - 50;// Available height + const lineHeight = 6 * 2; + const nbLine = Math.ceil(height / (lineHeight+4)); + g.setFont("6x8", 2).setFontAlign(-1,-1); + + const words = message.body.replace("\n", "").split(" "); + var currentWords = 0; + for (var i = 0; i < nbLine; i++) { + if (currentWords >= words.length) continue; + var line = ""; + for(let x = currentWords; x < words.length; x++) { + var word = words[x]; + if (g.stringWidth(line + " " + word) > width) { + break; + } else { + line += " " + word; + currentWords = x; + } + } + currentWords++; + g.drawString( + line, + 5, + g.getHeight() / 2 - g.getHeight() / 3 + 40 + ((lineHeight + 4) * i) + ); + } +} + +function drawActionsButtons() { + g.setFont("6x8", 2.5).setFontAlign(0,0); + + // Draw Button actions + g.setColor(0.278, 0.886, 0.235); + g.fillCircle( + g.getWidth() / 2 - g.getWidth() / 3.8, + g.getHeight() / 2 + g.getHeight() / 4 + 20, + 35 + ); + g.setColor(0,0,0); + g.drawString( + "Seen", + g.getWidth() / 2 - g.getWidth() / 3.8, + g.getHeight() / 2 + g.getHeight() / 4 +20 + ); + + g.setColor(0.886, 0.235, 0.466); + g.fillCircle( + g.getWidth() / 2 + g.getWidth() / 3.8, + g.getHeight() / 2 + g.getHeight() / 4 + 20, + 35 + ); + + g.setColor(0,0,0); + g.drawString( + "Not\nseen", + g.getWidth() / 2 + g.getWidth() / 3.8, + g.getHeight() / 2 + g.getHeight() / 4 +20 + ); +} + + + +function onMessage(message) { + const oldMode = Bangle.getLCDMode(); + Bangle.setLCDMode("direct"); + Bangle.setLCDPower(1); + //g.setLCDOffset(g.getHeight()); + drawMessage(message); + Bangle.buzz(); + setTimeout( _ => Bangle.buzz(), 1000); + let isClose = false; + + function close() { + isClose = true; + g.clearRect(0,g.getHeight() / 2 - g.getHeight() / 3, g.getWidth(), g.getHeight()); + Bangle.setLCDMode(oldMode); + //g.setLCDOffset(0); + } + + setWatch(() => { + if (!global.GadgetBridge || isClose) return; + global.GadgetBridge.messageResponse(message, true); + close(); + }, BTN4, {edge:"both", repeat: false}); + + setWatch(() => { + if (!global.GadgetBridge || isClose) return; + close(); + global.GadgetBridge.messageResponse(message, false); + }, BTN5, {edge:"both", repeat: false}); +} + +onMessage({ + body: "slkdfjsljdf, sfsdfsdf", + sender: "Victor", + id: 23 +}); + +global.GadgetBridge.onEvent("notify", (message) => onMessage(message)); + */ \ No newline at end of file From fe3963a6e010a1dfedf24339d790b9b5a5c51866 Mon Sep 17 00:00:00 2001 From: Victor Serain Date: Tue, 16 Aug 2022 11:55:31 +0200 Subject: [PATCH 13/13] feat: add swipeclock --- apps.json | 26 +++- apps/omgbc/boot.js | 17 ++- apps/omgbhbf/boot.js | 3 +- apps/simplyclock/app.js | 4 +- apps/swipeclock/ChangeLog | 1 + apps/swipeclock/app.js | 277 ++++++++++++++++++++++++++++++++++++++ apps/swipeclock/icon.js | 1 + apps/swipeclock/icon.png | Bin 0 -> 279 bytes 8 files changed, 317 insertions(+), 12 deletions(-) create mode 100644 apps/swipeclock/ChangeLog create mode 100644 apps/swipeclock/app.js create mode 100644 apps/swipeclock/icon.js create mode 100644 apps/swipeclock/icon.png diff --git a/apps.json b/apps.json index 85e1bab4e8..80ce2b9e57 100644 --- a/apps.json +++ b/apps.json @@ -5067,7 +5067,7 @@ "id": "omgbc", "name": "Oh My Gadget Bridge Core", "icon": "omgbc.png", - "version": "0.01", + "version": "0.02", "description": "A custom implementation of gadget bridge, expose an API for other app", "type": "bootloader", "tags": "tools, system", @@ -5082,7 +5082,7 @@ { "id": "omgbhbf", "name": "Oh My Gadget Bridge (Health, Battery, Find)", - "version": "0.01", + "version": "0.02", "description": "Implement Health, Battery, Find", "icon": "omgbhbf.png", "type": "bootloader", @@ -5094,8 +5094,9 @@ {"name":"omgbhbf.boot.js","url":"boot.js"}, {"name":"omgbhbf.img","url":"icon.js","evaluate":true}, {"name":"omgbhbf.settings.js","url":"settings.js"} - ]}, - { + ] + }, + { "id": "simplyclock", "name": "Simply Clock", "version": "1.01", @@ -5105,9 +5106,26 @@ "tags": "clock", "allow_emulator": true, "supports": ["BANGLEJS"], + "dependencies": {"omgbc":"app"}, "storage": [ {"name":"simplyclock.app.js","url":"app.js"}, {"name":"simplyclock.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "swipeclock", + "name": "Swipe Clock", + "version": "1.00", + "description": "Swipe clock", + "icon": "icon.png", + "type": "clock", + "tags": "clock", + "allow_emulator": true, + "supports": ["BANGLEJS"], + "dependencies": {"omgbc":"app"}, + "storage": [ + {"name":"swipeclock.app.js","url":"app.js"}, + {"name":"swipeclock.img","url":"icon.js","evaluate":true} + ] } ] diff --git a/apps/omgbc/boot.js b/apps/omgbc/boot.js index 95895ee561..ff5fa2b226 100644 --- a/apps/omgbc/boot.js +++ b/apps/omgbc/boot.js @@ -43,11 +43,11 @@ }, musicControl: cmd => { // play/pause/next/previous/volumeup/volumedown - global.GadgetBridge.send({ t: "music", n:cmd }); + global.GadgetBridge.send({ t: "music", n: cmd }); }, messageResponse: (msg, response) => { if (!isFinite(msg.id)) return; - global.GadgetBridge.send({ t: "notify", n:response ? "OPEN" : "DISMISS", id: msg.id }); + global.GadgetBridge.send({ t: "notify", n: response ? "OPEN" : "DISMISS", id: msg.id }); }, findPhone: (search) => { @@ -60,11 +60,18 @@ }, "__private__" : { // Just for debbuging in WebIde dispatchEvent: dispatchEvent - } + }, + isConnected: false, }; - NRF.on("connect", () => dispatchEvent("connect", {})); - NRF.on("disconnect", () => dispatchEvent("disconnect", {})); + NRF.on("connect", () => { + GadgetBridge.isConnected = true; + dispatchEvent("connect", {}) + }); + NRF.on("disconnect", () => { + GadgetBridge.isConnected = false; + dispatchEvent("disconnect", {}) + }); var HANDLERS = { // {t:"notify",id:int, src,title,subject,body,sender,tel:string} add diff --git a/apps/omgbhbf/boot.js b/apps/omgbhbf/boot.js index 69f26a0710..8f7a05e2f2 100644 --- a/apps/omgbhbf/boot.js +++ b/apps/omgbhbf/boot.js @@ -2,9 +2,10 @@ function boot() { // Battery monitor function sendBattery() { - global.GadgetBridge.send({ t: "status", bat: E.getBattery() }); + global.GadgetBridge.send({ t: "status", bat: E.getBattery(), volt: E.getAnalogVRef(), chg: Bangle.isCharging() }); } setInterval(sendBattery, 10*60*1000); + global.GadgetBridge.onEvent("connect", () => setTimeout(sendBattery, 2000), { layer: 0 }); // Health tracking diff --git a/apps/simplyclock/app.js b/apps/simplyclock/app.js index 18bbaaf280..8e5291aa63 100644 --- a/apps/simplyclock/app.js +++ b/apps/simplyclock/app.js @@ -184,7 +184,7 @@ function listenEvent() { } function togglePlay() { - stat = (stat==="play" ? "pause" : "play"); + stat = ( stat === "play" ? "pause" : "play"); } function setAction(action) { @@ -192,7 +192,7 @@ function setAction(action) { actionTimeout = setTimeout(() => lastAction = null, 1000); lastAction = action; - Bluetooth.println(JSON.stringify({t:"music", n: action})); + global.GadgetBridge.musicControl(action); draw(); } diff --git a/apps/swipeclock/ChangeLog b/apps/swipeclock/ChangeLog new file mode 100644 index 0000000000..59e6934ed3 --- /dev/null +++ b/apps/swipeclock/ChangeLog @@ -0,0 +1 @@ +0.01: Init App diff --git a/apps/swipeclock/app.js b/apps/swipeclock/app.js new file mode 100644 index 0000000000..ddaaec1796 --- /dev/null +++ b/apps/swipeclock/app.js @@ -0,0 +1,277 @@ +var WIDTH = g.getWidth(); +var SIZE = Math.floor(WIDTH / (7*6)); + +function rotationString(fullTrackName, width, sizeOfChar, speed) { + const d = new Date(); + const maxCharVisible = Math.ceil(width / sizeOfChar) + const position =(d.getSeconds() * speed) % (fullTrackName.length - maxCharVisible); + return fullTrackName.length > maxCharVisible + ? fullTrackName.slice(position, position + maxCharVisible + 1) + : fullTrackName +} + +const screens = [ + { + name: "clock", + watchUiState: { + nightMode: false, + forceDraw: true, + width: WIDTH, + size: SIZE, + x: (WIDTH / 2) - SIZE * 6, + y: (g.getHeight()/2) - SIZE *7 + }, + render: () => { + var watchUiState = screens[currentScreen].watchUiState; + var d = new Date(); + var x = watchUiState.x; + var y = watchUiState.y; + var size = watchUiState.size; + var width = watchUiState.width; + + g.reset(); + if (watchUiState.nightMode) { + g.setColor("#ff1100"); + } + + g.setFont("7x11Numeric7Seg",size).setFontAlign(1,-1); + if ((d.getMinutes() == 0 && d.getSeconds() == 0) || watchUiState.forceDraw) { + g.clearRect(x - size * 14, y, x - size , y + size * 11); + g.drawString(d.getHours(), x, y); + } + + g.setFontAlign(-1,-1); + + if (d.getSeconds() % 2 == 0) g.drawString(":", x,y); + else g.clearRect(x, y, x + size *4, y + size * 12); + + if (d.getSeconds() == 0|| watchUiState.forceDraw) { + g.clearRect(x + size *4 , y, x + size * 17 , y + size * 11); + g.drawString(("0"+d.getMinutes()).substr(-2),x+size*4,y); + } + + // draw seconds + g.setFont("7x11Numeric7Seg",size/2); + g.clearRect(x+size*18,y + size*7,x+size*18 + size *8 ,y + size*12 ); + g.drawString(("0"+d.getSeconds()).substr(-2),x+size*18,y + size*7); + + if ((d.getHours() == 0 && d.getMinutes() == 0) || watchUiState.forceDraw) { + // date + var date = d.toString().split(" "); + g.setFont("6x8", size/1.5).setFontAlign(0,-1); + g.clearRect(width/4, y + size * 16, width/ 1.33 , y + size * 20); + g.drawString(date[2] + " " + date[1], width / 2 , y + size * 16); + } + + g.clearRect(width * 0.8, y + size * 18 , width , y + size * 26); + if (musicState && GadgetBridge.isConnected) { + g.setFont("6x8", size/2).setFontAlign(0,-1); + g.drawString(musicState.state === "play" ? "||" : '>', width * 0.9, y + size * 20); + } + + g.clearRect(width * 0.4, y - size * 12 , width , y - size * 8); + if (musicInfo && GadgetBridge.isConnected) { + const fullTrackName = musicInfo.track + " - " + musicInfo.artist; + g.setFont("6x8", size/2).setFontAlign(0,-1); + + g.drawString(rotationString(fullTrackName, width * 0.6, 6 * (size/2), 2), width * 0.68, y - size * 12) + } + + if ((d.getMinutes() % 2 == 0 && d.getSeconds() == 0) || watchUiState.forceDraw) { + var bat = E.getBattery(); + var color = bat <= 20 || watchUiState.nightMode ? "#ff1100" : "#ffffff"; + + if (Bangle.isCharging()) { + color = "#ffc413"; + } + + g.setColor(color); + g.setFont("6x8", size/1.5).setFontAlign(0,-1); + g.clearRect(0, y - size * 10, width , y - size * 6); + g.drawString(bat + "%", width / 8 + 10, y - size * 10); + } + + watchUiState.forceDraw = false; + }, + onButtonClick: (btn) => { + var watchUiState = screens[currentScreen].watchUiState; + if (btn == 1) { + watchUiState.nightMode = !watchUiState.nightMode; + if (watchUiState.nightMode) Bangle.setLCDBrightness(0.2); + else Bangle.setLCDBrightness(1); + + watchUiState.forceDraw = true; + screens[currentScreen].render(); + } else if (btn == 3) { + if (GadgetBridge.isConnected) GadgetBridge.musicControl(musicState && musicState.state === "play" ? "pause" : 'play'); + } + }, + }, +]; + +const musicView = { + name: "music", + watchUiState: { + nightMode: false, + forceDraw: true, + width: WIDTH, + size: SIZE, + x: (WIDTH / 2) - SIZE * 6, + y: (g.getHeight()/2) - SIZE *7 + }, + render: () => { + var watchUiState = musicView.watchUiState; + var y = watchUiState.y; + var size = watchUiState.size; + var width = watchUiState.width; + + g.reset(); + if (watchUiState.nightMode) { + g.setColor("#ff1100"); + } + + g.clearRect(0, y - size * 4 , width , y + size * 4); + if (musicInfo) { + if (musicInfo.track && GadgetBridge.isConnected) { + g.setFont("6x8", size/1.5).setFontAlign(0,-1); + const charSize = 6 * (size/1.5); + const margin = charSize * 2; + g.drawString(rotationString(musicInfo.track, width - margin, charSize, 1), width * 0.5 + (margin / 4), y - size * 4) + } + + g.clearRect(0, y + size * 2 , width , y + size * 6 ); + if (musicInfo.artist && GadgetBridge.isConnected) { + g.setFont("6x8", size/2).setFontAlign(0,-1); + g.drawString(rotationString("BY: " + musicInfo.artist, width, 6 * (size/2), 1), width * 0.5, y + size * 2) + } + } else { + g.setFont("6x8", size/1.5).setFontAlign(0,-1); + const charSize = 6 * (size/1.5); + const margin = charSize * 2; + g.drawString(rotationString("No Song.", width - margin, charSize, 1), width * 0.5 + (margin / 4), y - size * 4) + } + + g.clearRect(0, y + size * 10 , width , y + size * 18 ); + if (musicState && musicState.state && GadgetBridge.isConnected) { + g.setFont("6x8", size/2).setFontAlign(0,-1); + g.drawString(musicState.state == "play" ? "Playing" : "Paused", width * 0.5, y + size * 10) + } + + g.clearRect(0, y + size * 18 , width , y + size * 24); + if (GadgetBridge.isConnected) { + g.setFont("6x8", size/2).setFontAlign(0,-1); + g.drawString("<<", width * 0.25, y + size * 18) + g.drawString(">>", width * 0.75, y + size * 18) + g.drawString("+", width * 0.9, y - size * 12) + g.drawString("-", width * 0.9, y + size * 22) + } + + const d = new Date() + g.setFont("6x8", size/2).setFontAlign(0,-1); + g.clearRect(0, y - size * 10, (6 *(size/2)) * 5 , y - size * 6); + g.drawString(("0"+d.getHours()).substr(-2)+":"+("0"+d.getMinutes()).substr(-2), width / 8 + 10, y - size * 10); + }, + onButtonClick: (btn) => { + if (btn == 1) { + GadgetBridge.musicControl("volumeup"); + } else if (btn == 3) { + GadgetBridge.musicControl("volumedown"); + } else if (btn == 4) { + GadgetBridge.musicControl("previous"); + } else if (btn == 5) { + GadgetBridge.musicControl("next"); + } + }, +}; + +let currentScreen = 0; +let onSwipe = false; +let buttonTimeout; +let musicInfo = null; +let musicState = null; + +function clearScreen() { + g.clear(); + g.clearRect(0,0, g.getHeight(), WIDTH) + Bangle.setUI("clock"); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + + if (screens[currentScreen].watchUiState) screens[currentScreen].watchUiState.forceDraw = true; +} + + +function draw() { + screens[currentScreen].render(); +} + +function onButtonClick(button) { + if (onSwipe) return; + + if (buttonTimeout) clearTimeout(buttonTimeout); + buttonTimeout = setTimeout(() => { + screens[currentScreen].onButtonClick(button); + }, 150); +} + +function onScreenSwipe(direction) { + if (screens.length === 1) return; + if (buttonTimeout) clearTimeout(buttonTimeout); + + onSwipe = true; + const newScreenPos = currentScreen + direction; + + if (newScreenPos >= 0) { + currentScreen = newScreenPos % screens.length; + } else { + currentScreen = screens.length + newScreenPos; + } + + clearScreen(); + setTimeout(() => onSwipe = false, 150); +} + +function addMusicView() { + if (screens.find(v => v === musicView)) return; + screens.push(musicView); +} + +function main() { + require("Font7x11Numeric7Seg").add(Graphics); + + // Only update when display turns on + if (process.env.BOARD!="SMAQ3") // hack for Q3 which is always-on + setWatch(() => onButtonClick(1), BTN1, { edge:"rising", debounce: 50, repeat:true }); + setWatch(() => onButtonClick(2), BTN2, { edge:"rising", debounce: 50, repeat:true }); + setWatch(() => onButtonClick(3), BTN3, { edge:"rising", debounce: 50, repeat:true }); + setWatch(() => onButtonClick(4), BTN4, { edge:"rising", debounce: 50, repeat:true }); + setWatch(() => onButtonClick(5), BTN5, { edge:"rising", debounce: 50, repeat:true }); + + Bangle.on('swipe', (direction) => onScreenSwipe(direction)); + + GadgetBridge.onEvent('musicinfo', (info) =>{ + musicInfo = info; + GadgetBridge.__private__.info = info; + }); + GadgetBridge.onEvent('musicstate', (state) => { + musicState = state; + GadgetBridge.__private__.state = state; + }); + GadgetBridge.onEvent('connect', addMusicView); + GadgetBridge.onEvent('disconnect', () => { + const musicViewIndex = screens.findIndex(v => v === musicView); + if (index == -1) return + + if (currentScreen === musicViewIndex) currentScreen = 0; + + screens.splice(musicViewIndex, 1); + }); + + + if (GadgetBridge.isConnected) addMusicView(); + + clearScreen(); + + setInterval(draw, 1000); +} +main(); \ No newline at end of file diff --git a/apps/swipeclock/icon.js b/apps/swipeclock/icon.js new file mode 100644 index 0000000000..d5d9aaf682 --- /dev/null +++ b/apps/swipeclock/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mUygP/AC5BlH4MAn/gAwN/4EP/AFBsEMhkBwEAjEDgYJBgEGgHA4EYDwOAmEwBIIYyj/wgf+AoMH/kA/4eBJXwYLVxgAjh//AC3w")) diff --git a/apps/swipeclock/icon.png b/apps/swipeclock/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cb08aec5e1b88cbd097bd451c072ec7c04d3bea9 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-wj^(N7l!{JxM1({$v}}ao-U3d z8I5nJU*u{w5OK~wzAvjZ-u~~px328fnZ=O@Zai~1*e;N-byXs<=jBG%BflSI>;69a zbmv@K25$Di