From 1efadb816d2c344ff98d947aedb77500742ca0f5 Mon Sep 17 00:00:00 2001 From: Francesco Bedussi Date: Fri, 5 Feb 2021 22:47:32 +0100 Subject: [PATCH 001/163] fix(large clock): font size --- apps/largeclock/ChangeLog | 1 + apps/largeclock/largeclock.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/largeclock/ChangeLog b/apps/largeclock/ChangeLog index d06cc9edf..851829fcc 100644 --- a/apps/largeclock/ChangeLog +++ b/apps/largeclock/ChangeLog @@ -5,3 +5,4 @@ 0.05: Add support for 12 hour time 0.06: Allow to disable BTN1 and BTN3 buttons 0.07: Don't clear all intervals during initialisation +0.08: fix font size diff --git a/apps/largeclock/largeclock.js b/apps/largeclock/largeclock.js index 24127ac15..34409797c 100644 --- a/apps/largeclock/largeclock.js +++ b/apps/largeclock/largeclock.js @@ -140,13 +140,13 @@ function drawTime(d) { g.clearRect(0, 24, moonX - moonR - 10, 239); g.setColor(1, 1, 1); g.setFontAlign(-1, -1); - g.setFont("Vector", 100); + g.setFont("Vector", 130); g.drawString(hours, 40, 24, true); g.setColor(1, 50, 1); - g.drawString(minutes, 40, 135, true); + g.drawString(minutes, 40, 130, true); g.setFont("Vector", 20); g.setRotation(3); - g.drawString(`${dow} ${day} ${month}`, 50, 10, true); + g.drawString(`${dow} ${day} ${month}`, 60, 10, true); g.drawString(year, is12Hour ? 46 : 75, 205, true); lastMinutes = minutes; } From 5182777394ab9d86ec419eea9c1c1ca2f07a0007 Mon Sep 17 00:00:00 2001 From: Francesco Bedussi Date: Sun, 6 Jun 2021 17:33:02 +0200 Subject: [PATCH 002/163] chore: bump largeclock version in apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 89be44fcf..f50a5370c 100644 --- a/apps.json +++ b/apps.json @@ -1885,7 +1885,7 @@ "id": "largeclock", "name": "Large Clock", "icon": "largeclock.png", - "version": "0.07", + "version": "0.08", "description": "A readable and informational digital watch, with date, seconds and moon phase", "readme": "README.md", "tags": "clock", From dfa901c67304b2b3be762132a07a64baea1c5670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 18:02:53 +0200 Subject: [PATCH 003/163] Create some.js --- apps/BangleBridge/some.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/BangleBridge/some.js diff --git a/apps/BangleBridge/some.js b/apps/BangleBridge/some.js new file mode 100644 index 000000000..fd538074f --- /dev/null +++ b/apps/BangleBridge/some.js @@ -0,0 +1 @@ +E.showMessage("My\nSimple\nApp","My App") From e79680ae59026019011e05335f0e131d878d1c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 19:02:22 +0200 Subject: [PATCH 004/163] Update apps.json --- apps.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps.json b/apps.json index eeeff3d86..b68927516 100644 --- a/apps.json +++ b/apps.json @@ -3159,6 +3159,19 @@ {"name":"waypoints.json","url":"waypoints.json"} ] }, +{ "id": "banglebridge", + "name": "Bangle_Bridge Widget", + "shortName":"banglebridge", + "icon": "widget.png", + "version":"0.01", + "description": "Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App", + "tags": "widget", + "type": "widget", + "readme": "README.md", + "storage": [ + {"name":"7chname.wid.js","url":"widget.js"} + ] + }, { "id": "qmsched", "name": "Quiet Mode Schedule", "shortName":"Quiet Mode", From 31225385f1ee65a881dad5c543a7cd272fd196dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 19:10:31 +0200 Subject: [PATCH 005/163] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index b68927516..2ac9ce045 100644 --- a/apps.json +++ b/apps.json @@ -3169,7 +3169,7 @@ "type": "widget", "readme": "README.md", "storage": [ - {"name":"7chname.wid.js","url":"widget.js"} + {"name":"banglebridge.wid.js","url":"widget.js"} ] }, { "id": "qmsched", From efb67968d8214acf05c4637edc85b1ca73fd4fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 19:12:36 +0200 Subject: [PATCH 006/163] First commit to App Loader --- apps/BangleBridge/README.md | 2 + apps/BangleBridge/heart.img | 1 + apps/BangleBridge/iconWatch.img | Bin 0 -> 255 bytes apps/BangleBridge/widget.js | 293 ++++++++++++++++++++++++++++++++ apps/BangleBridge/widget.png | Bin 0 -> 72126 bytes 5 files changed, 296 insertions(+) create mode 100644 apps/BangleBridge/README.md create mode 100644 apps/BangleBridge/heart.img create mode 100644 apps/BangleBridge/iconWatch.img create mode 100644 apps/BangleBridge/widget.js create mode 100644 apps/BangleBridge/widget.png diff --git a/apps/BangleBridge/README.md b/apps/BangleBridge/README.md new file mode 100644 index 000000000..18c71f571 --- /dev/null +++ b/apps/BangleBridge/README.md @@ -0,0 +1,2 @@ +Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App +Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html \ No newline at end of file diff --git a/apps/BangleBridge/heart.img b/apps/BangleBridge/heart.img new file mode 100644 index 000000000..b8e339b30 --- /dev/null +++ b/apps/BangleBridge/heart.img @@ -0,0 +1 @@ +00ˆþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ þþþþþþþþþþþþþþ þþþþþþþþþþþþþþþþþþ þþþþþþþþþþ þþþþþþþþþþþþþþþ þþþþþþ þþþþþþþþþþþþþ þþþþ þþþþþþþþþþþ þþ ?? þþþþþþþþþ ÿÿ þþþþþþþþ ÿÿ þþþþþþþ ÿÿ þþþþþþ ÿÿ þþþþþþ ?ÿÿÿÿÿÿÿÿÿÿ? þþþþþþ ?ÿÿÿÿÿÿÿÿÿÿ? þþþþþþ ÿÿ ''' 'þþþþþþ ÿÿ' '''þþþþþþ ÿÿ' ''''þþþþþþþ 'ÿÿ' '''''þþþþþþþþ '??'''''''þþþþþþþþþ ''''''''þþþþþþþþþþ ''''''''þþþþþþþþþþþ '''''''''þþþþþþþþþþþþ ''''''''''þþþþþþþþþþþþþ '''''''''''þþþþþþþþþþþþþþþ ''''''''''''þþþþþþþþþþþþþþþþþ ''''''''''''þþþþþþþþþþþþþþþþþþþ '''''''''''''þþþþþþþþþþþþþþþþþþþþþ '''''''''''''þþþþþþþþþþþþþþþþþþþþþþþ ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþ ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþ '''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþ '''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ \ No newline at end of file diff --git a/apps/BangleBridge/iconWatch.img b/apps/BangleBridge/iconWatch.img new file mode 100644 index 0000000000000000000000000000000000000000..4a8434583521668bf41f87e690e750d6fa743be1 GIT binary patch literal 255 zcmW;HyAFad6b9hGA+ZawD+8gs6C(p&9*L2GV2LkQ6Q4tC7+kyQV66XXhcBlmJ(spS zg%WZO*;!Oc)GtTPMLZUsjw*}5xI?5p23ljJ4Rd_Y8*5PkC+(OCg=xc=8|ph3_4-CRf-{2_ VqY;Pvo9@dHds!6LX9aAt!XL*LHO&A3 literal 0 HcmV?d00001 diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js new file mode 100644 index 000000000..5026b8446 --- /dev/null +++ b/apps/BangleBridge/widget.js @@ -0,0 +1,293 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + + if (flip == 1) { //when off + console.log("--------------------------------------------------------------- 1"); + flip = 0; + + g.clear(); + } else { //when on + console.log("--------------------------------------------------------------- 0"); + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + WIDGETS["banglebridge"] = { + area: "tl", + width: 10, + draw: draw, + }; + + initSensors(); + + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + + + setInterval(function () { + + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); + +})(); //End of Widget \ No newline at end of file diff --git a/apps/BangleBridge/widget.png b/apps/BangleBridge/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..b381b1aa1fc09020622ca40ccda9efb6a5d2e5f3 GIT binary patch literal 72126 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∾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 literal 0 HcmV?d00001 From 7f9f7678091199896edbe18de653047e1d4262e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 19:31:46 +0200 Subject: [PATCH 007/163] Fix of inofrmation display --- apps/BangleBridge/README.md | 10 +++++++++- apps/BangleBridge/widget.png | Bin 72126 -> 3492 bytes 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/BangleBridge/README.md b/apps/BangleBridge/README.md index 18c71f571..21a9b7bc1 100644 --- a/apps/BangleBridge/README.md +++ b/apps/BangleBridge/README.md @@ -1,2 +1,10 @@ Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App -Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html \ No newline at end of file +Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html + +# BangleBridge + +Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App. + +## Compilation + +Part of smartPPE project[SmartPEE](https://jorgepramos.github.io/Smart_PPE/index.html). \ No newline at end of file diff --git a/apps/BangleBridge/widget.png b/apps/BangleBridge/widget.png index b381b1aa1fc09020622ca40ccda9efb6a5d2e5f3..3c1e693fce81785e47c0291619f3a9a62bc7dffb 100644 GIT binary patch literal 3492 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 S@FYF}0000{}RE#1;cjv^x6or*}8q~vq6 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∾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 From f53554d63c2193507bc5b41fa323397c4c1216e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 19:36:45 +0200 Subject: [PATCH 008/163] Update Visuals --- apps/BangleBridge/README.md | 4 ++-- apps/BangleBridge/banglebridge.png | Bin 0 -> 3492 bytes 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 apps/BangleBridge/banglebridge.png diff --git a/apps/BangleBridge/README.md b/apps/BangleBridge/README.md index 21a9b7bc1..9897971f8 100644 --- a/apps/BangleBridge/README.md +++ b/apps/BangleBridge/README.md @@ -5,6 +5,6 @@ Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App. -## Compilation +## Full Project -Part of smartPPE project[SmartPEE](https://jorgepramos.github.io/Smart_PPE/index.html). \ No newline at end of file +Part of smartPPE project [SmartPEE](https://jorgepramos.github.io/Smart_PPE/index.html). \ No newline at end of file diff --git a/apps/BangleBridge/banglebridge.png b/apps/BangleBridge/banglebridge.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1e693fce81785e47c0291619f3a9a62bc7dffb GIT binary patch literal 3492 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 S@FYF}0000 Date: Fri, 25 Jun 2021 19:44:22 +0200 Subject: [PATCH 009/163] Update apps.json --- apps.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 2ac9ce045..2df7cacae 100644 --- a/apps.json +++ b/apps.json @@ -3159,9 +3159,9 @@ {"name":"waypoints.json","url":"waypoints.json"} ] }, -{ "id": "banglebridge", - "name": "Bangle_Bridge Widget", - "shortName":"banglebridge", +{ "id": "Banglebridge", + "name": "BangleBridge", + "shortName":"Banglebridge", "icon": "widget.png", "version":"0.01", "description": "Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App", @@ -3169,7 +3169,7 @@ "type": "widget", "readme": "README.md", "storage": [ - {"name":"banglebridge.wid.js","url":"widget.js"} + {"name":"Banglebridge.wid.js","url":"widget.js"} ] }, { "id": "qmsched", From 5f769e2fe29ed70ac2fb60526afe87727bc2f7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 19:50:07 +0200 Subject: [PATCH 010/163] Update apps.json --- apps.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 2df7cacae..5af0f3d73 100644 --- a/apps.json +++ b/apps.json @@ -3159,9 +3159,9 @@ {"name":"waypoints.json","url":"waypoints.json"} ] }, -{ "id": "Banglebridge", +{ "id": "BangleBridge", "name": "BangleBridge", - "shortName":"Banglebridge", + "shortName":"BangleBridge", "icon": "widget.png", "version":"0.01", "description": "Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App", @@ -3169,7 +3169,7 @@ "type": "widget", "readme": "README.md", "storage": [ - {"name":"Banglebridge.wid.js","url":"widget.js"} + {"name":"BangleBridge.wid.js","url":"widget.js"} ] }, { "id": "qmsched", From 3cb1d3481fdb9c3c153ab96c8c8e80790a0b224a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 19:56:10 +0200 Subject: [PATCH 011/163] Delete apps/BangleBridge directory --- apps/BangleBridge/README.md | 10 - apps/BangleBridge/banglebridge.png | Bin 3492 -> 0 bytes apps/BangleBridge/heart.img | 1 - apps/BangleBridge/iconWatch.img | Bin 255 -> 0 bytes apps/BangleBridge/some.js | 1 - apps/BangleBridge/widget.js | 293 ----------------------------- apps/BangleBridge/widget.png | Bin 3492 -> 0 bytes 7 files changed, 305 deletions(-) delete mode 100644 apps/BangleBridge/README.md delete mode 100644 apps/BangleBridge/banglebridge.png delete mode 100644 apps/BangleBridge/heart.img delete mode 100644 apps/BangleBridge/iconWatch.img delete mode 100644 apps/BangleBridge/some.js delete mode 100644 apps/BangleBridge/widget.js delete mode 100644 apps/BangleBridge/widget.png diff --git a/apps/BangleBridge/README.md b/apps/BangleBridge/README.md deleted file mode 100644 index 9897971f8..000000000 --- a/apps/BangleBridge/README.md +++ /dev/null @@ -1,10 +0,0 @@ -Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App -Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html - -# BangleBridge - -Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App. - -## Full Project - -Part of smartPPE project [SmartPEE](https://jorgepramos.github.io/Smart_PPE/index.html). \ No newline at end of file diff --git a/apps/BangleBridge/banglebridge.png b/apps/BangleBridge/banglebridge.png deleted file mode 100644 index 3c1e693fce81785e47c0291619f3a9a62bc7dffb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3492 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 S@FYF}0000xc=8|ph3_4-CRf-{2_ VqY;Pvo9@dHds!6LX9aAt!XL*LHO&A3 diff --git a/apps/BangleBridge/some.js b/apps/BangleBridge/some.js deleted file mode 100644 index fd538074f..000000000 --- a/apps/BangleBridge/some.js +++ /dev/null @@ -1 +0,0 @@ -E.showMessage("My\nSimple\nApp","My App") diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js deleted file mode 100644 index 5026b8446..000000000 --- a/apps/BangleBridge/widget.js +++ /dev/null @@ -1,293 +0,0 @@ -(() => { - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - - if (flip == 1) { //when off - console.log("--------------------------------------------------------------- 1"); - flip = 0; - - g.clear(); - } else { //when on - console.log("--------------------------------------------------------------- 0"); - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - // Finally add widget - WIDGETS["banglebridge"] = { - area: "tl", - width: 10, - draw: draw, - }; - - initSensors(); - - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - - - setInterval(function () { - - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); - -})(); //End of Widget \ No newline at end of file diff --git a/apps/BangleBridge/widget.png b/apps/BangleBridge/widget.png deleted file mode 100644 index 3c1e693fce81785e47c0291619f3a9a62bc7dffb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3492 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 S@FYF}0000 Date: Fri, 25 Jun 2021 19:56:38 +0200 Subject: [PATCH 012/163] Create some.js --- apps/Banglebridge/some.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/Banglebridge/some.js diff --git a/apps/Banglebridge/some.js b/apps/Banglebridge/some.js new file mode 100644 index 000000000..5c1b14949 --- /dev/null +++ b/apps/Banglebridge/some.js @@ -0,0 +1 @@ +hola From 2984fd5fc8d6e0d704e59a20ce35b2046aaa956f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 20:05:40 +0200 Subject: [PATCH 013/163] Add files via upload --- apps/Banglebridge/README.md | 10 + apps/Banglebridge/banglebridge.png | Bin 0 -> 3492 bytes apps/Banglebridge/heart.img | 1 + apps/Banglebridge/iconWatch.img | Bin 0 -> 255 bytes apps/Banglebridge/widget.js | 293 +++++++++++++++++++++++++++++ 5 files changed, 304 insertions(+) create mode 100644 apps/Banglebridge/README.md create mode 100644 apps/Banglebridge/banglebridge.png create mode 100644 apps/Banglebridge/heart.img create mode 100644 apps/Banglebridge/iconWatch.img create mode 100644 apps/Banglebridge/widget.js diff --git a/apps/Banglebridge/README.md b/apps/Banglebridge/README.md new file mode 100644 index 000000000..9897971f8 --- /dev/null +++ b/apps/Banglebridge/README.md @@ -0,0 +1,10 @@ +Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App +Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html + +# BangleBridge + +Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App. + +## Full Project + +Part of smartPPE project [SmartPEE](https://jorgepramos.github.io/Smart_PPE/index.html). \ No newline at end of file diff --git a/apps/Banglebridge/banglebridge.png b/apps/Banglebridge/banglebridge.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1e693fce81785e47c0291619f3a9a62bc7dffb GIT binary patch literal 3492 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 S@FYF}0000xc=8|ph3_4-CRf-{2_ VqY;Pvo9@dHds!6LX9aAt!XL*LHO&A3 literal 0 HcmV?d00001 diff --git a/apps/Banglebridge/widget.js b/apps/Banglebridge/widget.js new file mode 100644 index 000000000..5026b8446 --- /dev/null +++ b/apps/Banglebridge/widget.js @@ -0,0 +1,293 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + + if (flip == 1) { //when off + console.log("--------------------------------------------------------------- 1"); + flip = 0; + + g.clear(); + } else { //when on + console.log("--------------------------------------------------------------- 0"); + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + WIDGETS["banglebridge"] = { + area: "tl", + width: 10, + draw: draw, + }; + + initSensors(); + + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + + + setInterval(function () { + + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); + +})(); //End of Widget \ No newline at end of file From b49335181d27f641816ae027e25a7637d3e2d331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 20:16:21 +0200 Subject: [PATCH 014/163] Delete apps/Banglebridge directory --- apps/Banglebridge/README.md | 10 - apps/Banglebridge/banglebridge.png | Bin 3492 -> 0 bytes apps/Banglebridge/heart.img | 1 - apps/Banglebridge/iconWatch.img | Bin 255 -> 0 bytes apps/Banglebridge/some.js | 1 - apps/Banglebridge/widget.js | 293 ----------------------------- 6 files changed, 305 deletions(-) delete mode 100644 apps/Banglebridge/README.md delete mode 100644 apps/Banglebridge/banglebridge.png delete mode 100644 apps/Banglebridge/heart.img delete mode 100644 apps/Banglebridge/iconWatch.img delete mode 100644 apps/Banglebridge/some.js delete mode 100644 apps/Banglebridge/widget.js diff --git a/apps/Banglebridge/README.md b/apps/Banglebridge/README.md deleted file mode 100644 index 9897971f8..000000000 --- a/apps/Banglebridge/README.md +++ /dev/null @@ -1,10 +0,0 @@ -Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App -Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html - -# BangleBridge - -Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App. - -## Full Project - -Part of smartPPE project [SmartPEE](https://jorgepramos.github.io/Smart_PPE/index.html). \ No newline at end of file diff --git a/apps/Banglebridge/banglebridge.png b/apps/Banglebridge/banglebridge.png deleted file mode 100644 index 3c1e693fce81785e47c0291619f3a9a62bc7dffb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3492 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 S@FYF}0000xc=8|ph3_4-CRf-{2_ VqY;Pvo9@dHds!6LX9aAt!XL*LHO&A3 diff --git a/apps/Banglebridge/some.js b/apps/Banglebridge/some.js deleted file mode 100644 index 5c1b14949..000000000 --- a/apps/Banglebridge/some.js +++ /dev/null @@ -1 +0,0 @@ -hola diff --git a/apps/Banglebridge/widget.js b/apps/Banglebridge/widget.js deleted file mode 100644 index 5026b8446..000000000 --- a/apps/Banglebridge/widget.js +++ /dev/null @@ -1,293 +0,0 @@ -(() => { - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - - if (flip == 1) { //when off - console.log("--------------------------------------------------------------- 1"); - flip = 0; - - g.clear(); - } else { //when on - console.log("--------------------------------------------------------------- 0"); - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - // Finally add widget - WIDGETS["banglebridge"] = { - area: "tl", - width: 10, - draw: draw, - }; - - initSensors(); - - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - - - setInterval(function () { - - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); - -})(); //End of Widget \ No newline at end of file From 058047bf6d0ec7e6a477932906a3414b6ff1b2b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 20:16:49 +0200 Subject: [PATCH 015/163] Create algo.txt --- apps/BangleBridge/algo.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/BangleBridge/algo.txt diff --git a/apps/BangleBridge/algo.txt b/apps/BangleBridge/algo.txt new file mode 100644 index 000000000..1df28a22d --- /dev/null +++ b/apps/BangleBridge/algo.txt @@ -0,0 +1 @@ +ss From d552bb8e8ac7e81a30c15b5ea3b44d506aab8aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 20:17:26 +0200 Subject: [PATCH 016/163] Add files via upload --- apps/BangleBridge/README.md | 10 + apps/BangleBridge/banglebridge.png | Bin 0 -> 3492 bytes apps/BangleBridge/heart.img | 1 + apps/BangleBridge/iconWatch.img | Bin 0 -> 255 bytes apps/BangleBridge/widget.js | 293 +++++++++++++++++++++++++++++ 5 files changed, 304 insertions(+) create mode 100644 apps/BangleBridge/README.md create mode 100644 apps/BangleBridge/banglebridge.png create mode 100644 apps/BangleBridge/heart.img create mode 100644 apps/BangleBridge/iconWatch.img create mode 100644 apps/BangleBridge/widget.js diff --git a/apps/BangleBridge/README.md b/apps/BangleBridge/README.md new file mode 100644 index 000000000..9897971f8 --- /dev/null +++ b/apps/BangleBridge/README.md @@ -0,0 +1,10 @@ +Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App +Part of smartPPE project https://jorgepramos.github.io/Smart_PPE/index.html + +# BangleBridge + +Widget that allows Bangle Js to record pair and end data using Bluetooth Low Energy in combination with the BangleBridge Android App. + +## Full Project + +Part of smartPPE project [SmartPEE](https://jorgepramos.github.io/Smart_PPE/index.html). \ No newline at end of file diff --git a/apps/BangleBridge/banglebridge.png b/apps/BangleBridge/banglebridge.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1e693fce81785e47c0291619f3a9a62bc7dffb GIT binary patch literal 3492 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 S@FYF}0000xc=8|ph3_4-CRf-{2_ VqY;Pvo9@dHds!6LX9aAt!XL*LHO&A3 literal 0 HcmV?d00001 diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js new file mode 100644 index 000000000..5026b8446 --- /dev/null +++ b/apps/BangleBridge/widget.js @@ -0,0 +1,293 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + + if (flip == 1) { //when off + console.log("--------------------------------------------------------------- 1"); + flip = 0; + + g.clear(); + } else { //when on + console.log("--------------------------------------------------------------- 0"); + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + WIDGETS["banglebridge"] = { + area: "tl", + width: 10, + draw: draw, + }; + + initSensors(); + + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + + + setInterval(function () { + + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); + +})(); //End of Widget \ No newline at end of file From 0188dbeff5bcb09f6f4d004e8d60d7c8c83ea17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Fri, 25 Jun 2021 20:25:56 +0200 Subject: [PATCH 017/163] Add files via upload --- apps/BangleBridge/widget.png | Bin 0 -> 3492 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/BangleBridge/widget.png diff --git a/apps/BangleBridge/widget.png b/apps/BangleBridge/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1e693fce81785e47c0291619f3a9a62bc7dffb GIT binary patch literal 3492 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 S@FYF}0000 Date: Thu, 8 Jul 2021 11:12:49 +0100 Subject: [PATCH 018/163] ability to package all files up into a binary blob --- bin/build_bangle2_c.js | 98 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100755 bin/build_bangle2_c.js diff --git a/bin/build_bangle2_c.js b/bin/build_bangle2_c.js new file mode 100755 index 000000000..5e086b980 --- /dev/null +++ b/bin/build_bangle2_c.js @@ -0,0 +1,98 @@ +#!/usr/bin/nodejs +/* +Mashes together a bunch of different apps into a big binary blob. +We then store this *inside* the Bangle.js firmware and can use it +to populate Storage initially. + +Bangle.js 1 doesn't really have anough flash space for this, +but we have enough on v2. +*/ +var SETTINGS = { + pretokenise : true +}; + +var path = require('path'); +var ROOTDIR = path.join(__dirname, '..'); +var APPDIR = ROOTDIR+'/apps'; +var APPJSON = ROOTDIR+'/apps.json'; +var OUTFILE = path.join(ROOTDIR, '../Espruino/libs/banglejs/banglejs2_storage_default.c'); +var APPS = [ // IDs of apps to install + "boot","launchb2","s7clk","setting", + "about","alarm","widlock","widbat","widbt" +]; +var MINIFY = true; + +var fs = require("fs"); +global.Const = { + /* Are we only putting a single app on a device? If so + apps should all be saved as .bootcde and we write info + about the current app into app.info */ + SINGLE_APP_ONLY : false, +}; + +var AppInfo = require(ROOTDIR+"/core/js/appinfo.js"); +var appjson = JSON.parse(fs.readFileSync(APPJSON).toString()); +var appfiles = []; + +function fileGetter(url) { + console.log("Loading "+url) + if (MINIFY) { + if (url.endsWith(".json")) { + var f = url.slice(0,-5); + console.log("MINIFYING JSON "+f); + var j = eval("("+fs.readFileSync(url).toString("binary")+")"); + var code = JSON.stringify(j); + //console.log(code); + url = f+".min.json"; + fs.writeFileSync(url, code); + } + } + return Promise.resolve(fs.readFileSync(url).toString("binary")); +} + +Promise.all(APPS.map(appid => { + var app = appjson.find(app=>app.id==appid); + if (app===undefined) throw new Error(`App ${appid} not found`); + return AppInfo.getFiles(app, { + fileGetter : fileGetter, + settings : SETTINGS + }).then(files => { + appfiles = appfiles.concat(files); + }); +})).then(() => { + // work out what goes in storage + var storageContent = ""; + appfiles.forEach((file) => { + var fileLength = file.content.length; + console.log(file.name+" -> "+fileLength+"b"); + // set up header + var header = new Uint8Array(32); + header.fill(0); + header.set([fileLength,fileLength>>8,fileLength>>16,fileLength>>24],0); // length + for (var i=0;ic.charCodeAt()).join(",")+",\n"; +} +cfile += `}; +`; + fs.writeFileSync(OUTFILE, cfile); + console.log("Output written to "+OUTFILE); +}); From 6670d517243934e809fe462c342fcc4885bdf7d6 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 9 Jul 2021 17:43:21 +0100 Subject: [PATCH 019/163] new firmware --- loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader.js b/loader.js index 1e4dbd9b9..e0e1399b1 100644 --- a/loader.js +++ b/loader.js @@ -11,7 +11,7 @@ if (window.location.host=="banglejs.com") { 'This is not the official Bangle.js App Loader - you can try the Official Version here.'; } -var RECOMMENDED_VERSION = "2v08"; +var RECOMMENDED_VERSION = "2v09"; // could check http://www.espruino.com/json/BANGLEJS.json for this (function() { From c3e91b4a30711e045f46468bf894327c36345e00 Mon Sep 17 00:00:00 2001 From: Eric Willisson Date: Fri, 9 Jul 2021 14:46:24 -0400 Subject: [PATCH 020/163] Adds support for dismissing Gadgetbridge notifications through notify app. Most of the support was already there, so this is just a few small steps: - notify.js gets a dismiss_and_hide() exported function that can send the "notify-" event to Gadgetbridge, if installed - dismiss_and_hide() is called when the Bangle.js screen is touched, instead of just hide() - Gadgetbridge's widget.js saves "notify"-type events to a variable - Gadgetbridge's widget.js sends a DISMISS action back to the Android app on "notify-" events, using the saved event data Note that this is a limited implementation. For example, only the most recent notfication is saved (when a new one comes in, the old one is overridden in the variable), so it will be dismissed on the phone. A more advanced implementation might make it possible to choose which notification to dismiss. From my own testing, this does properly count as a "swipe-away" style dismiss event in Android, so apps that react to notifications being swiped away will be triggered as expected. --- apps/gbridge/widget.js | 20 +++++++++++++------- apps/notify/notify.js | 19 ++++++++++++++++++- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index b4ce71907..35aacd846 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -1,4 +1,7 @@ (() => { + // Current shown notification, saved for dismissing. + var currentNot = null; + // Music handling const state = { music: "stop", @@ -151,15 +154,18 @@ global.GB = (event) => { switch (event.t) { case "notify": - case "notify-": - if (event.t === "notify") { - require("notify").show(prettifyNotificationEvent(event)); - if (!(require('Storage').readJSON('setting.json',1)||{}).quiet) { + currentNot = prettifyNotificationEvent(event); + require("notify").show(currentNot); + if (!(require('Storage').readJSON('setting.json',1)||{}).quiet) { Bangle.buzz(); - } - } else { // notify- - require("notify").hide(event); } + break; + case "notify-": + currentNot.t = "notify"; + currentNot.n = "DISMISS"; + gbSend(currentNot); + currentNot = null; + require("notify").hide(event); break; case "musicinfo": state.musicInfo = event; diff --git a/apps/notify/notify.js b/apps/notify/notify.js index b5ef32d8b..230cf9d10 100644 --- a/apps/notify/notify.js +++ b/apps/notify/notify.js @@ -141,7 +141,7 @@ exports.show = function(options) { if (pos > -size) setTimeout(anim, 15); } anim(); - Bangle.on("touch", exports.hide); + Bangle.on("touch", exports.dismiss_and_hide); }; /** @@ -162,3 +162,20 @@ exports.hide = function(options) { } anim(); }; + +/** + Calls exports.hide(), but if Gadgetbridge is installed, dismiss through it + instead (which will call call exports.hide() itself). +*/ +exports.dismiss_and_hide = function(options) { + options = options||{}; + if (typeof(options) == "number") { + options = {}; + } + if ("GB" in global) { + options["t"] = "notify-"; + GB(options); + } else { + exports.hide(options); + } +}; From 3e41465d643aa8111c50af94ce56940f9e803098 Mon Sep 17 00:00:00 2001 From: Eric Willisson Date: Fri, 9 Jul 2021 20:10:13 -0400 Subject: [PATCH 021/163] Fix tabbing --- apps/gbridge/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 35aacd846..70abfd610 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -157,9 +157,9 @@ currentNot = prettifyNotificationEvent(event); require("notify").show(currentNot); if (!(require('Storage').readJSON('setting.json',1)||{}).quiet) { - Bangle.buzz(); + Bangle.buzz(); } - break; + break; case "notify-": currentNot.t = "notify"; currentNot.n = "DISMISS"; From c882c52b2719a6590e1486d78966780ffcd942ba Mon Sep 17 00:00:00 2001 From: fxiii Date: Sun, 11 Jul 2021 21:07:20 +0200 Subject: [PATCH 022/163] Black Jack game: ignoring buttons events on pauses --- apps.json | 2 +- apps/blackjack/ChangeLog | 3 ++- apps/blackjack/blackjack.app.js | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index cc21f3115..25a947b87 100644 --- a/apps.json +++ b/apps.json @@ -1746,7 +1746,7 @@ "name": "Black Jack game", "shortName":"Black Jack game", "icon": "blackjack.png", - "version":"0.01", + "version":"0.02", "description": "Simple implementation of card game Black Jack", "tags": "game", "allow_emulator":true, diff --git a/apps/blackjack/ChangeLog b/apps/blackjack/ChangeLog index c941d90e5..25b5f9195 100644 --- a/apps/blackjack/ChangeLog +++ b/apps/blackjack/ChangeLog @@ -1 +1,2 @@ -0.01: New game! BTN4- Hit card, BTN5- Stand \ No newline at end of file +0.01: New game! BTN4- Hit card, BTN5- Stand +0.02: ignore buttons on pauses \ No newline at end of file diff --git a/apps/blackjack/blackjack.app.js b/apps/blackjack/blackjack.app.js index bbee8137b..b88432fd9 100644 --- a/apps/blackjack/blackjack.app.js +++ b/apps/blackjack/blackjack.app.js @@ -18,6 +18,7 @@ const Diamonds = { width : 48, height : 48, bpp : 4, var deck = []; var player = {Hand:[]}; var computer = {Hand:[]}; +var ctx = {ready:true}; function createDeck() { var suits = ["Spades", "Hearts", "Diamonds", "Clubs"]; @@ -44,6 +45,7 @@ function shuffle(a) { } function EndGameMessdage(msg){ + ctx.ready = false; g.drawString(msg, 155, 200); setTimeout(function(){ startGame(); @@ -52,6 +54,7 @@ function EndGameMessdage(msg){ } function hitMe() { + if (!ctx.ready) return; player.Hand.push(deck.pop()); renderOnScreen(1); var playerWeight = calcWeight(player.Hand, 0); @@ -97,6 +100,8 @@ function calcWeight(hand, hideCard) { } function stand(){ + if (!ctx.ready) return; + ctx.ready = false; function sleepFor( sleepDuration ){ console.log("Sleeping..."); var now = new Date().getTime(); @@ -156,6 +161,7 @@ function renderOnScreen(HideCard) { function dealHands() { player.Hand= []; computer.Hand= []; + ctx.ready = false; setTimeout(function(){ player.Hand.push(deck.pop()); @@ -175,6 +181,7 @@ function dealHands() { setTimeout(function(){ computer.Hand.push(deck.pop()); renderOnScreen(1); + ctx.ready = true; }, 2000); } From fc0989ca41456ea9914e5929b8acbcf3d46fb12a Mon Sep 17 00:00:00 2001 From: fxiii Date: Sun, 11 Jul 2021 21:13:18 +0200 Subject: [PATCH 023/163] Desktop Launcher: reset to clock after 2 mins of inactivity --- apps.json | 2 +- apps/dtlaunch/ChangeLog | 2 +- apps/dtlaunch/app.js | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 25a947b87..1b30a782a 100644 --- a/apps.json +++ b/apps.json @@ -2667,7 +2667,7 @@ { "id": "dtlaunch", "name": "Desktop Launcher", "icon": "icon.png", - "version":"0.03", + "version":"0.04", "description": "Desktop style App Launcher with six apps per page - fast access if you have lots of apps installed.", "readme": "README.md", "tags": "tool,system,launcher", diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index 3df4ab63b..985321e91 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -1,4 +1,4 @@ 0.01: Initial version 0.02: Multiple pages 0.03: cycle thru pages - +0.04: reset to clock after 2 mins of inactivity diff --git a/apps/dtlaunch/app.js b/apps/dtlaunch/app.js index 329a96958..9bbf3e219 100644 --- a/apps/dtlaunch/app.js +++ b/apps/dtlaunch/app.js @@ -2,6 +2,20 @@ * */ +function wdog(handle,timeout){ + if(handle !== undefined){ + wdog.handle = handle; + wdog.timeout = timeout; + } + if(wdog.timer){ + clearTimeout(wdog.timer) + } + wdog.timer = setTimeout(wdog.handle,wdog.timeout) +} + +// reset after two minutes of inactivity +wdog(load,120000) + var s = require("Storage"); var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)); apps.sort((a,b)=>{ @@ -42,6 +56,7 @@ function drawPage(p){ } Bangle.on("swipe",(dir)=>{ + wdog() selected = 0; oldselected=-1; if (dir<0){ @@ -54,6 +69,7 @@ Bangle.on("swipe",(dir)=>{ }); function nextapp(d){ + wdog(); oldselected = selected; selected+=d; selected = selected<0?5:selected>5?0:selected; From d62dec7dcbbffa756c8688ca685e13002c3d54ac Mon Sep 17 00:00:00 2001 From: fxiii Date: Sun, 11 Jul 2021 21:18:13 +0200 Subject: [PATCH 024/163] App Manager: Allow negative numbers when manual-sorting --- apps.json | 2 +- apps/files/ChangeLog | 3 ++- apps/files/files.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 1b30a782a..8f9f86918 100644 --- a/apps.json +++ b/apps.json @@ -533,7 +533,7 @@ { "id": "files", "name": "App Manager", "icon": "files.png", - "version":"0.06", + "version":"0.07", "description": "Show currently installed apps, free space, and allow their deletion from the watch", "tags": "tool,system,files", "storage": [ diff --git a/apps/files/ChangeLog b/apps/files/ChangeLog index b4037a733..1908f7e5c 100644 --- a/apps/files/ChangeLog +++ b/apps/files/ChangeLog @@ -2,4 +2,5 @@ 0.03: Add support for data files 0.04: Add functionality to sort apps manually or alphabetically ascending/descending. 0.05: Tweaks to help with memory usage -0.06: Reduce memory usage \ No newline at end of file +0.06: Reduce memory usage +0.07: Allow negative numbers when manual-sorting \ No newline at end of file diff --git a/apps/files/files.js b/apps/files/files.js index 9e6c97702..9ac6ebb35 100644 --- a/apps/files/files.js +++ b/apps/files/files.js @@ -180,7 +180,7 @@ function showSortAppsManually() { appList.reduce((menu, app) => { menu[app.name] = { value: app.sortorder || 0, - min: 0, + min: -appList.length, max: appList.length, step: 1, onchange: val => setSortorder(app, val) From c341947e7d48a78c5b58e1d39d419b2b7edfcbaf Mon Sep 17 00:00:00 2001 From: fxiii Date: Sun, 11 Jul 2021 21:27:09 +0200 Subject: [PATCH 025/163] Red torch: like torch but red :D --- apps.json | 13 +++++++++++++ apps/rtorch/ChangeLog | 1 + apps/rtorch/app-icon.js | 1 + apps/rtorch/app.js | 22 ++++++++++++++++++++++ apps/rtorch/app.png | Bin 0 -> 1770 bytes apps/rtorch/widget.js | 26 ++++++++++++++++++++++++++ 6 files changed, 63 insertions(+) create mode 100644 apps/rtorch/ChangeLog create mode 100644 apps/rtorch/app-icon.js create mode 100644 apps/rtorch/app.js create mode 100644 apps/rtorch/app.png create mode 100644 apps/rtorch/widget.js diff --git a/apps.json b/apps.json index 8f9f86918..a2ff7b571 100644 --- a/apps.json +++ b/apps.json @@ -1244,6 +1244,19 @@ {"name":"torch.img","url":"app-icon.js","evaluate":true} ] }, + { "id": "rtorch", + "name": "Red Torch", + "shortName":"RedTorch", + "icon": "app.png", + "version":"0.01", + "description": "Turns screen RED to help you see in the dark without breaking your night vision. Select from the launcher or press BTN3,BTN1,BTN3,BTN1 quickly to start when in any app that shows widgets", + "tags": "tool,torch", + "storage": [ + {"name":"rtorch.app.js","url":"app.js"}, + {"name":"rtorch.wid.js","url":"widget.js"}, + {"name":"rtorch.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "wohrm", "name": "Workout HRM", "icon": "app.png", diff --git a/apps/rtorch/ChangeLog b/apps/rtorch/ChangeLog new file mode 100644 index 000000000..06f10fe08 --- /dev/null +++ b/apps/rtorch/ChangeLog @@ -0,0 +1 @@ +0.01: Cloning torch and making it red :D diff --git a/apps/rtorch/app-icon.js b/apps/rtorch/app-icon.js new file mode 100644 index 000000000..ff1265c9b --- /dev/null +++ b/apps/rtorch/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///oP4gH+t9TCQ1VAAYLpgILunoLK/4LJgf/6oLIh//+oLK/oLIhapBBZEqBYIwDBYu/GAgLE1WvGAgLF1YwEBQcC1WqGAgLGGAgLDhQLBGAdQBYwwCBQgLDGASlFlQLC3/8BYoIBGAXwBQkCFgILC4AuFBYeAFw2v/wLBBQqNCBYOgBQp1B1/qCw5dDFoxdEBQwuBAAOoBQykCHI4uXgZPBFxEP/QuJn5/CFw7DBLpILB9QuHEYP//QuHHYP//wuHKYL0HGAoLJn/8BZMP+ALJgfABRA=")) \ No newline at end of file diff --git a/apps/rtorch/app.js b/apps/rtorch/app.js new file mode 100644 index 000000000..4f6b1d6f7 --- /dev/null +++ b/apps/rtorch/app.js @@ -0,0 +1,22 @@ +Bangle.setLCDPower(1); +Bangle.setLCDTimeout(0); +g.reset(); +c = 1; +function setColor(delta){ + c+=delta; + c = Math.max(c,0); + c = Math.min(c,2); + if (c<1){ + g.setColor(c,0,0); + }else{ + g.setColor(1,c-1,c-1); + } + g.fillRect(0,0,g.getWidth(),g.getHeight()); +} +setColor(0) +// BTN1 light up toward white +// BTN3 light down to red +// BTN2 to reset +setWatch(()=>setColor(0.1), BTN1, { repeat:true, edge:"rising", debounce: 50 }); +setWatch(()=>load(), BTN2); +setWatch(()=>setColor(-0.1), BTN3, { repeat:true, edge:"rising", debounce: 50 }); diff --git a/apps/rtorch/app.png b/apps/rtorch/app.png new file mode 100644 index 0000000000000000000000000000000000000000..17b0f3efcd9ff5c3fb5656b12b728983569670c9 GIT binary patch literal 1770 zcmVpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H126stB zK~!jg?U`+CTUQy!f9GDuzVW+bJ9VE0hf~F-=-07%v|-B-Acw0*$p}w1Nr* zlTeZN0av0R_(FwHp%V}d_My;qA2zX}ma(oc+8P#G&{n1;OVT8c7bmfuI8OX}4en=Q-y&_g=v!OWJII2U?AaCyWYIjwG0{*^+=}R7}OFKxN5h z+l7Jfu-OLS9-{;P-@q#MziU9wY#4itj=Om?plMBj$LO#dzKyoEwW)ed%c*=a@z_&W zFWVlu*==Zi)zD~*6bglusOoOdPEQ_;4h@d6U1#@R3fzCHIpo0&>IIU4Rq*L7?z51v3Rx~lSLhZ|Qm zOUrm{-Q#T7BF;`F+ZMwMARdhn8;|poh8_GfP`B=JHe?2*M4_kfc*h4Wzt!oUhadis z$wUkx1m4;@I(P1-Wu57?AqGO9(SG=`n&_j=wRyVJcazuES@13Dz z`8p@>G)ctMt33mAgIdj=YHj}2pVqx1Xd^$DBNVp%V>%3dv#68LJveU^h1EGWF z{Rr_?sWv`q62CJ~M}IB8x_S7~@Bm1O-Q~d*sO8PZJ8>t*%Bt9gorUBZmUF=8%4z%F zXe~d!vY+^PmYFK8W1p=R0P*1nsfh&NAM9ga&-;tJ_afyr;5u;K5CifREZ8h@pt9UP z*FUW1$a8xr6bjhgUOd|ZbMUunMX)+h_~Y3>yoeAt(DhCfh_ zHax)HfdP&_QpvBcd=i`Yzv2CLL3FFVU8GXqC>3YjYd}f_{pzoPW+`E4NYc{_kqG4S z;B*SaGV{E%dW_b_7;g^lWF!)ug;(&`1+iG|r$?*IU+=qcLEkU~QX;r$IRSiCO6dMT z^4hteyOL&`J&nt?e5U%WNjw!Jyn4-!K*3iRM4N$s{6Z*{Ux{JO28!Un za|`}&@3=T|aR;faiF97!y{LnSnxfRylwN9$RSC>m<-c!cc2{UN`|~2w_2erjPZrAI zSkoF<01x!^N-o}T@{3E`$?Nm56{p)Wht%Nz*0{>9*5s{ z1Q)=Y6v=_se*C_Y(XOJ%BjSNv=W03T##v3{<=_Ddi{QWgKo1Y@o}jjN$@J+3ah$!G zb|F~xQ!iH8b)Xm?ARLy2hvx79BkZERBS?iRIe2eBd+(Z{dB=hsXbQN5l&6ShUlL!Y ztQY+|unm9*W`5Ba~xUr#nO|%k)^gR!pI#;7e%{{3-Tkz9|H9eVEIu z|5l09GM|C|n63yIy$NQMo6%T}41`nVp ziu`MQIMQ_MEIxCbwb3==c6G%0Lu8-usRQ4k7l(|$mbau=wo;+!{O7P zWh!S`s_&M=11LhbJZRP`CuZR7bMU!r2D7H2xSBY2v5jPA!5iak0S~i_xb4tU7n=H) zd_I3)F}%O75k*x=rzXiHhIsD48`L-_ZX0+g+D6+B9d(Vw!rjx!q_4uFQC&X+Kb=f6 z7Mb}$5v+40{`8yYt8N!~C@N%Up8e^#+2s6$)!~ZH!Kadp&cZvYyhvL^@9hK+iz@NC z(a?uI*OpKcY#^>NgRF(EtDd M07*qoM6N<$f@-*GDF6Tf literal 0 HcmV?d00001 diff --git a/apps/rtorch/widget.js b/apps/rtorch/widget.js new file mode 100644 index 000000000..89009266d --- /dev/null +++ b/apps/rtorch/widget.js @@ -0,0 +1,26 @@ +(function() { + var clickTimes = []; + var clickPattern = ""; + var TAPS = 4; // number of taps + var PERIOD = 1; // seconds + + // we don't actually create/draw a widget here at all... + Bangle.on("lcdPower",function(on) { + // First click (that turns LCD on) isn't given to + // setWatch, so handle it here + if (!on) return; + clickTimes=[getTime()]; + clickPattern="x"; + }); + function tap(e,c) { + clickPattern = clickPattern.substr(-3)+c; + while (clickTimes.length>=TAPS) clickTimes.shift(); + clickTimes.push(e.time); + var clickPeriod = e.time-clickTimes[0]; + if (clickPeriod Date: Sun, 11 Jul 2021 21:40:17 +0200 Subject: [PATCH 026/163] Magic 8 Ball Italiano : like Magic 8 Ball but in italian :D --- apps.json | 14 +++++++ apps/jbm8b_IT/ChangeLog | 1 + apps/jbm8b_IT/app-icon.js | 1 + apps/jbm8b_IT/app.js | 79 ++++++++++++++++++++++++++++++++++++++ apps/jbm8b_IT/app.png | Bin 0 -> 1548 bytes 5 files changed, 95 insertions(+) create mode 100644 apps/jbm8b_IT/ChangeLog create mode 100644 apps/jbm8b_IT/app-icon.js create mode 100644 apps/jbm8b_IT/app.js create mode 100644 apps/jbm8b_IT/app.png diff --git a/apps.json b/apps.json index a2ff7b571..ed49e19ac 100644 --- a/apps.json +++ b/apps.json @@ -2110,6 +2110,20 @@ { "name": "jbm8b.img", "url": "app-icon.js", "evaluate": true } ] }, + { + "id": "jbm8b_IT", + "name": "Magic 8 Ball Italiano", + "shortName": "Magic 8 Ball IT", + "icon": "app.png", + "description": "La palla predice il futuro", + "tags": "game", + "version": "0.03", + "allow_emulator":true, + "storage": [ + { "name": "jbm8b_IT.app.js", "url": "app.js" }, + { "name": "jbm8b_IT.img", "url": "app-icon.js", "evaluate": true } + ] + }, { "id": "BLEcontroller", "name": "BLE Customisable Controller with Joystick", "shortName": "BLE Controller", diff --git a/apps/jbm8b_IT/ChangeLog b/apps/jbm8b_IT/ChangeLog new file mode 100644 index 000000000..b7b783924 --- /dev/null +++ b/apps/jbm8b_IT/ChangeLog @@ -0,0 +1 @@ +0.01: Cloning Magic 8 Ball and make it speak italian \ No newline at end of file diff --git a/apps/jbm8b_IT/app-icon.js b/apps/jbm8b_IT/app-icon.js new file mode 100644 index 000000000..09bf032a6 --- /dev/null +++ b/apps/jbm8b_IT/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwhBC/AGMrq2B1gAEwNWlYthq2s64AKGYIydFpoAEGLUrFqIADqxcXFqhiDFymBFy7GCF1owTRjCSVlYudeiGsF7/XlaNqSKBeP1mBwJxQMBReO1gaEleBMDBLN1hAC1hhBAoIwNCwQAGlZINqxvFGAIXOSBAXQN4hPBC5yQIVBxfBCAgvQSBC+NFAYRDMwJHOF654DqxkBYooALF6+sbIhkEF8Z3CRIWBR6AvXFAzvQF6wnIYQJgNd5AWNdoLoGBBAvPO5pfYH4IvUUwS/GVBzXBYCpHCq2s1mBDwKOWDwRgNPAwVVMCRLCwIABCZ6OJJSAATLxZgRACJeLAAMrFz9WFxiRgRpoADwIub1guQGDmsXhqSfRiL0G1jqkMRYxRwKLUGK2sFryVEq2B1gAEwNWFkIA/AH4A/AH4AQ")) \ No newline at end of file diff --git a/apps/jbm8b_IT/app.js b/apps/jbm8b_IT/app.js new file mode 100644 index 000000000..13ab3d39d --- /dev/null +++ b/apps/jbm8b_IT/app.js @@ -0,0 +1,79 @@ +const affirmative = [ + 'È certo.', + 'È decisamente\ncosì.', + 'Senza alcun\ndubbio.', + 'Sì,\nsenza dubbio.', + 'Ci puoi\ncontare.', + 'Da quanto\nvedo,\nsì.', + 'Molto\nprobabilmente.', + 'Le prospettive\nsono buone.', + 'Sì.', + 'I segni\nindicano\ndi sì.' +]; +const nonCommittal = [ + 'È difficile\ndirlo,\nprova di nuovo.', + 'Rifai la domanda\npiù tardi.', + 'Meglio non\nrisponderti\nadesso.', + 'Non posso\npredirlo ora.', + 'Concentrati e\nrifai la\ndomanda.' +]; +const negative = [ + 'Non ci\ncontare.', + 'La mia\nrisposta\nè no.', + 'Le mie\nfonti dicono\ndi no.', + 'Le prospettive\nnon sono\nbuone.', + 'È molto\ndubbio.' +]; +const title = 'Magic 8 Ball'; + +const answers = [affirmative, nonCommittal, negative]; + +function getRandomArbitrary(min, max) { + return Math.random() * (max - min) + min; +} + +function predict() { + // affirmative, negative or non-committal + let max = answers.length; + const a = Math.floor(getRandomArbitrary(0, max)); + // sets max compared to answer category + max = answers[a].length; + const b = Math.floor(getRandomArbitrary(0, max)); + // get the answer + const response = answers[a][b]; + return response; +} + +function draw(msg) { + // console.log(msg); + g.clear(); + E.showMessage(msg, title); +} + +function reply(button) { + const theButton = (typeof button === 'undefined' || isNaN(button)) ? 1 : button; + const timer = Math.floor(getRandomArbitrary(0, theButton) * 1000); + // Thinking... + draw('...'); + setTimeout('draw(predict());', timer); +} + +function ask() { + draw('Ponimi una\ndomanda\nSì/No e\ntocca lo\nschermo'); +} + +g.clear(); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); +ask(); + +// Event Handlers + +Bangle.on('touch', (button) => reply(button)); + +setWatch(ask, BTN1, { repeat: true, edge: "falling" }); +setWatch(reply, BTN3, { repeat: true, edge: "falling" }); + +// Back to launcher +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); \ No newline at end of file diff --git a/apps/jbm8b_IT/app.png b/apps/jbm8b_IT/app.png new file mode 100644 index 0000000000000000000000000000000000000000..24c3013de011db9c1517ed544e9d383f5c60378c GIT binary patch literal 1548 zcmeH_{WsGK9LK-L%+owW>~?OVSQ<5jdzFVG z7KTZRJWrN~OKhyo#XZ;1!5ArX5tskq{sH%M&g=6&?{nTieLn9rUvGD)hOq_!08md4 zSHEpNvV)rP_9l(0*KLau&ClH#sOsN6vu#wuusAFL)I8MOAcFxw8SwoP@3s?CQUZZM z%F4SrKP2nm6f%%wT+F9t*xz{ zo!zlx$L#IxF&K=aqocF4^O-Ye+}+)AI2<02_xJZF5C{PQ0YoB^L?V&Nh&d$!w&CScp%g@g*C@3f_EG#ZAE-5J~EiGlU z*=1#A<>loS6%`x~r?RrLy1JUn<<`{H)YjJ4)z!Uy`?jH>p|P>Csi~>Cxw)mKrM0!S zt*wp6<8^d&bar;~`TP$bK6G_;b$567^z`)h_V)Gl4Gatn4h{+g0-;biJUlECiNs>D zL?Rg(85tcN9UB`PA0MBXn2<`PQ&UsZ)6+9EGqba^b8~YtnQVT3eqmujE|)JZE-o!C zEiW&B{rdIWw{I&eD++~Tb#--ZZEbyhePd(e`}gmgo10r(Tib8_fBwq_1kdR=w{z+- z9sx7}FhK91^i-dZ002<7rz;lk;Wd^mxh!--q=Y>&&l(UI44!qv`yxh>c)U{^O1JFU z%a;}ljh)Wt4!yc(lI+jS(N5&_O}>~%hcC4sX#H*D+Vm)f7G{2Yve4IU+B&)Y z?$GYABWY+zFG-Kpm_z2WjDs}KYx^G4fTKz8{Q=y znAAd`uHOq9nnlG&5e52-Jn?}ZIE6l?!8crQIGwGipOq&~#_GtX zD~=*r(WQ3Ws}1WYw0Hk7s}L*Y_TFdz8p>hw=$GoNY8}NwHyK=%CDZoxj9q=&`O)F? zFYqmdD{5tmeB<-{!{ESspW6NiN0f4}>{GzaqJ-qY-0Ea~S=Wr@I@;&SMcbbb*IPJT z4e#>niaQQAnGzM)Fupi=8I*C?gtXV2ciZ28Vc~8;FCM25x-Kz6ck~n2)5~CQ#Dpt_ zdpH<_?oEccI&B%8cz^dN{vASx^s!Lxt{PbGrAhhdlpj&{sd6L#pDhOKv`zbaUMoJO QXs6wtZr-j{&ZOjj0hD%CN&o-= literal 0 HcmV?d00001 From f39f1d6804ba51bc90187dd055267de014dbfb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 20:56:31 +0200 Subject: [PATCH 027/163] Add files via upload --- apps/BangleBridge/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 5026b8446..736946049 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -234,12 +234,12 @@ Bangle.on('lcdPower', function (on) { if (flip == 1) { //when off - console.log("--------------------------------------------------------------- 1"); + flip = 0; g.clear(); } else { //when on - console.log("--------------------------------------------------------------- 0"); + flip = 1; g.setFont("Vector", 30); From 749eed2a613bd4de7521e1e06602fbc4f8a37777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 20:59:49 +0200 Subject: [PATCH 028/163] Add files via upload --- apps/BangleBridge/widget.js | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 736946049..3a70a0f68 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -137,6 +137,7 @@ }, 2 * 1000); } + //2021-06-11T19:21:58.000Z function hrm() { @@ -145,7 +146,7 @@ function roundInsert(nueva) { let indexFinal = (lastInsert + 1) % (msr.length); - + //console.log("Index ==> "+ index); msr[indexFinal] = nueva; item = nueva; @@ -232,15 +233,18 @@ var flip = 1; Bangle.on('lcdPower', function (on) { - + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ if (flip == 1) { //when off - + flip = 0; - + //Bangle.buzz(1000); g.clear(); } else { //when on - - + flip = 1; g.setFont("Vector", 30); g.drawString(data[0], 65, 180); @@ -251,29 +255,30 @@ function draw() { - + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); g.drawImage(storage.read("heart.img"), 145, 167); } // Finally add widget - WIDGETS["banglebridge"] = { + WIDGETS["bangle.Sensors"] = { area: "tl", width: 10, draw: draw, }; initSensors(); - + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); data[0] = 80.5; g.setFont("Vector", 30); g.drawString(data[0], 65, 180); Bangle.drawWidgets(); - - setInterval(function () { - + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); var measurement = { hrm: data[0], step: data[1], @@ -282,12 +287,13 @@ com: data[4], gps: data[5] }; - + /* g.clear(); + g.drawString(compssS,100,200); + */ Bluetooth.println(JSON.stringify(measurement) + "#"); }, 5 * 1000); - })(); //End of Widget \ No newline at end of file From 596fcfd01cc858cb18981e00efa1cae288bf9865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:02:08 +0200 Subject: [PATCH 029/163] Delete widget.js --- apps/BangleBridge/widget.js | 299 ------------------------------------ 1 file changed, 299 deletions(-) delete mode 100644 apps/BangleBridge/widget.js diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js deleted file mode 100644 index 3a70a0f68..000000000 --- a/apps/BangleBridge/widget.js +++ /dev/null @@ -1,299 +0,0 @@ -(() => { - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - //2021-06-11T19:21:58.000Z - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - //console.log("Index ==> "+ index); - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - /* - prueba ++; - Bangle.drawWidgets(); - g.setFont("Vector", 45); - g.drawString(prueba,100,200);*/ - if (flip == 1) { //when off - - flip = 0; - //Bangle.buzz(1000); - g.clear(); - } else { //when on - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - // Finally add widget - WIDGETS["bangle.Sensors"] = { - area: "tl", - width: 10, - draw: draw, - }; - - initSensors(); - // Bangle.drawWidgets(); - // Terminal.println("Running BangleBridge"); - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - setInterval(function () { - //console.log("---------------------------------------------------------------"); - //console.log(data); - //Bluetooth.println(data[0]); - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - /* g.clear(); - g.drawString(compssS,100,200); - */ - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); -})(); //End of Widget \ No newline at end of file From 6caa55054fc3aa29ccd3461dbf608d67871cb48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:02:22 +0200 Subject: [PATCH 030/163] Add files via upload --- apps/BangleBridge/connection.wid.js | 299 ++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 apps/BangleBridge/connection.wid.js diff --git a/apps/BangleBridge/connection.wid.js b/apps/BangleBridge/connection.wid.js new file mode 100644 index 000000000..de873376f --- /dev/null +++ b/apps/BangleBridge/connection.wid.js @@ -0,0 +1,299 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + //2021-06-11T19:21:58.000Z + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + //console.log("Index ==> "+ index); + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ + if (flip == 1) { //when off + + flip = 0; + //Bangle.buzz(1000); + g.clear(); + } else { //when on + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + WIDGETS["bangle.Sensors"] = { + area: "tl", + width: 10, + draw: draw, + }; + + initSensors(); + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + setInterval(function () { + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + /* g.clear(); + g.drawString(compssS,100,200); + */ + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); +})(); //End of Widget \ No newline at end of file From 51f380099c66c3cb957ea23ae89fffe905cb54fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:04:45 +0200 Subject: [PATCH 031/163] Rename connection.wid.js to widget.js --- apps/BangleBridge/{connection.wid.js => widget.js} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename apps/BangleBridge/{connection.wid.js => widget.js} (99%) diff --git a/apps/BangleBridge/connection.wid.js b/apps/BangleBridge/widget.js similarity index 99% rename from apps/BangleBridge/connection.wid.js rename to apps/BangleBridge/widget.js index de873376f..15823e99e 100644 --- a/apps/BangleBridge/connection.wid.js +++ b/apps/BangleBridge/widget.js @@ -296,4 +296,4 @@ Bluetooth.println(JSON.stringify(measurement) + "#"); }, 5 * 1000); -})(); //End of Widget \ No newline at end of file +})(); //End of Widget From 284beede2ad2f94473ef1c0212f5e46c5e6ddaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:13:23 +0200 Subject: [PATCH 032/163] Add files via upload --- apps/BangleBridge/widget.js | 601 ++++++++++++++++++------------------ 1 file changed, 302 insertions(+), 299 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 15823e99e..f770053c5 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -1,299 +1,302 @@ -(() => { - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - //2021-06-11T19:21:58.000Z - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - //console.log("Index ==> "+ index); - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - /* - prueba ++; - Bangle.drawWidgets(); - g.setFont("Vector", 45); - g.drawString(prueba,100,200);*/ - if (flip == 1) { //when off - - flip = 0; - //Bangle.buzz(1000); - g.clear(); - } else { //when on - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - // Finally add widget - WIDGETS["bangle.Sensors"] = { - area: "tl", - width: 10, - draw: draw, - }; - - initSensors(); - // Bangle.drawWidgets(); - // Terminal.println("Running BangleBridge"); - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - setInterval(function () { - //console.log("---------------------------------------------------------------"); - //console.log(data); - //Bluetooth.println(data[0]); - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - /* g.clear(); - g.drawString(compssS,100,200); - */ - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); -})(); //End of Widget +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + //2021-06-11T19:21:58.000Z + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + //console.log("Index ==> "+ index); + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ + if (flip == 1) { //when off + + flip = 0; + //Bangle.buzz(1000); + g.clear(); + } else { //when on + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + + + initSensors(); + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + setInterval(function () { + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + /* g.clear(); + g.drawString(compssS,100,200); + */ + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); +})(); //End of Widget + // add your widget + WIDGETS["bangle.Sensors"]={ + area: "tl", + width: 10, + draw: draw, + }; +})() \ No newline at end of file From 5838f49683719cc4f6e73b98586b3aa66f4ddf10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:21:02 +0200 Subject: [PATCH 033/163] Add files via upload --- apps/BangleBridge/widget.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index f770053c5..4d7bf67e5 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -255,8 +255,9 @@ function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("iconWatch.img"), 1,1); + g.drawImage(storage.read("heart.img"), 145, 167); } From b20e1ff2de8474013a8baff9eee6dcf01063fd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:25:12 +0200 Subject: [PATCH 034/163] Add files via upload --- apps/BangleBridge/widget.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 4d7bf67e5..e8f6eb0f0 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -255,15 +255,18 @@ function draw() { - // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("iconWatch.img"), 1,1); - + + g.drawImage(storage.read("iconWatch.img"), 1, 1); g.drawImage(storage.read("heart.img"), 145, 167); } // Finally add widget - + WIDGETS["bangle.Sensors"] = { + area: "tl", + width: 10, + draw: draw, + }; initSensors(); // Bangle.drawWidgets(); From 8d9b078a4882827994914999036fad31580ba75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:26:42 +0200 Subject: [PATCH 035/163] Delete widget.js --- apps/BangleBridge/widget.js | 306 ------------------------------------ 1 file changed, 306 deletions(-) delete mode 100644 apps/BangleBridge/widget.js diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js deleted file mode 100644 index e8f6eb0f0..000000000 --- a/apps/BangleBridge/widget.js +++ /dev/null @@ -1,306 +0,0 @@ -(() => { - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - //2021-06-11T19:21:58.000Z - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - //console.log("Index ==> "+ index); - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - /* - prueba ++; - Bangle.drawWidgets(); - g.setFont("Vector", 45); - g.drawString(prueba,100,200);*/ - if (flip == 1) { //when off - - flip = 0; - //Bangle.buzz(1000); - g.clear(); - } else { //when on - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), 1, 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - // Finally add widget - WIDGETS["bangle.Sensors"] = { - area: "tl", - width: 10, - draw: draw, - }; - - initSensors(); - // Bangle.drawWidgets(); - // Terminal.println("Running BangleBridge"); - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - setInterval(function () { - //console.log("---------------------------------------------------------------"); - //console.log(data); - //Bluetooth.println(data[0]); - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - /* g.clear(); - g.drawString(compssS,100,200); - */ - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); -})(); //End of Widget - // add your widget - WIDGETS["bangle.Sensors"]={ - area: "tl", - width: 10, - draw: draw, - }; -})() \ No newline at end of file From 223ccb7e3810a27a385e683ab161998a2f1d16d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:26:49 +0200 Subject: [PATCH 036/163] Delete algo.txt --- apps/BangleBridge/algo.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/BangleBridge/algo.txt diff --git a/apps/BangleBridge/algo.txt b/apps/BangleBridge/algo.txt deleted file mode 100644 index 1df28a22d..000000000 --- a/apps/BangleBridge/algo.txt +++ /dev/null @@ -1 +0,0 @@ -ss From c7abb95f90b6ae509545c48f5364ebc4cbbaefc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:28:30 +0200 Subject: [PATCH 037/163] Add files via upload --- apps/BangleBridge/app.js | 299 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 apps/BangleBridge/app.js diff --git a/apps/BangleBridge/app.js b/apps/BangleBridge/app.js new file mode 100644 index 000000000..3a70a0f68 --- /dev/null +++ b/apps/BangleBridge/app.js @@ -0,0 +1,299 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + //2021-06-11T19:21:58.000Z + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + //console.log("Index ==> "+ index); + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ + if (flip == 1) { //when off + + flip = 0; + //Bangle.buzz(1000); + g.clear(); + } else { //when on + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + WIDGETS["bangle.Sensors"] = { + area: "tl", + width: 10, + draw: draw, + }; + + initSensors(); + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + setInterval(function () { + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + /* g.clear(); + g.drawString(compssS,100,200); + */ + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); +})(); //End of Widget \ No newline at end of file From 230d8e195e2c1ce8c4f3ca0b8a9df238368d2b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:32:10 +0200 Subject: [PATCH 038/163] Delete app.js --- apps/BangleBridge/app.js | 299 --------------------------------------- 1 file changed, 299 deletions(-) delete mode 100644 apps/BangleBridge/app.js diff --git a/apps/BangleBridge/app.js b/apps/BangleBridge/app.js deleted file mode 100644 index 3a70a0f68..000000000 --- a/apps/BangleBridge/app.js +++ /dev/null @@ -1,299 +0,0 @@ -(() => { - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - //2021-06-11T19:21:58.000Z - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - //console.log("Index ==> "+ index); - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - /* - prueba ++; - Bangle.drawWidgets(); - g.setFont("Vector", 45); - g.drawString(prueba,100,200);*/ - if (flip == 1) { //when off - - flip = 0; - //Bangle.buzz(1000); - g.clear(); - } else { //when on - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - // Finally add widget - WIDGETS["bangle.Sensors"] = { - area: "tl", - width: 10, - draw: draw, - }; - - initSensors(); - // Bangle.drawWidgets(); - // Terminal.println("Running BangleBridge"); - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - setInterval(function () { - //console.log("---------------------------------------------------------------"); - //console.log(data); - //Bluetooth.println(data[0]); - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - /* g.clear(); - g.drawString(compssS,100,200); - */ - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); -})(); //End of Widget \ No newline at end of file From f1fc7256b704ab7fe6a2677c1a9cd7869acf29bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:36:35 +0200 Subject: [PATCH 039/163] Add files via upload --- apps/BangleBridge/widget.js | 304 ++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 apps/BangleBridge/widget.js diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js new file mode 100644 index 000000000..514acf4dc --- /dev/null +++ b/apps/BangleBridge/widget.js @@ -0,0 +1,304 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + //2021-06-11T19:21:58.000Z + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + //console.log("Index ==> "+ index); + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ + if (flip == 1) { //when off + + flip = 0; + //Bangle.buzz(1000); + g.clear(); + } else { //when on + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("iconWatch.img"), 1,1); + + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + + + initSensors(); + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + // Bangle.drawWidgets(); + setInterval(function () { + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + /* g.clear(); + g.drawString(compssS,100,200); + */ + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + WIDGETS["bangle.Sensors"].draw(WIDGETS["bangle.Sensors"]); + + }, 5 * 1000); +})(); //End of Widget + // add your widget + WIDGETS["bangle.Sensors"]={ + area: "tl", + width: 10, + draw: draw, + }; +})() \ No newline at end of file From 42b4f71f4fddeb938aa512c75e921e6fe23baf0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:42:00 +0200 Subject: [PATCH 040/163] Add files via upload --- apps/BangleBridge/widget.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 514acf4dc..0d33b53c5 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -8,6 +8,11 @@ */ //Font + WIDGETS["bangle.Sensors"]={ + area: "tl", + width: 10, + draw: draw, + }; g.setFont("Vector", 100); //variabangle.Sensorss let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings @@ -295,10 +300,3 @@ }, 5 * 1000); })(); //End of Widget - // add your widget - WIDGETS["bangle.Sensors"]={ - area: "tl", - width: 10, - draw: draw, - }; -})() \ No newline at end of file From da87512cb80a0596340012cb53cfedf75ae564f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:44:10 +0200 Subject: [PATCH 041/163] Add files via upload --- apps/BangleBridge/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 0d33b53c5..13ada1be2 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -296,7 +296,7 @@ Bluetooth.println(JSON.stringify(measurement) + "#"); - WIDGETS["bangle.Sensors"].draw(WIDGETS["bangle.Sensors"]); + draw(); }, 5 * 1000); })(); //End of Widget From 696385b38d770fd9c30d2aad1688096af9e74c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 21:51:02 +0200 Subject: [PATCH 042/163] Add files via upload --- apps/BangleBridge/widget.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 13ada1be2..d408fa319 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -8,11 +8,7 @@ */ //Font - WIDGETS["bangle.Sensors"]={ - area: "tl", - width: 10, - draw: draw, - }; + g.setFont("Vector", 100); //variabangle.Sensorss let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings @@ -299,4 +295,10 @@ draw(); }, 5 * 1000); + + WIDGETS["bangle.Sensors"]={ + area: "tl", + width: 10, + draw: draw, + }; })(); //End of Widget From bdfb28ab42a57e54a7f3e9c418d40cb1289e3518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 22:13:28 +0200 Subject: [PATCH 043/163] Add files via upload --- apps/BangleBridge/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index d408fa319..3b0b31c8f 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -257,8 +257,8 @@ function draw() { // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("iconWatch.img"), 1,1); - + g.drawImage(storage.read("iconWatch.img"),this.x + 1,this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); } From 9839e65fe61ce6789587a5606dfd0f2baeaa2e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 22:22:29 +0200 Subject: [PATCH 044/163] Add files via upload --- apps/BangleBridge/app.js | 299 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 apps/BangleBridge/app.js diff --git a/apps/BangleBridge/app.js b/apps/BangleBridge/app.js new file mode 100644 index 000000000..3a70a0f68 --- /dev/null +++ b/apps/BangleBridge/app.js @@ -0,0 +1,299 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + //2021-06-11T19:21:58.000Z + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + //console.log("Index ==> "+ index); + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ + if (flip == 1) { //when off + + flip = 0; + //Bangle.buzz(1000); + g.clear(); + } else { //when on + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + WIDGETS["bangle.Sensors"] = { + area: "tl", + width: 10, + draw: draw, + }; + + initSensors(); + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + setInterval(function () { + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + /* g.clear(); + g.drawString(compssS,100,200); + */ + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); +})(); //End of Widget \ No newline at end of file From 99860e9ff6fe1ff16bb85ff12be4b05b4c582bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Mon, 12 Jul 2021 22:22:54 +0200 Subject: [PATCH 045/163] Delete widget.js --- apps/BangleBridge/widget.js | 304 ------------------------------------ 1 file changed, 304 deletions(-) delete mode 100644 apps/BangleBridge/widget.js diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js deleted file mode 100644 index 3b0b31c8f..000000000 --- a/apps/BangleBridge/widget.js +++ /dev/null @@ -1,304 +0,0 @@ -(() => { - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - //2021-06-11T19:21:58.000Z - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - //console.log("Index ==> "+ index); - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - /* - prueba ++; - Bangle.drawWidgets(); - g.setFont("Vector", 45); - g.drawString(prueba,100,200);*/ - if (flip == 1) { //when off - - flip = 0; - //Bangle.buzz(1000); - g.clear(); - } else { //when on - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("iconWatch.img"),this.x + 1,this.y + 1); - - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - // Finally add widget - - - initSensors(); - // Bangle.drawWidgets(); - // Terminal.println("Running BangleBridge"); - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - // Bangle.drawWidgets(); - setInterval(function () { - //console.log("---------------------------------------------------------------"); - //console.log(data); - //Bluetooth.println(data[0]); - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - /* g.clear(); - g.drawString(compssS,100,200); - */ - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - draw(); - - }, 5 * 1000); - - WIDGETS["bangle.Sensors"]={ - area: "tl", - width: 10, - draw: draw, - }; -})(); //End of Widget From bd32905794275a7d7d888e89912a4fbf8d066bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 15:28:56 +0200 Subject: [PATCH 046/163] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 5af0f3d73..c2ccf5eb2 100644 --- a/apps.json +++ b/apps.json @@ -3169,7 +3169,7 @@ "type": "widget", "readme": "README.md", "storage": [ - {"name":"BangleBridge.wid.js","url":"widget.js"} + {"name":"BangleBridge.app.js","url":"app.js"} ] }, { "id": "qmsched", From 6acfa724fa4d3e94254eea0e0abd932656b97439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 15:33:02 +0200 Subject: [PATCH 047/163] Add files via upload --- apps/BangleBridge/app.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/BangleBridge/app.js b/apps/BangleBridge/app.js index 3a70a0f68..4ce084f37 100644 --- a/apps/BangleBridge/app.js +++ b/apps/BangleBridge/app.js @@ -1,4 +1,4 @@ -(() => { + /** * Widget measurements * Description: @@ -261,12 +261,6 @@ } - // Finally add widget - WIDGETS["bangle.Sensors"] = { - area: "tl", - width: 10, - draw: draw, - }; initSensors(); // Bangle.drawWidgets(); @@ -296,4 +290,3 @@ Bluetooth.println(JSON.stringify(measurement) + "#"); }, 5 * 1000); -})(); //End of Widget \ No newline at end of file From 7aa9fb88ee4d1aa5fd33cf7cd0521348204cbf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 15:33:16 +0200 Subject: [PATCH 048/163] Add files via upload --- app.js | 292 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 app.js diff --git a/app.js b/app.js new file mode 100644 index 000000000..4ce084f37 --- /dev/null +++ b/app.js @@ -0,0 +1,292 @@ + + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + //2021-06-11T19:21:58.000Z + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + //console.log("Index ==> "+ index); + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ + if (flip == 1) { //when off + + flip = 0; + //Bangle.buzz(1000); + g.clear(); + } else { //when on + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + + g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + + initSensors(); + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + setInterval(function () { + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + /* g.clear(); + g.drawString(compssS,100,200); + */ + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + + }, 5 * 1000); From 185a57a1912e01660600a71d56baf5cd0327a6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:12:49 +0200 Subject: [PATCH 049/163] Update apps.json --- apps.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index c2ccf5eb2..8967651be 100644 --- a/apps.json +++ b/apps.json @@ -3169,7 +3169,9 @@ "type": "widget", "readme": "README.md", "storage": [ - {"name":"BangleBridge.app.js","url":"app.js"} + {"name":"BangleBridge.app.js","url":"app.js"}, + {"name":"iconWatch.img","url":"iconWatch.img","evaluate":true}, + {"name":"heart.img","url":"heart.img","evaluate":true} ] }, { "id": "qmsched", From 1a95cbf7f6d18d57e24df7500f5177f948be645d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:18:37 +0200 Subject: [PATCH 050/163] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 8967651be..28e484deb 100644 --- a/apps.json +++ b/apps.json @@ -3170,8 +3170,8 @@ "readme": "README.md", "storage": [ {"name":"BangleBridge.app.js","url":"app.js"}, - {"name":"iconWatch.img","url":"iconWatch.img","evaluate":true}, - {"name":"heart.img","url":"heart.img","evaluate":true} + {"name":"iconWatch.img","url":"iconWatch.img"}, + {"name":"heart.img","url":"heart.img"} ] }, { "id": "qmsched", From 232c49a6ce075beb7ef3d117721cf0e51893bdc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:33:41 +0200 Subject: [PATCH 051/163] Delete app.js --- apps/BangleBridge/app.js | 292 --------------------------------------- 1 file changed, 292 deletions(-) delete mode 100644 apps/BangleBridge/app.js diff --git a/apps/BangleBridge/app.js b/apps/BangleBridge/app.js deleted file mode 100644 index 4ce084f37..000000000 --- a/apps/BangleBridge/app.js +++ /dev/null @@ -1,292 +0,0 @@ - - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - //2021-06-11T19:21:58.000Z - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - //console.log("Index ==> "+ index); - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - /* - prueba ++; - Bangle.drawWidgets(); - g.setFont("Vector", 45); - g.drawString(prueba,100,200);*/ - if (flip == 1) { //when off - - flip = 0; - //Bangle.buzz(1000); - g.clear(); - } else { //when on - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - - initSensors(); - // Bangle.drawWidgets(); - // Terminal.println("Running BangleBridge"); - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - setInterval(function () { - //console.log("---------------------------------------------------------------"); - //console.log(data); - //Bluetooth.println(data[0]); - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - /* g.clear(); - g.drawString(compssS,100,200); - */ - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); From 12fd3ca464649f944e3026230630db9e78992beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:34:52 +0200 Subject: [PATCH 052/163] Delete iconWatch.img --- apps/BangleBridge/iconWatch.img | Bin 255 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/BangleBridge/iconWatch.img diff --git a/apps/BangleBridge/iconWatch.img b/apps/BangleBridge/iconWatch.img deleted file mode 100644 index 4a8434583521668bf41f87e690e750d6fa743be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 zcmW;HyAFad6b9hGA+ZawD+8gs6C(p&9*L2GV2LkQ6Q4tC7+kyQV66XXhcBlmJ(spS zg%WZO*;!Oc)GtTPMLZUsjw*}5xI?5p23ljJ4Rd_Y8*5PkC+(OCg=xc=8|ph3_4-CRf-{2_ VqY;Pvo9@dHds!6LX9aAt!XL*LHO&A3 From 78bf4516f2d1d263ec69e5170a0328162fc0e5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:35:06 +0200 Subject: [PATCH 053/163] Delete heart.img --- apps/BangleBridge/heart.img | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/BangleBridge/heart.img diff --git a/apps/BangleBridge/heart.img b/apps/BangleBridge/heart.img deleted file mode 100644 index b8e339b30..000000000 --- a/apps/BangleBridge/heart.img +++ /dev/null @@ -1 +0,0 @@ -00ˆþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ þþþþþþþþþþþþþþ þþþþþþþþþþþþþþþþþþ þþþþþþþþþþ þþþþþþþþþþþþþþþ þþþþþþ þþþþþþþþþþþþþ þþþþ þþþþþþþþþþþ þþ ?? þþþþþþþþþ ÿÿ þþþþþþþþ ÿÿ þþþþþþþ ÿÿ þþþþþþ ÿÿ þþþþþþ ?ÿÿÿÿÿÿÿÿÿÿ? þþþþþþ ?ÿÿÿÿÿÿÿÿÿÿ? þþþþþþ ÿÿ ''' 'þþþþþþ ÿÿ' '''þþþþþþ ÿÿ' ''''þþþþþþþ 'ÿÿ' '''''þþþþþþþþ '??'''''''þþþþþþþþþ ''''''''þþþþþþþþþþ ''''''''þþþþþþþþþþþ '''''''''þþþþþþþþþþþþ ''''''''''þþþþþþþþþþþþþ '''''''''''þþþþþþþþþþþþþþþ ''''''''''''þþþþþþþþþþþþþþþþþ ''''''''''''þþþþþþþþþþþþþþþþþþþ '''''''''''''þþþþþþþþþþþþþþþþþþþþþ '''''''''''''þþþþþþþþþþþþþþþþþþþþþþþ ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþ ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþ '''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþ '''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ \ No newline at end of file From 185ed9ed9ba30fb5e7f28b6861192288ab632082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:35:42 +0200 Subject: [PATCH 054/163] Add files via upload --- apps/BangleBridge/heart.png | 1 + apps/BangleBridge/iconWatch.png | Bin 0 -> 255 bytes apps/BangleBridge/widget.js | 304 ++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 apps/BangleBridge/heart.png create mode 100644 apps/BangleBridge/iconWatch.png create mode 100644 apps/BangleBridge/widget.js diff --git a/apps/BangleBridge/heart.png b/apps/BangleBridge/heart.png new file mode 100644 index 000000000..b8e339b30 --- /dev/null +++ b/apps/BangleBridge/heart.png @@ -0,0 +1 @@ +00ˆþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ þþþþþþþþþþþþþþ þþþþþþþþþþþþþþþþþþ þþþþþþþþþþ þþþþþþþþþþþþþþþ þþþþþþ þþþþþþþþþþþþþ þþþþ þþþþþþþþþþþ þþ ?? þþþþþþþþþ ÿÿ þþþþþþþþ ÿÿ þþþþþþþ ÿÿ þþþþþþ ÿÿ þþþþþþ ?ÿÿÿÿÿÿÿÿÿÿ? þþþþþþ ?ÿÿÿÿÿÿÿÿÿÿ? þþþþþþ ÿÿ ''' 'þþþþþþ ÿÿ' '''þþþþþþ ÿÿ' ''''þþþþþþþ 'ÿÿ' '''''þþþþþþþþ '??'''''''þþþþþþþþþ ''''''''þþþþþþþþþþ ''''''''þþþþþþþþþþþ '''''''''þþþþþþþþþþþþ ''''''''''þþþþþþþþþþþþþ '''''''''''þþþþþþþþþþþþþþþ ''''''''''''þþþþþþþþþþþþþþþþþ ''''''''''''þþþþþþþþþþþþþþþþþþþ '''''''''''''þþþþþþþþþþþþþþþþþþþþþ '''''''''''''þþþþþþþþþþþþþþþþþþþþþþþ ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþ ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþ '''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþ '''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''''''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ''þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ \ No newline at end of file diff --git a/apps/BangleBridge/iconWatch.png b/apps/BangleBridge/iconWatch.png new file mode 100644 index 0000000000000000000000000000000000000000..4a8434583521668bf41f87e690e750d6fa743be1 GIT binary patch literal 255 zcmW;HyAFad6b9hGA+ZawD+8gs6C(p&9*L2GV2LkQ6Q4tC7+kyQV66XXhcBlmJ(spS zg%WZO*;!Oc)GtTPMLZUsjw*}5xI?5p23ljJ4Rd_Y8*5PkC+(OCg=xc=8|ph3_4-CRf-{2_ VqY;Pvo9@dHds!6LX9aAt!XL*LHO&A3 literal 0 HcmV?d00001 diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js new file mode 100644 index 000000000..3b0b31c8f --- /dev/null +++ b/apps/BangleBridge/widget.js @@ -0,0 +1,304 @@ +(() => { + /** + * Widget measurements + * Description: + * name: connection.wid.js + *icon: conectionIcon.icon + * + */ + + //Font + + g.setFont("Vector", 100); + //variabangle.Sensorss + let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings + let accelN, compssN, gpsN, hrmN, stepN; //Num + let prueba = 1; + let data = [0, 0, 0, 0, 0, 0]; + //Constants for redabangle.Sensors code + let storage = require('Storage'); + let deCom = require('heatshrink'); + + + + + //Sensors code + /** + * + * @author Jorge + */ + function accel() { + + Bangle.on('accel', function (acc) { + // acc = {x,y,z,diff,mag} + accelN = acc; + }); + + setInterval(function () { + + acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; + data[3] = accelN; + }, 2 * 1000); + + } + + function btt() { + + setInterval(function () { + + bttS = E.getBattery(); //return String + data[2] = E.getBattery(); + }, 15 * 1000); + + } + + + + function compss() { + + Bangle.setCompassPower(1); + Bangle.on('mag', function (mag) { + // mag = {x,y,z,dx,dy,dz,heading} + compssN = mag; + }); + + + setInterval(function () { + + compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + + "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + + "C: " + compssN.heading; //return String + data[4] = compssN; + }, 2 * 1000); + + } + + + + function gps() { + + Bangle.setGPSPower(1); + Bangle.on('GPS', function (gps) { + // gps = {lat,lon,alt,speed,etc} + gpsN = gps; + + }); + + setInterval(function () { + + gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + + "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String + // work out how to display the current time + var d = new Date(); + var year = d.getFullYear(); + + var month = d.getMonth() + 1; + var finalMonth = 0; + if (month < 10) { + finalMonth = "0" + month; + } else { + finalMonth = month; + } + var day = d.getDate(); + var finalDay = 0; + if (day < 10) { + finalDay = "0" + day; + } else { + finalDay = day; + } + var h = d.getHours(), + m = d.getMinutes(); + var finalh = 0; + if (h < 10) { + finalh = "0" + h; + } else { + finalh = h; + } + var finalM = 0; + if (m < 10) { + finalM = "0" + m; + } else { + finalM = m; + } + + var s = d.getSeconds(); + var finalS = 0; + if (s < 10) { + finalS = "0" + s; + } else { + finalS = s; + } + var z = d.getMilliseconds(); + var zFinal = new String(z); + zFinal = zFinal.replace('.', ''); + var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; + var time = h + ":" + ("0" + m).substr(-2); + gpsN.time = completeTime; + data[5] = gpsN; + }, 2 * 1000); + } + + //2021-06-11T19:21:58.000Z + + function hrm() { + + let msr = [0, 0, 0, 0, 0]; + let lastInsert = -1; + + function roundInsert(nueva) { + let indexFinal = (lastInsert + 1) % (msr.length); + //console.log("Index ==> "+ index); + msr[indexFinal] = nueva; + + item = nueva; + lastInsert = indexFinal; + + } + + function normalize(nueva) { + + let normalize = 0; + roundInsert(nueva); + + + msr.forEach(function (number) { + normalize += number; + }); + normalize = normalize / msr.length; + + return normalize; + + } + + + + + setInterval(function () { + + if (!isNaN(hrmN)) { + + + hrmN = normalize(hrmN); + var roundedRate = parseFloat(hrmN).toFixed(2); + hrmS = String.valueOf(roundedRate); //return String + //console.log("array----->" + msr); + data[0] = roundedRate; + + } + + + + + + }, 2 * 1000); + + } + + + function steps() { + + Bangle.on('step', s => { + + stepN = s; + }); + + + setInterval(function () { + + stepS = String.valueOf(stepN); //return String + data[1] = stepN; + }, 2 * 1000); + + + } + + function initSensors() { + + //need power control + Bangle.setHRMPower(1); + + Bangle.on('HRM', function (hrm) { + hrmN = hrm.bpm; + + + }); + console.log("Sensors are being Init...."); + accel(); + btt(); + compss(); + gps(); + hrm(); + steps(); + + } + + var flip = 1; + Bangle.on('lcdPower', function (on) { + /* + prueba ++; + Bangle.drawWidgets(); + g.setFont("Vector", 45); + g.drawString(prueba,100,200);*/ + if (flip == 1) { //when off + + flip = 0; + //Bangle.buzz(1000); + g.clear(); + } else { //when on + + flip = 1; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + Bangle.drawWidgets(); + } + + }); + + + function draw() { + // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); + g.drawImage(storage.read("iconWatch.img"),this.x + 1,this.y + 1); + + g.drawImage(storage.read("heart.img"), 145, 167); + } + + + // Finally add widget + + + initSensors(); + // Bangle.drawWidgets(); + // Terminal.println("Running BangleBridge"); + data[0] = 80.5; + g.setFont("Vector", 30); + g.drawString(data[0], 65, 180); + // Bangle.drawWidgets(); + setInterval(function () { + //console.log("---------------------------------------------------------------"); + //console.log(data); + //Bluetooth.println(data[0]); + var measurement = { + hrm: data[0], + step: data[1], + batt: data[2], + acc: data[3], + com: data[4], + gps: data[5] + }; + /* g.clear(); + g.drawString(compssS,100,200); + */ + + + + Bluetooth.println(JSON.stringify(measurement) + "#"); + draw(); + + }, 5 * 1000); + + WIDGETS["bangle.Sensors"]={ + area: "tl", + width: 10, + draw: draw, + }; +})(); //End of Widget From e9abfa160e65aa99eb89401ac5d657136cd86fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:40:47 +0200 Subject: [PATCH 055/163] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 28e484deb..e1ba1d078 100644 --- a/apps.json +++ b/apps.json @@ -3169,7 +3169,7 @@ "type": "widget", "readme": "README.md", "storage": [ - {"name":"BangleBridge.app.js","url":"app.js"}, + {"name":"banglebridge.wid.js","url":"widget.js"}, {"name":"iconWatch.img","url":"iconWatch.img"}, {"name":"heart.img","url":"heart.img"} ] From 4c8cd1f58104b017be7ecab448652bbf43ba4a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:41:05 +0200 Subject: [PATCH 056/163] Add files via upload --- apps/BangleBridge/widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index 3b0b31c8f..ee480268e 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -257,9 +257,9 @@ function draw() { // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("iconWatch.img"),this.x + 1,this.y + 1); - - g.drawImage(storage.read("heart.img"), 145, 167); + g.drawImage(storage.read("iconWatch.png"),this.x + 1,this.y + 1); + + g.drawImage(storage.read("heart.png"), 145, 167); } @@ -296,7 +296,7 @@ }, 5 * 1000); - WIDGETS["bangle.Sensors"]={ + WIDGETS["banglebridge"]={ area: "tl", width: 10, draw: draw, From 8197f96e24be42432b94463fc14762ea7e553dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:42:32 +0200 Subject: [PATCH 057/163] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index e1ba1d078..e91d9b5a7 100644 --- a/apps.json +++ b/apps.json @@ -3170,8 +3170,8 @@ "readme": "README.md", "storage": [ {"name":"banglebridge.wid.js","url":"widget.js"}, - {"name":"iconWatch.img","url":"iconWatch.img"}, - {"name":"heart.img","url":"heart.img"} + {"name":"iconWatch.png","url":"iconWatch.png"}, + {"name":"heart.png","url":"heart.png"} ] }, { "id": "qmsched", From 906b530f5888d0a7bfa0a737f22a43734cbf7a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez=20Ramos?= Date: Thu, 15 Jul 2021 16:45:52 +0200 Subject: [PATCH 058/163] Add files via upload --- apps/BangleBridge/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/BangleBridge/widget.js b/apps/BangleBridge/widget.js index ee480268e..9feecc703 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/BangleBridge/widget.js @@ -292,7 +292,7 @@ Bluetooth.println(JSON.stringify(measurement) + "#"); - draw(); + //draw(); }, 5 * 1000); From 7c5369d11fcd03141073c96c0ad71bb94c6b7aac Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 17 Jul 2021 15:49:50 -0400 Subject: [PATCH 059/163] Update app.js --- apps/doztime/app.js | 50 ++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/apps/doztime/app.js b/apps/doztime/app.js index 83f536018..9faede70a 100644 --- a/apps/doztime/app.js +++ b/apps/doztime/app.js @@ -17,7 +17,7 @@ const timeColour = "#f2f2f2"; const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#0000ff","#ff00ff","#ff0080"]; const calen10 = {"size":32,"pt0":[32-g_x_off,16],"step":[20,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line const calen7 = {"size":32,"pt0":[62-g_x_off,16],"step":[20,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line -const time5 = {"size":48,"pt0":[64-g_x_off,24],"step":[30,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line; was 64 +const time5 = {"size":48,"pt0":[64-g_x_off,24],"step":[30,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line const time6 = {"size":48,"pt0":[48-g_x_off,24],"step":[30,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line const baseYear = 11584; const baseDate = Date(2020,11,21); // month values run from 0 to 11 @@ -30,8 +30,11 @@ let lastX = 999999999; let res = {}; //var last_time_log = 0; +var drawtime_timeout; + // Date and time graphics buffers var dateColour = "#ffffff"; // override later +var timeColour2 = timeColour; var g_d = Graphics.createArrayBuffer(g_width,g_height_d,1,{'msb':true}); var g_t = Graphics.createArrayBuffer(g_width,g_height_t,1,{'msb':true}); // Set screen mode and function to write graphics buffers @@ -46,7 +49,7 @@ g.flip = function() height:g_height_d, buffer:g_d.buffer }, g_x_off, g_y_off + g_y_off_d); - g.setColor(timeColour); + g.setColor(timeColour2); g.drawImage( { width:g_width, @@ -118,7 +121,7 @@ function formatDate(res,dateFormat){ return(yyyy+"-"+m+"-"+w+"-"+d); } -function writeDozTime(text,def,colour){ +function writeDozTime(text,def){ let pts = def.pts; let x=def.pt0[0]; let y=def.pt0[1]; @@ -133,6 +136,7 @@ function writeDozTime(text,def,colour){ } } function writeDozDate(text,def,colour){ + dateColour = colour; let pts = def.pts; let x=def.pt0[0]; @@ -177,10 +181,10 @@ function drawTime() { // Write to background buffers, then display on screen writeDozDate(date,calenDef,res.colour); - writeDozTime(time,timeDef,timeColour); + writeDozTime(time,timeDef); g.flip(); // Ready next interval - setTimeout(drawTime,wait); + drawtime_timeout = setTimeout(drawTime,wait); } else { @@ -196,22 +200,14 @@ function modeTime() timeActiveUntil = new Date(); timeActiveUntil.setDate(timeActiveUntil.getDate()); timeActiveUntil.setSeconds(timeActiveUntil.getSeconds()+15); - //Bangle.setLCDPower(true); - clearTimeout(); + if (typeof drawtime_timeout !== 'undefined') + { + clearTimeout(drawtime_timeout); + } drawTime(); } - Bangle.loadWidgets(); - -// Time-logging function -/*function logTime(label) -{ - var d = new Date(); - var t = d.getTime(); - var diff_test = t - last_time_log; - last_time_log = t; - console.log(label + " at time: " + t + ", since last: " + diff_test); -}*/ +Bangle.drawWidgets(); // Functions for weather mode - TODO function drawWeather() {} @@ -222,4 +218,20 @@ Bangle.on('twist', function() { modeTime(); }); -Bangle.drawWidgets(); +// Time fix with GPS +function fixTime() { + Bangle.on("GPS",function cb(g) { + Bangle.setGPSPower(0,"time"); + Bangle.removeListener("GPS",cb); + if (!g.time || (g.time.getFullYear()<2000) || + (g.time.getFullYear()>2200)) { + } else { + // We have a GPS time. Set time + setTime(g.time.getTime()/1000); + } + }); + Bangle.setGPSPower(1,"time"); + setTimeout(fixTime, 10*60*1000); // every 10 minutes +} +// Start time fixing with GPS on next 10 minute interval +setTimeout(fixTime, ((60-(new Date()).getMinutes()) % 10) * 60 * 1000); From 13598a209a12a2ac5f78df796bf7ca7501312845 Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 17 Jul 2021 15:57:58 -0400 Subject: [PATCH 060/163] Update ChangeLog --- apps/doztime/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/doztime/ChangeLog b/apps/doztime/ChangeLog index 5560f00bc..f615b246e 100644 --- a/apps/doztime/ChangeLog +++ b/apps/doztime/ChangeLog @@ -1 +1,3 @@ 0.01: New App! +0.02 added emulator capability and display of widgets +0.03 bug of advancing time fixed; doztime now correct within 1 second From 03716d5b80cee614ab26edffc829e8d9df9cd8f3 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sat, 17 Jul 2021 21:04:04 +0100 Subject: [PATCH 061/163] solar clock: First Commit --- apps.json | 25 ++ apps/solarclock/ChangeLog | 1 + apps/solarclock/README.md | 1 + apps/solarclock/app.png | Bin 0 -> 33522 bytes apps/solarclock/solar_clock-icon.js | 1 + apps/solarclock/solar_clock.js | 466 +++++++++++++++++++++++++ apps/solarclock/solar_clock.png | Bin 0 -> 2669 bytes apps/solarclock/solar_colors.js | 14 + apps/solarclock/solar_controller.js | 247 +++++++++++++ apps/solarclock/solar_date_utils.js | 132 +++++++ apps/solarclock/solar_graphic_utils.js | 94 +++++ apps/solarclock/solar_loc.Iceland.json | 4 + apps/solarclock/solar_loc.Kauai.json | 4 + apps/solarclock/solar_loc.Tokyo.json | 4 + apps/solarclock/solar_loc.local.json | 3 + apps/solarclock/solar_location.js | 84 +++++ apps/solarclock/solar_locations.json | 1 + apps/solarclock/solar_math_utils.js | 34 ++ 18 files changed, 1115 insertions(+) create mode 100644 apps/solarclock/ChangeLog create mode 100644 apps/solarclock/README.md create mode 100644 apps/solarclock/app.png create mode 100644 apps/solarclock/solar_clock-icon.js create mode 100644 apps/solarclock/solar_clock.js create mode 100644 apps/solarclock/solar_clock.png create mode 100644 apps/solarclock/solar_colors.js create mode 100644 apps/solarclock/solar_controller.js create mode 100644 apps/solarclock/solar_date_utils.js create mode 100644 apps/solarclock/solar_graphic_utils.js create mode 100644 apps/solarclock/solar_loc.Iceland.json create mode 100644 apps/solarclock/solar_loc.Kauai.json create mode 100644 apps/solarclock/solar_loc.Tokyo.json create mode 100644 apps/solarclock/solar_loc.local.json create mode 100644 apps/solarclock/solar_location.js create mode 100644 apps/solarclock/solar_locations.json create mode 100644 apps/solarclock/solar_math_utils.js diff --git a/apps.json b/apps.json index 80dc1e2b1..b6192b2e1 100644 --- a/apps.json +++ b/apps.json @@ -265,6 +265,31 @@ {"name":"slidingtext.dtfmt.js","url":"slidingtext.dtfmt.js"} ] }, + { "id": "solarclock", + "name": "Solar Clock", + "icon": "solar_clock.png", + "version":"0.01", + "description": "The solar clock will use your current or chosen location to work out the the current sun phase of the day", + "tags": "clock", + "type":"clock", + "allow_emulator":false, + "readme": "README.md", + "storage": [ + {"name":"solarclock.app.js","url":"solar_clock.js"}, + {"name":"solarclock.img","url":"solar_clock-icon.js","evaluate":true}, + {"name":"solar_colors.js","url":"solar_colors.js"}, + {"name":"solar_controller.js","url":"solar_controller.js"}, + {"name":"solar_date_utils.js","url":"solar_date_utils.js"}, + {"name":"solar_graphic_utils.js","url":"solar_graphic_utils.js"}, + {"name":"solar_location.js","url":"solar_location.js"}, + {"name":"solar_math_utils.js","url":"solar_math_utils.js"}, + {"name":"solar_loc.Iceland.json","url":"solar_loc.Iceland.json"}, + {"name":"solar_loc.Kauai.json","url":"solar_loc.Kauai.json"}, + {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, + {"name":"solar_loc.local.json","url":"solar_loc.local.json"} + {"name":"solar_locations.json","url":"solar_locations.json"} + ] + }, { "id": "sweepclock", "name": "Sweep Clock", "icon": "sweepclock.png", diff --git a/apps/solarclock/ChangeLog b/apps/solarclock/ChangeLog new file mode 100644 index 000000000..d53df991b --- /dev/null +++ b/apps/solarclock/ChangeLog @@ -0,0 +1 @@ +0.01: Initial Release diff --git a/apps/solarclock/README.md b/apps/solarclock/README.md new file mode 100644 index 000000000..51c95139b --- /dev/null +++ b/apps/solarclock/README.md @@ -0,0 +1 @@ +# Solar Clock diff --git a/apps/solarclock/app.png b/apps/solarclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..763c00b1de9f5c73ca4af264c6d65cc5eb08c090 GIT binary patch literal 33522 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Ν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 literal 0 HcmV?d00001 diff --git a/apps/solarclock/solar_clock-icon.js b/apps/solarclock/solar_clock-icon.js new file mode 100644 index 000000000..d9bdd8c65 --- /dev/null +++ b/apps/solarclock/solar_clock-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("lEowkA/4AGmYIHABHzmVCCaE0kUin4TPmUimQTQ+UzmcvJ6EjCaP/kYABCaEymYTl+Q7SMgITTmQTQPAK0RMgITm+QTS+ciPCcikQpPY4MjmYTO+czmcyHh4TCmcvJ54nCPCBjBJx4oECc8zJ6ATTn48RE4YTTHh4SDH4ImRFBwTGFBgTGFBgSGFBYmHUgITRmcyFBASFAoUjE5PzkQLBHJxiDAQP/GxAA==")) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js new file mode 100644 index 000000000..d1154e110 --- /dev/null +++ b/apps/solarclock/solar_clock.js @@ -0,0 +1,466 @@ +const DateUtils = require("solar_date_utils.js"); +const Math2 = require("solar_math_utils.js"); +const GraphicUtils = require("solar_graphic_utils.js"); +const Colors = require("solar_colors.js"); +const LocationUtils = require("solar_location.js"); + +var screen_info = { + screen_width : g.getWidth(), + screen_start_x : 0, + screen_centre_x: g.getWidth()/2, + screen_height : (g.getHeight()-100), + screen_start_y : 100, + screen_centre_y : 90 + (g.getHeight()-100)/2, + screen_bg_color : Colors.BLACK, + sun_radius: 8, + sun_x : null, + sun_y : null, + sunrise_y : null, +} +const img_width=40; +const img_height=30; +var img_buffer = Graphics.createArrayBuffer(img_width,img_height,8); +var img = {width:img_width,height:img_height,bpp:8,transparent:0,buffer:img_buffer.buffer}; +var img_info = { + x: null, + y: null, + img: img, + img_buffer: img_buffer +} +const COSINE_COLOUR= Colors.GREY; +const HORIZON_COLOUR = Colors.GREY; +const SolarController = require("solar_controller.js"); +var controller = new SolarController(); +var curr_mode = null; +var last_sun_draw_time = null; +var draw_full_cosine = true; + +function draw_sun(now, day_info) { + + var now_fraction = (now.getTime() - day_info.day_start.getTime())/DateUtils.DAY_MILLIS; + var now_x = now_fraction * screen_info.screen_width; + if(screen_info.sun_x != null && Math.abs(now_x- screen_info.sun_x) < 1){ + console.log("no sun movement"); + return false; + } + // now calculate thew new sun coordinates + var now_radians = Math2.TWO_PI *(now_x - screen_info.screen_centre_x)/screen_info.screen_width; + var now_y = screen_info.screen_centre_y - (screen_info.screen_height * Math.cos(now_radians) / 2); + if(Math.abs(now_x - screen_info.sun_x) > 5){ + clear_sun(); + } + // update the screen info with the new sun info + screen_info.sun_x = now_x; + screen_info.sun_y = now_y; + last_sun_draw_time = now; + + if(draw_full_cosine){ + //console.log("drawing full cosine"); + GraphicUtils.draw_cosine(screen_info.screen_start_x, + screen_info.screen_width, + COSINE_COLOUR, + screen_info); + draw_full_cosine = false; + } + if(curr_mode == null) { + GraphicUtils.draw_sunrise_line(HORIZON_COLOUR, day_info, screen_info); + } + // decide on the new sun drawing mode and draw + curr_mode = controller.mode(now,day_info,screen_info); + img_info.img_buffer.clear(); + img_info.img_buffer.setColor(screen_info.screen_bg_color[0], + screen_info.screen_bg_color[1], + screen_info.screen_bg_color[2], + ); + img_info.img_buffer.fillRect(0,0,img_width, img_height); + img_info.x = screen_info.sun_x - img_info.img.width/2; + img_info.y = screen_info.sun_y - img_info.img.height/2; + + var cosine_dist = screen_info.sun_radius/Math.sqrt(2); + GraphicUtils.draw_cosine(img_info.x, + screen_info.sun_x - cosine_dist, + COSINE_COLOUR, + screen_info, + img_info); + GraphicUtils.draw_cosine(screen_info.sun_x + cosine_dist, + screen_info.sun_x + img_width, + COSINE_COLOUR, + screen_info, + img_info); + + curr_mode.draw(now,day_info,screen_info,img_info); + + var sunrise_dist = Math.abs(screen_info.sunrise_y-screen_info.sun_y); + if( sunrise_dist <= img_height) { + GraphicUtils.draw_sunrise_line(HORIZON_COLOUR, day_info, screen_info,img_info); + } else if(sunrise_dist <= img_height*2.5) { + GraphicUtils.draw_sunrise_line(HORIZON_COLOUR, day_info, screen_info); + } + // we draw a blank where the image is going to be drawn to clear out the area + g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + g.fillRect(img_info.x,img_info.y-2,img_info.x+img_width,img_info.y + img_height + 2); + g.drawImage(img,img_info.x,img_info.y); + // paint the cosine curve back to the normal color where it just came from + GraphicUtils.draw_cosine(img_info.x - 3, + img_info.x, + COSINE_COLOUR, + screen_info); + GraphicUtils.draw_cosine(img_info.x + img_width, + img_info.x + img_width + 3, + COSINE_COLOUR, + screen_info); + return true; +} + +function clear_sun(){ + g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + g.fillRect(img_info.x,img_info.y,img_info.x+img_width,img_info.y + img_width); + GraphicUtils.draw_cosine(img_info.x - 4, + img_info.x + img_width + 4, + COSINE_COLOUR, + screen_info); + GraphicUtils.draw_sunrise_line(HORIZON_COLOUR, day_info, screen_info); + screen_info.sun_x = null; + screen_info.sun_y = null; +} + +var last_time = null; +var last_offset = null; +var last_date = null; + +const time_color = Colors.WHITE; +const date_color = Colors.YELLOW; +const DATE_Y_COORD = 35; +const DATE_X_COORD = 10; +const TIME_X_COORD = 140; +const TIME_Y_COORD = 35; +const OFFSET_Y_COORD = 70; +const LOCATION_Y_COORD = 55; + +function write_date(now){ + var new_date = require('locale').dow(now,1) + " " + Math2.format00(now.getDate()); + //console.log("writing date:" + new_date) + g.setFont("Vector",15); + g.setFontAlign(-1,-1,0); + if(last_date != null){ + if(new_date == last_date){ + return; + } + g.setColor(screen_info.screen_bg_color[0], + screen_info.screen_bg_color[1], + screen_info.screen_bg_color[2]); + g.drawString(last_date, DATE_X_COORD,DATE_Y_COORD); + } + g.setColor(date_color[0],date_color[1],date_color[2]); + g.drawString(new_date, DATE_X_COORD,DATE_Y_COORD); + last_date = new_date; +} + +var last_status_msg = "" +var last_gps_coords_msg_n = ""; +var last_gps_coords_msg_e = ""; +const GPS_MSG_X_COORD = 70; +const GPS_MSG_Y = 220; +const GPS_MSG_COORDS_Y_E = 80; +const GPS_MSG_COORDS_Y_N = 90; + +function write_GPS_status(){ + var gps_coords = location.getCoordinates(); + var gps_coords_msg_n; + var gps_coords_msg_e; + if(gps_coords != null){ + gps_coords_msg_n = "N: " + gps_coords[0]; + gps_coords_msg_n = gps_coords_msg_n.substr(0,Math.min(gps_coords_msg_n.length - 1,10)); + gps_coords_msg_e = "E: " + gps_coords[1]; + gps_coords_msg_e = gps_coords_msg_e.substr(0,Math.min(gps_coords_msg_e.length - 1,10)); + } else { + gps_coords_msg_n = ""; + gps_coords_msg_e = ""; + } + var status_msg = ""; + if(location.isGPSLocation()) { + if(gps_coords == null) { + if (location.getGPSPower() > 0) { + status_msg = "Finding GPS Position"; + } else { + status_msg = "ERROR GPS Position not found"; + } + } else { + if (location.getGPSPower() > 0) { + status_msg = "Updating GPS Position"; + } + } + } + g.setFont("Vector",11); + g.setFontAlign(-1,-1,0); + if(last_status_msg != status_msg) { + g.setColor(screen_info.screen_bg_color[0], + screen_info.screen_bg_color[1], + screen_info.screen_bg_color[2]); + g.drawString(last_status_msg, GPS_MSG_X_COORD, GPS_MSG_Y); + g.setColor(Colors.YELLOW[0],Colors.YELLOW[1],Colors.YELLOW[2]); + g.drawString(status_msg, GPS_MSG_X_COORD, GPS_MSG_Y); + last_status_msg = status_msg; + } + + if(last_gps_coords_msg_e != gps_coords_msg_e) { + g.setColor(screen_info.screen_bg_color[0], + screen_info.screen_bg_color[1], + screen_info.screen_bg_color[2]); + g.drawString(last_gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); + g.drawString(last_gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); + g.setColor(Colors.WHITE[0],Colors.WHITE[1],Colors.WHITE[2]); + + g.drawString(gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); + g.drawString(gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); + last_gps_coords_msg_e = gps_coords_msg_e; + last_gps_coords_msg_n = gps_coords_msg_n; + } +} + +function write_time(now){ + var new_time = format_time(now); + g.setFont("Vector",35); + g.setFontAlign(-1,-1,0); + if(last_time != null){ + g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + g.drawString(last_time, TIME_X_COORD,TIME_Y_COORD); + } + g.setColor(time_color[0],time_color[1],time_color[2]); + g.drawString(new_time, TIME_X_COORD,TIME_Y_COORD); + last_time = new_time; +} + +function format_time(now){ + var time = new Date(now.getTime() - time_offset); + var hours = time.getHours() % 12; + if(hours < 1){ + hours = 12; + } + return Math2.format00(hours) + ":" + Math2.format00(time.getMinutes()); +} + +function write_offset(){ + var new_offset = format_offset(); + g.setFont("Vector",15); + g.setFontAlign(-1,-1,0); + if(last_offset != null){ + g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + g.drawString(last_offset, TIME_X_COORD,OFFSET_Y_COORD); + } + g.setColor(time_color[0],time_color[1],time_color[2]); + g.drawString(new_offset, TIME_X_COORD,OFFSET_Y_COORD); + last_offset = new_offset; +} + +function format_offset(){ + if(time_offset == 0) + return ""; + + var hours_offset = Math.abs(time_offset) / DateUtils.HOUR_MILLIS; + var mins_offset = Math.abs(time_offset) / DateUtils.MIN_MILLIS; + var mins_offset_from_hour = mins_offset % 60; + //console.log("mins offset=" + mins_offset + " mins_offset_from_hour=" + mins_offset_from_hour); + var sign = "+"; + if(time_offset < 0) + sign = "-"; + + return sign + Math2.format00(hours_offset) + ":" + Math2.format00(mins_offset_from_hour); +} + +let time_offset = 0; +let last_draw_time = null; +var day_info = null; +var location = LocationUtils.load_locations(); +var last_location_name = null; + +function write_location_name() { + var new_location_name = location.getName(); + g.setFont("Vector", 20); + g.setFontAlign(-1, -1, 0); + if (last_location_name != null) { + g.setColor(screen_info.screen_bg_color[0], screen_info.screen_bg_color[1], screen_info.screen_bg_color[2]); + g.drawString(last_location_name, DATE_X_COORD, LOCATION_Y_COORD); + } + g.setColor(time_color[0], time_color[1], time_color[2]); + if (new_location_name != "local") { + g.drawString(new_location_name, DATE_X_COORD, LOCATION_Y_COORD); + } + last_location_name = new_location_name; +} + +location.addUpdateListener( + (loc)=>{ + console.log("location update:" + JSON.stringify(loc)); + clear_sun(); + GraphicUtils.draw_sunrise_line(screen_info.screen_bg_color, day_info, screen_info); + day_info = null; + screen_info.sunrise_y = null; + curr_mode = null; + draw_clock(); + } +); + + + +function dayInfo(now) { + if (day_info == null || now > day_info.day_end) { + var coords = location.getCoordinates(); + if(coords != null) { + day_info = DateUtils.sunrise_sunset(now, coords[0], coords[1], location.getUTCOffset()); + //console.log("day info:" + JSON.stringify(day_info)); + } else { + day_info = null; + } + } + return day_info; +} + +function time_now() { + var timezone_offset_hours = location.getUTCOffset(); + if(timezone_offset_hours != null) { + var local_offset_hours = -new Date().getTimezoneOffset()/60; + var timezone_offset_millis = + (timezone_offset_hours - local_offset_hours) * DateUtils.HOUR_MILLIS; + return new Date(Date.now() + time_offset + timezone_offset_millis); + } else { + return new Date(Date.now() + time_offset); + } +} + + +function draw_clock(){ + var start_time = Date.now(); + var now = time_now(); + + var day_info = dayInfo(now); + if(day_info != null) { + draw_sun(now, day_info); + } + write_time(now); + write_date(now); + write_offset(); + write_location_name(); + write_GPS_status(); + last_draw_time = now; + log_memory_used(); + var time_taken = Date.now() - start_time; + console.log("drawing clock:" + now.toISOString() + " time taken:" + time_taken ); +} + +function log_memory_used() { + var memory = process.memory(); + console.log("memory used:" + memory.usage + + " total:" + memory.total + "->" + + " ->" + memory.usage/memory.total + ); +} + +function button1pressed(){ + console.log("button 1 pressed"); + time_offset = 0; + clear_sun(); + day_info = null; + draw_clock(); +} + +function button3pressed(){ + console.log("button 3 pressed"); + time_offset = 0; + location.nextLocation(); +} + +function button4pressed(){ + time_offset -= DateUtils.HOUR_MILLIS/4; + draw_clock(); + setTimeout(()=>{ + if(BTN4.read()){ + button4pressed(); + } + }, + 50 + ) +} + +function button5pressed(){ + time_offset += DateUtils.HOUR_MILLIS/4; + draw_clock(); + setTimeout(()=>{ + if(BTN5.read()){ + button5pressed(); + } + }, + 50 + ) +} + +// The interval reference for updating the clock +let interval_ref = null; +function clear_timers(){ + if(interval_ref != null) { + clearInterval(interval_ref); + interval_ref = null; + } +} + +function start_timers(){ + var date = new Date(); + var secs = date.getSeconds(); + var nextMinuteStart = 60 - secs; + setTimeout(schedule_draw_clock,nextMinuteStart * 1000); + draw_clock(); +} +function schedule_draw_clock(){ + clear_timers(); + if (Bangle.isLCDOn()) { + interval_ref = setInterval(() => { + if (!Bangle.isLCDOn()) { + console.log("draw clock callback - skipped redraw"); + } else { + draw_clock(); + } + }, DateUtils.MIN_MILLIS + ); + draw_clock(); + } else { + console.log("scheduleDrawClock - skipped not visible"); + } +} + +Bangle.on('lcdPower', (on) => { + if (on) { + console.log("lcdPower: on"); + draw_clock(); + start_timers(); + } else { + console.log("lcdPower: off"); + clear_timers(); + } +}); + +Bangle.on('faceUp',function(up){ + if (up && !Bangle.isLCDOn()) { + clear_timers(); + Bangle.setLCDPower(true); + } +}); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +start_timers(); + +function button2pressed(){ + controller = null; + + location.shutdown(); + location = null; + + Bangle.showLauncher(); +} +setWatch(button2pressed, BTN2,{repeat:false,edge:"falling"}); +setWatch(button1pressed, BTN1,{repeat:true,edge:"falling"}); +setWatch(button3pressed, BTN3,{repeat:true,edge:"falling"}); +setWatch(button4pressed, BTN4,{repeat:true,edge:"rising"}); +setWatch(button5pressed, BTN5,{repeat:true,edge:"rising"}); \ No newline at end of file diff --git a/apps/solarclock/solar_clock.png b/apps/solarclock/solar_clock.png new file mode 100644 index 0000000000000000000000000000000000000000..70a1cd5327a61bc1b0d393b57e2093864e565b9c GIT binary patch literal 2669 zcmZ`*c{r478-GXk?p)c+{?6b0`1>Ob#g46*ZED8Wt*`}}=0PxoWfVXY{ zfXV;>X=+ZL9h&W6k_cEY8yi5At@8ssAaP(DTLZB_03-)+qOmo=5+wg!$AdJ!VYmPw zmJD!z!yIKx&az-{4rfbp<#BySXyk4Cp>v@3B_kEtLV#-FLzzm!eb76qq9$j;1di66$OI@1_nX{wV@Q+aTr`* zUmvE0fFTeNHUdIF?aOdyLVW4Fwu1aG4u(Ycq>-r%GR0S!6W85?;?FPygE@)5udO;6 zWUn8YeCglXVmAomcwlg-7VK9v5|jKdG>&JB_O-9AbZAa6)FB#~#4eaqmJuBNHNpSc zew4R`$CKz3Z+{Nl!I#W1LVTnA!~7GAlN)7AW|F*}Fk~N+FP)PKp`(R{{nGPGCgES1 zKY9MiG^2P^X!cZhPZFoGugQKgeM6&RoLT%do2|irwX!E~B#4H6zePrZBc{Isgchv(`i zxF%HKsg(i4gtInws%mGY)4<0qdZJy{N_E7pmFcU7E18)6HqG*yZ+zjjWgs#JK606g|s|TG?#Q19D1d+;5eF>Pv+vGdCU{;UUV% z)SZb^S-z<8dz!4|ec{%&p7~&IJxt=e2b4mx$G}`3-T%5P@!`tVD`}u}N>Sk{-Rt1Q z!!aX<8{mT3h0eTjJtEv$uCo(R>q2-I%nJ*)o2|5lgRwVs7kD4<(WW`yN8sUzdk-Qz z9)Fa`J`ywQyp5;d)=^#m|4q?xxQtWnX4Xu_uV}=%0G5y*N zf>Z>umgyU2bUdl*BNrljje9C$mFv;tbSXB)Vca$j}6@(Skd7K&84YGW61+)W)(% zuUX+kN}+^%+P0W6Jl0xgy_k0Z{}ck!;DXiExZRMzpmeQUXEE(li*bm zDGjsY4>G++N#^eG1-|)1!)>Nm(CDX^Kr2j7W(jBHHD_lW5fz4TyR1akS3c`u97cxyvnhGZ&z*n z! zB|H4m)x7F&j6->kCwk$P%j<@EF_S+ZKMIOQ8WZE}2VM~(-PI-eBd7d3L)x!q60k{j zs1V^jg~bkr(k23TDl?0U)K+jJ0`7@jZ3EAaEvjDHf8_9gzz~ybepqXDbWG#XkixdL z?ws|d8D~JPQc2?d4Lc8bqLxe|LHXhnjM?r^2FS&+&OlVA%Hd89t3pT0rc&O48^P19 z2i_+6setc2em}G~^ggMi!xm*BK5E_=?mD7EIKTHdKPe%)xY3a(>Zn{LM5ge`$%L7-nhS`xJ~7Z(*1h2WfX^!9!|e>b(_N>%l46OF^w2ee>-7Aa>hk3bd_I7B`pp|q<8Ds0JZ#^k_^x03vT^>KzyIA6-Gin$_mX}?-;uCu}@oDBVkIq zYiE(YT|`4xZ{E=ov+AV*O`{33eO%d+hrHU42)`mjy~}ZlPnCjlQN8hFE9N5UtH7>_ z#nEdAbE?m4LRQ{y(i{BMGpAgN`X_Jpwdsa#%CoAg%POjPwSC7IW+b2mmmZ&Nu+_(Y zZf$R`)l_vKo~^Gb3+0Op5lrggzp}9*%6NS`Vmn5qIVlr)cVh(Pb1~G6-=eQEpgwYG zwwIsxQcY9SfyL*B3PT|~tK@7<@7&(!=<8#JO&t%iDD*C{$Eu!VX+rZYGz05uRM!yd guW3u`ALm1XW#=8{i!Y day_info.sunset_date){ + return SUNSET_COLOUR; + } else if(now < day_info.sunrise_date){ + return SUNRISE_COLOUR; + } else if(now < day_info.solar_noon) { + var sunrise_fraction = (day_info.sunrise_date - day_info.day_start) / DateUtils.DAY_MILLIS; + var rise_to_midday_fraction = (now_fraction_of_day - sunrise_fraction) / (0.5 - sunrise_fraction); + return Math2.interpolate(SUNRISE_COLOUR, MIDDAY_COLOUR, rise_to_midday_fraction); + } else { + var sunset_fraction = (day_info.day_end - day_info.sunset_date) / DateUtils.DAY_MILLIS; + var midday_to_sunset_fraction = (now_fraction_of_day - 0.5)/(0.5 - sunset_fraction); + //console.log("sunset_fraction=" + sunset_fraction + " midday_to_sunset_fraction=" + midday_to_sunset_fraction) + return Math2.interpolate(MIDDAY_COLOUR,SUNSET_COLOUR,midday_to_sunset_fraction); + } +} + +function draw_night_sun(sun_x,sun_y,sun_radius,img_info){ + var draw_info = GraphicUtils.draw_info(img_info); + draw_info.buff.setColor(Colors.WHITE[0],Colors.WHITE[1],Colors.WHITE[2]); + draw_info.buff.fillCircle(sun_x - draw_info.offset_x, + sun_y - draw_info.offset_y, + sun_radius); + draw_info.buff.setColor(NIGHT_COLOUR[0],NIGHT_COLOUR[1],NIGHT_COLOUR[2]); + draw_info.buff.fillCircle(sun_x - draw_info.offset_x, + sun_y - draw_info.offset_y, + sun_radius-1); +} + +function draw_partial_sun(time, day_info, screen_info,img_info){ + var sun_height = screen_info.sunrise_y - screen_info.sun_y; + if(sun_height > screen_info.sun_radius){ + var sun_color = daytime_sun_color(time,day_info); + var draw_info = GraphicUtils.draw_info(img_info); + draw_info.buff.setColor(sun_color[0],sun_color[1],sun_color[2]); + draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, + screen_info.sun_y - draw_info.offset_y, + screen_info.sun_radius + ); + } else if(sun_height < -screen_info.sun_radius){ + draw_night_sun(screen_info.sun_x,screen_info.sun_y,screen_info.sun_radius, img_info); + } else { + var draw_info = GraphicUtils.draw_info(img_info); + draw_info.buff.setColor(NIGHT_COLOUR[0],NIGHT_COLOUR[1],NIGHT_COLOUR[2]); + draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, + screen_info.sun_y - draw_info.offset_y, + screen_info.sun_radius-1); + var sun_color = daytime_sun_color(time,day_info); + draw_info.buff.setColor(sun_color[0],sun_color[1],sun_color[2]); + draw_info.buff.drawCircle(screen_info.sun_x - draw_info.offset_x, + screen_info.sun_y - draw_info.offset_y, + screen_info.sun_radius); + GraphicUtils.fill_circle_partial_y(screen_info.sun_x, + screen_info.sun_y, + screen_info.sun_radius, + screen_info.sun_y - screen_info.sun_radius, + screen_info.sunrise_y, + img_info + ); + } +} +function draw_random_background(screen_info, + img_info, + rgb_init, + rgb_step + ){ + var draw_info = GraphicUtils.draw_info(img_info); + var rgb = rgb_init; + var sky_to = Math.min(screen_info.sunrise_y-1, img_info.y + img_info.img.height - 3); + for(var sky_y=img_info.y+3;sky_y0) + rgb[i] = Math2.random_walk(rgb[i],rgb_step[i],1,0); + } + draw_info.buff.setColor(rgb[0],rgb[1],rgb[2]); + draw_info.buff.moveTo(screen_info.sun_x + + Math.random()*img_info.img.width/8 - + 0.4*img_info.img.width - + draw_info.offset_x, + sky_y - draw_info.offset_y); + draw_info.buff.lineTo(screen_info.sun_x + + 0.4*img_info.img.width - + Math.random()*img_info.img.width/8 - + draw_info.offset_x, + sky_y - draw_info.offset_y); + } + draw_info.buff.setColor(NIGHT_COLOUR[0],NIGHT_COLOUR[1],NIGHT_COLOUR[2]); + draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, + screen_info.sun_y - draw_info.offset_y, + screen_info.sun_radius+1); +} +class SolarMode { + test(time, day_info, screen_info){ throw "test undefined";} + draw(time, day_info, screen_info, img_buffer_info){ + throw "sun drawing undefined"; + } +} +class NightMode extends SolarMode { + toString(){return "NightMode";} + test(time, day_info, screen_info, img_info) { + return (time < day_info.sunrise_date || time > day_info.sunset_date); + } + draw(time, day_info, screen_info, img_info){ + draw_night_sun(screen_info.sun_x,screen_info.sun_y,screen_info.sun_radius, img_info); + } +} +class DayLightMode extends SolarMode { + toString(){ + return "DayLightMode"; + } + test(time, day_info, screen_info){ + var sun_height = screen_info.sunrise_y - screen_info.sun_y; + /*console.log("DayLightMode " + + "time=" + time.toISOString() + + " sunset_date=" + day_info.sunset_date.toISOString() + + " sunrise_date=" + day_info.sunrise_date.toISOString() + );*/ + return time < day_info.sunset_date && + time > day_info.sunrise_date && + sun_height >= screen_info.sun_radius * 2 + SUNSET_START_HEIGHT; + } + _calc_corona_radius(now, day_info){ + if(now < day_info.sunset_date && + now > day_info.sunrise_date){ + var now_fraction_of_day =DateUtils.now_fraction_of_day(now,day_info); + var sunset_fraction = (day_info.sunset_date.getTime() - day_info.day_start.getTime())/DateUtils.DAY_MILLIS; + var now_fraction_from_midday = + 1 - Math.abs(now_fraction_of_day-0.5)/(sunset_fraction-0.5); + return CORONA_RADIUS * now_fraction_from_midday; + } else { + return 0; + } + } + _drawCorona(corona_radius,sun_x,sun_y,sun_radius, draw_info){ + var thickness_rads = (Math2.TWO_PI/CORONA_LINES)/3; + var from_radius = sun_radius + CORONA_GAP; + if(corona_radius > from_radius + CORONA_MIN_LENGTH) { + for (var i = 0; i < CORONA_LINES; i++) { + var to_x1 = sun_x - draw_info.offset_x + from_radius * Math.cos(i * Math2.TWO_PI / CORONA_LINES + thickness_rads); + var to_y1 = sun_y - draw_info.offset_y + from_radius * Math.sin(i * Math2.TWO_PI / CORONA_LINES + thickness_rads); + var to_x2 = sun_x - draw_info.offset_x + from_radius * Math.cos(i * Math2.TWO_PI / CORONA_LINES - thickness_rads); + var to_y2 = sun_y - draw_info.offset_y + from_radius * Math.sin(i * Math2.TWO_PI / CORONA_LINES - thickness_rads); + var to_x3 = sun_x - draw_info.offset_x + corona_radius * Math.cos(i * Math2.TWO_PI / CORONA_LINES); + var to_y3 = sun_y - draw_info.offset_y + corona_radius * Math.sin(i * Math2.TWO_PI / CORONA_LINES); + draw_info.buff.fillPoly([to_x1, to_y1, to_x2, to_y2, to_x3, to_y3]); + } + } + } + draw(now, day_info, screen_info, img_info){ + var sun_color = daytime_sun_color(now,day_info); + var corona_radius = this._calc_corona_radius(now, day_info); + var draw_info = GraphicUtils.draw_info(img_info); + draw_info.buff.setColor(sun_color[0],sun_color[1],sun_color[2]); + if(corona_radius > screen_info.sun_radius){ + this._drawCorona(corona_radius, + screen_info.sun_x, + screen_info.sun_y, + screen_info.sun_radius, + draw_info); + } + draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, + screen_info.sun_y - draw_info.offset_y, + screen_info.sun_radius); + } +} +class TwiLightMode extends SolarMode { + toString(){ + return "TwilightMode"; + } + test(time, day_info, screen_info){ + if(screen_info.sunrise_y == null) { + console.log("warning no sunrise_defined"); + return false; + } + var sun_height = screen_info.sunrise_y - screen_info.sun_y; + /*console.log("TwilightMode " + + "time=" + time.toISOString() + + " sun_height=" + sun_height + + " sun_radius=" + screen_info.sun_radius + );*/ + if(sun_height > -screen_info.sun_radius && + sun_height < screen_info.sun_radius * 2 + SUNSET_START_HEIGHT + ){ + //console.log("selected TwilightMode"); + return true; + } + return false; + } + draw(time, day_info, screen_info, img_info){ + if(time < day_info.solar_noon) { + draw_random_background(screen_info, + img_info, + [0,0.8,1], + [0.05,0.05,0.0]); + } else { + draw_random_background(screen_info, + img_info, + [1,0.75,Math.random()], + [0,0.05,0.05]); + } + draw_partial_sun(time,day_info,screen_info,img_info); + } +} +class SolarControllerImpl { + constructor(){ + this.solar_modes = [new TwiLightMode(), new DayLightMode()]; + this.default_mode = new NightMode(); + this.last = null; + } + toString(){ + return "SolarControllerImpl"; + } + mode(time, day_info, screen_info){ + if(this.last != null){ + if(this.last.test(time,day_info,screen_info)){ + return this.last; + } + } + for(var i=0; i" + solar_noon_datetime.toISOString()); + + var sunrise_time_LST = (solar_noon*1440-HA_sunrise_degrees*4)/1440; + var sunrise_time_LST_datetime = _to_time(now,sunrise_time_LST); + console.log("sunrise_time_LST=" + sunrise_time_LST + + "->" + sunrise_time_LST_datetime.toISOString()); + + var sunset_time_LST =(solar_noon*1440+HA_sunrise_degrees*4)/1440; + var sunset_time_LST_datetime = _to_time(now,sunset_time_LST); + console.log("sunset_time_LST=" + sunset_time_LST + + "->" + sunset_time_LST_datetime.toISOString()); + return { + day_start: new Date(solar_noon_datetime.getTime() - _DAY_MILLIS / 2), + sunrise_date: sunrise_time_LST_datetime, + //sunrise_fraction: sunrise_time_LST, + sunset_date: sunset_time_LST_datetime, + //sunset_fraction: sunset_time_LST, + solar_noon: solar_noon_datetime, + day_end: new Date(solar_noon_datetime.getTime() + _DAY_MILLIS / 2) + }; + }, + now_fraction_of_day: (now,day_info)=>{ + return (now.getTime() - day_info.day_start.getTime())/_DAY_MILLIS; + }, +} +module.exports = DateUtils; \ No newline at end of file diff --git a/apps/solarclock/solar_graphic_utils.js b/apps/solarclock/solar_graphic_utils.js new file mode 100644 index 000000000..3c2afec88 --- /dev/null +++ b/apps/solarclock/solar_graphic_utils.js @@ -0,0 +1,94 @@ +var DateUtils = require("solar_date_utils.js"); +var Math2 = require("solar_math_utils.js"); + +function _draw_info(img_info){ + if (img_info == null) { + return { + buff: g, + offset_x: 0, + offset_y: 0 + }; + } else { + return { + buff: img_info.img_buffer, + offset_x: img_info.x, + offset_y: img_info.y + }; + } + +} +const GraphicUtils = { + draw_info : (img_info)=>_draw_info(img_info), + draw_cosine : (from_x,to_x, line_colour, screen_info, img_info)=>{ + //console.log("draw_cosine from_x=" + from_x + " to_x=" + to_x); + var draw_info = _draw_info(img_info); + + draw_info.buff.reset(); + draw_info.buff.setColor(line_colour[0],line_colour[1],line_colour[2]); + first = true; + for(var x=from_x; x { + if (!this.in_use) + return; + + if (g.fix) { + var loc_info = { + last_update: new Date(), + coordinates: [g.lon, g.lat] + }; + console.log("Received gps fixing:" + JSON.stringify(loc_info)); + storage.writeJSON("solar_loc.local.json", this.location_info); + if(this.isGPSLocation()){ + this.location_info = loc_info; + this.notifyUpdate(); + } + this.setGPSPower(0); + } + }); + } + isGPSLocation(){return this.getName() == 'local';} + addUpdateListener(listener){this.listeners.push(listener);} + nextLocation() { + if(this.locations.length > 1) { + this.idx += 1; + this.idx = this.idx % this.locations.length; + console.log("location now:" + this.getName()); + this.init(); + this.notifyUpdate(); + } else { + console.log("no extra locations found"); + } + } + notifyUpdate(){ + for(var i=0; i{ + var locations = storage.readJSON(LOCATIONS_FILE); + console.log("loaded locations:" + locations); + var mgr = new LocationManager(locations); + mgr.init(); + return mgr; + } +} +module.exports = LocationUtils; \ No newline at end of file diff --git a/apps/solarclock/solar_locations.json b/apps/solarclock/solar_locations.json new file mode 100644 index 000000000..750b43206 --- /dev/null +++ b/apps/solarclock/solar_locations.json @@ -0,0 +1 @@ +["local","Tokyo","Iceland","Kauai"] \ No newline at end of file diff --git a/apps/solarclock/solar_math_utils.js b/apps/solarclock/solar_math_utils.js new file mode 100644 index 000000000..c88ba9961 --- /dev/null +++ b/apps/solarclock/solar_math_utils.js @@ -0,0 +1,34 @@ +const _TWO_PI = 2 * Math.PI; +const Maths2 = { + TWO_PI: _TWO_PI, + to_radians: (degrees)=> _TWO_PI * degrees / 360, + to_degrees: (radians)=> 360 * radians/ (_TWO_PI), + interpolate: (vector1, vector2, fraction)=>{ + var result = []; + for(var i=0; i< vector1.length; i++){ + var value = vector1[i] + (vector2[i] - vector1[i]) * fraction; + result.push(value); + } + return result; + }, + format00: (num)=>{ + var value = (num | 0); + if(value > 99 || value < 0) + throw "must be between in range 0-99"; + if(value < 10) + return "0" + value.toString(); + else + return value.toString(); + }, + random_walk: (value,step,max,min)=>{ + if(Math.random()>0.5){ + value -= step; + } else { + value += step; + } + value = Math.min(value,max); + value = Math.max(value,min); + return value; + } +} +module.exports = Maths2; \ No newline at end of file From ecf497d0106cbe8b97ad5c51ea3bc3d539582ac9 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sat, 17 Jul 2021 21:10:07 +0100 Subject: [PATCH 062/163] solar clock: fixed typo apps index --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 19a2e21f2..abdfcbd3c 100644 --- a/apps.json +++ b/apps.json @@ -299,7 +299,7 @@ {"name":"solar_loc.Iceland.json","url":"solar_loc.Iceland.json"}, {"name":"solar_loc.Kauai.json","url":"solar_loc.Kauai.json"}, {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, - {"name":"solar_loc.local.json","url":"solar_loc.local.json"} + {"name":"solar_loc.local.json","url":"solar_loc.local.json"}, {"name":"solar_locations.json","url":"solar_locations.json"} ] }, From 9ffb1062eb35d3d606faa9f12ffc26ae7d07d810 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sat, 17 Jul 2021 21:36:20 +0100 Subject: [PATCH 063/163] solar clock: display North and East around the wrong way --- apps/solarclock/solar_clock.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index d1154e110..27253018a 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -169,9 +169,9 @@ function write_GPS_status(){ var gps_coords_msg_n; var gps_coords_msg_e; if(gps_coords != null){ - gps_coords_msg_n = "N: " + gps_coords[0]; + gps_coords_msg_n = "N: " + gps_coords[1]; gps_coords_msg_n = gps_coords_msg_n.substr(0,Math.min(gps_coords_msg_n.length - 1,10)); - gps_coords_msg_e = "E: " + gps_coords[1]; + gps_coords_msg_e = "E: " + gps_coords[0]; gps_coords_msg_e = gps_coords_msg_e.substr(0,Math.min(gps_coords_msg_e.length - 1,10)); } else { gps_coords_msg_n = ""; From ba63388a0939de6fd17fab74eef8710f889bfebe Mon Sep 17 00:00:00 2001 From: numerist Date: Sun, 18 Jul 2021 06:31:23 -0400 Subject: [PATCH 064/163] Update ChangeLog --- apps/doztime/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/doztime/ChangeLog b/apps/doztime/ChangeLog index f615b246e..ffa84b497 100644 --- a/apps/doztime/ChangeLog +++ b/apps/doztime/ChangeLog @@ -1,3 +1,3 @@ 0.01: New App! 0.02 added emulator capability and display of widgets -0.03 bug of advancing time fixed; doztime now correct within 1 second +0.03 bug of advancing time fixed; doztime now correct within ca. 1 second From a8dac4729b4a2e4d68f507a45920552e2091167d Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sun, 18 Jul 2021 14:11:56 +0100 Subject: [PATCH 065/163] solar clock: added the sun up and sundown times - also tidied up long and lat readouts --- apps/solarclock/solar_clock.js | 69 ++++++++++++++++++++++++----- apps/solarclock/solar_date_utils.js | 2 +- apps/solarclock/solar_math_utils.js | 28 +++++++++--- 3 files changed, 79 insertions(+), 20 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 27253018a..874708a72 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -131,7 +131,7 @@ var last_date = null; const time_color = Colors.WHITE; const date_color = Colors.YELLOW; const DATE_Y_COORD = 35; -const DATE_X_COORD = 10; +const DATE_X_COORD = 5; const TIME_X_COORD = 140; const TIME_Y_COORD = 35; const OFFSET_Y_COORD = 70; @@ -159,20 +159,18 @@ function write_date(now){ var last_status_msg = "" var last_gps_coords_msg_n = ""; var last_gps_coords_msg_e = ""; -const GPS_MSG_X_COORD = 70; +const GPS_MSG_X_COORD = 65; const GPS_MSG_Y = 220; -const GPS_MSG_COORDS_Y_E = 80; -const GPS_MSG_COORDS_Y_N = 90; +const GPS_MSG_COORDS_Y_E = 90; +const GPS_MSG_COORDS_Y_N = 105; function write_GPS_status(){ var gps_coords = location.getCoordinates(); var gps_coords_msg_n; var gps_coords_msg_e; if(gps_coords != null){ - gps_coords_msg_n = "N: " + gps_coords[1]; - gps_coords_msg_n = gps_coords_msg_n.substr(0,Math.min(gps_coords_msg_n.length - 1,10)); - gps_coords_msg_e = "E: " + gps_coords[0]; - gps_coords_msg_e = gps_coords_msg_e.substr(0,Math.min(gps_coords_msg_e.length - 1,10)); + gps_coords_msg_n = "N:" + Math2.format000_00(gps_coords[1]); + gps_coords_msg_e = "E:" + Math2.format000_00(gps_coords[0]); } else { gps_coords_msg_n = ""; gps_coords_msg_e = ""; @@ -191,7 +189,7 @@ function write_GPS_status(){ } } } - g.setFont("Vector",11); + g.setFont("Vector",13); g.setFontAlign(-1,-1,0); if(last_status_msg != status_msg) { g.setColor(screen_info.screen_bg_color[0], @@ -209,7 +207,7 @@ function write_GPS_status(){ screen_info.screen_bg_color[2]); g.drawString(last_gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); g.drawString(last_gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); - g.setColor(Colors.WHITE[0],Colors.WHITE[1],Colors.WHITE[2]); + g.setColor(0.9,0.9,0.9); g.drawString(gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); g.drawString(gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); @@ -218,6 +216,43 @@ function write_GPS_status(){ } } +const TWILIGHT_X_COORD = 200; +const SUNUP_Y_COORD = 90; +const SUNDOWN_Y_COORD = 105; +var last_sunup = ""; +var last_sundown = ""; +function write_twilight_times(){ + var sunup; + var sundown; + if(day_info != null) { + sunup = format_time(day_info.sunrise_date); + sundown = format_time(day_info.sunset_date); + } else { + sunup = ""; + sundown = ""; + } + + g.setFont("Vector",13); + g.setFontAlign(-1,-1,0); + if(last_sunup != "" && last_sunup != sunup){ + g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + g.drawString(last_sunup, TWILIGHT_X_COORD,SUNUP_Y_COORD); + g.drawString(last_sundown, TWILIGHT_X_COORD,SUNDOWN_Y_COORD); + } + g.setColor(Colors.YELLOW[0],Colors.YELLOW[1],Colors.YELLOW[2]); + g.drawString(sunup, TWILIGHT_X_COORD,SUNUP_Y_COORD); + GraphicUtils.fill_circle_partial_y(TWILIGHT_X_COORD-15, + SUNUP_Y_COORD+7, + 7, + SUNUP_Y_COORD+7, + SUNUP_Y_COORD); + g.setColor(1,0.7,0); + g.drawString(sundown, TWILIGHT_X_COORD,SUNDOWN_Y_COORD); + + last_sunup = sunup; + last_sundown = sundown; +} + function write_time(now){ var new_time = format_time(now); g.setFont("Vector",35); @@ -298,6 +333,9 @@ location.addUpdateListener( screen_info.sunrise_y = null; curr_mode = null; draw_clock(); + write_location_name(); + write_GPS_status(); + write_twilight_times(); } ); @@ -340,8 +378,15 @@ function draw_clock(){ write_time(now); write_date(now); write_offset(); - write_location_name(); - write_GPS_status(); + if(last_location_name == "") + write_location_name(); + + if(last_gps_coords_msg_n == "") + write_GPS_status(); + + if(last_sunup == "") + write_twilight_times(); + last_draw_time = now; log_memory_used(); var time_taken = Date.now() - start_time; diff --git a/apps/solarclock/solar_date_utils.js b/apps/solarclock/solar_date_utils.js index d4ebba525..f6fffaf93 100644 --- a/apps/solarclock/solar_date_utils.js +++ b/apps/solarclock/solar_date_utils.js @@ -95,7 +95,7 @@ const DateUtils = { if(utc_offset == null){ utc_offset = -local_offset_hours; } - var timezone_offset_hours = (utc_offset - local_offset_hours); + var timezone_offset_hours = utc_offset; //(utc_offset - local_offset_hours); console.log("timezone_offset_hours=" + timezone_offset_hours + " longitude" + longitude + " utc_offset=" + utc_offset diff --git a/apps/solarclock/solar_math_utils.js b/apps/solarclock/solar_math_utils.js index c88ba9961..6399dacca 100644 --- a/apps/solarclock/solar_math_utils.js +++ b/apps/solarclock/solar_math_utils.js @@ -1,4 +1,14 @@ const _TWO_PI = 2 * Math.PI; + +function _format00(num){ + var value = (num | 0); + if(value > 99 || value < 0) + throw "must be between in range 0-99"; + if(value < 10) + return "0" + value.toString(); + else + return value.toString(); +} const Maths2 = { TWO_PI: _TWO_PI, to_radians: (degrees)=> _TWO_PI * degrees / 360, @@ -12,13 +22,17 @@ const Maths2 = { return result; }, format00: (num)=>{ - var value = (num | 0); - if(value > 99 || value < 0) - throw "must be between in range 0-99"; - if(value < 10) - return "0" + value.toString(); - else - return value.toString(); + return _format00(num) + }, + format000_00: (num)=>{ + var mantissa = (num | 0); + var mantissa_abs = Math.abs(mantissa); + var remainder = ((Math.abs(num) - mantissa_abs)*100|0); + var sign = "-"; + if(num >= 0) + sign = "+"; + return sign + mantissa_abs.toString() + "." + _format00(remainder); + }, random_walk: (value,step,max,min)=>{ if(Math.random()>0.5){ From 07698a9cf1d371a4e64f3b7b3ef7709b953456aa Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Mon, 19 Jul 2021 01:51:38 +0100 Subject: [PATCH 066/163] Solar Clock - need to update the twilight times on a new day --- apps/solarclock/solar_clock.js | 36 ++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 874708a72..b3a21bf22 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -159,12 +159,16 @@ function write_date(now){ var last_status_msg = "" var last_gps_coords_msg_n = ""; var last_gps_coords_msg_e = ""; -const GPS_MSG_X_COORD = 65; +const GPS_MSG_X_COORD = 55; const GPS_MSG_Y = 220; const GPS_MSG_COORDS_Y_E = 90; const GPS_MSG_COORDS_Y_N = 105; +var gps_status_requires_update = true; function write_GPS_status(){ + if(!gps_status_requires_update) + return; + var gps_coords = location.getCoordinates(); var gps_coords_msg_n; var gps_coords_msg_e; @@ -214,6 +218,8 @@ function write_GPS_status(){ last_gps_coords_msg_e = gps_coords_msg_e; last_gps_coords_msg_n = gps_coords_msg_n; } + + gps_status_requires_update = false; } const TWILIGHT_X_COORD = 200; @@ -221,7 +227,11 @@ const SUNUP_Y_COORD = 90; const SUNDOWN_Y_COORD = 105; var last_sunup = ""; var last_sundown = ""; +var twilight_times_requires_update = true; function write_twilight_times(){ + if(!twilight_times_requires_update) + return; + var sunup; var sundown; if(day_info != null) { @@ -251,6 +261,7 @@ function write_twilight_times(){ last_sunup = sunup; last_sundown = sundown; + twilight_times_requires_update = false; } function write_time(now){ @@ -308,8 +319,12 @@ let last_draw_time = null; var day_info = null; var location = LocationUtils.load_locations(); var last_location_name = null; +var location_requires_update = true; function write_location_name() { + if(!location_requires_update) + return; + var new_location_name = location.getName(); g.setFont("Vector", 20); g.setFontAlign(-1, -1, 0); @@ -322,6 +337,7 @@ function write_location_name() { g.drawString(new_location_name, DATE_X_COORD, LOCATION_Y_COORD); } last_location_name = new_location_name; + location_requires_update = false; } location.addUpdateListener( @@ -332,10 +348,10 @@ location.addUpdateListener( day_info = null; screen_info.sunrise_y = null; curr_mode = null; + gps_status_requires_update = true; + location_requires_update = true; + twilight_times_requires_update = true; draw_clock(); - write_location_name(); - write_GPS_status(); - write_twilight_times(); } ); @@ -346,6 +362,7 @@ function dayInfo(now) { var coords = location.getCoordinates(); if(coords != null) { day_info = DateUtils.sunrise_sunset(now, coords[0], coords[1], location.getUTCOffset()); + twilight_times_requires_update = true; //console.log("day info:" + JSON.stringify(day_info)); } else { day_info = null; @@ -378,14 +395,9 @@ function draw_clock(){ write_time(now); write_date(now); write_offset(); - if(last_location_name == "") - write_location_name(); - - if(last_gps_coords_msg_n == "") - write_GPS_status(); - - if(last_sunup == "") - write_twilight_times(); + write_location_name(); + write_GPS_status(); + write_twilight_times(); last_draw_time = now; log_memory_used(); From 224975ea81fecaa842082d7a979511099091f530 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Mon, 19 Jul 2021 09:18:14 +0100 Subject: [PATCH 067/163] solar clock BUGFIX. Clock missing GPS update on screen --- apps/solarclock/README.md | 34 +++++++++++++++++++++++++++++++ apps/solarclock/solar_clock.js | 1 + apps/solarclock/solar_location.js | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/solarclock/README.md b/apps/solarclock/README.md index 51c95139b..0a28af561 100644 --- a/apps/solarclock/README.md +++ b/apps/solarclock/README.md @@ -1 +1,35 @@ # Solar Clock + +## Introduction + +Ever wondered when Sunset really is, what time will it hit? When the Sun will be highest in the sky? When you phone your friend in another country, you can easily find the time, but is it light where they are? The solar clock gives you a pictoral view of the day. It also gives you the opportunity to get the same view on another city in another timezone. + +## Usage + + + +### Uploading the clock + + + +### Reading the clock through the day + +### Button 3 +Change Location + +### Button 4 and 5 +Move Time backwards and forwards + +### Button 1 +Rest to now + +## Further Details +For further details of design and working please visit [The Project Page]( https://adrianwkirk.notion.site/Solar-Clock-a2b6268075a6481686b86ecc2094dc14) + +## Requests + +Reach out to adrian@adriankirk.com if you have feature requests or notice bugs. + +## Creator + +Made by [Adrian Kirk](mailto:adrian@adriankirk.com) \ No newline at end of file diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index b3a21bf22..4c6f2f8a1 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -487,6 +487,7 @@ function schedule_draw_clock(){ Bangle.on('lcdPower', (on) => { if (on) { console.log("lcdPower: on"); + gps_status_requires_update = true; draw_clock(); start_timers(); } else { diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index 2f900ea06..84364393c 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -37,11 +37,12 @@ class LocationManager { }; console.log("Received gps fixing:" + JSON.stringify(loc_info)); storage.writeJSON("solar_loc.local.json", this.location_info); + this.setGPSPower(0); if(this.isGPSLocation()){ this.location_info = loc_info; this.notifyUpdate(); } - this.setGPSPower(0); + } }); } From 1733489df59c46342918dcfc6251474f5e435828 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Tue, 20 Jul 2021 01:59:04 +0100 Subject: [PATCH 068/163] Solar Clock: Decreasing the memory consumption - deleting the Long and Lat readout --- apps/solarclock/solar_clock.js | 31 ++--------------------------- apps/solarclock/solar_math_utils.js | 10 ---------- 2 files changed, 2 insertions(+), 39 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 4c6f2f8a1..1c24e495e 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -157,12 +157,8 @@ function write_date(now){ } var last_status_msg = "" -var last_gps_coords_msg_n = ""; -var last_gps_coords_msg_e = ""; const GPS_MSG_X_COORD = 55; const GPS_MSG_Y = 220; -const GPS_MSG_COORDS_Y_E = 90; -const GPS_MSG_COORDS_Y_N = 105; var gps_status_requires_update = true; function write_GPS_status(){ @@ -170,18 +166,9 @@ function write_GPS_status(){ return; var gps_coords = location.getCoordinates(); - var gps_coords_msg_n; - var gps_coords_msg_e; - if(gps_coords != null){ - gps_coords_msg_n = "N:" + Math2.format000_00(gps_coords[1]); - gps_coords_msg_e = "E:" + Math2.format000_00(gps_coords[0]); - } else { - gps_coords_msg_n = ""; - gps_coords_msg_e = ""; - } var status_msg = ""; if(location.isGPSLocation()) { - if(gps_coords == null) { + if (gps_coords == null) { if (location.getGPSPower() > 0) { status_msg = "Finding GPS Position"; } else { @@ -200,25 +187,11 @@ function write_GPS_status(){ screen_info.screen_bg_color[1], screen_info.screen_bg_color[2]); g.drawString(last_status_msg, GPS_MSG_X_COORD, GPS_MSG_Y); - g.setColor(Colors.YELLOW[0],Colors.YELLOW[1],Colors.YELLOW[2]); + g.setColor(Colors.GREY[0],Colors.GREY[1],Colors.GREY[2]); g.drawString(status_msg, GPS_MSG_X_COORD, GPS_MSG_Y); last_status_msg = status_msg; } - if(last_gps_coords_msg_e != gps_coords_msg_e) { - g.setColor(screen_info.screen_bg_color[0], - screen_info.screen_bg_color[1], - screen_info.screen_bg_color[2]); - g.drawString(last_gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); - g.drawString(last_gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); - g.setColor(0.9,0.9,0.9); - - g.drawString(gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); - g.drawString(gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); - last_gps_coords_msg_e = gps_coords_msg_e; - last_gps_coords_msg_n = gps_coords_msg_n; - } - gps_status_requires_update = false; } diff --git a/apps/solarclock/solar_math_utils.js b/apps/solarclock/solar_math_utils.js index 6399dacca..98227d609 100644 --- a/apps/solarclock/solar_math_utils.js +++ b/apps/solarclock/solar_math_utils.js @@ -24,16 +24,6 @@ const Maths2 = { format00: (num)=>{ return _format00(num) }, - format000_00: (num)=>{ - var mantissa = (num | 0); - var mantissa_abs = Math.abs(mantissa); - var remainder = ((Math.abs(num) - mantissa_abs)*100|0); - var sign = "-"; - if(num >= 0) - sign = "+"; - return sign + mantissa_abs.toString() + "." + _format00(remainder); - - }, random_walk: (value,step,max,min)=>{ if(Math.random()>0.5){ value -= step; From 967cd6a86114c2b0bc61ca448c1a5d1778b9dd80 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Tue, 20 Jul 2021 16:36:48 +0100 Subject: [PATCH 069/163] Solar clock - changed back to having long and lat combined with status --- apps/solarclock/solar_clock.js | 44 ++++++++++++++++++++--------- apps/solarclock/solar_location.js | 4 +-- apps/solarclock/solar_math_utils.js | 10 +++++++ 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 1c24e495e..d0c86e056 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -156,40 +156,58 @@ function write_date(now){ last_date = new_date; } -var last_status_msg = "" -const GPS_MSG_X_COORD = 55; -const GPS_MSG_Y = 220; + +const GPS_MSG_COORDS_Y_E = 90; +const GPS_MSG_COORDS_Y_N = 105; var gps_status_requires_update = true; +var last_gps_coords_msg_n = ""; +var last_gps_coords_msg_e = ""; function write_GPS_status(){ if(!gps_status_requires_update) return; var gps_coords = location.getCoordinates(); - var status_msg = ""; + var gps_coords_msg_n; + var gps_coords_msg_e; + if(location.isGPSLocation()) { - if (gps_coords == null) { + if(gps_coords == null) { if (location.getGPSPower() > 0) { - status_msg = "Finding GPS Position"; + gps_coords_msg_n = "Locating"; + gps_coords_msg_e = "GPS"; } else { - status_msg = "ERROR GPS Position not found"; + gps_coords_msg_n = "ERROR"; + gps_coords_msg_e = "GPS"; } } else { if (location.getGPSPower() > 0) { - status_msg = "Updating GPS Position"; + gps_coords_msg_n = "Updating"; + gps_coords_msg_e = "GPS"; } } } + + if(gps_coords_msg_n == null){ + gps_coords_msg_n = "N:" + Math2.format000_00(gps_coords[1]); + gps_coords_msg_e = "E:" + Math2.format000_00(gps_coords[0]); + } + g.setFont("Vector",13); g.setFontAlign(-1,-1,0); - if(last_status_msg != status_msg) { + console.log("n:" + gps_coords_msg_n + " e:" + gps_coords_msg_e); + if(last_gps_coords_msg_e != gps_coords_msg_e) { g.setColor(screen_info.screen_bg_color[0], screen_info.screen_bg_color[1], screen_info.screen_bg_color[2]); - g.drawString(last_status_msg, GPS_MSG_X_COORD, GPS_MSG_Y); - g.setColor(Colors.GREY[0],Colors.GREY[1],Colors.GREY[2]); - g.drawString(status_msg, GPS_MSG_X_COORD, GPS_MSG_Y); - last_status_msg = status_msg; + g.drawString(last_gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); + g.drawString(last_gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); + g.setColor(0.9,0.9,0.9); + + g.drawString(gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); + g.drawString(gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); + last_gps_coords_msg_e = gps_coords_msg_e; + last_gps_coords_msg_n = gps_coords_msg_n; } gps_status_requires_update = false; diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index 84364393c..d56808f22 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -15,9 +15,7 @@ class LocationManager { console.log("updating local location"); this._gpsUpdate(); this.gps_queried = true; - } else { - - } + } } setGPSPower(power){ this.gpsPower = power; diff --git a/apps/solarclock/solar_math_utils.js b/apps/solarclock/solar_math_utils.js index 98227d609..6399dacca 100644 --- a/apps/solarclock/solar_math_utils.js +++ b/apps/solarclock/solar_math_utils.js @@ -24,6 +24,16 @@ const Maths2 = { format00: (num)=>{ return _format00(num) }, + format000_00: (num)=>{ + var mantissa = (num | 0); + var mantissa_abs = Math.abs(mantissa); + var remainder = ((Math.abs(num) - mantissa_abs)*100|0); + var sign = "-"; + if(num >= 0) + sign = "+"; + return sign + mantissa_abs.toString() + "." + _format00(remainder); + + }, random_walk: (value,step,max,min)=>{ if(Math.random()>0.5){ value -= step; From 432636106e1b7d7eb20f45f4483a96aed4c43f50 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Tue, 20 Jul 2021 19:07:52 +0100 Subject: [PATCH 070/163] solar clock: BUGFIX current location not being written to file --- apps/solarclock/solar_location.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index d56808f22..2af73746d 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -34,7 +34,7 @@ class LocationManager { coordinates: [g.lon, g.lat] }; console.log("Received gps fixing:" + JSON.stringify(loc_info)); - storage.writeJSON("solar_loc.local.json", this.location_info); + storage.writeJSON("solar_loc.local.json", loc_info); this.setGPSPower(0); if(this.isGPSLocation()){ this.location_info = loc_info; From 563030affbbd81c6515b17edd4ccf574a6d89d43 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Wed, 21 Jul 2021 14:09:40 +0200 Subject: [PATCH 071/163] Added HC Clock Application --- apps.json | 14 +++ apps/hcclock/ChangeLog | 2 + apps/hcclock/hcclock-icon.js | 1 + apps/hcclock/hcclock-icon.png | Bin 0 -> 590 bytes apps/hcclock/hcclock.app.js | 191 ++++++++++++++++++++++++++++++++++ 5 files changed, 208 insertions(+) create mode 100644 apps/hcclock/ChangeLog create mode 100644 apps/hcclock/hcclock-icon.js create mode 100644 apps/hcclock/hcclock-icon.png create mode 100644 apps/hcclock/hcclock.app.js diff --git a/apps.json b/apps.json index cc21f3115..5d191229c 100644 --- a/apps.json +++ b/apps.json @@ -3316,5 +3316,19 @@ {"name":"mysticclock.settings.js","url":"mystic-clock-settings.js"}, {"name":"mysticclock.img","url":"mystic-clock-icon.js","evaluate":true} ] +}, +{ "id": "hcclock", + "name": "HiContrast Clock", + "icon": "hcclock-icon.png", + "version":"0.01", + "description": "High Contrast Clock", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"hcclock.app.js","url":"hcclock.app.js"}, + {"name":"hcclock.img","url":"hcclock-icon.js","evaluate":true} + ], + "sortorder" : -9 } ] diff --git a/apps/hcclock/ChangeLog b/apps/hcclock/ChangeLog new file mode 100644 index 000000000..0ca30d066 --- /dev/null +++ b/apps/hcclock/ChangeLog @@ -0,0 +1,2 @@ +0.01: base code + diff --git a/apps/hcclock/hcclock-icon.js b/apps/hcclock/hcclock-icon.js new file mode 100644 index 000000000..b41bd6fcc --- /dev/null +++ b/apps/hcclock/hcclock-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATiwAGFdYzlFp4xeFyYwZD49kxGt2fX6+z1uIsgxcDQtAxArCAA+zxFAGDAYFxAsJAAuIGCxcF1ouPAAOsGCouERRSUKSYguoGARgRCIiMSAAutGCDqUABNkF5yNEFzKRQLzwABxAvRdgYFBDgYFFBphgEF5lkEJwNOYIaORF7KQMBYetEJoDHAo+sF56+DF7TAMBYaBQBpwv/R97vvxCPdxAvLGAdkF7tkFxbAIF7C+MSBQAXRxovEoAvboAvNMD69DFxYvEi2sFy+sDwgvLGAryDACTsEFxrCGGCmzXh5gJSSaMFF6AwGshiPdQguSGA8WxAxK2eIRYguUGBBjBxGsGYWz1mILYwuWGJQANFq4wWFzQxSFrozNFcYA/AH4Av")) diff --git a/apps/hcclock/hcclock-icon.png b/apps/hcclock/hcclock-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..824062aedaded6605ecab000d555a519557ddd50 GIT binary patch literal 590 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s`2jv5u0Wb$%|V8>2N~8JVpx5U zVcj8yHTxJ=?PXYX48#RWtv&!EAqdC@i9l^T=394*!|0D^)Q|n3+{bZ=Ml6vn$cx?FmfJu z=|nYGZBG7NyFkWYu9|`GKL@vI-P>F}efgxFEK8y>zXwnKEyp^E(ahAYZiIW>)3mr6OV%r$25F}!S;>jsvYc^>)ZPo1~z znD6MiRJZ4K82{t2){WNhq8oRJukHH%<#y|%xX8>Waa|v8ZV YS?g0SGc5aa6O=GKUHx3vIVCg!0Fhi2)Bpeg literal 0 HcmV?d00001 diff --git a/apps/hcclock/hcclock.app.js b/apps/hcclock/hcclock.app.js new file mode 100644 index 000000000..cfff16c8b --- /dev/null +++ b/apps/hcclock/hcclock.app.js @@ -0,0 +1,191 @@ +{ +////////////////////////////////////////////////////// +// Numbers Rect order (left, top, right, bottom) +// Each number defines a set of rects to draw + +const numbers = +[ + [// Zero + [0, 0, 1, 0.2], + [0, 0.8, 1, 1], + [0, 0, 0.1, 1], + [0.9, 0, 1, 1] + ], + [// One + [0.7, 0, 1, 0.2], + [0.9, 0, 1, 1] + ], + [// Two + [0, 0, 1, 0.2], + [0, 0.4, 1, 0.6], + [0, 0.8, 1, 1], + [0, 0.4, 0.1, 1], + [0.9, 0, 1, 0.6] + ], + [// Three + [0, 0, 1, 0.2], + [0.5, 0.4, 1, 0.6], + [0, 0.8, 1, 1], + [0.9, 0, 1, 1] + ], + [// Four + [0, 0.4, 1, 0.6], + [0, 0, 0.1, 0.6], + [0.9, 0, 1, 1] + ], + [// Five + [0, 0, 1, 0.2], + [0, 0.4, 1, 0.6], + [0, 0.8, 1, 1], + [0, 0, 0.1, 0.6], + [0.9, 0.4, 1, 1] + ], + [// Six + [0, 0, 1, 0.2], + [0, 0.4, 1, 0.6], + [0, 0.8, 1, 1], + [0, 0, 0.1, 1.0], + [0.9, 0.4, 1, 1] + ], + [// Seven + [0.0, 0, 1, 0.2], + [0.9, 0, 1, 1] + ], + [// Eight + [0, 0, 1, 0.2], + [0, 0.4, 1, 0.6], + [0, 0.8, 1, 1], + [0, 0, 0.1, 1], + [0.9, 0, 1, 1] + ], + [// Nine + [0, 0, 1, 0.2], + [0, 0.4, 1, 0.6], + [0, 0.8, 1, 1], + [0, 0, 0.1, 0.6], + [0.9, 0, 1, 1] + ] +]; + +const months = [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ]; + +const interval = 1000; // in ms +const top = 32; + +let bg = 255; +let fg = 0; + +let mins = -1; +let hour = -1; +let day = -1; + +function refresh() +{ + g.setColor(bg,bg,bg); + g.fillRect(0,45,240,210); + Bangle.drawWidgets(); + updateTime(); +} + +function updateTime() +{ + let now = new Date(); + let m = now.getMinutes(); + let h = now.getHours(); + let mo = now.getMonth(); + let y = now.getFullYear(); + let d = now.getDay(); + + if(h != hour) + { + hour = h; + g.setColor(bg,bg,bg); + g.fillRect(0,60,240,110); + g.setColor(fg,fg,fg); + drawDigits(60, hour); + } + if(m != mins) + { + mins = m; + g.setColor(bg,bg,bg); + g.fillRect(0,145,240,195); + g.setColor(fg,fg,fg); + drawDigits(145, mins); + } + if(d != day) + { + day = d; + g.setFont("6x8", 2); + g.setFontAlign(0, -1, 0); + g.drawString(fmtDate(d,mo,y), 120, 120); + } +} + +function drawDigits(x, value) +{ + drawChar(Math.floor(value/10), 15, x, 115, x+50); + if(value%10 == 1) + drawChar(value%10, 55, x, 155, x+50); + else + drawChar(value%10, 125, x, 225, x+50); +} + +function drawChar(i, xMin, yMin, xMax, yMax) +{ + numbers[i].forEach(rect => { + r = place(rect, xMin, yMin, xMax, yMax); + g.setColor(fg,fg,fg); + g.fillRect(r[0], r[1], r[2], r[3]); + }); +} + +function place(array, xMin, yMin, xMax, yMax) +{ + return [ + lerp(xMin,xMax,array[0]), + lerp(yMin,yMax,array[1]), + lerp(xMin,xMax,array[2]), + lerp(yMin,yMax,array[3]) + ]; +} + +function lerp(a,b,t) +{ + return a + t*(b-a); +} + +function fmtDate(day,month,year) +{ + return months[month] + " " + day + " " + year; +} + +// Handles Flipping colors, then refreshes the UI +function flipColors() +{ + let t = bg; + bg = fg; + fg = t; + mins = -1; + hour = -1; + day = -1; + refresh(); +} + +////////////////////////////////////////// +// +// MAIN FUNCTION() +// + +// Initialize +g.clear(); +Bangle.loadWidgets(); +refresh(); + +// Define Refresh Interval +setInterval(updateTime, interval); + +// Handle Button Press +setWatch(flipColors, BTN1, true); +setWatch(Bangle.showLauncher, BTN2, false); + +} From 90988a309b8c9faaecf55568af57a5d499f92855 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Wed, 21 Jul 2021 14:21:59 +0200 Subject: [PATCH 072/163] Updated App Name and Description --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 5d191229c..6585a7c89 100644 --- a/apps.json +++ b/apps.json @@ -3318,10 +3318,10 @@ ] }, { "id": "hcclock", - "name": "HiContrast Clock", + "name": "High Contrast Clock", "icon": "hcclock-icon.png", "version":"0.01", - "description": "High Contrast Clock", + "description": "High Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.", "tags": "clock", "type":"clock", "allow_emulator":true, From 8550b1a09a077cc6900dedccc28c94223f47da2a Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Wed, 21 Jul 2021 15:27:58 +0200 Subject: [PATCH 073/163] Fixed buttons at startup, app visibility, added AM/PM support --- apps.json | 7 +++---- apps/hcclock/hcclock.app.js | 25 ++++++++++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/apps.json b/apps.json index 6585a7c89..f879fca22 100644 --- a/apps.json +++ b/apps.json @@ -3318,17 +3318,16 @@ ] }, { "id": "hcclock", - "name": "High Contrast Clock", + "name": "Hi-Contrast Clock", "icon": "hcclock-icon.png", "version":"0.01", - "description": "High Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.", + "description": "Hi-Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.", "tags": "clock", "type":"clock", "allow_emulator":true, "storage": [ {"name":"hcclock.app.js","url":"hcclock.app.js"}, {"name":"hcclock.img","url":"hcclock-icon.js","evaluate":true} - ], - "sortorder" : -9 + ] } ] diff --git a/apps/hcclock/hcclock.app.js b/apps/hcclock/hcclock.app.js index cfff16c8b..d1866c11b 100644 --- a/apps/hcclock/hcclock.app.js +++ b/apps/hcclock/hcclock.app.js @@ -1,4 +1,4 @@ -{ + ////////////////////////////////////////////////////// // Numbers Rect order (left, top, right, bottom) // Each number defines a set of rects to draw @@ -72,6 +72,8 @@ const months = [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", const interval = 1000; // in ms const top = 32; +let ampm = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; + let bg = 255; let fg = 0; @@ -94,7 +96,7 @@ function updateTime() let h = now.getHours(); let mo = now.getMonth(); let y = now.getFullYear(); - let d = now.getDay(); + let d = now.getDate(); if(h != hour) { @@ -102,7 +104,9 @@ function updateTime() g.setColor(bg,bg,bg); g.fillRect(0,60,240,110); g.setColor(fg,fg,fg); - drawDigits(60, hour); + if(ampm) + h = h%12; + drawDigits(60, h); } if(m != mins) { @@ -117,7 +121,7 @@ function updateTime() day = d; g.setFont("6x8", 2); g.setFontAlign(0, -1, 0); - g.drawString(fmtDate(d,mo,y), 120, 120); + g.drawString(fmtDate(d,mo,y,hour), 120, 120); } } @@ -154,9 +158,17 @@ function lerp(a,b,t) return a + t*(b-a); } -function fmtDate(day,month,year) +function fmtDate(day,month,year,hour) { - return months[month] + " " + day + " " + year; + if(ampm) + { + let ap = "(AM)"; + if(hour == 0 || hour > 12) + ap = "(PM)"; + return months[month] + " " + day + " " + year + " "+ ap; + } + else + return months[month] + " " + day + " " + year; } // Handles Flipping colors, then refreshes the UI @@ -188,4 +200,3 @@ setInterval(updateTime, interval); setWatch(flipColors, BTN1, true); setWatch(Bangle.showLauncher, BTN2, false); -} From 19dcb38dfbe8b8e8f7cbf364f064411f18cdc7e2 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Wed, 21 Jul 2021 15:35:53 +0200 Subject: [PATCH 074/163] Shortened Months to fit width in AMPM mode --- apps/hcclock/hcclock.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/hcclock/hcclock.app.js b/apps/hcclock/hcclock.app.js index d1866c11b..3b3906923 100644 --- a/apps/hcclock/hcclock.app.js +++ b/apps/hcclock/hcclock.app.js @@ -67,7 +67,7 @@ const numbers = ] ]; -const months = [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ]; +const months = [ "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" ]; const interval = 1000; // in ms const top = 32; @@ -168,7 +168,7 @@ function fmtDate(day,month,year,hour) return months[month] + " " + day + " " + year + " "+ ap; } else - return months[month] + " " + day + " " + year; + return months[month] + ". " + day + " " + year; } // Handles Flipping colors, then refreshes the UI From 42ef7f23d234784eace4cf4469f9ac361e21762d Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Wed, 21 Jul 2021 15:59:30 +0200 Subject: [PATCH 075/163] Updated Icon --- apps/hcclock/hcclock-icon.js | 2 +- apps/hcclock/hcclock-icon.png | Bin 590 -> 353 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hcclock/hcclock-icon.js b/apps/hcclock/hcclock-icon.js index b41bd6fcc..52b3d5cb6 100644 --- a/apps/hcclock/hcclock-icon.js +++ b/apps/hcclock/hcclock-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATiwAGFdYzlFp4xeFyYwZD49kxGt2fX6+z1uIsgxcDQtAxArCAA+zxFAGDAYFxAsJAAuIGCxcF1ouPAAOsGCouERRSUKSYguoGARgRCIiMSAAutGCDqUABNkF5yNEFzKRQLzwABxAvRdgYFBDgYFFBphgEF5lkEJwNOYIaORF7KQMBYetEJoDHAo+sF56+DF7TAMBYaBQBpwv/R97vvxCPdxAvLGAdkF7tkFxbAIF7C+MSBQAXRxovEoAvboAvNMD69DFxYvEi2sFy+sDwgvLGAryDACTsEFxrCGGCmzXh5gJSSaMFF6AwGshiPdQguSGA8WxAxK2eIRYguUGBBjBxGsGYWz1mILYwuWGJQANFq4wWFzQxSFrozNFcYA/AH4Av")) +var img = E.toArrayBuffer(atob("MDABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/////AAf/////AAf/////AAeAAwf/AAf/+/f/AAeAA/f/AAe///f/AAeAA/f/AAf/////AAf/////AAeFBQAHAAfFZQcHAAf/////AAf/////AAeAA3/3AAf/+3/3AAf+AwAHAAf/+//3AAeAA//3AAf/////AAf/////AAf/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) diff --git a/apps/hcclock/hcclock-icon.png b/apps/hcclock/hcclock-icon.png index 824062aedaded6605ecab000d555a519557ddd50..29b113a46581a6c9a4a2802f85917b13de0454aa 100644 GIT binary patch delta 194 zcmX@d@{nnQ3Lj%}kh>GZx^prw85kH!C#n|n0cjuz^iatMQtA^INYwww1Poo3APwoB zE{-7{oyiFjtcw#G8aWaT1f)VHGEVW{!n;aCq|i)YA>-w{A=?_C1Smx^-%wq3;X%mJ z0!15!k2BXicH!}4AkZbDlay)P-;<9BHl$~En23Um-J aXJ9!0#P#+gt`?w`3=E#GelF{r5}E)qn@q|8 delta 453 zcmV;$0XqKS0?q`GBmr-cGIM`0y$(bG000zpQchC<`RtdiS2r6HwBm+%)zXp)dgO@7 zXr5#M00DYQL_t(Y$K6%w&Vn!yltV>P@aO^M2H*b~zYbrD1=^b6KPSN@b@-;@K4}n(d2)O=MMfrMMMZ(r%^(>0yk}$v*7H$e@l!Qq1yLJa?eXa=CkAvce7C4P^6~rNn-usD zKUx{$4Y8o%OH)Vmt0z_r=%C*7CkzogGMI`r!C9UQb&)1TD+v#6K2ZVsMJZA5^HYW@ z-m`m`r;@n@q?DA)BnW?%Bf9{e!bxzIr$(pXH5Uj;NhSfhmdkRPSpc&+dN&Es1?INI z(20!#Wyw_oQY?s7-Y4u1etC~Z#U&bwz!``MWro_>sAlrR)smSJMLS7xEHO8`}Es| v;$B&4 Date: Wed, 21 Jul 2021 20:45:08 +0200 Subject: [PATCH 076/163] Tentative : make icon work --- apps/hcclock/hcclock-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hcclock/hcclock-icon.js b/apps/hcclock/hcclock-icon.js index 52b3d5cb6..2a164c8e1 100644 --- a/apps/hcclock/hcclock-icon.js +++ b/apps/hcclock/hcclock-icon.js @@ -1 +1 @@ -var img = E.toArrayBuffer(atob("MDABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/////AAf/////AAf/////AAeAAwf/AAf/+/f/AAeAA/f/AAe///f/AAeAA/f/AAf/////AAf/////AAeFBQAHAAfFZQcHAAf/////AAf/////AAeAA3/3AAf/+3/3AAf+AwAHAAf/+//3AAeAA//3AAf/////AAf/////AAf/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) +E.toArrayBuffer(atob("MDABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/////AAf/////AAf/////AAeAAwf/AAf/+/f/AAeAA/f/AAe///f/AAeAA/f/AAf/////AAf/////AAeFBQAHAAfFZQcHAAf/////AAf/////AAeAA3/3AAf/+3/3AAf+AwAHAAf/+//3AAeAA//3AAf/////AAf/////AAf/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) From 54b961d7d6074bffa30ecacb75c18d1f93de213d Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Thu, 22 Jul 2021 10:11:58 +0200 Subject: [PATCH 077/163] Updated Icon --- apps/hcclock/hcclock-icon.js | 2 +- apps/hcclock/hcclock-icon.png | Bin 353 -> 368 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hcclock/hcclock-icon.js b/apps/hcclock/hcclock-icon.js index 2a164c8e1..2486c6500 100644 --- a/apps/hcclock/hcclock-icon.js +++ b/apps/hcclock/hcclock-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("MDABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/////AAf/////AAf/////AAeAAwf/AAf/+/f/AAeAA/f/AAe///f/AAeAA/f/AAf/////AAf/////AAeFBQAHAAfFZQcHAAf/////AAf/////AAeAA3/3AAf/+3/3AAf+AwAHAAf/+//3AAeAA//3AAf/////AAf/////AAf/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) +E.toArrayBuffer(atob("MDAB////////////////////////////////////////////////////////////////////////////////4AABgAAH4AABgAAH///5n//n///5n//n4AABn//n4AABn//n5///n//n5///n//n4AABgAAH4AABgAAH/////////////////////////015urF//3d+vZt//1V5uNV/////////////////5//5gAAH5//5gAAH5//5n//n5//5n//n4AABgAAH4AABgAAH///5n//n///5n//n///5gAAH///5gAAH////////////////////////////////////////////////////////////////////////////////")) diff --git a/apps/hcclock/hcclock-icon.png b/apps/hcclock/hcclock-icon.png index 29b113a46581a6c9a4a2802f85917b13de0454aa..5d5506249558a90aa6d989fb48133ef628f7ae61 100644 GIT binary patch delta 147 zcmV;E0Brx^0`LNm<$rcbL_t(YiS5(@3cw%;1<(%R6}Q7bpoUn*)0Quxt)kEmZ=mtvb*@2PYbVV!ZNx8@ytRA(s007VAMcd*Ega7~l002ovPDHLkV1nR&Fp>ZO From 09ee8a5cf9df57fe9277d854948bf7747340b285 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Thu, 22 Jul 2021 15:46:39 +0200 Subject: [PATCH 078/163] Optimized when lcd off, back lcd on screen --- apps/hcclock/hcclock.app.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/hcclock/hcclock.app.js b/apps/hcclock/hcclock.app.js index 3b3906923..dac5063cb 100644 --- a/apps/hcclock/hcclock.app.js +++ b/apps/hcclock/hcclock.app.js @@ -81,8 +81,14 @@ let mins = -1; let hour = -1; let day = -1; -function refresh() -{ +function redraw() { + mins = -1; + hour = -1; + day = -1; + refresh(); +} + +function refresh() { g.setColor(bg,bg,bg); g.fillRect(0,45,240,210); Bangle.drawWidgets(); @@ -127,6 +133,9 @@ function updateTime() function drawDigits(x, value) { + if(!Bangle.isLCDOn()) // No need to draw when LCD Off + return; + drawChar(Math.floor(value/10), 15, x, 115, x+50); if(value%10 == 1) drawChar(value%10, 55, x, 155, x+50); @@ -177,10 +186,7 @@ function flipColors() let t = bg; bg = fg; fg = t; - mins = -1; - hour = -1; - day = -1; - refresh(); + redraw(); } ////////////////////////////////////////// @@ -191,7 +197,7 @@ function flipColors() // Initialize g.clear(); Bangle.loadWidgets(); -refresh(); +redraw(); // Define Refresh Interval setInterval(updateTime, interval); @@ -200,3 +206,5 @@ setInterval(updateTime, interval); setWatch(flipColors, BTN1, true); setWatch(Bangle.showLauncher, BTN2, false); +// Handle redraw on LCD on +Bangle.on('lcdPower', (on) => { if(on) redraw(); }); From 627dee86bfcc884e269bcbb8580033fa4da452ea Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Thu, 22 Jul 2021 15:59:40 +0200 Subject: [PATCH 079/163] Added Readme --- apps/hcclock/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 apps/hcclock/README.md diff --git a/apps/hcclock/README.md b/apps/hcclock/README.md new file mode 100644 index 000000000..328f1fe03 --- /dev/null +++ b/apps/hcclock/README.md @@ -0,0 +1,13 @@ +# Hi-Contrast Clock + +A High-contrast, black-on-white or white-on-black clock displaying huge pixel digits. It is purposed for being both elegant and readable in high luminosity environments. The goal is to keep the clock as simple and efficient as possible. + +## Usage + +* BTN 1 switches between the two modes : black-on-white or white-on-black +* That's it! + +## Issues and Requests + +If you have issues, feel free to contact me at https://github.com/peeweek/ + From d19f96f8ce8b9288f0f52c3a5d9f01b7b91bfae3 Mon Sep 17 00:00:00 2001 From: numerist Date: Thu, 22 Jul 2021 11:56:14 -0400 Subject: [PATCH 080/163] Update ChangeLog --- apps/doztime/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/doztime/ChangeLog b/apps/doztime/ChangeLog index ffa84b497..de00f009c 100644 --- a/apps/doztime/ChangeLog +++ b/apps/doztime/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02 added emulator capability and display of widgets 0.03 bug of advancing time fixed; doztime now correct within ca. 1 second +0.04 changed time colour from slightly off white to pure white From b5b85fe7f604d76496a43e99674acd31b83beca5 Mon Sep 17 00:00:00 2001 From: numerist Date: Thu, 22 Jul 2021 12:08:15 -0400 Subject: [PATCH 081/163] Update app.js --- apps/doztime/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/doztime/app.js b/apps/doztime/app.js index 9faede70a..38c5acbac 100644 --- a/apps/doztime/app.js +++ b/apps/doztime/app.js @@ -13,7 +13,7 @@ const g_height_t = 48; // height of time region const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; -const timeColour = "#f2f2f2"; +const timeColour = "#ffffff"; const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#0000ff","#ff00ff","#ff0080"]; const calen10 = {"size":32,"pt0":[32-g_x_off,16],"step":[20,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line const calen7 = {"size":32,"pt0":[62-g_x_off,16],"step":[20,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line From 1d5dc855d07ee93df0327f1a678a09ba35fb12a1 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 09:34:03 -0700 Subject: [PATCH 082/163] Added Fahrenheit Thermometer --- apps.json | 17 +++++++++++++++++ apps/thermomF/app-icon.js | 2 ++ apps/thermomF/app..png | Bin 0 -> 1189 bytes apps/thermomF/app.js | 28 ++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 apps/thermomF/app-icon.js create mode 100644 apps/thermomF/app..png create mode 100644 apps/thermomF/app.js diff --git a/apps.json b/apps.json index cc21f3115..2148fb5f6 100644 --- a/apps.json +++ b/apps.json @@ -3316,5 +3316,22 @@ {"name":"mysticclock.settings.js","url":"mystic-clock-settings.js"}, {"name":"mysticclock.img","url":"mystic-clock-icon.js","evaluate":true} ] +}, + + +{ "id": "thermomF", + "name": "Fahrenheit Thermometer", + "shortName":"Thermometer F", + "icon": "app.png", + "version":"0.01", + "description": "A modification of the Thermometer App to display temprature in Fahrenheit", + "tags": "", + "storage": [ + {"name":"thermof.app.js","url":"app.js"}, + {"name":"thermof.png","url":"app-icon.js","evaluate":true} + ] } ] + + + diff --git a/apps/thermomF/app-icon.js b/apps/thermomF/app-icon.js new file mode 100644 index 000000000..3a5bb959f --- /dev/null +++ b/apps/thermomF/app-icon.js @@ -0,0 +1,2 @@ +require("heatshrink").decompress(atob("AH4A/AAMIxGIwAXTxACEACIsChAXqLwQDBMCQXYI4YvUCgIXVF6xH/I8DX/R/4ANgUgAIYX/C+MiC4ciFyQCGC54aEgAXQIIUiAYYXRgUzmYtBC6ASCC4IcCC5+wgGzC4M7gELC6O7C4O7C6ISC2c7DgQXRAQIDDC58LFYIFIGB4uSFQRFDFyJeDMAYA/AH4")) +} \ No newline at end of file diff --git a/apps/thermomF/app..png b/apps/thermomF/app..png new file mode 100644 index 0000000000000000000000000000000000000000..bb33cb939d63a9682e318025e2f94c7c1f0ea31b GIT binary patch literal 1189 zcmV;W1X}xvP)nbkt*}t8k&unGMZv-!*9L9P7LD0b z$gE+K)ifw5s5ZsGe@q54Q4?BH5!OTshs9=5bi*=m{V<9_)2Li(Qenkb?8kkd(;xS~ z+nBrl(fi!m#T|J5c+NST@AKt3&pGG47p7%eE^SfS3LJYvmN-HjK!i_E?@`CHfn%M( z{3oTz8Kzy}t_h}2m89YOm(-s&@f@4M0Q^DPwV~QKH2DrO-y!A;&7R>7?eMy7JgaiU zBeJBlQKW3WG)=UXt(T_KMv<}&vdAW;)f@2PR&Br^Vc!L|5%y^VI-tTPrd0y2p->x8 zaHf2nNclRE(02S4bygd211__Psci=H0TB>I%Vc&>Kv^yuRtad6B5?FI)tt$0n}F36 z(k8WTTO(5Wplr!xw~A>sSo#K(qJ@A@CbLiZ6hh$L{gbDVXRzKnvywt}_leZ4&e0SC zP|#vzk`xj^CTb&M+6?BK)cM|gD{~6j9=_~9V&MLjV-0No!LetnbA^D)(8zLzz^iXx zq>u}~2$_WCYJawle0Cv2msz&Wo znSh_3g~sp4iB=*1?*_!TRLTrnxK;>k ztB@;(JrbU>gd8*T}bwAsLpOkn3ysn>>k-GFDGKB^9f`qsEC(1tnMFlX0Nxh~W{^Reo54b9rH zsENgSpfq|@qFVk^&G&93#D2qK1i0sP;JW3?*i{jaG?6pZuKER+alQtH2E_rc<3WF z_;1e;=>`gg`C4$CfSyq2L4(dGnZE*xW~SE66`=D8TxbaWT&!wG2#_4}?Joe+&)jhDCOPjYP!OpaMY@3*hI870FT_Rz26U@)I0Zk# zl_RND@B_GKaWr&?exBi)bffz@${8XNSp5~JJi{5^P!sA3|7N={^!>gUGuQ!x9dLdx z#)Cd@i0z@D4>g|Q^qMdD>3<`jP@)Y7T*EybH>OHueXr_w0~Wc%v=4mFz+a!y?c#~YM15N_p=pm|Wzf(gO^Y2<9dC5Ey3QAp{ z>uZmzU!&kh?gJ~oR=;S&S}nx!>3pYHW@qy4S|C^9)1`&Qj<7cB;lbkP#rq}l0Pr%x zpulcX9P(Xy0Y;LPD2I9skE6&Fc(~?UwciG=)!{Z#EG57;U^(DUFb4__8O5gCdsVM3 z%&h#)nkbgp+E67hFAZ`!>5!;8p?=E--n2~1r7ZsdH4U76`VJt+00000NkvXXu0mjf DV^KD_ literal 0 HcmV?d00001 diff --git a/apps/thermomF/app.js b/apps/thermomF/app.js new file mode 100644 index 000000000..76f15b481 --- /dev/null +++ b/apps/thermomF/app.js @@ -0,0 +1,28 @@ +function onTemperature(p) { + g.reset(1).clearRect(0,24,g.getWidth(),g.getHeight()); + g.setFont("6x8",2).setFontAlign(0,0); + var x = g.getWidth()/2; + var y = g.getHeight()/2 + 10; + g.drawString("Temperature", x, y - 45); + g.setFontVector(70).setFontAlign(0,0); + g.drawString(p.temperature.toFixed(1), x, y); +} + +function drawTemperature() { + if (Bangle.getPressure) { + Bangle.getPressure().then(onTemperature); + } else { + onTemperature({ + temperature : E.getTemperature() * (9/5) + 32, + }); + } +} + + +setInterval(function() { + drawTemperature(); +}, 20000); +drawTemperature(); +E.showMessage("Loading..."); +Bangle.loadWidgets(); +Bangle.drawWidgets(); \ No newline at end of file From fcc17e075edcafdb2aaa6cf3f5b8d77b5f4fa76f Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 09:51:50 -0700 Subject: [PATCH 083/163] Update apps.json fixed formatting --- apps.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps.json b/apps.json index 2148fb5f6..6a486e7e5 100644 --- a/apps.json +++ b/apps.json @@ -3317,8 +3317,6 @@ {"name":"mysticclock.img","url":"mystic-clock-icon.js","evaluate":true} ] }, - - { "id": "thermomF", "name": "Fahrenheit Thermometer", "shortName":"Thermometer F", From 3f50989e03225fb8e400165eaf01ab13d76aa268 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 09:59:39 -0700 Subject: [PATCH 084/163] Formating fixes --- apps.json | 2 -- apps/thermomF/{app..png => app.png} | Bin 2 files changed, 2 deletions(-) rename apps/thermomF/{app..png => app.png} (100%) diff --git a/apps.json b/apps.json index 2148fb5f6..6a486e7e5 100644 --- a/apps.json +++ b/apps.json @@ -3317,8 +3317,6 @@ {"name":"mysticclock.img","url":"mystic-clock-icon.js","evaluate":true} ] }, - - { "id": "thermomF", "name": "Fahrenheit Thermometer", "shortName":"Thermometer F", diff --git a/apps/thermomF/app..png b/apps/thermomF/app.png similarity index 100% rename from apps/thermomF/app..png rename to apps/thermomF/app.png From 51a10df84c10ea184f88d64bd72aad978ea3da40 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 10:11:24 -0700 Subject: [PATCH 085/163] formatting fixes (forgive the noob) --- apps.json | 8 ++++---- apps/thermomF/{app.png => thermf.png} | Bin 2 files changed, 4 insertions(+), 4 deletions(-) rename apps/thermomF/{app.png => thermf.png} (100%) diff --git a/apps.json b/apps.json index 6a486e7e5..d64b6c017 100644 --- a/apps.json +++ b/apps.json @@ -3318,15 +3318,15 @@ ] }, { "id": "thermomF", - "name": "Fahrenheit Thermometer", - "shortName":"Thermometer F", - "icon": "app.png", + "name": "Fahrenheit Temp", + "shortName":"F Temp", + "icon": "thermf.png", "version":"0.01", "description": "A modification of the Thermometer App to display temprature in Fahrenheit", "tags": "", "storage": [ {"name":"thermof.app.js","url":"app.js"}, - {"name":"thermof.png","url":"app-icon.js","evaluate":true} + {"name":"thermof.img","url":"app-icon.js","evaluate":true} ] } ] diff --git a/apps/thermomF/app.png b/apps/thermomF/thermf.png similarity index 100% rename from apps/thermomF/app.png rename to apps/thermomF/thermf.png From 89f67dff6e1a04f209514d89b575f958e679cc47 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 10:20:06 -0700 Subject: [PATCH 086/163] another format fix *sigh* --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index d64b6c017..4befd9965 100644 --- a/apps.json +++ b/apps.json @@ -3325,8 +3325,8 @@ "description": "A modification of the Thermometer App to display temprature in Fahrenheit", "tags": "", "storage": [ - {"name":"thermof.app.js","url":"app.js"}, - {"name":"thermof.img","url":"app-icon.js","evaluate":true} + {"name":"thermomF.app.js","url":"app.js"}, + {"name":"thermomF.img","url":"app-icon.js","evaluate":true} ] } ] From f43b2d33190ecf730d4f0bb5fdec8e30810cdc61 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 10:27:16 -0700 Subject: [PATCH 087/163] YAFF --- apps.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4befd9965..18b7e9c66 100644 --- a/apps.json +++ b/apps.json @@ -3319,11 +3319,10 @@ }, { "id": "thermomF", "name": "Fahrenheit Temp", - "shortName":"F Temp", "icon": "thermf.png", "version":"0.01", "description": "A modification of the Thermometer App to display temprature in Fahrenheit", - "tags": "", + "tags": "Temperature, Thermometer", "storage": [ {"name":"thermomF.app.js","url":"app.js"}, {"name":"thermomF.img","url":"app-icon.js","evaluate":true} From 53a138f11656e7d434a14518efd7017f0abe6188 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 10:34:41 -0700 Subject: [PATCH 088/163] YAFF a comma --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 18b7e9c66..c6e3a5af0 100644 --- a/apps.json +++ b/apps.json @@ -3327,7 +3327,7 @@ {"name":"thermomF.app.js","url":"app.js"}, {"name":"thermomF.img","url":"app-icon.js","evaluate":true} ] -} +}, ] From 0d6524ff2e18c8fed80ab093cbdbbbcf080fb26e Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 10:45:24 -0700 Subject: [PATCH 089/163] fixed synatx error --- apps/thermomF/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thermomF/app.js b/apps/thermomF/app.js index 76f15b481..2961e1efc 100644 --- a/apps/thermomF/app.js +++ b/apps/thermomF/app.js @@ -13,7 +13,7 @@ function drawTemperature() { Bangle.getPressure().then(onTemperature); } else { onTemperature({ - temperature : E.getTemperature() * (9/5) + 32, + temperature : E.getTemperature() * (9/5) + 32 }); } } From 13b65888f840a883f2e841381111ab63b0730599 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 10:48:34 -0700 Subject: [PATCH 090/163] YAFF --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index c6e3a5af0..18b7e9c66 100644 --- a/apps.json +++ b/apps.json @@ -3327,7 +3327,7 @@ {"name":"thermomF.app.js","url":"app.js"}, {"name":"thermomF.img","url":"app-icon.js","evaluate":true} ] -}, +} ] From e4880a57d4ad506399c6524d6f34fe55b7da4fd1 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 10:59:29 -0700 Subject: [PATCH 091/163] YAFF --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 18b7e9c66..690c03e8b 100644 --- a/apps.json +++ b/apps.json @@ -3322,7 +3322,7 @@ "icon": "thermf.png", "version":"0.01", "description": "A modification of the Thermometer App to display temprature in Fahrenheit", - "tags": "Temperature, Thermometer", + "tags": "tool", "storage": [ {"name":"thermomF.app.js","url":"app.js"}, {"name":"thermomF.img","url":"app-icon.js","evaluate":true} From 026c63f7dd9373bc6f3fad73043b0ad0cf29ae67 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 11:53:26 -0700 Subject: [PATCH 092/163] correct syntax error --- apps/thermomF/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thermomF/app-icon.js b/apps/thermomF/app-icon.js index 3a5bb959f..45e3675b6 100644 --- a/apps/thermomF/app-icon.js +++ b/apps/thermomF/app-icon.js @@ -1,2 +1,2 @@ require("heatshrink").decompress(atob("AH4A/AAMIxGIwAXTxACEACIsChAXqLwQDBMCQXYI4YvUCgIXVF6xH/I8DX/R/4ANgUgAIYX/C+MiC4ciFyQCGC54aEgAXQIIUiAYYXRgUzmYtBC6ASCC4IcCC5+wgGzC4M7gELC6O7C4O7C6ISC2c7DgQXRAQIDDC58LFYIFIGB4uSFQRFDFyJeDMAYA/AH4")) -} \ No newline at end of file +}; \ No newline at end of file From 2c952dc281615754f7176ce416c54bd7f9fa3dde Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 11:58:03 -0700 Subject: [PATCH 093/163] FAFF --- apps/thermomF/app-icon.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/thermomF/app-icon.js b/apps/thermomF/app-icon.js index 45e3675b6..64edafeed 100644 --- a/apps/thermomF/app-icon.js +++ b/apps/thermomF/app-icon.js @@ -1,2 +1 @@ -require("heatshrink").decompress(atob("AH4A/AAMIxGIwAXTxACEACIsChAXqLwQDBMCQXYI4YvUCgIXVF6xH/I8DX/R/4ANgUgAIYX/C+MiC4ciFyQCGC54aEgAXQIIUiAYYXRgUzmYtBC6ASCC4IcCC5+wgGzC4M7gELC6O7C4O7C6ISC2c7DgQXRAQIDDC58LFYIFIGB4uSFQRFDFyJeDMAYA/AH4")) -}; \ No newline at end of file +require("heatshrink").decompress(atob("AH4A/AAMIxGIwAXTxACEACIsChAXqLwQDBMCQXYI4YvUCgIXVF6xH/I8DX/R/4ANgUgAIYX/C+MiC4ciFyQCGC54aEgAXQIIUiAYYXRgUzmYtBC6ASCC4IcCC5+wgGzC4M7gELC6O7C4O7C6ISC2c7DgQXRAQIDDC58LFYIFIGB4uSFQRFDFyJeDMAYA/AH4"))} \ No newline at end of file From dda544bd5810bf1e90e1e7b88e6dd4ff0c73fe44 Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 12:17:58 -0700 Subject: [PATCH 094/163] Fixed Syntax error --- apps/thermomF/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thermomF/app-icon.js b/apps/thermomF/app-icon.js index 64edafeed..0f733eeac 100644 --- a/apps/thermomF/app-icon.js +++ b/apps/thermomF/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("AH4A/AAMIxGIwAXTxACEACIsChAXqLwQDBMCQXYI4YvUCgIXVF6xH/I8DX/R/4ANgUgAIYX/C+MiC4ciFyQCGC54aEgAXQIIUiAYYXRgUzmYtBC6ASCC4IcCC5+wgGzC4M7gELC6O7C4O7C6ISC2c7DgQXRAQIDDC58LFYIFIGB4uSFQRFDFyJeDMAYA/AH4"))} \ No newline at end of file +require("heatshrink").decompress(atob("AH4A/AAMIxGIwAXTxACEACIsChAXqLwQDBMCQXYI4YvUCgIXVF6xH/I8DX/R/4ANgUgAIYX/C+MiC4ciFyQCGC54aEgAXQIIUiAYYXRgUzmYtBC6ASCC4IcCC5+wgGzC4M7gELC6O7C4O7C6ISC2c7DgQXRAQIDDC58LFYIFIGB4uSFQRFDFyJeDMAYA/AH4")) \ No newline at end of file From 944d89468bc18f25a07c384d0306ddfd335d107b Mon Sep 17 00:00:00 2001 From: "L. Christopher Bird" Date: Thu, 22 Jul 2021 12:38:24 -0700 Subject: [PATCH 095/163] fkxed icon from object to string --- apps/thermomF/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/thermomF/app-icon.js b/apps/thermomF/app-icon.js index 0f733eeac..fe1fa86b7 100644 --- a/apps/thermomF/app-icon.js +++ b/apps/thermomF/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("AH4A/AAMIxGIwAXTxACEACIsChAXqLwQDBMCQXYI4YvUCgIXVF6xH/I8DX/R/4ANgUgAIYX/C+MiC4ciFyQCGC54aEgAXQIIUiAYYXRgUzmYtBC6ASCC4IcCC5+wgGzC4M7gELC6O7C4O7C6ISC2c7DgQXRAQIDDC58LFYIFIGB4uSFQRFDFyJeDMAYA/AH4")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwwhC/AH4AChGIxGAC6eIAQgARFgUIC9ReCAYJgSC7BHDF6gUBC6ovWI/5Hga/6P/ABsCkABDC/4XxkQXDkQuSAQwXPDQkAC6BBCkQDDC6MCmczFoIXQCQQXBDgQXP2EA2YXBncAhYXR3YXB3YXRCQWznYcCC6ICBAYYXPhYrBApAwPFyQqCIoYuRLwZgDAH4A/")) \ No newline at end of file From 2b09d7022622e195d377698e77bae422649094bc Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Thu, 22 Jul 2021 20:48:09 +0100 Subject: [PATCH 096/163] Solar clock: shaving off memory usage on the side panels --- apps/solarclock/solar_clock.js | 80 +++++++++++----------------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index d0c86e056..03503b622 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -157,101 +157,73 @@ function write_date(now){ } -const GPS_MSG_COORDS_Y_E = 90; -const GPS_MSG_COORDS_Y_N = 105; +const INFO_PANEL_LINE_Y1 = 90; +const INFO_PANEL_LINE_Y2 = 105; var gps_status_requires_update = true; -var last_gps_coords_msg_n = ""; -var last_gps_coords_msg_e = ""; function write_GPS_status(){ if(!gps_status_requires_update) return; var gps_coords = location.getCoordinates(); - var gps_coords_msg_n; - var gps_coords_msg_e; + var gps_coords_msg = []; if(location.isGPSLocation()) { if(gps_coords == null) { if (location.getGPSPower() > 0) { - gps_coords_msg_n = "Locating"; - gps_coords_msg_e = "GPS"; + gps_coords_msg = ["Locating","GPS"]; } else { - gps_coords_msg_n = "ERROR"; - gps_coords_msg_e = "GPS"; + gps_coords_msg = ["ERROR","GPS"]; } } else { if (location.getGPSPower() > 0) { - gps_coords_msg_n = "Updating"; - gps_coords_msg_e = "GPS"; + gps_coords_msg = ["Updating","GPS"]; } } } - if(gps_coords_msg_n == null){ - gps_coords_msg_n = "N:" + Math2.format000_00(gps_coords[1]); - gps_coords_msg_e = "E:" + Math2.format000_00(gps_coords[0]); + if(gps_coords_msg.length == 0){ + gps_coords_msg = ["N:" + Math2.format000_00(gps_coords[1]), + "E:" + Math2.format000_00(gps_coords[0])]; } + g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + //g.setColor(0.5,0.5,0.5); + g.fillRect(DATE_X_COORD,INFO_PANEL_LINE_Y1,60,INFO_PANEL_LINE_Y2 + 13); g.setFont("Vector",13); g.setFontAlign(-1,-1,0); - console.log("n:" + gps_coords_msg_n + " e:" + gps_coords_msg_e); - if(last_gps_coords_msg_e != gps_coords_msg_e) { - g.setColor(screen_info.screen_bg_color[0], - screen_info.screen_bg_color[1], - screen_info.screen_bg_color[2]); - g.drawString(last_gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); - g.drawString(last_gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); - g.setColor(0.9,0.9,0.9); - - g.drawString(gps_coords_msg_e, DATE_X_COORD, GPS_MSG_COORDS_Y_E); - g.drawString(gps_coords_msg_n, DATE_X_COORD, GPS_MSG_COORDS_Y_N); - last_gps_coords_msg_e = gps_coords_msg_e; - last_gps_coords_msg_n = gps_coords_msg_n; - } + g.drawString(gps_coords_msg[0], DATE_X_COORD, INFO_PANEL_LINE_Y1,1); + g.drawString(gps_coords_msg[1], DATE_X_COORD, INFO_PANEL_LINE_Y2,1); gps_status_requires_update = false; } const TWILIGHT_X_COORD = 200; -const SUNUP_Y_COORD = 90; -const SUNDOWN_Y_COORD = 105; -var last_sunup = ""; -var last_sundown = ""; + var twilight_times_requires_update = true; function write_twilight_times(){ if(!twilight_times_requires_update) return; - var sunup; - var sundown; + var twilight_msg=[]; if(day_info != null) { - sunup = format_time(day_info.sunrise_date); - sundown = format_time(day_info.sunset_date); - } else { - sunup = ""; - sundown = ""; + twilight_msg = [format_time(day_info.sunrise_date), format_time(day_info.sunset_date)]; } - + g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + g.fillRect(TWILIGHT_X_COORD,INFO_PANEL_LINE_Y1,240,INFO_PANEL_LINE_Y2 + 13); g.setFont("Vector",13); g.setFontAlign(-1,-1,0); - if(last_sunup != "" && last_sunup != sunup){ - g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); - g.drawString(last_sunup, TWILIGHT_X_COORD,SUNUP_Y_COORD); - g.drawString(last_sundown, TWILIGHT_X_COORD,SUNDOWN_Y_COORD); - } g.setColor(Colors.YELLOW[0],Colors.YELLOW[1],Colors.YELLOW[2]); - g.drawString(sunup, TWILIGHT_X_COORD,SUNUP_Y_COORD); GraphicUtils.fill_circle_partial_y(TWILIGHT_X_COORD-15, - SUNUP_Y_COORD+7, + INFO_PANEL_LINE_Y1+7, 7, - SUNUP_Y_COORD+7, - SUNUP_Y_COORD); - g.setColor(1,0.7,0); - g.drawString(sundown, TWILIGHT_X_COORD,SUNDOWN_Y_COORD); + INFO_PANEL_LINE_Y1+7, + INFO_PANEL_LINE_Y1); + + g.drawString(twilight_msg[0], TWILIGHT_X_COORD,INFO_PANEL_LINE_Y1,1); + g.setColor(1,0.8,0); + g.drawString(twilight_msg[1], TWILIGHT_X_COORD,INFO_PANEL_LINE_Y2,1); - last_sunup = sunup; - last_sundown = sundown; twilight_times_requires_update = false; } From 945ef8e1de58be5286cce31afef46210651f2a3c Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Thu, 22 Jul 2021 21:01:02 +0100 Subject: [PATCH 097/163] solar clock: typo side panels --- apps/solarclock/solar_clock.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 03503b622..53ceeba63 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -188,10 +188,10 @@ function write_GPS_status(){ } g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); - //g.setColor(0.5,0.5,0.5); g.fillRect(DATE_X_COORD,INFO_PANEL_LINE_Y1,60,INFO_PANEL_LINE_Y2 + 13); g.setFont("Vector",13); g.setFontAlign(-1,-1,0); + g.setColor(Colors.WHITE[0], Colors.WHITE[1], Colors.WHITE[0]); g.drawString(gps_coords_msg[0], DATE_X_COORD, INFO_PANEL_LINE_Y1,1); g.drawString(gps_coords_msg[1], DATE_X_COORD, INFO_PANEL_LINE_Y2,1); From 452c27b1bed832c4ca508ae546860c2fef01c2e4 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Fri, 23 Jul 2021 15:52:51 +0200 Subject: [PATCH 098/163] Notify Hide callback to redraw clock --- apps/hcclock/hcclock.app.js | 2 ++ apps/notify/notify.js | 5 ++++- apps/notifyfs/notify.js | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/hcclock/hcclock.app.js b/apps/hcclock/hcclock.app.js index dac5063cb..d060c4b2f 100644 --- a/apps/hcclock/hcclock.app.js +++ b/apps/hcclock/hcclock.app.js @@ -208,3 +208,5 @@ setWatch(Bangle.showLauncher, BTN2, false); // Handle redraw on LCD on Bangle.on('lcdPower', (on) => { if(on) redraw(); }); +// Handle redraw on Dismissed Notifications +Bangle.on('notifyHide', () => { redraw(); } ); diff --git a/apps/notify/notify.js b/apps/notify/notify.js index 230cf9d10..89c843246 100644 --- a/apps/notify/notify.js +++ b/apps/notify/notify.js @@ -156,7 +156,10 @@ exports.hide = function(options) { Bangle.removeListener("touch", exports.hide); function anim() { pos += 4; - if (pos > 0) pos = 0; + if (pos > 0){ + pos = 0; + Bangle.emit('notifyHide'); + } Bangle.setLCDOffset(pos); if (pos < 0) setTimeout(anim, 10); } diff --git a/apps/notifyfs/notify.js b/apps/notifyfs/notify.js index 07801cedb..71d56acb6 100644 --- a/apps/notifyfs/notify.js +++ b/apps/notifyfs/notify.js @@ -126,4 +126,5 @@ exports.hide = function(options) { global["\xff"].watches[Bangle.btnWatches[0]].callback(); global["\xff"].watches[Bangle.btnWatches[1]].callback(); } + Bangle.emit('notifyHide'); }; From 72d82c641ff1148ff630f7170d3a219747f0bdf0 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Fri, 23 Jul 2021 16:06:35 +0200 Subject: [PATCH 099/163] nofity.js emits a 'notifyHide' event upon dismiss --- apps/notify/ChangeLog | 1 + apps/notifyfs/ChangeLog | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/notify/ChangeLog b/apps/notify/ChangeLog index 2b7a4f990..c27ce5e2c 100644 --- a/apps/notify/ChangeLog +++ b/apps/notify/ChangeLog @@ -5,3 +5,4 @@ 0.06: Support background color 0.07: Auto-calculate height, and pad text down even when there's no title (so it stays on-screen) 0.08: Don't turn on screen during Quiet Mode +0.09: Emits a 'notifyHide' event when dismissing notifications \ No newline at end of file diff --git a/apps/notifyfs/ChangeLog b/apps/notifyfs/ChangeLog index 974e138f7..b49b7dab4 100644 --- a/apps/notifyfs/ChangeLog +++ b/apps/notifyfs/ChangeLog @@ -6,3 +6,4 @@ 0.06: Adjust position of notification src text and notifications without title 0.07: Support background color 0.08: Don't turn on screen during Quiet Mode +0.09: Emits a 'notifyHide' event when dismissing notifications \ No newline at end of file From 1088c6bf53d0fdf6b9b8d0ac26b39693493500be Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Fri, 23 Jul 2021 16:12:15 +0200 Subject: [PATCH 100/163] Bumped versions of notify and notifyfx --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index da22623f8..579a8f740 100644 --- a/apps.json +++ b/apps.json @@ -94,7 +94,7 @@ "name": "Notifications (default)", "shortName":"Notifications", "icon": "notify.png", - "version":"0.08", + "version":"0.09", "description": "A handler for displaying notifications that displays them in a bar at the top of the screen", "tags": "widget", "type": "notify", @@ -107,7 +107,7 @@ "name": "Fullscreen Notifications", "shortName":"Notifications", "icon": "notify.png", - "version":"0.08", + "version":"0.09", "description": "A handler for displaying notifications that displays them fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notifications library.", "tags": "widget", "type": "notify", From 8653c9c72e3241645c1558f3c4e38b0d0d9f62f4 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sat, 24 Jul 2021 01:48:04 +0100 Subject: [PATCH 101/163] Solar Clock: Shaved off some memory use with location --- apps/solarclock/solar_clock.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 53ceeba63..43a4f564b 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -188,7 +188,7 @@ function write_GPS_status(){ } g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); - g.fillRect(DATE_X_COORD,INFO_PANEL_LINE_Y1,60,INFO_PANEL_LINE_Y2 + 13); + g.fillRect(DATE_X_COORD,INFO_PANEL_LINE_Y1,70,INFO_PANEL_LINE_Y2 + 13); g.setFont("Vector",13); g.setFontAlign(-1,-1,0); g.setColor(Colors.WHITE[0], Colors.WHITE[1], Colors.WHITE[0]); @@ -281,7 +281,6 @@ let time_offset = 0; let last_draw_time = null; var day_info = null; var location = LocationUtils.load_locations(); -var last_location_name = null; var location_requires_update = true; function write_location_name() { @@ -291,15 +290,14 @@ function write_location_name() { var new_location_name = location.getName(); g.setFont("Vector", 20); g.setFontAlign(-1, -1, 0); - if (last_location_name != null) { - g.setColor(screen_info.screen_bg_color[0], screen_info.screen_bg_color[1], screen_info.screen_bg_color[2]); - g.drawString(last_location_name, DATE_X_COORD, LOCATION_Y_COORD); - } - g.setColor(time_color[0], time_color[1], time_color[2]); + + g.setColor(screen_info.screen_bg_color[0], screen_info.screen_bg_color[1], screen_info.screen_bg_color[2]); + g.fillRect(DATE_X_COORD, LOCATION_Y_COORD, DATE_X_COORD + 95, LOCATION_Y_COORD + 20); + if (new_location_name != "local") { + g.setColor(time_color[0], time_color[1], time_color[2]); g.drawString(new_location_name, DATE_X_COORD, LOCATION_Y_COORD); } - last_location_name = new_location_name; location_requires_update = false; } @@ -351,6 +349,8 @@ function draw_clock(){ var start_time = Date.now(); var now = time_now(); + write_location_name(); + write_GPS_status(); var day_info = dayInfo(now); if(day_info != null) { draw_sun(now, day_info); @@ -358,8 +358,6 @@ function draw_clock(){ write_time(now); write_date(now); write_offset(); - write_location_name(); - write_GPS_status(); write_twilight_times(); last_draw_time = now; @@ -424,6 +422,7 @@ function clear_timers(){ } function start_timers(){ + console.log("start timers") var date = new Date(); var secs = date.getSeconds(); var nextMinuteStart = 60 - secs; @@ -451,7 +450,7 @@ Bangle.on('lcdPower', (on) => { if (on) { console.log("lcdPower: on"); gps_status_requires_update = true; - draw_clock(); + time_offset = 0; start_timers(); } else { console.log("lcdPower: off"); From 1dded3904f0ec4031f731c2b476ef377cc69c7bd Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sat, 24 Jul 2021 01:48:34 +0100 Subject: [PATCH 102/163] Solar Clock: changed to proper location names --- apps/solarclock/solar_loc.Honolulu.json | 4 ++++ apps/solarclock/solar_loc.Kauai.json | 4 ---- .../{solar_loc.Iceland.json => solar_loc.Reykjavik.json} | 0 apps/solarclock/solar_locations.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 apps/solarclock/solar_loc.Honolulu.json delete mode 100644 apps/solarclock/solar_loc.Kauai.json rename apps/solarclock/{solar_loc.Iceland.json => solar_loc.Reykjavik.json} (100%) diff --git a/apps/solarclock/solar_loc.Honolulu.json b/apps/solarclock/solar_loc.Honolulu.json new file mode 100644 index 000000000..7201b3199 --- /dev/null +++ b/apps/solarclock/solar_loc.Honolulu.json @@ -0,0 +1,4 @@ +{ + "coordinates": [-157.82608933598385,21.276531647042795], + "utc_offset": -10 +} diff --git a/apps/solarclock/solar_loc.Kauai.json b/apps/solarclock/solar_loc.Kauai.json deleted file mode 100644 index e2f0b1fe0..000000000 --- a/apps/solarclock/solar_loc.Kauai.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "coordinates": [-159.4879501,22.2224610], - "utc_offset": -10 -} diff --git a/apps/solarclock/solar_loc.Iceland.json b/apps/solarclock/solar_loc.Reykjavik.json similarity index 100% rename from apps/solarclock/solar_loc.Iceland.json rename to apps/solarclock/solar_loc.Reykjavik.json diff --git a/apps/solarclock/solar_locations.json b/apps/solarclock/solar_locations.json index 750b43206..501048e61 100644 --- a/apps/solarclock/solar_locations.json +++ b/apps/solarclock/solar_locations.json @@ -1 +1 @@ -["local","Tokyo","Iceland","Kauai"] \ No newline at end of file +["local","Tokyo","Reykjavik","Honolulu"] \ No newline at end of file From 6c96a02a5eadd9c6f6fb058e437ad49227fece20 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sat, 24 Jul 2021 16:45:43 +0100 Subject: [PATCH 103/163] Solar Clock: GPS location now only updates once per day. --- apps.json | 5 ++--- apps/solarclock/solar_clock.js | 5 ++++- apps/solarclock/solar_loc.local.json | 3 --- apps/solarclock/solar_location.js | 27 +++++++++++++++++++++------ 4 files changed, 27 insertions(+), 13 deletions(-) delete mode 100644 apps/solarclock/solar_loc.local.json diff --git a/apps.json b/apps.json index abdfcbd3c..e5195ec02 100644 --- a/apps.json +++ b/apps.json @@ -296,10 +296,9 @@ {"name":"solar_graphic_utils.js","url":"solar_graphic_utils.js"}, {"name":"solar_location.js","url":"solar_location.js"}, {"name":"solar_math_utils.js","url":"solar_math_utils.js"}, - {"name":"solar_loc.Iceland.json","url":"solar_loc.Iceland.json"}, - {"name":"solar_loc.Kauai.json","url":"solar_loc.Kauai.json"}, + {"name":"solar_loc.Reykjavik.json","url":"solar_loc.Reykjavik.json"}, + {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, - {"name":"solar_loc.local.json","url":"solar_loc.local.json"}, {"name":"solar_locations.json","url":"solar_locations.json"} ] }, diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 43a4f564b..279f7f664 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -199,15 +199,18 @@ function write_GPS_status(){ } const TWILIGHT_X_COORD = 200; +const NO_TIME = "--:--"; var twilight_times_requires_update = true; function write_twilight_times(){ if(!twilight_times_requires_update) return; - var twilight_msg=[]; + var twilight_msg; if(day_info != null) { twilight_msg = [format_time(day_info.sunrise_date), format_time(day_info.sunset_date)]; + } else { + twilight_msg = [NO_TIME,NO_TIME]; } g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); g.fillRect(TWILIGHT_X_COORD,INFO_PANEL_LINE_Y1,240,INFO_PANEL_LINE_Y2 + 13); diff --git a/apps/solarclock/solar_loc.local.json b/apps/solarclock/solar_loc.local.json deleted file mode 100644 index c1b2c7d33..000000000 --- a/apps/solarclock/solar_loc.local.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "coordinates": [-0.12574, 51.50853] -} \ No newline at end of file diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index 2af73746d..dbe5a5cbe 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -1,4 +1,5 @@ const storage = require("Storage"); +const DateUtils = require("solar_date_utils.js"); class LocationManager { constructor(locations) { this.idx=0; @@ -10,12 +11,26 @@ class LocationManager { this.location_info = null; } init(){ - this.location_info = storage.readJSON("solar_loc." + this.getName() + ".json"); - if(this.isGPSLocation() && !this.gps_queried) { - console.log("updating local location"); - this._gpsUpdate(); - this.gps_queried = true; - } + try { + this.location_info = storage.readJSON("solar_loc." + this.getName() + ".json"); + } catch(e){ + console.log("failed to load location:" + this.getName()) + } + if(this.location_info == null){ + this.location_info = {}; + } + if (this.isGPSLocation() && !this.gps_queried) { + //console.log("gps location:" + JSON.stringify(this.location_info)); + var last_update_str = this.location_info.last_update; + if(last_update_str == null || + (Date.now() - new Date(last_update_str).getTime() > DateUtils.DAY_MILLIS ) ){ + console.log("updating local location last update:" + last_update_str); + this._gpsUpdate(); + this.gps_queried = true; + } else { + console.log("gps update not required last update:" + last_update_str); + } + } } setGPSPower(power){ this.gpsPower = power; From e5c0216656f5474be9c325aa443714f82d8ffa11 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sun, 25 Jul 2021 10:41:36 +0100 Subject: [PATCH 104/163] Solar Clock: changed icon --- apps/solarclock/app.png | Bin 33522 -> 38330 bytes apps/solarclock/solar_clock-icon.js | 2 +- apps/solarclock/solar_clock.png | Bin 2669 -> 6833 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/solarclock/app.png b/apps/solarclock/app.png index 763c00b1de9f5c73ca4af264c6d65cc5eb08c090..549ee5a5c7f4cc43696ea24426b248da3ddcbdda 100644 GIT binary patch literal 38330 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Ν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 diff --git a/apps/solarclock/solar_clock-icon.js b/apps/solarclock/solar_clock-icon.js index d9bdd8c65..2dd3ac0e6 100644 --- a/apps/solarclock/solar_clock-icon.js +++ b/apps/solarclock/solar_clock-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("lEowkA/4AGmYIHABHzmVCCaE0kUin4TPmUimQTQ+UzmcvJ6EjCaP/kYABCaEymYTl+Q7SMgITTmQTQPAK0RMgITm+QTS+ciPCcikQpPY4MjmYTO+czmcyHh4TCmcvJ54nCPCBjBJx4oECc8zJ6ATTn48RE4YTTHh4SDH4ImRFBwTGFBgTGFBgSGFBYmHUgITRmcyFBASFAoUjE5PzkQLBHJxiDAQP/GxAA==")) +require("heatshrink").decompress(atob("lEowkG/4Av+YTS+svCaMtoYTRp3iAYMyiZONqlFn/ypvSCBMikYDBmcz//x7wTKlvUn4HEjpTKmnkOgvyPZX0oRPBkVEkQsFMA4fBkne93dqSJNLwPuAAJBCFwI+JjoSCAAJ2Bmver4SH+QmDFASiB9onF+adBmgSEAAMv+dECQtEOoMtEwvuT4LdF+C9Cl3u71ECQICB6aIHroJBp3uoICB9oCBbZHyqYTCAArvJn/zCY/iY5QTJ+bgHCYp2BHYX1JAIAGCYdNOwJ3Cno+GDQKfD6gYCp4JBZYJ3E6jmBJwrYCmtFCYk0BQKjBRREzHQkt6gaBmVN7oAB6gmBOo8ykYeDkQABEQK+CUBIHGmjIJ//xD40kZBX09qFB+czJgPyqITK91DQoNEoR1HAAny8hyB+XeYoIALN4fzrwrBABZ3EmorBACCQHAHgA=")) diff --git a/apps/solarclock/solar_clock.png b/apps/solarclock/solar_clock.png index 70a1cd5327a61bc1b0d393b57e2093864e565b9c..81b7d823f24563235d34436a80675b99e22b75da 100644 GIT binary patch delta 6196 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 SMPh0I0000004R>004l5008;`004mK z004C`008P>0026e000+ooVrmw0001ZlbH-rNJszx0096107w7;00963paK8{00001 z0000epaTE|000010000e00000#uS4c00009a7bBm000XU000XU0RWnu7ytkQXp>M4 z)00{bB$G!D6O$tjB$F!-Zj<>A4wKCeY9eKLX=XY@Z)|UJQ*dEpWj--HFJ*XXW;#P} zY;ST?aA9L*laUWLf3mfh1ONaA>q$gGR9FecS=(+K*A-pEx$rjPMG|$hF0`H4a#A@c z90x)C7NF<{^hf#&eeLHYK=alnXaeLRF_5%&-B^lEQ6wdb7m*@oNX~^_`>-?+qp>+8 zfgV6Z4(GOJ?Y-Ao`$%)$?ii7V2GcU(`vK0Y6;xiHU}d#{f4hf=2!a5brbW8j+fFv# zcEYRU<1w^Y459Di_@7U3UM`{b(+{|)mC+i+@W(&>8R>L-=^$qYC^Q?oj=%opa~yy3 zIdX*?7zV)R-aA-#J9zp089w;%V>0V6mBrXAhGzPrA(^%r(k*1y*0Hgk$7&{xd@hg5 z@iTb7hZtF2f98mExA8c{{Ra=Rv9$#|VIq}GkS#K6#WCzQ;P(3jsAJ4@Sk{;spd`P9 z&(36#+q(<5*Ch}rFfoQc7LMTXH!Zf@BAFTBlo5IU!M!5{nxWVewlpn)UcWEdE_eS{(RmMArme;E|U48z3E?Rx|`M2zgoZ>DKt z*z2Hkb){Zp%J`z6kpYq(gn^IE{UVH1hTlE@BBbf?$e`mmWHDSC$jAUC%rax7?FG5al3v_F^|ErEP@jj)uDwp za{&|(3KWS zQZ9i!g>Wu_a^;wEqElK{cW+`e8cvFWsQTAkB{fpn)4vH9^KIt_s1l5Mw!XcK00uz? z%)JE8&&o=ye~HT387?X(%(D>h9X&uYnZ(GGyqmb4>2*;* z=VDMEGD-L`MS6e-4<8{BH=zd&WOD1u?dZWJT&ItCE~lzDDzNGKb2B)(fi_`?J7T-U z;fRUgObrA*jARO2aMD`{;IyKLERb>FDASrs#+i?{!r!@SzG8avLeaMi0hGsyf8;bS z>sZUL5TJpJdJEURK1@Snk5a{OI8x_Chc>xlA%GLf3DIuVkxE$<ry;^>z#QV*h{qpEs041~@6Yi=}Vlj*`e;ABdAePcZ zLnp{|0bN(RI}aGORj-`3vosb>v>R0fG6l^zA_ElmqzCR&LN3pL#$~I=P&!Bw;6=TG zUf&^DlPeB!77KF{K338uI-MRenG9;>fAP9AvMq~DZ#NQ=017y9&8~Be>voAuXxP26 z&G2=}2TPdqu9#9;zga63e-Ml}Z-N)W4+;Rrmdu?}jGIyt45dN;=RnhG6bwtv!;a&s7m>Cze{I_^(z|p$yfz#n zN8?Z~R~P{Y`Ai(&e)Sm(?MxNiul3P0GboGZ7t9~0Q&EDvn$MtGt3$W)*eX8cLo5QD z6i;TwRt(x{E^M++jMN@_ojT8n;rK-jmHGf9`2U^6AeA2A8 Date: Sun, 25 Jul 2021 11:01:19 +0100 Subject: [PATCH 105/163] Solar Clock: Updated description --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e5195ec02..b7947b323 100644 --- a/apps.json +++ b/apps.json @@ -282,7 +282,7 @@ "name": "Solar Clock", "icon": "solar_clock.png", "version":"0.01", - "description": "The solar clock will use your current or chosen location to work out the the current sun phase of the day", + "description": "Using your current or chosen location the solar watch face shows the Sun's sky position, time and date. Also allows you to wind backwards and forwards in time to see the sun's position", "tags": "clock", "type":"clock", "allow_emulator":false, From cb31c2cef554211f3fe8b6812b49a2cc332e25e8 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sun, 25 Jul 2021 20:42:41 +0100 Subject: [PATCH 106/163] Adding the custom page to choose locations --- apps.json | 1 + apps/solarclock/custom.html | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 apps/solarclock/custom.html diff --git a/apps.json b/apps.json index b7947b323..f1f0b08f4 100644 --- a/apps.json +++ b/apps.json @@ -287,6 +287,7 @@ "type":"clock", "allow_emulator":false, "readme": "README.md", + "custom":"custom.html", "storage": [ {"name":"solarclock.app.js","url":"solar_clock.js"}, {"name":"solarclock.img","url":"solar_clock-icon.js","evaluate":true}, diff --git a/apps/solarclock/custom.html b/apps/solarclock/custom.html new file mode 100644 index 000000000..ed9737aed --- /dev/null +++ b/apps/solarclock/custom.html @@ -0,0 +1,65 @@ + + + + + + +

Please select watch locations

+ + + + + + +
EnabledName
+ +

Click

+ + + + + + From bed3878a05e57d305570b4a9d122e4c2ae68ab62 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sun, 25 Jul 2021 20:57:17 +0100 Subject: [PATCH 107/163] solar clock: fixed typo in custom.html --- apps.json | 1 - apps/solarclock/custom.html | 7 +++++-- apps/solarclock/solar_location.js | 10 +++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index f1f0b08f4..c05c682d6 100644 --- a/apps.json +++ b/apps.json @@ -300,7 +300,6 @@ {"name":"solar_loc.Reykjavik.json","url":"solar_loc.Reykjavik.json"}, {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, - {"name":"solar_locations.json","url":"solar_locations.json"} ] }, { "id": "sweepclock", diff --git a/apps/solarclock/custom.html b/apps/solarclock/custom.html index ed9737aed..032087795 100644 --- a/apps/solarclock/custom.html +++ b/apps/solarclock/custom.html @@ -56,8 +56,11 @@ } console.log("new selected locations:" + new_selected_locations); localStorage.setItem('solar_locations',JSON.stringify(new_selected_locations)); - // send finished app (in addition to contents of app.json) - sendCustomizedApp(JSON.stringify(new_selected_locations)); + sendCustomizedApp({ + storage:[ + {name:"solar_locations.json", content:JSON.stringify(new_selected_locations)}, + ] + }); }); diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index dbe5a5cbe..8d2d1a7fc 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -88,7 +88,15 @@ class LocationManager { const LOCATIONS_FILE = "solar_locations.json"; const LocationUtils = { load_locations : ()=>{ - var locations = storage.readJSON(LOCATIONS_FILE); + var locations; + try { + locations = storage.readJSON(LOCATIONS_FILE); + } catch(e){ + console.log("failed to load locations file:" + e); + } + if(locations == null) + locations = ['local']; + console.log("loaded locations:" + locations); var mgr = new LocationManager(locations); mgr.init(); From 543d7448c7876e129e58f93bb12edca95363ac0e Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sun, 25 Jul 2021 21:11:52 +0100 Subject: [PATCH 108/163] Solar clock: now a typo in the apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index c05c682d6..ec5528702 100644 --- a/apps.json +++ b/apps.json @@ -299,7 +299,7 @@ {"name":"solar_math_utils.js","url":"solar_math_utils.js"}, {"name":"solar_loc.Reykjavik.json","url":"solar_loc.Reykjavik.json"}, {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, - {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, + {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"} ] }, { "id": "sweepclock", From 8c5b0e4c362512781984269f353b212d6ebc09ba Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 26 Jul 2021 09:10:22 +0100 Subject: [PATCH 109/163] tidying --- app.js | 292 ------------------------------------------------------ apps.json | 4 +- 2 files changed, 2 insertions(+), 294 deletions(-) delete mode 100644 app.js diff --git a/app.js b/app.js deleted file mode 100644 index 4ce084f37..000000000 --- a/app.js +++ /dev/null @@ -1,292 +0,0 @@ - - /** - * Widget measurements - * Description: - * name: connection.wid.js - *icon: conectionIcon.icon - * - */ - - //Font - g.setFont("Vector", 100); - //variabangle.Sensorss - let acclS, bttS, compssS, gpsS, hrmS, stepS; //Strings - let accelN, compssN, gpsN, hrmN, stepN; //Num - let prueba = 1; - let data = [0, 0, 0, 0, 0, 0]; - //Constants for redabangle.Sensors code - let storage = require('Storage'); - let deCom = require('heatshrink'); - - - - - //Sensors code - /** - * - * @author Jorge - */ - function accel() { - - Bangle.on('accel', function (acc) { - // acc = {x,y,z,diff,mag} - accelN = acc; - }); - - setInterval(function () { - - acclS = accelN.x + "##" + accelN.y + "##" + accelN.z + "\n" + accelN.diff + "##" + accelN.mag; - data[3] = accelN; - }, 2 * 1000); - - } - - function btt() { - - setInterval(function () { - - bttS = E.getBattery(); //return String - data[2] = E.getBattery(); - }, 15 * 1000); - - } - - - - function compss() { - - Bangle.setCompassPower(1); - Bangle.on('mag', function (mag) { - // mag = {x,y,z,dx,dy,dz,heading} - compssN = mag; - }); - - - setInterval(function () { - - compssS = "A: " + compssN.x + " ## " + compssN.y + " ## " + compssN.z + "\n" + - "B: " + compssN.dx + " ## " + compssN.dy + " ## " + compssN.dz + " ## " + "\n" + - "C: " + compssN.heading; //return String - data[4] = compssN; - }, 2 * 1000); - - } - - - - function gps() { - - Bangle.setGPSPower(1); - Bangle.on('GPS', function (gps) { - // gps = {lat,lon,alt,speed,etc} - gpsN = gps; - - }); - - setInterval(function () { - - gpsS = "A: " + gpsN.lat + " ## " + gpsN.lon + " ## " + gpsN.alt + "\n" + "B: " + gpsN.speed + " ## " + gpsN.course + " ## " + gpsN.time + "\n" + - "C: " + gpsN.satellites + " ## " + gpsN.fix; //return String - // work out how to display the current time - var d = new Date(); - var year = d.getFullYear(); - - var month = d.getMonth() + 1; - var finalMonth = 0; - if (month < 10) { - finalMonth = "0" + month; - } else { - finalMonth = month; - } - var day = d.getDate(); - var finalDay = 0; - if (day < 10) { - finalDay = "0" + day; - } else { - finalDay = day; - } - var h = d.getHours(), - m = d.getMinutes(); - var finalh = 0; - if (h < 10) { - finalh = "0" + h; - } else { - finalh = h; - } - var finalM = 0; - if (m < 10) { - finalM = "0" + m; - } else { - finalM = m; - } - - var s = d.getSeconds(); - var finalS = 0; - if (s < 10) { - finalS = "0" + s; - } else { - finalS = s; - } - var z = d.getMilliseconds(); - var zFinal = new String(z); - zFinal = zFinal.replace('.', ''); - var completeTime = year + "-" + finalMonth + "-" + finalDay + "T" + finalh + ":" + finalM + ":" + finalS + "." + z + "Z"; - var time = h + ":" + ("0" + m).substr(-2); - gpsN.time = completeTime; - data[5] = gpsN; - }, 2 * 1000); - } - - //2021-06-11T19:21:58.000Z - - function hrm() { - - let msr = [0, 0, 0, 0, 0]; - let lastInsert = -1; - - function roundInsert(nueva) { - let indexFinal = (lastInsert + 1) % (msr.length); - //console.log("Index ==> "+ index); - msr[indexFinal] = nueva; - - item = nueva; - lastInsert = indexFinal; - - } - - function normalize(nueva) { - - let normalize = 0; - roundInsert(nueva); - - - msr.forEach(function (number) { - normalize += number; - }); - normalize = normalize / msr.length; - - return normalize; - - } - - - - - setInterval(function () { - - if (!isNaN(hrmN)) { - - - hrmN = normalize(hrmN); - var roundedRate = parseFloat(hrmN).toFixed(2); - hrmS = String.valueOf(roundedRate); //return String - //console.log("array----->" + msr); - data[0] = roundedRate; - - } - - - - - - }, 2 * 1000); - - } - - - function steps() { - - Bangle.on('step', s => { - - stepN = s; - }); - - - setInterval(function () { - - stepS = String.valueOf(stepN); //return String - data[1] = stepN; - }, 2 * 1000); - - - } - - function initSensors() { - - //need power control - Bangle.setHRMPower(1); - - Bangle.on('HRM', function (hrm) { - hrmN = hrm.bpm; - - - }); - console.log("Sensors are being Init...."); - accel(); - btt(); - compss(); - gps(); - hrm(); - steps(); - - } - - var flip = 1; - Bangle.on('lcdPower', function (on) { - /* - prueba ++; - Bangle.drawWidgets(); - g.setFont("Vector", 45); - g.drawString(prueba,100,200);*/ - if (flip == 1) { //when off - - flip = 0; - //Bangle.buzz(1000); - g.clear(); - } else { //when on - - flip = 1; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - } - - }); - - - function draw() { - - g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("heart.img"), 145, 167); - } - - - - initSensors(); - // Bangle.drawWidgets(); - // Terminal.println("Running BangleBridge"); - data[0] = 80.5; - g.setFont("Vector", 30); - g.drawString(data[0], 65, 180); - Bangle.drawWidgets(); - setInterval(function () { - //console.log("---------------------------------------------------------------"); - //console.log(data); - //Bluetooth.println(data[0]); - var measurement = { - hrm: data[0], - step: data[1], - batt: data[2], - acc: data[3], - com: data[4], - gps: data[5] - }; - /* g.clear(); - g.drawString(compssS,100,200); - */ - - - - Bluetooth.println(JSON.stringify(measurement) + "#"); - - }, 5 * 1000); diff --git a/apps.json b/apps.json index 190038600..aa4d712fe 100644 --- a/apps.json +++ b/apps.json @@ -3210,7 +3210,7 @@ "readme": "README.md", "storage": [ {"name":"banglebridge.wid.js","url":"widget.js"}, - {"name":"iconWatch.png","url":"iconWatch.png"}, + {"name":"iconWatch.png","url":"iconWatch.png"}, {"name":"heart.png","url":"heart.png"} ] }, @@ -3291,7 +3291,7 @@ "name":"Dozenal Time", "shortName":"Dozenal Time", "icon":"app.png", - "version":"0.01", + "version":"0.04", "description":"A dozenal Holocene calendar and dozenal diurnal clock", "tags":"clock", "type":"clock", From 788e72a5cb62584887ac0d382858cda747eca81c Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Mon, 26 Jul 2021 14:35:39 +0100 Subject: [PATCH 110/163] Solar Clock - filled out README file --- apps.json | 2 + apps/solarclock/01-screen-initial-load.png | Bin 0 -> 15153 bytes apps/solarclock/02-screen-layout.png | Bin 0 -> 95907 bytes apps/solarclock/03-night-view.png | Bin 0 -> 25122 bytes apps/solarclock/04-dawn-view.png | Bin 0 -> 24604 bytes apps/solarclock/05-midday-view.png | Bin 0 -> 22552 bytes apps/solarclock/06-sunset-view.png | Bin 0 -> 25314 bytes apps/solarclock/07-offsetting-time.png | Bin 0 -> 31896 bytes apps/solarclock/README.md | 60 +++++++++++++++++++-- apps/solarclock/custom.html | 2 + apps/solarclock/solar_clock.js | 14 ++--- apps/solarclock/solar_loc.HongKong.json | 4 ++ apps/solarclock/solar_loc.Rio.json | 4 ++ apps/solarclock/solar_locations.json | 2 +- 14 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 apps/solarclock/01-screen-initial-load.png create mode 100644 apps/solarclock/02-screen-layout.png create mode 100644 apps/solarclock/03-night-view.png create mode 100644 apps/solarclock/04-dawn-view.png create mode 100644 apps/solarclock/05-midday-view.png create mode 100644 apps/solarclock/06-sunset-view.png create mode 100644 apps/solarclock/07-offsetting-time.png create mode 100644 apps/solarclock/solar_loc.HongKong.json create mode 100644 apps/solarclock/solar_loc.Rio.json diff --git a/apps.json b/apps.json index ec5528702..dd98e14cd 100644 --- a/apps.json +++ b/apps.json @@ -298,7 +298,9 @@ {"name":"solar_location.js","url":"solar_location.js"}, {"name":"solar_math_utils.js","url":"solar_math_utils.js"}, {"name":"solar_loc.Reykjavik.json","url":"solar_loc.Reykjavik.json"}, + {"name":"solar_loc.HongKong.json","url":"solar_loc.HongKong.json"}, {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, + {"name":"solar_loc.Rio.json","url":"solar_loc.Rio.json"}, {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"} ] }, diff --git a/apps/solarclock/01-screen-initial-load.png b/apps/solarclock/01-screen-initial-load.png new file mode 100644 index 0000000000000000000000000000000000000000..8b1c4389b8a138a4d01810c03c66a3e3e3d734bb GIT binary patch literal 15153 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
9Z83@A<|o&fF%*;oTfwlj%rM{jEJ_N(544 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 literal 0 HcmV?d00001 diff --git a/apps/solarclock/02-screen-layout.png b/apps/solarclock/02-screen-layout.png new file mode 100644 index 0000000000000000000000000000000000000000..2142731242ee999454fa655f4bf7babb0d6c430e GIT binary patch literal 95907 zcmc$_gL@~zvp1UL8{4+cjcsh~jcwaDHnul*vaxO3wr#!HbAIQ%_uhZt&OH5eO-gKyZ>0B8osjz_I@dB=|SSuZwN`y8<;8lo131s*Qnp*9ZGP zCNz{#lmPJbgBmg#FYvJgkhK2s=)JoBFI=>(nLlEi29p` z1Ofv_1_FFjz~4I%FgDOXv~LPX3K-{qX+>bl|Hyy<0fm|af&NEE)bA zwWilMvNbTKceA$prv=30#`R5F8$0O}x>;M+4#tFR^o;b3#C*_%goHc}MkZW}B4Ynh|32a+Hgj^a<6>ZNb#9ux3wYshpTU3>+Hl!O#IK# z|8D>7r<1wK|FvY}_@8EdH<01q83rbLMuz{z{#NDr$K{f9FgO0T{12axiRZs0|6jcS z*x_OLXZ-)+%zwA^zqsE`<%8y7_}^~hgT~U?fdB#$0Fo3DRCWVC_lD5J9a#9Pb2`=j zYqXL~JCf{qwSl>QJeU`REd<4jINQ1ZrYPYTv@b`Q2PQ!T3Q32mBpnII#%8nJ{6s$1 z=y64H^4YbumN9qgMQx)u&Zp_>*;dC=XKT8dp;r9U#H2_Z*N$;pue--D5Euert(W^V zg&r9fmzLZ0GBLxp^OwiNDVa@^W@~PHpTMd>y5s793&Mko5EB!Vva+f?p0ALUt5qk@ z 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 literal 0 HcmV?d00001 diff --git a/apps/solarclock/03-night-view.png b/apps/solarclock/03-night-view.png new file mode 100644 index 0000000000000000000000000000000000000000..2aba2d73acad66be6c260d97257289fef4b7c07d GIT binary patch literal 25122 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 Date: Mon, 26 Jul 2021 15:53:46 +0100 Subject: [PATCH 111/163] bootloader 0.28: Fix double clock load after settings are changed --- apps.json | 5 +---- apps/boot/ChangeLog | 1 + apps/boot/bootupdate.js | 5 +++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index 2399b53c7..f4343600f 100644 --- a/apps.json +++ b/apps.json @@ -4,7 +4,7 @@ "tags": "tool,system,b2", "type":"bootloader", "icon": "bootloader.png", - "version":"0.27", + "version":"0.28", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "storage": [ {"name":".boot0","url":"boot0.js"}, @@ -3371,6 +3371,3 @@ ] } ] - - - diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index ccf97a9eb..4a8c62d59 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -26,3 +26,4 @@ 0.25: Fix error in 'no clock app' message 0.26: Remove buzz in setUI polyfill (#750) 0.27: Update polyfill for most recent changes +0.28: Fix double clock load after settings are changed diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 014edd552..4c4efed29 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -136,8 +136,9 @@ require('Storage').list(/\.boot\.js/).forEach(bootFile=>{ boot += "//"+bootFile+"\n"+require('Storage').read(bootFile)+"\n"; }); boot += "}\n";// initial 'if' -var s = require('Storage').write('.boot0',boot); +require('Storage').write('.boot0',boot); delete boot; E.showMessage("Reloading..."); eval(require('Storage').read('.boot0')); -eval(require('Storage').read('.bootcde')); +// .bootcde should be run automatically after if required, since +// we normally get called automatically from '.boot0' From 12894bf1b3a637df2d4c9ccbaeb6e689e933999c Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Mon, 26 Jul 2021 21:45:53 +0200 Subject: [PATCH 112/163] Rolled back non-fullscreen notify.js as emit was not necesary + added comment in notifyfs about the emit() --- apps.json | 2 +- apps/notify/ChangeLog | 3 +-- apps/notify/notify.js | 5 +---- apps/notifyfs/notify.js | 1 + 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/apps.json b/apps.json index 579a8f740..85379d1cb 100644 --- a/apps.json +++ b/apps.json @@ -94,7 +94,7 @@ "name": "Notifications (default)", "shortName":"Notifications", "icon": "notify.png", - "version":"0.09", + "version":"0.08", "description": "A handler for displaying notifications that displays them in a bar at the top of the screen", "tags": "widget", "type": "notify", diff --git a/apps/notify/ChangeLog b/apps/notify/ChangeLog index c27ce5e2c..ffbda52f0 100644 --- a/apps/notify/ChangeLog +++ b/apps/notify/ChangeLog @@ -4,5 +4,4 @@ 0.05: Adjust position of notification src text 0.06: Support background color 0.07: Auto-calculate height, and pad text down even when there's no title (so it stays on-screen) -0.08: Don't turn on screen during Quiet Mode -0.09: Emits a 'notifyHide' event when dismissing notifications \ No newline at end of file +0.08: Don't turn on screen during Quiet Mode \ No newline at end of file diff --git a/apps/notify/notify.js b/apps/notify/notify.js index 89c843246..230cf9d10 100644 --- a/apps/notify/notify.js +++ b/apps/notify/notify.js @@ -156,10 +156,7 @@ exports.hide = function(options) { Bangle.removeListener("touch", exports.hide); function anim() { pos += 4; - if (pos > 0){ - pos = 0; - Bangle.emit('notifyHide'); - } + if (pos > 0) pos = 0; Bangle.setLCDOffset(pos); if (pos < 0) setTimeout(anim, 10); } diff --git a/apps/notifyfs/notify.js b/apps/notifyfs/notify.js index 71d56acb6..6d3501b8c 100644 --- a/apps/notifyfs/notify.js +++ b/apps/notifyfs/notify.js @@ -126,5 +126,6 @@ exports.hide = function(options) { global["\xff"].watches[Bangle.btnWatches[0]].callback(); global["\xff"].watches[Bangle.btnWatches[1]].callback(); } + // Emits a notifyHide event that other apps can catch in order to redraw, if previous statements were unsuccessful. Bangle.emit('notifyHide'); }; From 81a5c0847e36f0015930428727f1817d3c699224 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Mon, 26 Jul 2021 22:38:23 +0100 Subject: [PATCH 113/163] Solar Clock: changed from daily GPS update to GPS update on request because it can take hours to get a GPS fix indoors which will drain the battery. Replaced it with GPS on request of button1 --- apps/solarclock/solar_clock.js | 38 ++++++++++++++++------ apps/solarclock/solar_location.js | 54 ++++++++++++++----------------- 2 files changed, 52 insertions(+), 40 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 3ab05cee2..8ba042a23 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -379,18 +379,36 @@ function log_memory_used() { ); } +var button1pressStart = null; function button1pressed(){ - console.log("button 1 pressed"); - time_offset = 0; - clear_sun(); - day_info = null; - draw_clock(); + if(button1pressStart == null) { + button1pressStart = Date.now(); + } + //console.log("button 1 pressed for:" + (Date.now() - button1pressStart)); + if(BTN1.read()){ + setTimeout(button1pressed,100); + } else { + var buttonPressTime = Date.now() - button1pressStart; + button1pressStart = null; + console.log("button press time=" + buttonPressTime); + if (buttonPressTime < 3000) { + //console.log("offset reset"); + time_offset = 0; + clear_sun(); + day_info = null; + } else { + //console.log("requesting gps update"); + location.requestGpsUpdate(); + gps_status_requires_update = true; + } + draw_clock(); + } } -function button3pressed(){ - console.log("button 3 pressed"); - time_offset = 0; - location.nextLocation(); +function button3pressed() { + console.log("button 3 pressed"); + time_offset = 0; + location.nextLocation(); } function button4pressed(){ @@ -485,7 +503,7 @@ function button2pressed(){ Bangle.showLauncher(); } setWatch(button2pressed, BTN2,{repeat:false,edge:"falling"}); -setWatch(button1pressed, BTN1,{repeat:true,edge:"falling"}); +setWatch(button1pressed, BTN1,{repeat:true,edge:"rising"}); setWatch(button3pressed, BTN3,{repeat:true,edge:"falling"}); setWatch(button4pressed, BTN4,{repeat:true,edge:"rising"}); setWatch(button5pressed, BTN5,{repeat:true,edge:"rising"}); \ No newline at end of file diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index 8d2d1a7fc..3384d14d1 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -1,44 +1,14 @@ const storage = require("Storage"); -const DateUtils = require("solar_date_utils.js"); class LocationManager { constructor(locations) { this.idx=0; this.locations = locations; this.listeners = []; this.in_use = true; - this.gps_queried = false; this.gpsPower = 0; this.location_info = null; } init(){ - try { - this.location_info = storage.readJSON("solar_loc." + this.getName() + ".json"); - } catch(e){ - console.log("failed to load location:" + this.getName()) - } - if(this.location_info == null){ - this.location_info = {}; - } - if (this.isGPSLocation() && !this.gps_queried) { - //console.log("gps location:" + JSON.stringify(this.location_info)); - var last_update_str = this.location_info.last_update; - if(last_update_str == null || - (Date.now() - new Date(last_update_str).getTime() > DateUtils.DAY_MILLIS ) ){ - console.log("updating local location last update:" + last_update_str); - this._gpsUpdate(); - this.gps_queried = true; - } else { - console.log("gps update not required last update:" + last_update_str); - } - } - } - setGPSPower(power){ - this.gpsPower = power; - Bangle.setGPSPower(this.gpsPower); - } - getGPSPower(){return this.gpsPower;} - _gpsUpdate(){ - this.setGPSPower(1); Bangle.on('GPS', (g) => { if (!this.in_use) return; @@ -58,6 +28,30 @@ class LocationManager { } }); + try { + this.location_info = storage.readJSON("solar_loc." + this.getName() + ".json"); + } catch(e){ + console.log("failed to load location:" + this.getName()) + } + if(this.location_info == null){ + this.location_info = {}; + } + if (this.isGPSLocation() && this.getCoordinates() == null) { + this.requestGpsUpdate(); + } + } + setGPSPower(power){ + this.gpsPower = power; + Bangle.setGPSPower(this.gpsPower); + } + getGPSPower(){return this.gpsPower;} + requestGpsUpdate(){ + if (this.getGPSPower() == 0) { + console.log("updating gps location update"); + this.setGPSPower(1); + } else { + console.log("gps already updating"); + } } isGPSLocation(){return this.getName() == 'local';} addUpdateListener(listener){this.listeners.push(listener);} From e137452baff8bd6e46af54a37cb3620d765e7627 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Tue, 27 Jul 2021 01:54:00 +0100 Subject: [PATCH 114/163] Solar Clock: fixed memory leak. GPS callbacks being installed for every location change --- apps/solarclock/solar_clock.js | 7 ++--- apps/solarclock/solar_location.js | 43 +++++++++++++++++-------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 8ba042a23..bbccdf1db 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -168,7 +168,7 @@ function write_GPS_status(){ return; var gps_coords = location.getCoordinates(); - var gps_coords_msg = []; + var gps_coords_msg; if(location.isGPSLocation()) { if(gps_coords == null) { @@ -184,7 +184,7 @@ function write_GPS_status(){ } } - if(gps_coords_msg.length == 0){ + if(gps_coords_msg == null){ gps_coords_msg = ["N:" + Math2.format000_00(gps_coords[1]), "E:" + Math2.format000_00(gps_coords[0])]; } @@ -283,7 +283,6 @@ function format_offset(){ } let time_offset = 0; -let last_draw_time = null; var day_info = null; var location = LocationUtils.load_locations(); var location_requires_update = true; @@ -364,8 +363,6 @@ function draw_clock(){ write_date(now); write_offset(); write_twilight_times(); - - last_draw_time = now; log_memory_used(); var time_taken = Date.now() - start_time; console.log("drawing clock:" + now.toISOString() + " time taken:" + time_taken ); diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index 3384d14d1..3841ef28a 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -7,27 +7,9 @@ class LocationManager { this.in_use = true; this.gpsPower = 0; this.location_info = null; + this.gpsRequested = false; } init(){ - Bangle.on('GPS', (g) => { - if (!this.in_use) - return; - - if (g.fix) { - var loc_info = { - last_update: new Date(), - coordinates: [g.lon, g.lat] - }; - console.log("Received gps fixing:" + JSON.stringify(loc_info)); - storage.writeJSON("solar_loc.local.json", loc_info); - this.setGPSPower(0); - if(this.isGPSLocation()){ - this.location_info = loc_info; - this.notifyUpdate(); - } - - } - }); try { this.location_info = storage.readJSON("solar_loc." + this.getName() + ".json"); } catch(e){ @@ -40,8 +22,31 @@ class LocationManager { this.requestGpsUpdate(); } } + initCallback(){ + Bangle.on('GPS', (g) => { + if (!this.in_use) + return; + + if (g.fix) { + var loc_info = { + coordinates: [g.lon, g.lat] + }; + console.log("Received gps fixing:" + JSON.stringify(loc_info)); + storage.writeJSON("solar_loc.local.json", loc_info); + this.setGPSPower(0); + if(this.isGPSLocation()){ + this.location_info = loc_info; + this.notifyUpdate(); + } + } + }); + } setGPSPower(power){ + if(power && !this.gpsRequested){ + this.initCallback(); + } this.gpsPower = power; + this.gpsRequested = true; Bangle.setGPSPower(this.gpsPower); } getGPSPower(){return this.gpsPower;} From 66096e5d912780ae0d1d6f2e7fdc8e1b4029ba8e Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Tue, 27 Jul 2021 02:06:16 +0100 Subject: [PATCH 115/163] Solar Clock: Change of variable name for gps callback installation --- apps/solarclock/solar_location.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/solarclock/solar_location.js b/apps/solarclock/solar_location.js index 3841ef28a..ab31fa879 100644 --- a/apps/solarclock/solar_location.js +++ b/apps/solarclock/solar_location.js @@ -7,7 +7,7 @@ class LocationManager { this.in_use = true; this.gpsPower = 0; this.location_info = null; - this.gpsRequested = false; + this.gpsCallbackInstalled = false; } init(){ try { @@ -42,11 +42,11 @@ class LocationManager { }); } setGPSPower(power){ - if(power && !this.gpsRequested){ + if(power && !this.gpsCallbackInstalled){ this.initCallback(); + this.gpsCallbackInstalled = true; } this.gpsPower = power; - this.gpsRequested = true; Bangle.setGPSPower(this.gpsPower); } getGPSPower(){return this.gpsPower;} From 2dda299cabf308507c1f5ca6e16dc6b1937adced Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 27 Jul 2021 10:22:41 +0100 Subject: [PATCH 116/163] Fixing some issues after recent merges --- apps.json | 8 ++++---- apps/{BangleBridge => banglebridge}/README.md | 0 .../{BangleBridge => banglebridge}/banglebridge.png | Bin .../heart.png => banglebridge/heart.img} | 0 .../iconWatch.png => banglebridge/watch.img} | Bin apps/{BangleBridge => banglebridge}/widget.js | 6 ++---- apps/{BangleBridge => banglebridge}/widget.png | Bin apps/doztime/ChangeLog | 6 +++--- apps/launchb2/app.js | 1 + apps/thermom/ChangeLog | 1 + 10 files changed, 11 insertions(+), 11 deletions(-) rename apps/{BangleBridge => banglebridge}/README.md (100%) rename apps/{BangleBridge => banglebridge}/banglebridge.png (100%) rename apps/{BangleBridge/heart.png => banglebridge/heart.img} (100%) rename apps/{BangleBridge/iconWatch.png => banglebridge/watch.img} (100%) rename apps/{BangleBridge => banglebridge}/widget.js (92%) rename apps/{BangleBridge => banglebridge}/widget.png (100%) create mode 100644 apps/thermom/ChangeLog diff --git a/apps.json b/apps.json index f4343600f..0920efdb7 100644 --- a/apps.json +++ b/apps.json @@ -2117,7 +2117,7 @@ "icon": "app.png", "description": "La palla predice il futuro", "tags": "game", - "version": "0.03", + "version": "0.01", "allow_emulator":true, "storage": [ { "name": "jbm8b_IT.app.js", "url": "app.js" }, @@ -3199,7 +3199,7 @@ {"name":"waypoints.json","url":"waypoints.json"} ] }, -{ "id": "BangleBridge", +{ "id": "banglebridge", "name": "BangleBridge", "shortName":"BangleBridge", "icon": "widget.png", @@ -3210,8 +3210,8 @@ "readme": "README.md", "storage": [ {"name":"banglebridge.wid.js","url":"widget.js"}, - {"name":"iconWatch.png","url":"iconWatch.png"}, - {"name":"heart.png","url":"heart.png"} + {"name":"banglebridge.watch.img","url":"watch.img"}, + {"name":"banglebridge.heart.img","url":"heart.img"} ] }, { "id": "qmsched", diff --git a/apps/BangleBridge/README.md b/apps/banglebridge/README.md similarity index 100% rename from apps/BangleBridge/README.md rename to apps/banglebridge/README.md diff --git a/apps/BangleBridge/banglebridge.png b/apps/banglebridge/banglebridge.png similarity index 100% rename from apps/BangleBridge/banglebridge.png rename to apps/banglebridge/banglebridge.png diff --git a/apps/BangleBridge/heart.png b/apps/banglebridge/heart.img similarity index 100% rename from apps/BangleBridge/heart.png rename to apps/banglebridge/heart.img diff --git a/apps/BangleBridge/iconWatch.png b/apps/banglebridge/watch.img similarity index 100% rename from apps/BangleBridge/iconWatch.png rename to apps/banglebridge/watch.img diff --git a/apps/BangleBridge/widget.js b/apps/banglebridge/widget.js similarity index 92% rename from apps/BangleBridge/widget.js rename to apps/banglebridge/widget.js index 9feecc703..48078de30 100644 --- a/apps/BangleBridge/widget.js +++ b/apps/banglebridge/widget.js @@ -256,10 +256,8 @@ function draw() { - // g.drawImage(storage.read("iconWatch.img"), this.x + 1, this.y + 1); - g.drawImage(storage.read("iconWatch.png"),this.x + 1,this.y + 1); - - g.drawImage(storage.read("heart.png"), 145, 167); + g.drawImage(storage.read("banglebridge.watch.img"),this.x + 1,this.y + 1); + g.drawImage(storage.read("banglebridge.heart.img"), 145, 167); } diff --git a/apps/BangleBridge/widget.png b/apps/banglebridge/widget.png similarity index 100% rename from apps/BangleBridge/widget.png rename to apps/banglebridge/widget.png diff --git a/apps/doztime/ChangeLog b/apps/doztime/ChangeLog index de00f009c..6c4a25b26 100644 --- a/apps/doztime/ChangeLog +++ b/apps/doztime/ChangeLog @@ -1,4 +1,4 @@ 0.01: New App! -0.02 added emulator capability and display of widgets -0.03 bug of advancing time fixed; doztime now correct within ca. 1 second -0.04 changed time colour from slightly off white to pure white +0.02: added emulator capability and display of widgets +0.03: bug of advancing time fixed; doztime now correct within ca. 1 second +0.04: changed time colour from slightly off white to pure white diff --git a/apps/launchb2/app.js b/apps/launchb2/app.js index 56f3fd696..183c09745 100644 --- a/apps/launchb2/app.js +++ b/apps/launchb2/app.js @@ -36,6 +36,7 @@ function drawMenu() { } g.clear(); drawMenu(); +g.flip(); // force an update now to make this snappier Bangle.on('drag',e=>{ var dy = e.dy; if (menuScroll - dy < 0) diff --git a/apps/thermom/ChangeLog b/apps/thermom/ChangeLog new file mode 100644 index 000000000..78fed5826 --- /dev/null +++ b/apps/thermom/ChangeLog @@ -0,0 +1 @@ +0.02: New App! From 827e1538a88578adeacfdfbf85882159eb07f04f Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Tue, 27 Jul 2021 11:59:23 +0200 Subject: [PATCH 117/163] Test : removing callback attachment to notifyHide to evaluate if lcdPower On is enough --- apps/hcclock/hcclock.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hcclock/hcclock.app.js b/apps/hcclock/hcclock.app.js index d060c4b2f..45295d5a7 100644 --- a/apps/hcclock/hcclock.app.js +++ b/apps/hcclock/hcclock.app.js @@ -209,4 +209,4 @@ setWatch(Bangle.showLauncher, BTN2, false); // Handle redraw on LCD on Bangle.on('lcdPower', (on) => { if(on) redraw(); }); // Handle redraw on Dismissed Notifications -Bangle.on('notifyHide', () => { redraw(); } ); +// Bangle.on('notifyHide', () => { redraw(); } ); From ba10201442cf1b44f54cb50db9c7271f90b04e98 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:44:50 +0200 Subject: [PATCH 118/163] Removed emit from notifyfs as lcdPower event works --- apps.json | 2 +- apps/hcclock/hcclock.app.js | 4 +--- apps/notifyfs/ChangeLog | 3 +-- apps/notifyfs/notify.js | 2 -- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index 0d5c8c563..7c97c326a 100644 --- a/apps.json +++ b/apps.json @@ -107,7 +107,7 @@ "name": "Fullscreen Notifications", "shortName":"Notifications", "icon": "notify.png", - "version":"0.09", + "version":"0.08", "description": "A handler for displaying notifications that displays them fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notifications library.", "tags": "widget", "type": "notify", diff --git a/apps/hcclock/hcclock.app.js b/apps/hcclock/hcclock.app.js index 45295d5a7..98abbc6f3 100644 --- a/apps/hcclock/hcclock.app.js +++ b/apps/hcclock/hcclock.app.js @@ -206,7 +206,5 @@ setInterval(updateTime, interval); setWatch(flipColors, BTN1, true); setWatch(Bangle.showLauncher, BTN2, false); -// Handle redraw on LCD on +// Handle redraw on LCD on / fullscreen notifications dismissed Bangle.on('lcdPower', (on) => { if(on) redraw(); }); -// Handle redraw on Dismissed Notifications -// Bangle.on('notifyHide', () => { redraw(); } ); diff --git a/apps/notifyfs/ChangeLog b/apps/notifyfs/ChangeLog index b49b7dab4..125a9fab5 100644 --- a/apps/notifyfs/ChangeLog +++ b/apps/notifyfs/ChangeLog @@ -5,5 +5,4 @@ 0.05: Fix `g` corruption issue if .hide gets called twice 0.06: Adjust position of notification src text and notifications without title 0.07: Support background color -0.08: Don't turn on screen during Quiet Mode -0.09: Emits a 'notifyHide' event when dismissing notifications \ No newline at end of file +0.08: Don't turn on screen during Quiet Mode \ No newline at end of file diff --git a/apps/notifyfs/notify.js b/apps/notifyfs/notify.js index 6d3501b8c..07801cedb 100644 --- a/apps/notifyfs/notify.js +++ b/apps/notifyfs/notify.js @@ -126,6 +126,4 @@ exports.hide = function(options) { global["\xff"].watches[Bangle.btnWatches[0]].callback(); global["\xff"].watches[Bangle.btnWatches[1]].callback(); } - // Emits a notifyHide event that other apps can catch in order to redraw, if previous statements were unsuccessful. - Bangle.emit('notifyHide'); }; From 9c058a51f7c00381dd1b22386a86d4dbf40ca107 Mon Sep 17 00:00:00 2001 From: peeweek <4037271+peeweek@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:49:13 +0200 Subject: [PATCH 119/163] Fixed newlines --- apps/notify/ChangeLog | 2 +- apps/notifyfs/ChangeLog | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/notify/ChangeLog b/apps/notify/ChangeLog index ffbda52f0..2b7a4f990 100644 --- a/apps/notify/ChangeLog +++ b/apps/notify/ChangeLog @@ -4,4 +4,4 @@ 0.05: Adjust position of notification src text 0.06: Support background color 0.07: Auto-calculate height, and pad text down even when there's no title (so it stays on-screen) -0.08: Don't turn on screen during Quiet Mode \ No newline at end of file +0.08: Don't turn on screen during Quiet Mode diff --git a/apps/notifyfs/ChangeLog b/apps/notifyfs/ChangeLog index 125a9fab5..974e138f7 100644 --- a/apps/notifyfs/ChangeLog +++ b/apps/notifyfs/ChangeLog @@ -5,4 +5,4 @@ 0.05: Fix `g` corruption issue if .hide gets called twice 0.06: Adjust position of notification src text and notifications without title 0.07: Support background color -0.08: Don't turn on screen during Quiet Mode \ No newline at end of file +0.08: Don't turn on screen during Quiet Mode From c09ec2259990ceb5a8a5d7e841dc77e78d502853 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 27 Jul 2021 15:41:36 +0100 Subject: [PATCH 120/163] hrm 0.05: Tweaks for 'HRM-raw' handling --- apps.json | 2 +- apps/hrm/ChangeLog | 1 + apps/hrm/heartrate.js | 12 +++++++----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index 20ccccc07..dbbe95edb 100644 --- a/apps.json +++ b/apps.json @@ -683,7 +683,7 @@ { "id": "hrm", "name": "Heart Rate Monitor", "icon": "heartrate.png", - "version":"0.04", + "version":"0.05", "description": "Measure your heart rate and see live sensor data", "tags": "health", "storage": [ diff --git a/apps/hrm/ChangeLog b/apps/hrm/ChangeLog index 6cedf8f1b..d27886b15 100644 --- a/apps/hrm/ChangeLog +++ b/apps/hrm/ChangeLog @@ -2,3 +2,4 @@ 0.02: Use HRM data and calculations from Bangle.js (don't access hardware directly) 0.03: Fix timing issues, and use 1/2 scale to keep graph on screen 0.04: Update for new firmwares that have a 'HRM-raw' event +0.05: Tweaks for 'HRM-raw' handling diff --git a/apps/hrm/heartrate.js b/apps/hrm/heartrate.js index 09e8a826e..9bc708ee8 100644 --- a/apps/hrm/heartrate.js +++ b/apps/hrm/heartrate.js @@ -46,9 +46,12 @@ Bangle.on('HRM-raw', function(v) { g.moveTo(-100,0); } - y = E.clip(170 - (v.raw*2),100,230); - g.setColor(1,1,1); - g.lineTo(hrmOffset, y); + y = E.clip(170 - (v.raw),100,230); + g.setColor(g.theme.fg).lineTo(hrmOffset, y); + if (counter !==undefined) { + counter = undefined; + g.clear(); + } }); // It takes 5 secs for us to get the first HRM event @@ -80,7 +83,6 @@ function readHRM() { var a = hrmInfo.raw[hrmOffset]; hrmOffset++; y = E.clip(170 - (a*2),100,230); - g.setColor(1,1,1); - g.lineTo(hrmOffset, y); + g.setColor(g.theme.fg).lineTo(hrmOffset, y); } } From 3d9435e67e65ec7a58bcda6a0d73c5eea0b1d180 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 27 Jul 2021 17:01:00 +0100 Subject: [PATCH 121/163] more hrm tweaks - show filtered data if available --- apps/hrm/heartrate.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/hrm/heartrate.js b/apps/hrm/heartrate.js index 9bc708ee8..a6b8e791a 100644 --- a/apps/hrm/heartrate.js +++ b/apps/hrm/heartrate.js @@ -3,6 +3,8 @@ Bangle.setLCDTimeout(0); Bangle.setHRMPower(1); var hrmInfo, hrmOffset = 0; var hrmInterval; +var btm = g.getHeight()-1; + function onHRM(h) { if (counter!==undefined) { // the first time we're called remove @@ -26,7 +28,7 @@ function onHRM(h) { var px = g.getWidth()/2; g.setFontAlign(0,0); - g.clearRect(0,24,239,90); + g.clearRect(0,24,239,80); g.setFont("6x8").drawString("Confidence "+hrmInfo.confidence+"%", px, 75); var str = hrmInfo.bpm; g.setFontVector(40).drawString(str,px,45); @@ -38,15 +40,16 @@ Bangle.on('HRM', onHRM); /* On newer (2v10) firmwares we can subscribe to get HRM events as they happen */ Bangle.on('HRM-raw', function(v) { - var a = v.raw; hrmOffset++; if (hrmOffset>g.getWidth()) { hrmOffset=0; - g.clearRect(0,90,239,239); + g.clearRect(0,80,239,239); g.moveTo(-100,0); } - y = E.clip(170 - (v.raw),100,230); + y = E.clip(btm-v.filt/4,btm-10,btm); + g.setColor(1,0,0).fillRect(hrmOffset,btm, hrmOffset, y); + y = E.clip(170 - (v.raw/2),80,btm); g.setColor(g.theme.fg).lineTo(hrmOffset, y); if (counter !==undefined) { counter = undefined; From f6b46395fc3d6c198d65b67bd240716d1b012bb7 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 27 Jul 2021 17:01:21 +0100 Subject: [PATCH 122/163] add first draft of layout module --- modules/Layout.js | 232 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 modules/Layout.js diff --git a/modules/Layout.js b/modules/Layout.js new file mode 100644 index 000000000..f21fbe45d --- /dev/null +++ b/modules/Layout.js @@ -0,0 +1,232 @@ +if (!g.theme) { + g.theme = { + fg:-1,bg:0,fgH:-1,bgH:"#008" + }; +} + +function Layout(layout, buttons) { + this._l = this.l = layout; + this.b = buttons; + // Do we have physical buttons? + this.physBtn = process.env.HWVERSION!=2; + this.yOffset = Object.keys(global.WIDGETS).length ? 24 : 0; + + if (buttons) { + var btnHeight = Math.floor((g.getHeight()-this.yOffset) / buttons.length); + if (this.physBtn) { + if (Bangle.btnWatch) Bangle.btnWatch.forEach(clearWatch); + Bangle.btnWatch = []; + if (buttons[0]) Bangle.btnWatch.push(setWatch(pressHandler.bind(this,0), BTN1, {repeat:true,edge:-1})); + if (buttons[1]) Bangle.btnWatch.push(setWatch(pressHandler.bind(this,1), BTN2, {repeat:true,edge:-1})); + if (buttons[2]) Bangle.btnWatch.push(setWatch(pressHandler.bind(this,2), BTN3, {repeat:true,edge:-1})); + this._l.width = g.getWidth()-8; // text width + this._l = {type:"h", content: [ + this._l, + {type:"v", content: buttons.map(b=>(b.type="txt",b.font="6x8",b.height=btnHeight,b.r=1,b))} + ]}; + } else { // no physical buttons, use touchscreen + this._l.width = g.getWidth()-20; // button width + this._l = {type:"h", content: [ + this._l, + {type:"v", content: buttons.map(b=>(b.type="btn",b.height=btnHeight,b.width=32,b.r=1,b))} + ]}; + Bangle.touchHandler = (_,e) => touchHandler(this._l,e); + Bangle.on('touch',Bangle.touchHandler); + } + } +} + +Layout.prototype.remove = function (l) { + if (Bangle.btnWatch) { + Bangle.btnWatch.forEach(clearWatch); + delete Bangle.btnWatch; + } + if (Bangle.touchHandler) { + Bangle.removeListener("touch",Bangle.touchHandler); + delete Bangle.touchHandler; + } +}; + +// Handler for button watch events +function pressHandler(btn,e) { + if (e.time-e.lastTime > 0.75 && this.b[btn].cbl) + this.b[btn].cbl(e); + else + if (this.b[btn].cb) this.b[btn].cb(e); +} + +// Handler for touch events +function touchHandler(l,e) { + if (l.type=="btn" && l.cb && e.x>=l.x && e.y>=l.y && e.x<=l.x+l.w && e.y<=l.y+l.h) + l.cb(e); + if (l.content) l.content.forEach(n => touchHandler(n,e)); +} + + +function updateMin(l) { + switch (l.type) { + case "txt": { + if (l.font.endsWith("%")) + l.font = "Vector"+Math.round(g.getHeight()*l.font.slice(0,-1)/100); + g.setFont(l.font); + l._h = g.getFontHeight(); + l._w = g.stringWidth(l.label); + break; + } + case "btn": { + l._h = 24; + l._w = 14 + l.label.length*8; + break; + } + case "img": { + var im = E.toString(l.src()); + l._h = im.charCodeAt(0); + l._w = im.charCodeAt(1); + break; + } + case "custom": { + // size should already be set up in width/height + l._w = 0; + l._h = 0; + break; + } + case "h": { + l.content.forEach(updateMin); + l._h = l.content.reduce((a,b)=>Math.max(a,b._h+(b.pad<<1)),0); + l._w = l.content.reduce((a,b)=>a+b._w+(b.pad<<1),0); + l.fill |= l.content.some(c=>c.fill); + break; + } + case "v": { + l.content.forEach(updateMin); + l._h = l.content.reduce((a,b)=>a+b._h+(b.pad<<1),0); + l._w = l.content.reduce((a,b)=>Math.max(a,b._w+(b.pad<<1)),0); + l.fill |= l.content.some(c=>c.fill); + break; + } + default: throw "Unknown item type "+l.type; + } + if (l.r&1) { // rotation + var t = l._w;l._w=l._h;l._h=t; + } + l._w = Math.max(l._w, 0|l.width); + l._h = Math.max(l._h, 0|l.height); +} +function render(l) { + if (!l) l = this.l; + g.reset(); + if (l.col) g.setColor(l.col); + switch (l.type) { + case "txt": + g.setFont(l.font).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1)); + break; + case "btn": + var poly = [ + l.x,l.y+4, + l.x+4,l.y, + l.x+l.w-5,l.y, + l.x+l.w-1,l.y+4, + l.x+l.w-1,l.y+l.h-5, + l.x+l.w-5,l.y+l.h-1, + l.x+4,l.y+l.h-1, + l.x,l.y+l.h-5, + l.x,l.y+4 + ]; + g.setColor(g.theme.bgH).fillPoly(poly).setColor(l.selected ? g.theme.fgH : g.theme.fg).drawPoly(poly).setFont("4x6",2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); + break; + case "img": + g.drawImage(l.src(), l.x, l.y); + break; + case "custom": + l.render(l); + break; + } + if (l.content) l.content.forEach(render); +} + +Layout.prototype.render = function (l) { + if (!l) l = this._l; + render(l); +}; + +Layout.prototype.layout = function (l) { + // l = current layout element + // exw,exh = extra width/height available + var fill = l.content.reduce((a,l)=>a+(0|l.fill),0); + switch (l.type) { + case "h": { + let x = l.x + (l.w-l._w)/2; + if (fill) { x = l.x; } + l.content.forEach(c => { + c.w = c._w + (c.fill?(l.w-l._w)/fill:0); + c.h = c.fill ? l.h : c._h; + c.x = x; + c.y = l.y + (1+(0|c.valign))*(l.h-c.h)/2; + x += c.w; + if (c.pad) { + x += c.pad*2; + c.x += c.pad; + c.y += c.pad; + } + if (c.content) { + this.layout(c); + } + }); + break; + } + case "v": { + let y = l.y + (l.h-l._h)/2; + if (fill) { y = l.y; } + l.content.forEach(c => { + c.w = c.fill ? l.w : c._w; + c.h = c._h + (c.fill?(l.h-l._h)/fill:0); + c.x = l.x + (1+(0|c.halign))*(l.w-c.w)/2; + c.y = y; + y += c.h; + if (c.pad) { + y += c.pad*2; + c.x += c.pad; + c.y += c.pad; + } + if (c.content) this.layout(c); + }); + break; + } + } +}; +Layout.prototype.debug = function(l,c) { + if (!l) l = this._l; + c=c||1; + g.setColor(c&1,c&2,c&4).drawRect(l.x+c-1, l.y+c-1, l.x+l.w-c, l.y+l.h-c); + c++; + if (l.content) l.content.forEach(n => this.debug(n,c)); +}; +Layout.prototype.update = function() { + var l = this._l; + var w = g.getWidth(); + var y = this.yOffset; + var h = g.getHeight()-y; + // update sizes + updateMin(l); + // center + if (l.fill) { + l.w = w; + l.h = h; + l.x = 0; + l.y = y; + } else { + l.w = l._w; + l.h = l._h; + l.x = (w-l.w)/2; + l.y = y+(h-l.h)/2; + } + // layout children + this.layout(l); +}; + +Layout.prototype.clear = function(l) { + if (!l) l = this._l; + g.reset().clearRect(l.x,l.y,l.x+l.w-1,l.y+l.h-1); +}; + +exports = Layout; From 65e578c2a384f4352b2f1193281051f3bdb10bf7 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 28 Jul 2021 01:00:31 +0100 Subject: [PATCH 123/163] Solar Clock: Optimized Date writing - also allow place names with space --- apps/solarclock/custom.html | 2 +- apps/solarclock/solar_clock.js | 64 +++++++++---------- apps/solarclock/solar_controller.js | 17 ++--- apps/solarclock/solar_graphic_utils.js | 6 ++ ...HongKong.json => solar_loc.Hong_Kong.json} | 0 apps/solarclock/solar_locations.json | 2 +- 6 files changed, 46 insertions(+), 45 deletions(-) rename apps/solarclock/{solar_loc.HongKong.json => solar_loc.Hong_Kong.json} (100%) diff --git a/apps/solarclock/custom.html b/apps/solarclock/custom.html index 1062bcd6f..78c6afbfd 100644 --- a/apps/solarclock/custom.html +++ b/apps/solarclock/custom.html @@ -21,7 +21,7 @@ var locations=[ {name:"GPS Location", shortname:"local"}, - {name:"Hong Kong", shortname:"HongKong"}, + {name:"Hong Kong", shortname:"Hong_Kong"}, {name:"Honolulu", shortname:"Honolulu"}, {name: "Reykjavik", shortname:"Reykjavik"}, {name: "Rio", shortname:"Rio"}, diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index bbccdf1db..310ec84bf 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -3,6 +3,7 @@ const Math2 = require("solar_math_utils.js"); const GraphicUtils = require("solar_graphic_utils.js"); const Colors = require("solar_colors.js"); const LocationUtils = require("solar_location.js"); +const Locale = require('locale'); var screen_info = { screen_width : g.getWidth(), @@ -68,10 +69,7 @@ function draw_sun(now, day_info) { // decide on the new sun drawing mode and draw curr_mode = controller.mode(now,day_info,screen_info); img_info.img_buffer.clear(); - img_info.img_buffer.setColor(screen_info.screen_bg_color[0], - screen_info.screen_bg_color[1], - screen_info.screen_bg_color[2], - ); + GraphicUtils.set_color(screen_info.screen_bg_color, img_info.img_buffer); img_info.img_buffer.fillRect(0,0,img_width, img_height); img_info.x = screen_info.sun_x - img_info.img.width/2; img_info.y = screen_info.sun_y - img_info.img.height/2; @@ -97,7 +95,7 @@ function draw_sun(now, day_info) { GraphicUtils.draw_sunrise_line(HORIZON_COLOUR, day_info, screen_info); } // we draw a blank where the image is going to be drawn to clear out the area - g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + GraphicUtils.set_color(screen_info.screen_bg_color); g.fillRect(img_info.x,img_info.y-2,img_info.x+img_width,img_info.y + img_height + 2); g.drawImage(img,img_info.x,img_info.y); // paint the cosine curve back to the normal color where it just came from @@ -114,7 +112,7 @@ function draw_sun(now, day_info) { function clear_sun(){ if(img_info.x != null && img_info.y != null) { - g.setColor(screen_info.screen_bg_color[0], screen_info.screen_bg_color[1], screen_info.screen_bg_color[2]); + GraphicUtils.set_color(screen_info.screen_bg_color); g.fillRect(img_info.x, img_info.y, img_info.x + img_width, img_info.y + img_width); GraphicUtils.draw_cosine(img_info.x - 4, img_info.x + img_width + 4, @@ -140,24 +138,20 @@ const OFFSET_Y_COORD = 70; const LOCATION_Y_COORD = 55; function write_date(now){ - var new_date = require('locale').dow(now,1) + " " + Math2.format00(now.getDate()); - //console.log("writing date:" + new_date) - g.setFont("Vector",15); - g.setFontAlign(-1,-1,0); - if(last_date != null){ - if(new_date == last_date){ - return; - } - g.setColor(screen_info.screen_bg_color[0], - screen_info.screen_bg_color[1], - screen_info.screen_bg_color[2]); - g.drawString(last_date, DATE_X_COORD,DATE_Y_COORD); - } - g.setColor(date_color[0],date_color[1],date_color[2]); - g.drawString(new_date, DATE_X_COORD,DATE_Y_COORD); - last_date = new_date; -} + var new_date = now.getDate(); + if(last_date == null || new_date != last_date){ + GraphicUtils.set_color(screen_info.screen_bg_color); + g.fillRect(DATE_X_COORD,DATE_Y_COORD, DATE_X_COORD+80,DATE_Y_COORD+15); + g.setFont("Vector",15); + g.setFontAlign(-1,-1,0); + GraphicUtils.set_color(date_color); + var date_str = Locale.dow(now,1) + " " + Math2.format00(now.getDate()); + //console.log("writing date:" + new_date) + g.drawString(date_str, DATE_X_COORD,DATE_Y_COORD); + last_date = new_date; + } +} const INFO_PANEL_LINE_Y1 = 90; const INFO_PANEL_LINE_Y2 = 105; @@ -189,11 +183,11 @@ function write_GPS_status(){ "E:" + Math2.format000_00(gps_coords[0])]; } - g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + GraphicUtils.set_color(screen_info.screen_bg_color); g.fillRect(DATE_X_COORD,INFO_PANEL_LINE_Y1,70,INFO_PANEL_LINE_Y2 + 13); g.setFont("Vector",13); g.setFontAlign(-1,-1,0); - g.setColor(Colors.WHITE[0], Colors.WHITE[1], Colors.WHITE[0]); + GraphicUtils.set_color(Colors.WHITE); g.drawString(gps_coords_msg[0], DATE_X_COORD, INFO_PANEL_LINE_Y1,1); g.drawString(gps_coords_msg[1], DATE_X_COORD, INFO_PANEL_LINE_Y2,1); @@ -214,11 +208,11 @@ function write_twilight_times(){ } else { twilight_msg = [NO_TIME,NO_TIME]; } - g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + GraphicUtils.set_color(screen_info.screen_bg_color); g.fillRect(TWILIGHT_X_COORD,INFO_PANEL_LINE_Y1,240,INFO_PANEL_LINE_Y2 + 13); g.setFont("Vector",13); g.setFontAlign(-1,-1,0); - g.setColor(Colors.YELLOW[0],Colors.YELLOW[1],Colors.YELLOW[2]); + GraphicUtils.set_color(Colors.YELLOW); GraphicUtils.fill_circle_partial_y(TWILIGHT_X_COORD-15, INFO_PANEL_LINE_Y1+7, 7, @@ -237,10 +231,10 @@ function write_time(now){ g.setFont("Vector",35); g.setFontAlign(-1,-1,0); if(last_time != null){ - g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + GraphicUtils.set_color(screen_info.screen_bg_color); g.drawString(last_time, TIME_X_COORD,TIME_Y_COORD); - } - g.setColor(time_color[0],time_color[1],time_color[2]); + } + GraphicUtils.set_color(time_color); g.drawString(new_time, TIME_X_COORD,TIME_Y_COORD); last_time = new_time; } @@ -259,10 +253,10 @@ function write_offset(){ g.setFont("Vector",15); g.setFontAlign(-1,-1,0); if(last_offset != null){ - g.setColor(screen_info.screen_bg_color[0],screen_info.screen_bg_color[1],screen_info.screen_bg_color[2]); + GraphicUtils.set_color(screen_info.screen_bg_color); g.drawString(last_offset, TIME_X_COORD,OFFSET_Y_COORD); } - g.setColor(time_color[0],time_color[1],time_color[2]); + GraphicUtils.set_color(time_color); g.drawString(new_offset, TIME_X_COORD,OFFSET_Y_COORD); last_offset = new_offset; } @@ -295,12 +289,12 @@ function write_location_name() { g.setFont("Vector", 20); g.setFontAlign(-1, -1, 0); - g.setColor(screen_info.screen_bg_color[0], screen_info.screen_bg_color[1], screen_info.screen_bg_color[2]); + GraphicUtils.set_color(screen_info.screen_bg_color); g.fillRect(DATE_X_COORD, LOCATION_Y_COORD, DATE_X_COORD + 95, LOCATION_Y_COORD + 20); if (new_location_name != "local") { - g.setColor(time_color[0], time_color[1], time_color[2]); - g.drawString(new_location_name, DATE_X_COORD, LOCATION_Y_COORD); + GraphicUtils.set_color(time_color); + g.drawString(new_location_name.replace("_", " "), DATE_X_COORD, LOCATION_Y_COORD); } location_requires_update = false; } diff --git a/apps/solarclock/solar_controller.js b/apps/solarclock/solar_controller.js index 12a2933de..73f42c3f8 100644 --- a/apps/solarclock/solar_controller.js +++ b/apps/solarclock/solar_controller.js @@ -33,11 +33,11 @@ function daytime_sun_color(now,day_info){ function draw_night_sun(sun_x,sun_y,sun_radius,img_info){ var draw_info = GraphicUtils.draw_info(img_info); - draw_info.buff.setColor(Colors.WHITE[0],Colors.WHITE[1],Colors.WHITE[2]); + GraphicUtils.set_color(Colors.WHITE,draw_info.buff); draw_info.buff.fillCircle(sun_x - draw_info.offset_x, sun_y - draw_info.offset_y, sun_radius); - draw_info.buff.setColor(NIGHT_COLOUR[0],NIGHT_COLOUR[1],NIGHT_COLOUR[2]); + GraphicUtils.set_color(NIGHT_COLOUR,draw_info.buff); draw_info.buff.fillCircle(sun_x - draw_info.offset_x, sun_y - draw_info.offset_y, sun_radius-1); @@ -48,7 +48,7 @@ function draw_partial_sun(time, day_info, screen_info,img_info){ if(sun_height > screen_info.sun_radius){ var sun_color = daytime_sun_color(time,day_info); var draw_info = GraphicUtils.draw_info(img_info); - draw_info.buff.setColor(sun_color[0],sun_color[1],sun_color[2]); + GraphicUtils.set_color(sun_color,draw_info.buff); draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, screen_info.sun_y - draw_info.offset_y, screen_info.sun_radius @@ -57,12 +57,12 @@ function draw_partial_sun(time, day_info, screen_info,img_info){ draw_night_sun(screen_info.sun_x,screen_info.sun_y,screen_info.sun_radius, img_info); } else { var draw_info = GraphicUtils.draw_info(img_info); - draw_info.buff.setColor(NIGHT_COLOUR[0],NIGHT_COLOUR[1],NIGHT_COLOUR[2]); + GraphicUtils.set_color(NIGHT_COLOUR,draw_info.buff); draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, screen_info.sun_y - draw_info.offset_y, screen_info.sun_radius-1); var sun_color = daytime_sun_color(time,day_info); - draw_info.buff.setColor(sun_color[0],sun_color[1],sun_color[2]); + GraphicUtils.set_color(sun_color[0],draw_info.buff); draw_info.buff.drawCircle(screen_info.sun_x - draw_info.offset_x, screen_info.sun_y - draw_info.offset_y, screen_info.sun_radius); @@ -88,7 +88,8 @@ function draw_random_background(screen_info, if(rgb_step[i]>0) rgb[i] = Math2.random_walk(rgb[i],rgb_step[i],1,0); } - draw_info.buff.setColor(rgb[0],rgb[1],rgb[2]); + + GraphicUtils.set_color(rgb,draw_info.buff); draw_info.buff.moveTo(screen_info.sun_x + Math.random()*img_info.img.width/8 - 0.4*img_info.img.width - @@ -100,7 +101,7 @@ function draw_random_background(screen_info, draw_info.offset_x, sky_y - draw_info.offset_y); } - draw_info.buff.setColor(NIGHT_COLOUR[0],NIGHT_COLOUR[1],NIGHT_COLOUR[2]); + GraphicUtils.set_color(NIGHT_COLOUR,draw_info.buff); draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, screen_info.sun_y - draw_info.offset_y, screen_info.sun_radius+1); @@ -166,7 +167,7 @@ class DayLightMode extends SolarMode { var sun_color = daytime_sun_color(now,day_info); var corona_radius = this._calc_corona_radius(now, day_info); var draw_info = GraphicUtils.draw_info(img_info); - draw_info.buff.setColor(sun_color[0],sun_color[1],sun_color[2]); + GraphicUtils.set_color(sun_color,draw_info.buff); if(corona_radius > screen_info.sun_radius){ this._drawCorona(corona_radius, screen_info.sun_x, diff --git a/apps/solarclock/solar_graphic_utils.js b/apps/solarclock/solar_graphic_utils.js index 3c2afec88..e2327df97 100644 --- a/apps/solarclock/solar_graphic_utils.js +++ b/apps/solarclock/solar_graphic_utils.js @@ -19,6 +19,12 @@ function _draw_info(img_info){ } const GraphicUtils = { draw_info : (img_info)=>_draw_info(img_info), + set_color: (color_vector,buff)=>{ + if(buff == null) + buff = g; + + buff.setColor(color_vector[0],color_vector[1],color_vector[2]) + }, draw_cosine : (from_x,to_x, line_colour, screen_info, img_info)=>{ //console.log("draw_cosine from_x=" + from_x + " to_x=" + to_x); var draw_info = _draw_info(img_info); diff --git a/apps/solarclock/solar_loc.HongKong.json b/apps/solarclock/solar_loc.Hong_Kong.json similarity index 100% rename from apps/solarclock/solar_loc.HongKong.json rename to apps/solarclock/solar_loc.Hong_Kong.json diff --git a/apps/solarclock/solar_locations.json b/apps/solarclock/solar_locations.json index 3a488db6e..14d3096b8 100644 --- a/apps/solarclock/solar_locations.json +++ b/apps/solarclock/solar_locations.json @@ -1 +1 @@ -["local","HongKong","Tokyo","Reykjavik","Rio","Honolulu"] \ No newline at end of file +["local","Hong_Kong","Tokyo","Reykjavik","Rio","Honolulu"] \ No newline at end of file From 3e0cbf5d8d18a3d0ae9b56fbdb5a8063554d77c4 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 28 Jul 2021 01:25:49 +0100 Subject: [PATCH 124/163] SolarClock: Hong Kong file changed it name --- apps.json | 2 +- apps/solarclock/custom.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index dd98e14cd..d11554c2c 100644 --- a/apps.json +++ b/apps.json @@ -298,7 +298,7 @@ {"name":"solar_location.js","url":"solar_location.js"}, {"name":"solar_math_utils.js","url":"solar_math_utils.js"}, {"name":"solar_loc.Reykjavik.json","url":"solar_loc.Reykjavik.json"}, - {"name":"solar_loc.HongKong.json","url":"solar_loc.HongKong.json"}, + {"name":"solar_loc.Hong_Kong.json","url":"solar_loc.Hong_Kong.json"}, {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, {"name":"solar_loc.Rio.json","url":"solar_loc.Rio.json"}, {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"} diff --git a/apps/solarclock/custom.html b/apps/solarclock/custom.html index 78c6afbfd..4e089a016 100644 --- a/apps/solarclock/custom.html +++ b/apps/solarclock/custom.html @@ -25,7 +25,7 @@ {name:"Honolulu", shortname:"Honolulu"}, {name: "Reykjavik", shortname:"Reykjavik"}, {name: "Rio", shortname:"Rio"}, - {name:"Tokyo", shortname:"Tokyo"}, + {name:"Tokyo", shortname:"Tokyo"} ]; var selected_locations = ["local"]; try{ From d03e7debd284535ca8c48c08ea9cd57dd0b7cde5 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 28 Jul 2021 01:37:25 +0100 Subject: [PATCH 125/163] Solar Clock: typo in set_color --- apps/solarclock/solar_controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/solarclock/solar_controller.js b/apps/solarclock/solar_controller.js index 73f42c3f8..8c116ecd5 100644 --- a/apps/solarclock/solar_controller.js +++ b/apps/solarclock/solar_controller.js @@ -62,7 +62,7 @@ function draw_partial_sun(time, day_info, screen_info,img_info){ screen_info.sun_y - draw_info.offset_y, screen_info.sun_radius-1); var sun_color = daytime_sun_color(time,day_info); - GraphicUtils.set_color(sun_color[0],draw_info.buff); + GraphicUtils.set_color(sun_color,draw_info.buff); draw_info.buff.drawCircle(screen_info.sun_x - draw_info.offset_x, screen_info.sun_y - draw_info.offset_y, screen_info.sun_radius); From 6d3fb37851d22964e981f59d5a506e7d650d69ef Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 28 Jul 2021 01:58:48 +0100 Subject: [PATCH 126/163] SolarClock: Updated the README for the GPS update --- apps/solarclock/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/solarclock/README.md b/apps/solarclock/README.md index 24d21516b..e661b47c5 100644 --- a/apps/solarclock/README.md +++ b/apps/solarclock/README.md @@ -71,7 +71,8 @@ Button 4 (left side of screen) will move the sun backwards in time and button 5 ![07-offsetting-time](07-offsetting-time.png) ### Button 1 -Pressing Button 1 by itself will change the offset time back to now +A short press of Button 1 by itself will change the time offset back to 0, making the sun go back to its current position +A long press of Button 1 will request a GPS update to your current position ## Further Details For further details of design and working please visit [The Project Page]( https://adrianwkirk.notion.site/Solar-Clock-a2b6268075a6481686b86ecc2094dc14) From 04b7af4a6a87e25fbf54edb323022c071563f53a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Jul 2021 09:41:27 +0100 Subject: [PATCH 127/163] Tweaks to notify to allow Gadgetbridge to dismiss notifications on phone from watch --- apps.json | 6 +++--- apps/gbridge/ChangeLog | 1 + apps/gbridge/widget.js | 4 ++++ apps/notify/ChangeLog | 1 + apps/notify/notify.js | 25 +++++++------------------ apps/notifyfs/ChangeLog | 1 + apps/notifyfs/notify.js | 7 ++++++- 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/apps.json b/apps.json index dbbe95edb..d392ea240 100644 --- a/apps.json +++ b/apps.json @@ -94,7 +94,7 @@ "name": "Notifications (default)", "shortName":"Notifications", "icon": "notify.png", - "version":"0.08", + "version":"0.09", "description": "A handler for displaying notifications that displays them in a bar at the top of the screen", "tags": "widget", "type": "notify", @@ -107,7 +107,7 @@ "name": "Fullscreen Notifications", "shortName":"Notifications", "icon": "notify.png", - "version":"0.08", + "version":"0.09", "description": "A handler for displaying notifications that displays them fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notifications library.", "tags": "widget", "type": "notify", @@ -153,7 +153,7 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.22", + "version":"0.23", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "readme": "README.md", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index f4837d60a..6e1c5b468 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -22,3 +22,4 @@ 0.20: Reduce memory usage 0.21: Fix HRM setting 0.22: Respect Quiet Mode +0.23: Allow notification dismiss to remove from phone too diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 70abfd610..2c61e61fa 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -155,6 +155,10 @@ switch (event.t) { case "notify": currentNot = prettifyNotificationEvent(event); + currentNot.onHide = function() { + // when notification hidden, remove from phone + gbSend({ t:"notify", n:"DISMISS", id:currentNot.id }); + }; require("notify").show(currentNot); if (!(require('Storage').readJSON('setting.json',1)||{}).quiet) { Bangle.buzz(); diff --git a/apps/notify/ChangeLog b/apps/notify/ChangeLog index 2b7a4f990..291f32a5a 100644 --- a/apps/notify/ChangeLog +++ b/apps/notify/ChangeLog @@ -5,3 +5,4 @@ 0.06: Support background color 0.07: Auto-calculate height, and pad text down even when there's no title (so it stays on-screen) 0.08: Don't turn on screen during Quiet Mode +0.09: Add onHide callback diff --git a/apps/notify/notify.js b/apps/notify/notify.js index 230cf9d10..68bc1a954 100644 --- a/apps/notify/notify.js +++ b/apps/notify/notify.js @@ -1,5 +1,6 @@ let pos = 0; let id = null; +let hideCallback = undefined; /** * Fit text into area, trying to insert newlines between words @@ -44,6 +45,7 @@ function fitWords(text,rows,width) { render : function(y) // function callback to render bgColor : int/string // optional background color (default black) titleBgColor : int/string // optional background color for title (default black) + onHide : function() // callback when notification is hidden } */ /* @@ -141,7 +143,9 @@ exports.show = function(options) { if (pos > -size) setTimeout(anim, 15); } anim(); - Bangle.on("touch", exports.dismiss_and_hide); + Bangle.on("touch", exports.hide); + if (options.onHide) + hideCallback = options.onHide; }; /** @@ -152,6 +156,8 @@ exports.show = function(options) { exports.hide = function(options) { options = options||{}; if ("id" in options && options.id!==id) return; + if (hideCallback) hideCallback({id:id}); + hideCallback = undefined; id = null; Bangle.removeListener("touch", exports.hide); function anim() { @@ -162,20 +168,3 @@ exports.hide = function(options) { } anim(); }; - -/** - Calls exports.hide(), but if Gadgetbridge is installed, dismiss through it - instead (which will call call exports.hide() itself). -*/ -exports.dismiss_and_hide = function(options) { - options = options||{}; - if (typeof(options) == "number") { - options = {}; - } - if ("GB" in global) { - options["t"] = "notify-"; - GB(options); - } else { - exports.hide(options); - } -}; diff --git a/apps/notifyfs/ChangeLog b/apps/notifyfs/ChangeLog index 974e138f7..18adecb4f 100644 --- a/apps/notifyfs/ChangeLog +++ b/apps/notifyfs/ChangeLog @@ -6,3 +6,4 @@ 0.06: Adjust position of notification src text and notifications without title 0.07: Support background color 0.08: Don't turn on screen during Quiet Mode +0.09: Add onHide callback diff --git a/apps/notifyfs/notify.js b/apps/notifyfs/notify.js index 07801cedb..b6b8dc43b 100644 --- a/apps/notifyfs/notify.js +++ b/apps/notifyfs/notify.js @@ -1,5 +1,6 @@ let oldg; let id = null; +let hideCallback = null; /** * See notify/notify.js @@ -40,6 +41,7 @@ function fitWords(text,rows,width) { render : function(y) // function callback to render bgColor : int/string // optional background color (default black) titleBgColor : int/string // optional background color for title (default black) + onHide : function() // callback when notification is hidden } */ exports.show = function(options) { @@ -65,7 +67,6 @@ exports.show = function(options) { if (options.title && options.src) { g.setColor(-1).setFontAlign(1, 1, 0).setFont("6x8", 2); // above drawing area, but we are fullscreen - print(options.src.substring(0, 10), w-23, y-4); g.drawString(options.src.substring(0, 10), w-16, y-4); } y += 30;h -= 30; @@ -94,6 +95,8 @@ exports.show = function(options) { Bangle.setLCDPower(1); // light up } Bangle.on("touch", exports.hide); + if (options.onHide) + hideCallback = options.onHide; // Create a fake graphics to hide draw attempts oldg = g; g = Graphics.createArrayBuffer(8,8,1); @@ -108,6 +111,8 @@ exports.show = function(options) { exports.hide = function(options) { options = options||{}; if ("id" in options && options.id!==id) return; + if (hideCallback) hideCallback({id:id}); + hideCallback = undefined; id = null; if (oldg) { g=oldg; From c1d06ef4d9470e771fbd505e114319dfebe20fed Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Jul 2021 09:55:22 +0100 Subject: [PATCH 128/163] Modified more clocks to use 'setUI' instead of a setWatch. All tested on Bangle.js 1 --- apps.json | 22 +++++++++++----------- apps/imgclock/ChangeLog | 3 ++- apps/imgclock/app.js | 4 ++-- apps/largeclock/ChangeLog | 1 + apps/largeclock/largeclock.js | 6 +++--- apps/mclock/ChangeLog | 1 + apps/mclock/clock-morphing.js | 4 ++-- apps/mclockplus/ChangeLog | 3 ++- apps/mclockplus/mclockplus.app.js | 4 ++-- apps/miclock/ChangeLog | 1 + apps/miclock/clock-mixed.js | 4 ++-- apps/minionclk/ChangeLog | 1 + apps/minionclk/app.js | 3 ++- apps/ncrclk/ChangeLog | 1 + apps/ncrclk/app.js | 4 ++-- apps/sclock/ChangeLog | 1 + apps/sclock/clock-simple.js | 5 ++--- apps/simplest/ChangeLog | 2 ++ apps/simplest/app.js | 3 ++- apps/slidingtext/ChangeLog | 9 +++++---- apps/slidingtext/slidingtext.js | 4 ++-- apps/svclock/ChangeLog | 1 + apps/svclock/vclock-simple.js | 4 ++-- 23 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 apps/simplest/ChangeLog diff --git a/apps.json b/apps.json index d392ea240..219ec2a43 100644 --- a/apps.json +++ b/apps.json @@ -171,7 +171,7 @@ { "id": "mclock", "name": "Morphing Clock", "icon": "clock-morphing.png", - "version":"0.06", + "version":"0.07", "description": "7 segment clock that morphs between minutes and hours", "tags": "clock", "type":"clock", @@ -258,7 +258,7 @@ { "id": "slidingtext", "name": "Sliding Clock", "icon": "slidingtext.png", - "version":"0.05", + "version":"0.06", "description": "Inspired by the Pebble sliding clock, old times are scrolled off the screen and new times on. You are also able to change language on the fly so you can see the time written in other languages using button 1. Currently English, French, Japanese, Spanish and German are supported", "tags": "clock", "type":"clock", @@ -296,7 +296,7 @@ "name": "Image background clock", "shortName":"Image Clock", "icon": "app.png", - "version":"0.07", + "version":"0.08", "description": "A clock with an image as a background", "tags": "clock", "type" : "clock", @@ -865,7 +865,7 @@ { "id": "sclock", "name": "Simple Clock", "icon": "clock-simple.png", - "version":"0.05", + "version":"0.06", "description": "A Simple Digital Clock", "tags": "clock,b2", "type":"clock", @@ -904,7 +904,7 @@ { "id": "svclock", "name": "Simple V-Clock", "icon": "vclock-simple.png", - "version":"0.01", + "version":"0.02", "description": "Modification of Simple Clock 0.04 to use Vectorfont", "tags": "clock", "type":"clock", @@ -1030,7 +1030,7 @@ { "id": "miclock", "name": "Mixed Clock", "icon": "clock-mixed.png", - "version":"0.04", + "version":"0.05", "description": "A mix of analog and digital Clock", "tags": "clock", "type":"clock", @@ -1476,7 +1476,7 @@ { "id": "minionclk", "name": "Minion clock", "icon": "minionclk.png", - "version": "0.04", + "version": "0.05", "description": "Minion themed clock.", "tags": "clock,minion", "type": "clock", @@ -1917,7 +1917,7 @@ "id": "largeclock", "name": "Large Clock", "icon": "largeclock.png", - "version": "0.07", + "version": "0.08", "description": "A readable and informational digital watch, with date, seconds and moon phase", "readme": "README.md", "tags": "clock", @@ -2610,7 +2610,7 @@ "name": "NCR Clock", "shortName":"NCR Clock", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "NodeConf Remote clock", "tags": "clock", "type": "clock", @@ -2883,7 +2883,7 @@ "name": "Morph Clock+", "shortName":"Morph Clock+", "icon": "mclockplus.png", - "version":"1.0", + "version":"0.02", "description": "Morphing Clock with more readable seconds and date and additional stopwatch", "tags": "clock", "type": "clock", @@ -3113,7 +3113,7 @@ { "id": "simplest", "name": "Simplest Clock", "icon": "simplest.png", - "version":"0.01", + "version":"0.02", "description": "The simplest working clock, acts as a tutorial piece", "tags": "clock", "type":"clock", diff --git a/apps/imgclock/ChangeLog b/apps/imgclock/ChangeLog index 20906fb87..01a6a4248 100644 --- a/apps/imgclock/ChangeLog +++ b/apps/imgclock/ChangeLog @@ -5,4 +5,5 @@ Scaling for background images <240px wide 0.05: Fix memory/interval leak when LCD turns on 0.06: Support 12 hour time -0.07: Don't cut off wide date formats \ No newline at end of file +0.07: Don't cut off wide date formats +0.08: Use Bangle.setUI for button/launcher handling diff --git a/apps/imgclock/app.js b/apps/imgclock/app.js index 751647a69..0e4435638 100644 --- a/apps/imgclock/app.js +++ b/apps/imgclock/app.js @@ -84,5 +84,5 @@ Bangle.on('lcdPower',on=>{ draw(); } }); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/largeclock/ChangeLog b/apps/largeclock/ChangeLog index d06cc9edf..496b0e4ae 100644 --- a/apps/largeclock/ChangeLog +++ b/apps/largeclock/ChangeLog @@ -5,3 +5,4 @@ 0.05: Add support for 12 hour time 0.06: Allow to disable BTN1 and BTN3 buttons 0.07: Don't clear all intervals during initialisation +0.08: Use Bangle.setUI for button/launcher handling diff --git a/apps/largeclock/largeclock.js b/apps/largeclock/largeclock.js index 24127ac15..79e1a1298 100644 --- a/apps/largeclock/largeclock.js +++ b/apps/largeclock/largeclock.js @@ -179,9 +179,9 @@ Bangle.on("lcdPower", function(on) { Bangle.setLCDMode(); -// Show launcher when middle button pressed -clearWatch(); -setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); +// Show launcher when button pressed +Bangle.setUI("clock"); + if (BTN1app) setWatch( function() { load(BTN1app); diff --git a/apps/mclock/ChangeLog b/apps/mclock/ChangeLog index cca1b6e6b..05b422406 100644 --- a/apps/mclock/ChangeLog +++ b/apps/mclock/ChangeLog @@ -4,3 +4,4 @@ 0.05: Add "ram" keyword to allow 2v06 Espruino builds to cache function that needs to be fast Fix issue where first digit could get stuck going from "2x:xx" to " x:xx" (fix #365) 0.06: Support 12 hour time +0.07: Use Bangle.setUI for button/launcher handling diff --git a/apps/mclock/clock-morphing.js b/apps/mclock/clock-morphing.js index 15ab206b9..f1254860b 100644 --- a/apps/mclock/clock-morphing.js +++ b/apps/mclock/clock-morphing.js @@ -216,5 +216,5 @@ Bangle.drawWidgets(); timeInterval = setInterval(showTime, 1000); showTime(); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/mclockplus/ChangeLog b/apps/mclockplus/ChangeLog index 835c33353..a1cecc698 100644 --- a/apps/mclockplus/ChangeLog +++ b/apps/mclockplus/ChangeLog @@ -1 +1,2 @@ -1.0: Created app +0.01: Created app +0.02: Use Bangle.setUI for button/launcher handling diff --git a/apps/mclockplus/mclockplus.app.js b/apps/mclockplus/mclockplus.app.js index 495e78f35..4c74ce1be 100644 --- a/apps/mclockplus/mclockplus.app.js +++ b/apps/mclockplus/mclockplus.app.js @@ -310,8 +310,8 @@ Bangle.drawWidgets(); timeInterval = setInterval(showTime, 1000); showTime(); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// Show launcher when button pressed +Bangle.setUI("clock"); // Start stopwatch when BTN3 is pressed setWatch(() => {swInterval=setInterval(stopWatch, 1000);stopWatch();}, BTN3, {repeat:false,edge:"falling"}); diff --git a/apps/miclock/ChangeLog b/apps/miclock/ChangeLog index f2e354bc1..e92bad2e3 100644 --- a/apps/miclock/ChangeLog +++ b/apps/miclock/ChangeLog @@ -1,3 +1,4 @@ 0.02: Modified for use with new bootloader and firmware 0.03: Localization 0.04: move jshint to the top +0.05: Use Bangle.setUI for button/launcher handling diff --git a/apps/miclock/clock-mixed.js b/apps/miclock/clock-mixed.js index 0bed137c6..b3d6bea8d 100644 --- a/apps/miclock/clock-mixed.js +++ b/apps/miclock/clock-mixed.js @@ -83,5 +83,5 @@ Bangle.drawWidgets(); setInterval(drawMixedClock, 5E3); drawMixedClock(); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/minionclk/ChangeLog b/apps/minionclk/ChangeLog index 27dab7259..a8b6efc81 100644 --- a/apps/minionclk/ChangeLog +++ b/apps/minionclk/ChangeLog @@ -2,3 +2,4 @@ 0.02: Improved date readability, fixed drawing of widgets 0.03: Fixed rendering for Espruino v2.06 0.04: Fixed overlapped rendering of dates +0.05: Use Bangle.setUI for button/launcher handling diff --git a/apps/minionclk/app.js b/apps/minionclk/app.js index f0afbc45c..9648e3d89 100644 --- a/apps/minionclk/app.js +++ b/apps/minionclk/app.js @@ -81,4 +81,5 @@ Bangle.on('lcdPower', (on) => { Bangle.loadWidgets(); startDrawing(); -setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: 'falling' }); +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/ncrclk/ChangeLog b/apps/ncrclk/ChangeLog index 68209352b..31e5d42c8 100644 --- a/apps/ncrclk/ChangeLog +++ b/apps/ncrclk/ChangeLog @@ -1 +1,2 @@ 0.01: A copy of the analogimgclk to work for NodeConf Remote +0.02: Use Bangle.setUI for button/launcher handling diff --git a/apps/ncrclk/app.js b/apps/ncrclk/app.js index acf611b1d..16724fa5e 100644 --- a/apps/ncrclk/app.js +++ b/apps/ncrclk/app.js @@ -125,5 +125,5 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); drawHands(true); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/sclock/ChangeLog b/apps/sclock/ChangeLog index a6e5b4f8e..44a0ec504 100644 --- a/apps/sclock/ChangeLog +++ b/apps/sclock/ChangeLog @@ -2,3 +2,4 @@ 0.03: Actually make into 24h clock since there's a 12h variant 0.04: Make this clock do 12h and 24h 0.05: setUI, screen size changes +0.06: Use Bangle.setUI for button/launcher handling diff --git a/apps/sclock/clock-simple.js b/apps/sclock/clock-simple.js index f61e7d5ad..8fb204d22 100644 --- a/apps/sclock/clock-simple.js +++ b/apps/sclock/clock-simple.js @@ -69,6 +69,8 @@ Bangle.on('lcdPower', function(on) { // clean app screen g.clear(); +// Show launcher when button pressed +Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -77,6 +79,3 @@ setInterval(drawSimpleClock, 15E3); // draw now drawSimpleClock(); - -// Show launcher when button pressed -Bangle.setUI("clock"); diff --git a/apps/simplest/ChangeLog b/apps/simplest/ChangeLog new file mode 100644 index 000000000..d69da4ddc --- /dev/null +++ b/apps/simplest/ChangeLog @@ -0,0 +1,2 @@ +0.01: Modified for use with new bootloader and firmware +0.02: Use Bangle.setUI for button/launcher handling diff --git a/apps/simplest/app.js b/apps/simplest/app.js index 32992534e..2ed4e5580 100644 --- a/apps/simplest/app.js +++ b/apps/simplest/app.js @@ -21,4 +21,5 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); setInterval(draw, 15000); // refresh every 15s draw(); -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/slidingtext/ChangeLog b/apps/slidingtext/ChangeLog index 932134ab1..413d50d40 100644 --- a/apps/slidingtext/ChangeLog +++ b/apps/slidingtext/ChangeLog @@ -1,5 +1,6 @@ -0.01: Initial Release -0.02: Color Themes, Smoother scrolling -0.03: Added Spanish Language -0.04: Added German Language +0.01: Initial Release +0.02: Color Themes, Smoother scrolling +0.03: Added Spanish Language +0.04: Added German Language 0.05: BUGFIX: pedometer widget interfered with the clock Font Alignment +0.06: Use Bangle.setUI for button/launcher handling diff --git a/apps/slidingtext/slidingtext.js b/apps/slidingtext/slidingtext.js index 9de3c9f44..9fa21ccc2 100644 --- a/apps/slidingtext/slidingtext.js +++ b/apps/slidingtext/slidingtext.js @@ -635,8 +635,8 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); startTimers(); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2,{repeat:false,edge:"falling"}); +// Show launcher when button pressed +Bangle.setUI("clock"); // Handle button 1 being pressed diff --git a/apps/svclock/ChangeLog b/apps/svclock/ChangeLog index a9e0036a3..671de492c 100644 --- a/apps/svclock/ChangeLog +++ b/apps/svclock/ChangeLog @@ -1 +1,2 @@ 0.01: Modification of SimpleClock 0.04 to use Vectorfont +0.02: Use Bangle.setUI for button/launcher handling diff --git a/apps/svclock/vclock-simple.js b/apps/svclock/vclock-simple.js index 2af8b74a4..f3ab911bc 100644 --- a/apps/svclock/vclock-simple.js +++ b/apps/svclock/vclock-simple.js @@ -80,5 +80,5 @@ setInterval(drawSimpleClock, 15E3); // draw now drawSimpleClock(); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// Show launcher when button pressed +Bangle.setUI("clock"); From 6d73d175eb99208956b653af9a3511eb6206f40d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Jul 2021 10:54:22 +0100 Subject: [PATCH 129/163] More testing and tweaking of existing clock apps --- apps.json | 18 +- apps/fclock/ChangeLog | 1 + apps/fclock/fclock.app.js | 347 +++++++++++----------- apps/impwclock/ChangeLog | 1 + apps/impwclock/clock-impword.js | 25 +- apps/isoclock/ChangeLog | 1 + apps/isoclock/isoclock.js | 97 +++--- apps/lazyclock/ChangeLog | 3 +- apps/lazyclock/lazyclock-app.js | 27 +- apps/lifeclk/ChangeLog | 3 +- apps/lifeclk/{app.js => app.min.js} | 10 +- apps/mysticclock/ChangeLog | 1 + apps/mysticclock/mystic-clock-app.js | 17 +- apps/rclock/ChangeLog | 4 +- apps/rclock/rclock.app.js | 423 +++++++++++++-------------- apps/swlclk/ChangeLog | 1 + apps/swlclk/app.js | 227 +++++++------- 17 files changed, 600 insertions(+), 606 deletions(-) rename apps/lifeclk/{app.js => app.min.js} (98%) diff --git a/apps.json b/apps.json index 219ec2a43..ee2028186 100644 --- a/apps.json +++ b/apps.json @@ -312,7 +312,7 @@ { "id": "impwclock", "name": "Imprecise Word Clock", "icon": "clock-impword.png", - "version":"0.02", + "version":"0.03", "description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.", "tags": "clock", "type":"clock", @@ -1785,7 +1785,7 @@ "name": "SWL Clock / Short Wave Listner Clock", "shortName": "SWL Clock", "icon": "swlclk.png", - "version":"0.01", + "version":"0.02", "description": "Display Local, UTC time and some programs on the shorts waves along the day, with the frequencies", "tags": "tool,clock", "type":"clock", @@ -1801,7 +1801,7 @@ "name": "Round clock with seconds, minutes and date", "shortName": "Round Clock", "icon": "app.png", - "version": "0.05", + "version": "0.06", "description": "Designed round clock with ticks for minutes and seconds and heart rate indication", "tags": "clock", "type": "clock", @@ -1815,7 +1815,7 @@ "name": "fclock", "shortName": "F Clock", "icon": "app.png", - "version": "0.01", + "version": "0.02", "description": "Simple design of a digital clock", "tags": "clock", "type": "clock", @@ -2623,7 +2623,7 @@ "name": "ISO Compliant Clock Face", "shortName":"ISO Clock", "icon": "isoclock.png", - "version":"0.01", + "version":"0.02", "description": "Tweaked fork of digiclock for ISO date and time", "tags": "clock", "type" : "clock", @@ -2781,7 +2781,7 @@ { "id": "lazyclock", "name": "Lazy Clock", "icon": "lazyclock.png", - "version":"0.02", + "version":"0.03", "readme": "README.md", "description": "Tells the time, roughly", "tags": "clock", @@ -2821,13 +2821,13 @@ "name": "Game of Life Clock", "shortName":"Conway's Clock", "icon": "app.png", - "version":"0.05", + "version":"0.06", "description": "Modification and clockification of Conway's Game of Life", "tags": "clock", "type" : "clock", "readme": "README.md", "storage": [ - {"name":"lifeclk.app.js","url":"app.js"}, + {"name":"lifeclk.app.js","url":"app.min.js"}, {"name":"lifeclk.img","url":"app-icon.js","evaluate":true} ] }, @@ -3347,7 +3347,7 @@ { "id": "mysticclock", "name": "Mystic Clock", "icon": "mystic-clock.png", - "version":"1.00", + "version":"1.01", "description": "A retro-inspired watchface featuring time, date, and an interactive data display line.", "tags": "clock", "type":"clock", diff --git a/apps/fclock/ChangeLog b/apps/fclock/ChangeLog index a8f708a0a..30e049f69 100644 --- a/apps/fclock/ChangeLog +++ b/apps/fclock/ChangeLog @@ -1 +1,2 @@ 0.01: First published version of app +0.02: Move to Bangle.setUI to launcher support diff --git a/apps/fclock/fclock.app.js b/apps/fclock/fclock.app.js index 044cde71f..afa0c5e2d 100644 --- a/apps/fclock/fclock.app.js +++ b/apps/fclock/fclock.app.js @@ -1,206 +1,203 @@ -{ - var minutes; - var seconds; - var hours; - var date; - var first = true; - var locale = require('locale'); - var _12hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"] || false; +var minutes; +var seconds; +var hours; +var date; +var first = true; +var locale = require('locale'); +var _12hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"] || false; - //HR variables - var id = 0; - var grow = true; - var size=10; +//HR variables +var id = 0; +var grow = true; +var size=10; - //Screen dimensions - const screen = { - width: g.getWidth(), - height: g.getWidth(), - middle: g.getWidth() / 2, - center: g.getHeight() / 2, - }; +//Screen dimensions +const screen = { + width: g.getWidth(), + height: g.getWidth(), + middle: g.getWidth() / 2, + center: g.getHeight() / 2, +}; - // Ssettings - const settings = { - time: { - color: '#dddddd', - font: 'Vector', - size: 100, - middle: screen.middle, - center: screen.center, - }, - date: { - color: '#dddddd', - font: 'Vector', - size: 15, - middle: screen.height-17, // at bottom of screen - center: screen.center, - }, - circle: { - colormin: '#ffffff', - colorsec: '#ffffff', - width: 10, - middle: screen.middle, - center: screen.center, - height: screen.height - }, - hr: { - color: '#333333', - size: 20, - x: screen.center, - y: screen.middle + 65 - } - }; +// Ssettings +const settings = { + time: { + color: '#dddddd', + font: 'Vector', + size: 100, + middle: screen.middle, + center: screen.center, + }, + date: { + color: '#dddddd', + font: 'Vector', + size: 15, + middle: screen.height-17, // at bottom of screen + center: screen.center, + }, + circle: { + colormin: '#ffffff', + colorsec: '#ffffff', + width: 10, + middle: screen.middle, + center: screen.center, + height: screen.height + }, + hr: { + color: '#333333', + size: 20, + x: screen.center, + y: screen.middle + 65 + } +}; - const dateStr = function (date) { - return locale.date(new Date(), 1); - }; +const dateStr = function (date) { + return locale.date(new Date(), 1); +}; - const getFormated = function(val) { - if (val<10) { - val='0'+val; - } +const getFormated = function(val) { + if (val<10) { + val='0'+val; + } - return val; - }; + return val; +}; - const drawMin = function (sections, color) { - - g.setFontAlign(0, 0, 0); - g.setColor('#000000'); - g.setFont(settings.time.font, settings.time.size/2); - g.drawString(getFormated(sections-1), settings.time.center+50, settings.time.middle); - g.setColor(settings.time.color); - g.setFont(settings.time.font, settings.time.size/2); - g.drawString(getFormated(sections), settings.time.center+50, settings.time.middle); - }; +const drawMin = function (sections, color) { - const drawSec = function (sections, color) { - g.setFontAlign(0, 0, 0); - g.setColor('#000000'); - g.setFont(settings.time.font, settings.time.size/4); - g.drawString(getFormated(sections-1), settings.time.center+100, settings.time.middle); - g.setColor(settings.time.color); - g.setFont(settings.time.font, settings.time.size/4); - g.drawString(getFormated(sections), settings.time.center+100, settings.time.middle); - }; + g.setFontAlign(0, 0, 0); + g.setColor('#000000'); + g.setFont(settings.time.font, settings.time.size/2); + g.drawString(getFormated(sections-1), settings.time.center+50, settings.time.middle); + g.setColor(settings.time.color); + g.setFont(settings.time.font, settings.time.size/2); + g.drawString(getFormated(sections), settings.time.center+50, settings.time.middle); +}; - const drawClock = function () { +const drawSec = function (sections, color) { + g.setFontAlign(0, 0, 0); + g.setColor('#000000'); + g.setFont(settings.time.font, settings.time.size/4); + g.drawString(getFormated(sections-1), settings.time.center+100, settings.time.middle); + g.setColor(settings.time.color); + g.setFont(settings.time.font, settings.time.size/4); + g.drawString(getFormated(sections), settings.time.center+100, settings.time.middle); +}; - currentTime = new Date(); +const drawClock = function () { - //Get date as a string - date = dateStr(currentTime); - - if(seconds==59) { - g.clear(); - } + currentTime = new Date(); - // Update minutes when needed - if (minutes != currentTime.getMinutes()) { - minutes = currentTime.getMinutes(); - drawMin(minutes, settings.circle.colormin); - } + //Get date as a string + date = dateStr(currentTime); - //Update seconds when needed - if (seconds != currentTime.getSeconds()) { - seconds = currentTime.getSeconds(); - drawSec(seconds, settings.circle.colorsec); - } + if(seconds==59) { + g.clear(); + } - //Write the time as configured in the settings - hours = currentTime.getHours(); - if (_12hour && hours > 13) { - hours = hours - 12; - } + // Update minutes when needed + if (minutes != currentTime.getMinutes()) { + minutes = currentTime.getMinutes(); + drawMin(minutes, settings.circle.colormin); + } - var meridian; + //Update seconds when needed + if (seconds != currentTime.getSeconds()) { + seconds = currentTime.getSeconds(); + drawSec(seconds, settings.circle.colorsec); + } - if (typeof locale.meridian === "function") { - meridian = locale.meridian(new Date()); - } else { - meridian = ""; - } + //Write the time as configured in the settings + hours = currentTime.getHours(); + if (_12hour && hours > 13) { + hours = hours - 12; + } - var timestr; + var meridian; - if (meridian.length > 0 && _12hour) { - timestr = hours + " " + meridian; - } else { - timestr = hours; - } - g.setFontAlign(0, 0, 0); - g.setColor(settings.time.color); - g.setFont(settings.time.font, settings.time.size); - g.drawString(timestr, settings.time.center-40, settings.time.middle); + if (typeof locale.meridian === "function") { + meridian = locale.meridian(new Date()); + } else { + meridian = ""; + } - //Write the date as configured in the settings - g.setColor(settings.date.color); - g.setFont(settings.date.font, settings.date.size); - g.drawString(date, settings.date.center, settings.date.middle); - }; + var timestr; - //setInterval for HR visualisation - const newBeats = function (hr) { - if (id != 0) { - changeInterval(id, 6e3 / hr.bpm); - } else { - id = setInterval(drawHR, 6e3 / hr.bpm); - } - }; + if (meridian.length > 0 && _12hour) { + timestr = hours + " " + meridian; + } else { + timestr = hours; + } + g.setFontAlign(0, 0, 0); + g.setColor(settings.time.color); + g.setFont(settings.time.font, settings.time.size); + g.drawString(timestr, settings.time.center-40, settings.time.middle); - //visualize HR with circles pulsating - const drawHR = function () { - if (grow && size < settings.hr.size) { - size++; - } + //Write the date as configured in the settings + g.setColor(settings.date.color); + g.setFont(settings.date.font, settings.date.size); + g.drawString(date, settings.date.center, settings.date.middle); +}; - if (!grow && size > 3) { - size--; - } +//setInterval for HR visualisation +const newBeats = function (hr) { + if (id != 0) { + changeInterval(id, 6e3 / hr.bpm); + } else { + id = setInterval(drawHR, 6e3 / hr.bpm); + } +}; - if (size == settings.hr.size || size == 3) { - grow = !grow; - } +//visualize HR with circles pulsating +const drawHR = function () { + if (grow && size < settings.hr.size) { + size++; + } - if (grow) { - color = settings.hr.color; - g.setColor(color); - g.fillCircle(settings.hr.x, settings.hr.y, size); - } else { - color = "#000000"; - g.setColor(color); - g.drawCircle(settings.hr.x, settings.hr.y, size); - } - }; + if (!grow && size > 3) { + size--; + } - // clean app screen - g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); + if (size == settings.hr.size || size == 3) { + grow = !grow; + } - //manage when things should be enabled and not - Bangle.on('lcdPower', function (on) { - if (on) { - Bangle.setHRMPower(1); - } else { - Bangle.setHRMPower(0); - } - }); + if (grow) { + color = settings.hr.color; + g.setColor(color); + g.fillCircle(settings.hr.x, settings.hr.y, size); + } else { + color = "#000000"; + g.setColor(color); + g.drawCircle(settings.hr.x, settings.hr.y, size); + } +}; - // refesh every second - setInterval(drawClock, 1E3); +// clean app screen +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); - //start HR monitor and update frequency of update - Bangle.setHRMPower(1); - Bangle.on('HRM', function (d) { - newBeats(d); - }); +//manage when things should be enabled and not +Bangle.on('lcdPower', function (on) { + if (on) { + Bangle.setHRMPower(1); + } else { + Bangle.setHRMPower(0); + } +}); - // draw now - drawClock(); +// refesh every second +setInterval(drawClock, 1E3); - // Show launcher when middle button pressed - setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); +//start HR monitor and update frequency of update +Bangle.setHRMPower(1); +Bangle.on('HRM', function (d) { + newBeats(d); +}); -} \ No newline at end of file +// draw now +drawClock(); + +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/impwclock/ChangeLog b/apps/impwclock/ChangeLog index c6974d37c..0592d4d04 100644 --- a/apps/impwclock/ChangeLog +++ b/apps/impwclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Stopped watchface from flashing every interval +0.03: Move to Bangle.setUI to launcher support diff --git a/apps/impwclock/clock-impword.js b/apps/impwclock/clock-impword.js index 94b92b778..5492eac15 100644 --- a/apps/impwclock/clock-impword.js +++ b/apps/impwclock/clock-impword.js @@ -47,10 +47,9 @@ const activeColorNight = 0xF800 /*red*/ ; const activeColorDay = 0xFFFF /* white */; var hidxPrev; +var showDigitalTime = false; function drawWordClock() { - - // get time var t = new Date(); var h = t.getHours(); @@ -141,7 +140,7 @@ function drawWordClock() { // Display digital time while button 1 is pressed g.clearRect(0, 215, 240, 240); - if (BTN1.read()){ + if (showDigitalTime){ g.setColor(activeColor); g.drawString(time, 120, 215); } @@ -158,8 +157,20 @@ Bangle.drawWidgets(); setInterval(drawWordClock, 1E4); drawWordClock(); -// Show digital time while top button is pressed -setWatch(drawWordClock, BTN1, {repeat:true,edge:"both"}); +// Show digital time while top button is pressed (if we have physical buttons) +if (global.BTN3) setWatch(function() { + showDigitalTime = BTN1.read(); + drawWordClock(); +}, BTN1, {repeat:true,edge:"both"}); -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// If LCD pressed (on Bangle.js 2) draw digital time +Bangle.on('drag',e=>{ + var pressed = e.b!=0; + if (pressed!=showDigitalTime) { + showDigitalTime = pressed; + drawWordClock(); + } +}); + +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/isoclock/ChangeLog b/apps/isoclock/ChangeLog index cd3ceea5c..809091ce4 100644 --- a/apps/isoclock/ChangeLog +++ b/apps/isoclock/ChangeLog @@ -1 +1,2 @@ 0.01: Created app based on digiclock with some small tweaks. +0.02: Swap to Bangle.setUI for launcher/buttons diff --git a/apps/isoclock/isoclock.js b/apps/isoclock/isoclock.js index 5f63a1248..59f28e66e 100644 --- a/apps/isoclock/isoclock.js +++ b/apps/isoclock/isoclock.js @@ -1,82 +1,82 @@ //load fonts require("Font7x11Numeric7Seg").add(Graphics); -require("FontHaxorNarrow7x17").add(Graphics); +require("FontHaxorNarrow7x17").add(Graphics); //screen position -const X = 170; -const Y = 140; +const X = 170; +const Y = 140; function draw() { // Date Variables - var date = new Date(); - var h = date.getHours(); - var m = date.getMinutes(); - var day = date.getDay(); + var date = new Date(); + var h = date.getHours(); + var m = date.getMinutes(); + var day = date.getDay(); var month = date.getMonth()+1; - var dateNum = date.getDate(); - var year = date.getFullYear(); - var half = "AM"; - var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2); - - //convert day into string + var dateNum = date.getDate(); + var year = date.getFullYear(); + var half = "AM"; + var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2); + + //convert day into string switch (day) { case 0: - day = "Sunday"; - break; - + day = "Sunday"; + break; + case 1: - day = "Monday"; - break; - + day = "Monday"; + break; + case 2: - day = "Tuesday"; - break; - + day = "Tuesday"; + break; + case 3: - day = "Wednesday"; - break; - + day = "Wednesday"; + break; + case 4: - day = "Thursday"; - break; - + day = "Thursday"; + break; + case 5: - day = "Friday"; - break; - + day = "Friday"; + break; + case 6: - day = "Saturday"; - break; - + day = "Saturday"; + break; + default: - day = "ERROR"; - break; + day = "ERROR"; + break; } - + if (h > 12) { - half = "PM"; - h = h - 12; + half = "PM"; + h = h - 12; } //reset graphics - g.reset(); + g.reset(); //draw the time g.setFont("7x11Numeric7Seg", 5); g.setFontAlign(1,1); g.drawString(time, X+10, Y, true /*clear background*/); - g.setFont("7x11Numeric7Seg", 3); - g.drawString(("0"+date.getSeconds()).substr(-2), X+55, Y, true /*clear background*/); + g.setFont("7x11Numeric7Seg", 3); + g.drawString(("0"+date.getSeconds()).substr(-2), X+55, Y, true /*clear background*/); g.setFontAlign(0,1); g.setFont("HaxorNarrow7x17", 3); g.drawString(day, X-60, Y+53, true); - g.drawString(year+"-"+month+"-"+dateNum, X-55, Y-55, true); - - + g.drawString(year+"-"+month+"-"+dateNum, X-55, Y-55, true); + + } //clear screen at startup -g.clear(); +g.clear(); //draw immediatly -draw(); +draw(); var secondInterval = setInterval(draw, 1000); // Stop updates when LCD is off, restart when on @@ -92,4 +92,5 @@ Bangle.on('lcdPower',on=>{ Bangle.loadWidgets(); Bangle.drawWidgets(); -setWatch(Bangle.showLauncher, BTN2, {repeat : false, edge: "falling"}); +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/lazyclock/ChangeLog b/apps/lazyclock/ChangeLog index 984d29869..a3f125786 100644 --- a/apps/lazyclock/ChangeLog +++ b/apps/lazyclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: Launch app -0.02: Fix bug with the elusive one o'clock monster; Only change template when going over boundaries; Re-jig wording options \ No newline at end of file +0.02: Fix bug with the elusive one o'clock monster; Only change template when going over boundaries; Re-jig wording options +0.03: Use Bangle.setUI for launcher/buttons diff --git a/apps/lazyclock/lazyclock-app.js b/apps/lazyclock/lazyclock-app.js index 400e26ede..604448ce6 100644 --- a/apps/lazyclock/lazyclock-app.js +++ b/apps/lazyclock/lazyclock-app.js @@ -221,22 +221,13 @@ function addEvents() { } }); - setWatch(switchMode, BTN1, { - repeat: true, - edge: "falling" - }); - - setWatch(Bangle.showLauncher, BTN2, { - repeat: false, - edge: "falling" - }); - - setWatch(() => { - currentFormatter = null; - refreshTime(); - }, BTN3, { - repeat: true, - edge: "falling" + // Show launcher when button pressed + Bangle.setUI("clockupdown", btn=>{ + if (btn<0) switchMode(); + if (btn>0) { + currentFormatter = null; + refreshTime(); + } }); } @@ -245,9 +236,9 @@ function init() { startClock(); Bangle.loadWidgets(); - Bangle.drawWidgets(); + Bangle.drawWidgets(); addEvents(); } -init(); \ No newline at end of file +init(); diff --git a/apps/lifeclk/ChangeLog b/apps/lifeclk/ChangeLog index dfd8b8775..cdde84463 100644 --- a/apps/lifeclk/ChangeLog +++ b/apps/lifeclk/ChangeLog @@ -2,4 +2,5 @@ 0.02: Faster algorithm, hours and minutes are now displayable whenever, using the upper button 2021-01-14 0.03: Ah yes. Some people prefer the 12 hour system 2021-01-14 0.04: Fixed a bug, doesn't run while display's on now 2021-01-18 -0.05: Fixed a bug, doesn't count the time it was asleep when calculating the update time 2021-01-19 \ No newline at end of file +0.05: Fixed a bug, doesn't count the time it was asleep when calculating the update time 2021-01-19 +0.06: Use Bangle.set UI, change to unminified upload to ensure this works ok on Bangle.js diff --git a/apps/lifeclk/app.js b/apps/lifeclk/app.min.js similarity index 98% rename from apps/lifeclk/app.js rename to apps/lifeclk/app.min.js index 6064aa162..51a8ff93c 100644 --- a/apps/lifeclk/app.js +++ b/apps/lifeclk/app.min.js @@ -1,4 +1,4 @@ -Bangle.setLCDTimeout(30); +// Name as .min.js so we don't try and pretokenise (which stops Bangle.js running this somehow) const is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; @@ -435,9 +435,11 @@ function showMinAgain(){ } function setButtons(){ - setWatch(showMinAgain, BTN1, {repeat:true,edge:"falling"}); - setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); - setWatch(regen, BTN3, {repeat:true,edge:"falling"}); + // Show launcher when button pressed + Bangle.setUI("clockupdown", btn=>{ + if (btn<0) showMinAgain(); + if (btn>0) regen(); + }); } let wentToSleepAt; diff --git a/apps/mysticclock/ChangeLog b/apps/mysticclock/ChangeLog index 34fe53627..b486a29a1 100644 --- a/apps/mysticclock/ChangeLog +++ b/apps/mysticclock/ChangeLog @@ -1 +1,2 @@ 1.00: First published version. +1.01: Use Bangle.setUI for Launcher/buttons diff --git a/apps/mysticclock/mystic-clock-app.js b/apps/mysticclock/mystic-clock-app.js index 22c2c8982..2d95633fe 100644 --- a/apps/mysticclock/mystic-clock-app.js +++ b/apps/mysticclock/mystic-clock-app.js @@ -200,16 +200,9 @@ if (Bangle.isLCDOn()) { drawAll(); // draw immediately } -// show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); - -// rotate through info when the buttons are pressed -setWatch(() => { - nextInfo(); +// Show launcher when button pressed +Bangle.setUI("clockupdown", btn=>{ + if (btn<0) prevInfo(); + if (btn>0) nextInfo(); drawAll(); -}, BTN3, { repeat: true }); - -setWatch(() => { - prevInfo(); - drawAll(); -}, BTN1, { repeat: true }); +}); diff --git a/apps/rclock/ChangeLog b/apps/rclock/ChangeLog index 61bf493c1..915fbc5d7 100644 --- a/apps/rclock/ChangeLog +++ b/apps/rclock/ChangeLog @@ -2,4 +2,6 @@ 0.02: Added support for locale and 12H clock 0.03: Added HR indication to clock 0.04: Update font size and alignment -0.05: Changes which circle show minutes and seconds \ No newline at end of file +0.05: Changes which circle show minutes and seconds +0.06: Avoid function wrapper, use setUI for launcher + Clock face smaller so no longer breaks widgets diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index ceaffe910..9c219ab3d 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -1,229 +1,226 @@ -{ - var minutes; - var seconds; - var hours; - var date; - var first = true; - var locale = require('locale'); - var _12hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"] || false; +var minutes; +var seconds; +var hours; +var date; +var first = true; +var locale = require('locale'); +var _12hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"] || false; - //HR variables - var id = 0; - var grow = true; - var size=10; +//HR variables +var id = 0; +var grow = true; +var size=10; - //Screen dimensions - const screen = { - width: g.getWidth(), - height: g.getWidth(), - middle: g.getWidth() / 2, - center: g.getHeight() / 2, - }; +//Screen dimensions +const screen = { + width: g.getWidth(), + height: g.getWidth(), + middle: g.getWidth() / 2, + center: g.getHeight() / 2, +}; - // Ssettings - const settings = { - time: { - color: '#D6ED17', - font: 'Vector', - size: 60, - middle: screen.middle, - center: screen.center, - }, - date: { - color: '#D6ED17', - font: 'Vector', - size: 15, - middle: screen.height-17, // at bottom of screen - center: screen.center, - }, - circle: { - colormin: '#ffffff', - colorsec: '#ffffff', - width: 10, - middle: screen.middle, - center: screen.center, - height: screen.height - }, - hr: { - color: '#333333', - size: 10, - x: screen.center, - y: screen.middle + 45 +// Settings +const settings = { + time: { + color: '#D6ED17', + font: 'Vector', + size: 60, + middle: screen.middle, + center: screen.center, + }, + date: { + color: '#D6ED17', + font: 'Vector', + size: 15, + middle: screen.height-17, // at bottom of screen + center: screen.center, + }, + circle: { + colormin: '#ffffff', + colorsec: '#ffffff', + width: 10, + middle: screen.middle, + center: screen.center, + height: screen.height-24 + }, + hr: { + color: '#333333', + size: 10, + x: screen.center, + y: screen.middle + 45 + } +}; + +const dateStr = function (date) { + return locale.date(new Date(), 1); +}; + +const getArcXY = function (centerX, centerY, radius, angle) { + var s, r = []; + s = 2 * Math.PI * angle / 360; + r.push(centerX + Math.round(Math.cos(s) * radius)); + r.push(centerY + Math.round(Math.sin(s) * radius)); + + return r; +}; + +const drawMinArc = function (sections, color) { + g.setColor(color); + var rad = (settings.circle.height / 2) - 40; + var r1 = getArcXY(settings.circle.middle, settings.circle.center, rad, sections * (360 / 60) - 90); + //g.setPixel(r[0],r[1]); + var r2 = getArcXY(settings.circle.middle, settings.circle.center, rad - settings.circle.width, sections * (360 / 60) - 90); + //g.setPixel(r[0],r[1]); + g.drawLine(r1[0], r1[1], r2[0], r2[1]); + g.setColor('#333333'); + g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width - 4); +}; + +const drawSecArc = function (sections, color) { + g.setColor(color); + var rad = (settings.circle.height / 2) - 20; + var r1 = getArcXY(settings.circle.middle, settings.circle.center, rad, sections * (360 / 60) - 90); + //g.setPixel(r[0],r[1]); + var r2 = getArcXY(settings.circle.middle, settings.circle.center, rad - settings.circle.width, sections * (360 / 60) - 90); + //g.setPixel(r[0],r[1]); + g.drawLine(r1[0], r1[1], r2[0], r2[1]); + g.setColor('#333333'); + g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width - 4); +}; + +const drawClock = function () { + g.reset(); + currentTime = new Date(); + + //Set to initial time when started + if (first == true) { + minutes = currentTime.getMinutes(); + seconds = currentTime.getSeconds(); + for (count = 0; count <= minutes; count++) { + drawMinArc(count, settings.circle.colormin); } - }; - const dateStr = function (date) { - return locale.date(new Date(), 1); - }; + for (count = 0; count <= seconds; count++) { + drawSecArc(count, settings.circle.colorsec); + } + first = false; + } - const getArcXY = function (centerX, centerY, radius, angle) { - var s, r = []; - s = 2 * Math.PI * angle / 360; - r.push(centerX + Math.round(Math.cos(s) * radius)); - r.push(centerY + Math.round(Math.sin(s) * radius)); + // Reset + if (seconds == 59) { + g.setColor('#000000'); + g.fillCircle(settings.circle.middle, settings.circle.center, (settings.circle.height / 2)); + for (count = 0; count <= minutes; count++) { + drawMinArc(count, settings.circle.colormin); + } + } - return r; - }; + //Get date as a string + date = dateStr(currentTime); - const drawMinArc = function (sections, color) { + // Update minutes when needed + if (minutes != currentTime.getMinutes()) { + minutes = currentTime.getMinutes(); + drawMinArc(minutes, settings.circle.colormin); + } + + //Update seconds when needed + if (seconds != currentTime.getSeconds()) { + seconds = currentTime.getSeconds(); + drawSecArc(seconds, settings.circle.colorsec); + } + + //Write the time as configured in the settings + hours = currentTime.getHours(); + if (_12hour && hours > 13) { + hours = hours - 12; + } + + var meridian; + + if (typeof locale.meridian === "function") { + meridian = locale.meridian(new Date()); + } else { + meridian = ""; + } + + var timestr; + + if (meridian.length > 0 && _12hour) { + timestr = hours + " " + meridian; + } else { + timestr = hours; + } + g.setFontAlign(0, 0, 0); + g.setColor(settings.time.color); + g.setFont(settings.time.font, settings.time.size); + g.drawString(timestr, settings.time.center, settings.time.middle); + + //Write the date as configured in the settings + g.setColor(settings.date.color); + g.setFont(settings.date.font, settings.date.size); + g.drawString(date, settings.date.center, settings.date.middle); +}; + +//setInterval for HR visualisation +const newBeats = function (hr) { + if (id != 0) { + changeInterval(id, 6e3 / hr.bpm); + } else { + id = setInterval(drawHR, 6e3 / hr.bpm); + } +}; + +//visualize HR with circles pulsating +const drawHR = function () { + if (grow && size < settings.hr.size) { + size++; + } + + if (!grow && size > 3) { + size--; + } + + if (size == settings.hr.size || size == 3) { + grow = !grow; + } + + if (grow) { + color = settings.hr.color; g.setColor(color); - rad = (settings.circle.height / 2) - 40; - r1 = getArcXY(settings.circle.middle, settings.circle.center, rad, sections * (360 / 60) - 90); - //g.setPixel(r[0],r[1]); - r2 = getArcXY(settings.circle.middle, settings.circle.center, rad - settings.circle.width, sections * (360 / 60) - 90); - //g.setPixel(r[0],r[1]); - g.drawLine(r1[0], r1[1], r2[0], r2[1]); - g.setColor('#333333'); - g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width - 4); - }; - - const drawSecArc = function (sections, color) { + g.fillCircle(settings.hr.x, settings.hr.y, size); + } else { + color = "#000000"; g.setColor(color); - rad = (settings.circle.height / 2) - 20; - r1 = getArcXY(settings.circle.middle, settings.circle.center, rad, sections * (360 / 60) - 90); - //g.setPixel(r[0],r[1]); - r2 = getArcXY(settings.circle.middle, settings.circle.center, rad - settings.circle.width, sections * (360 / 60) - 90); - //g.setPixel(r[0],r[1]); - g.drawLine(r1[0], r1[1], r2[0], r2[1]); - g.setColor('#333333'); - g.drawCircle(settings.circle.middle, settings.circle.center, rad - settings.circle.width - 4); - }; + g.drawCircle(settings.hr.x, settings.hr.y, size); + } +}; - const drawClock = function () { +// clean app screen +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); - currentTime = new Date(); +//manage when things should be enabled and not +Bangle.on('lcdPower', function (on) { + if (on) { + Bangle.setHRMPower(1); + } else { + Bangle.setHRMPower(0); + } +}); - //Set to initial time when started - if (first == true) { - minutes = currentTime.getMinutes(); - seconds = currentTime.getSeconds(); - for (count = 0; count <= minutes; count++) { - drawMinArc(count, settings.circle.colormin); - } +// refesh every second +setInterval(drawClock, 1E3); - for (count = 0; count <= seconds; count++) { - drawSecArc(count, settings.circle.colorsec); - } - first = false; - } +//start HR monitor and update frequency of update +Bangle.setHRMPower(1); +Bangle.on('HRM', function (d) { + newBeats(d); +}); - // Reset - if (seconds == 59) { - g.setColor('#000000'); - g.fillCircle(settings.circle.middle, settings.circle.center, (settings.circle.height / 2)); - for (count = 0; count <= minutes; count++) { - drawMinArc(count, settings.circle.colormin); - } - } +// draw now +drawClock(); - //Get date as a string - date = dateStr(currentTime); - - // Update minutes when needed - if (minutes != currentTime.getMinutes()) { - minutes = currentTime.getMinutes(); - drawMinArc(minutes, settings.circle.colormin); - } - - //Update seconds when needed - if (seconds != currentTime.getSeconds()) { - seconds = currentTime.getSeconds(); - drawSecArc(seconds, settings.circle.colorsec); - } - - //Write the time as configured in the settings - hours = currentTime.getHours(); - if (_12hour && hours > 13) { - hours = hours - 12; - } - - var meridian; - - if (typeof locale.meridian === "function") { - meridian = locale.meridian(new Date()); - } else { - meridian = ""; - } - - var timestr; - - if (meridian.length > 0 && _12hour) { - timestr = hours + " " + meridian; - } else { - timestr = hours; - } - g.setFontAlign(0, 0, 0); - g.setColor(settings.time.color); - g.setFont(settings.time.font, settings.time.size); - g.drawString(timestr, settings.time.center, settings.time.middle); - - //Write the date as configured in the settings - g.setColor(settings.date.color); - g.setFont(settings.date.font, settings.date.size); - g.drawString(date, settings.date.center, settings.date.middle); - }; - - //setInterval for HR visualisation - const newBeats = function (hr) { - if (id != 0) { - changeInterval(id, 6e3 / hr.bpm); - } else { - id = setInterval(drawHR, 6e3 / hr.bpm); - } - }; - - //visualize HR with circles pulsating - const drawHR = function () { - if (grow && size < settings.hr.size) { - size++; - } - - if (!grow && size > 3) { - size--; - } - - if (size == settings.hr.size || size == 3) { - grow = !grow; - } - - if (grow) { - color = settings.hr.color; - g.setColor(color); - g.fillCircle(settings.hr.x, settings.hr.y, size); - } else { - color = "#000000"; - g.setColor(color); - g.drawCircle(settings.hr.x, settings.hr.y, size); - } - }; - - // clean app screen - g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); - - //manage when things should be enabled and not - Bangle.on('lcdPower', function (on) { - if (on) { - Bangle.setHRMPower(1); - } else { - Bangle.setHRMPower(0); - } - }); - - // refesh every second - setInterval(drawClock, 1E3); - - //start HR monitor and update frequency of update - Bangle.setHRMPower(1); - Bangle.on('HRM', function (d) { - newBeats(d); - }); - - // draw now - drawClock(); - - // Show launcher when middle button pressed - setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); - -} \ No newline at end of file +// Show launcher when button pressed +Bangle.setUI("clock"); diff --git a/apps/swlclk/ChangeLog b/apps/swlclk/ChangeLog index 5560f00bc..3e072aee3 100644 --- a/apps/swlclk/ChangeLog +++ b/apps/swlclk/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Fix text alignment, move to setUI diff --git a/apps/swlclk/app.js b/apps/swlclk/app.js index d1abeda8a..24e150323 100644 --- a/apps/swlclk/app.js +++ b/apps/swlclk/app.js @@ -17,126 +17,119 @@ function drawTime(){ var utc = getUTCTime(d); var beats = Math.floor((((utc[0] + 1) % 24) + utc[1] / 60 + utc[2] / 3600) * 1000 / 24); - function drawStation(){ - g.setFont("Vector",10); - g.setColor("#ffffff"); - switch (utc[0]) { - case 0: - g.clearRect(0,25,240,80); - g.drawString("00h00-00h30 Radio Havane Cuba\n15730\n00h00-01h00 Radio for Peace Int.\n9395\n00h30-01h00 Radio Havane Cuba\n5040",xyCenter,30); - break; - case 1: - g.clearRect(0,25,240,80); - g.drawString("01h00-02h00 Radio Roumanie Int.\n6040 7375\n01h00-01h30 R. Argentine vers le monde\n9395",xyCenter,30); - break; - case 2: - g.clearRect(0,25,240,80); - g.drawString("02h30-03h00 R. Argentine vers le monde\n5800",xyCenter,30); - break; - case 4: - g.clearRect(0,25,240,80); - g.drawString("04h00-05h00 R.F.I.\n9790 11700\n04h00-05h00 Voix de la Corée\n13650 15105\n04h30-05h00 A.W.R.\n6155",xyCenter,30); - break; - case 5: - g.clearRect(0,25,240,80); - g.drawString("05h00-05h30 Radio Roumanie Int.\n6015 15340 17520\n05h00-06h00 Radio Ndarason Int.\n5960\n05h30-06h00 Radio Japon\n11730 13840\n",xyCenter,30); - break; - case 6: - g.clearRect(0,25,240,80); - g.drawString("06h00-06h30 B.B.C.\n5875 9440 11620\n06h00-06h30 Voix de l'Amérique\n4960 6180 9885 13830\n06h30-06h45 Vatican News\n11935",xyCenter,30); - break; - case 7: - g.clearRect(0,25,240,80); - g.drawString("07h00-07h30 B.B.C.\n9440 13810?\n07h00-08h00 Radio Chine Int.\n17865\n07h00-08h00 R.F.I.\n11700 13695 15300 17850 21580?",xyCenter,30); - break; - case 8: - g.clearRect(0,25,240,80); - g.drawString("08h00-08h30 A.W.R.\n15145\n08h00-09h00 W.B.C.Q.\n9330\n08h30-09h00 Voix de l'Amérique\n9410 13830 17530",xyCenter,30); - break; - case 9: - g.clearRect(0,25,240,80); - g.drawString("09h00-10h00 R. Argentine vers le monde\n5950\n09h00-10h00 R.F.I.\n13695 15300 15320",xyCenter,30); - break; - case 10: - g.clearRect(0,25,240,80); - g.drawString("10h00-10h30 Voix du Nigéria\n11770\n10h00-11h00 Radio MiAmigo\n6085",xyCenter,30); - break; - case 11: - g.clearRect(0,25,240,80); - g.drawString("11h00-12h00 Voix de la Corée\n11710 11735 13650 15180\n11h30-12h00 Radio Slovaquie Int.\n6005",xyCenter,30); - break; - case 12: - g.clearRect(0,25,240,80); - g.drawString("12h00-12h30 Voix du Vietnam\n7285\n12h00-13h00 Radio MiAmigo\n6085",xyCenter,30); - break; - case 13: - g.clearRect(0,25,240,80); - g.drawString("13h00-14h00 Radio for Peace Int.\n15770\n13h30-14h00 Radio Slovaquie Int.\n6005",xyCenter,30); - break; - case 14: - g.clearRect(0,25,240,80); - g.drawString("14h00-16h00 Radio saoudienne Int.\n17660\n14h00-16h00 Radio Chine Int.\n11920 13670\n14h55-15h25 T.W.R. Swaziland\n9585",xyCenter,30); - break; - case 15: - g.clearRect(0,25,240,80); - g.drawString("15h00-15h30 Radio Tirana\n3985\n15h00-15h30 Radio Nationale Lao\n6130 567",xyCenter,30); - break; - case 16: - g.clearRect(0,25,240,80); - g.drawString("16h00-16h15 Vatican News\n11950\n16h30-17h15 Voix de l'Afrique\n9505",xyCenter,30); - break; - case 17: - g.clearRect(0,25,240,80); - g.drawString("17h00-18h00 R.F.I.\n13740 13770 17850\n17h30-18h25 Voix de la Turquie\n7360",xyCenter,30); - break; - case 18: - g.clearRect(0,25,240,80); - g.drawString("18h00-18h11 Radio Algérie Int.\n13820\n18h30-19h00 Radio Slovaquie Int.\n3985",xyCenter,30); - break; - case 19: - g.clearRect(0,25,240,80); - g.drawString("19h00-19h30 Radio Taiwan Int.\n6005\n19h23-20h23 Voix de la République\nIslamique d'Iran\n7235",xyCenter,30); - break; - case 20: - g.clearRect(0,25,240,80); - g.drawString("20h00-21h15 Radio Le Caire\n9810\n20h00-21h00 Voix de l'Indonésie\n3325 4750\n20h30-20h50 Radio Belarus\n3985",xyCenter,30); - break; - case 21: - g.clearRect(0,25,240,80); - g.drawString("21h00-21h30 Voix de l'Amérique\n5970 9490 9740 11900\n21h00-22h00 Radio for Peace Int.\n6070",xyCenter,30); - break; - case 22: - g.clearRect(0,25,240,80); - g.drawString("22h00-22h15 T.W.R. Bénin\n1566\n22h30-23h00 Radio Extérieure d'Espagne\n9690 11670 11940",xyCenter,30); - break; - case 23: - g.clearRect(0,25,240,80); - g.drawString("23h23-00h23 Voix de la République\nIslamique d'Iran\n7230\n23h30-00h00 R. Argentine vers le monde\n7780",xyCenter,30); - break; - default: - g.clearRect(0,25,240,80); - g.drawString("17h00-18h00 R.F.I.\n13740 15300 17850\n17h00-18h00 R.F.I.\n7205 9790",xyCenter,30); - break; - } + g.reset().setFont("Vector",10).setFontAlign(0,0); + g.setColor("#ffffff"); + switch (utc[0]) { + case 0: + g.clearRect(0,25,240,80); + g.drawString("00h00-00h30 Radio Havane Cuba\n15730\n00h00-01h00 Radio for Peace Int.\n9395\n00h30-01h00 Radio Havane Cuba\n5040",xyCenter,30); + break; + case 1: + g.clearRect(0,25,240,80); + g.drawString("01h00-02h00 Radio Roumanie Int.\n6040 7375\n01h00-01h30 R. Argentine vers le monde\n9395",xyCenter,30); + break; + case 2: + g.clearRect(0,25,240,80); + g.drawString("02h30-03h00 R. Argentine vers le monde\n5800",xyCenter,30); + break; + case 4: + g.clearRect(0,25,240,80); + g.drawString("04h00-05h00 R.F.I.\n9790 11700\n04h00-05h00 Voix de la Corée\n13650 15105\n04h30-05h00 A.W.R.\n6155",xyCenter,30); + break; + case 5: + g.clearRect(0,25,240,80); + g.drawString("05h00-05h30 Radio Roumanie Int.\n6015 15340 17520\n05h00-06h00 Radio Ndarason Int.\n5960\n05h30-06h00 Radio Japon\n11730 13840\n",xyCenter,30); + break; + case 6: + g.clearRect(0,25,240,80); + g.drawString("06h00-06h30 B.B.C.\n5875 9440 11620\n06h00-06h30 Voix de l'Amérique\n4960 6180 9885 13830\n06h30-06h45 Vatican News\n11935",xyCenter,30); + break; + case 7: + g.clearRect(0,25,240,80); + g.drawString("07h00-07h30 B.B.C.\n9440 13810?\n07h00-08h00 Radio Chine Int.\n17865\n07h00-08h00 R.F.I.\n11700 13695 15300 17850 21580?",xyCenter,30); + break; + case 8: + g.clearRect(0,25,240,80); + g.drawString("08h00-08h30 A.W.R.\n15145\n08h00-09h00 W.B.C.Q.\n9330\n08h30-09h00 Voix de l'Amérique\n9410 13830 17530",xyCenter,30); + break; + case 9: + g.clearRect(0,25,240,80); + g.drawString("09h00-10h00 R. Argentine vers le monde\n5950\n09h00-10h00 R.F.I.\n13695 15300 15320",xyCenter,30); + break; + case 10: + g.clearRect(0,25,240,80); + g.drawString("10h00-10h30 Voix du Nigéria\n11770\n10h00-11h00 Radio MiAmigo\n6085",xyCenter,30); + break; + case 11: + g.clearRect(0,25,240,80); + g.drawString("11h00-12h00 Voix de la Corée\n11710 11735 13650 15180\n11h30-12h00 Radio Slovaquie Int.\n6005",xyCenter,30); + break; + case 12: + g.clearRect(0,25,240,80); + g.drawString("12h00-12h30 Voix du Vietnam\n7285\n12h00-13h00 Radio MiAmigo\n6085",xyCenter,30); + break; + case 13: + g.clearRect(0,25,240,80); + g.drawString("13h00-14h00 Radio for Peace Int.\n15770\n13h30-14h00 Radio Slovaquie Int.\n6005",xyCenter,30); + break; + case 14: + g.clearRect(0,25,240,80); + g.drawString("14h00-16h00 Radio saoudienne Int.\n17660\n14h00-16h00 Radio Chine Int.\n11920 13670\n14h55-15h25 T.W.R. Swaziland\n9585",xyCenter,30); + break; + case 15: + g.clearRect(0,25,240,80); + g.drawString("15h00-15h30 Radio Tirana\n3985\n15h00-15h30 Radio Nationale Lao\n6130 567",xyCenter,30); + break; + case 16: + g.clearRect(0,25,240,80); + g.drawString("16h00-16h15 Vatican News\n11950\n16h30-17h15 Voix de l'Afrique\n9505",xyCenter,30); + break; + case 17: + g.clearRect(0,25,240,80); + g.drawString("17h00-18h00 R.F.I.\n13740 13770 17850\n17h30-18h25 Voix de la Turquie\n7360",xyCenter,30); + break; + case 18: + g.clearRect(0,25,240,80); + g.drawString("18h00-18h11 Radio Algérie Int.\n13820\n18h30-19h00 Radio Slovaquie Int.\n3985",xyCenter,30); + break; + case 19: + g.clearRect(0,25,240,80); + g.drawString("19h00-19h30 Radio Taiwan Int.\n6005\n19h23-20h23 Voix de la République\nIslamique d'Iran\n7235",xyCenter,30); + break; + case 20: + g.clearRect(0,25,240,80); + g.drawString("20h00-21h15 Radio Le Caire\n9810\n20h00-21h00 Voix de l'Indonésie\n3325 4750\n20h30-20h50 Radio Belarus\n3985",xyCenter,30); + break; + case 21: + g.clearRect(0,25,240,80); + g.drawString("21h00-21h30 Voix de l'Amérique\n5970 9490 9740 11900\n21h00-22h00 Radio for Peace Int.\n6070",xyCenter,30); + break; + case 22: + g.clearRect(0,25,240,80); + g.drawString("22h00-22h15 T.W.R. Bénin\n1566\n22h30-23h00 Radio Extérieure d'Espagne\n9690 11670 11940",xyCenter,30); + break; + case 23: + g.clearRect(0,25,240,80); + g.drawString("23h23-00h23 Voix de la République\nIslamique d'Iran\n7230\n23h30-00h00 R. Argentine vers le monde\n7780",xyCenter,30); + break; + default: + g.clearRect(0,25,240,80); + g.drawString("17h00-18h00 R.F.I.\n13740 15300 17850\n17h00-18h00 R.F.I.\n7205 9790",xyCenter,30); + break; } - drawStation(); // Local time - g.setFont("6x8",1); - g.setColor("#cccccc"); + g.setFont("6x8",1).setColor("#cccccc"); g.drawString("Loc",10,85); - g.setFont("7x11Numeric7Seg",4); - g.setColor("#ffffff"); + g.setFont("7x11Numeric7Seg",4).setColor("#ffffff"); g.drawString(`${hours}:${minutes}:${seconds}`, xyCenter, 115, true); // UTC time - g.setFont("6x8",1); - g.setColor("#cccccc"); + g.setFont("6x8",1).setColor("#cccccc"); g.drawString("UTC",10,155); - g.setFont("7x11Numeric7Seg",4); - g.setColor("#ff0000"); + g.setFont("7x11Numeric7Seg",4).setColor("#ff0000"); g.drawString(utc[0]+`:${minutes}:${seconds}`, xyCenter, 185,true); // footer date @@ -147,6 +140,7 @@ function drawTime(){ } function setGpsTime(){ + print("set GPS time"); Bangle.setGPSPower(1); Bangle.on('GPS',function(fix) { if (fix.fix) { @@ -157,7 +151,7 @@ function setGpsTime(){ start(); } else { stop(); - g.setFont("Vector",10); + g.reset().setFont("Vector",10).setFontAlign(0,0); g.setColor("#cccccc"); g.clearRect(0,25,240,80); g.drawString("Mise à l'heure\npar satellites\nen cours...",xyCenter,40); @@ -166,14 +160,13 @@ function setGpsTime(){ } function setButtons(){ - // BTN 1 - setWatch(() => { + // Show launcher when button pressed + Bangle.setUI("clockupdown", btn=>{ + if (btn!=-1) return; + // if up pressed, turn GPS on and wait for new time setGpsTime(); Bangle.beep(500, 4000); - }, BTN1, {edge:"rising", repeat:true}); - - // BTN 2 - setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + }); } var intervalRef = null; From 6277fa3b7451e1f115542a7b2fb5395d0e053e90 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 28 Jul 2021 15:35:05 +0100 Subject: [PATCH 130/163] Solar Clock: Added Seoul --- apps/solarclock/custom.html | 3 ++- apps/solarclock/solar_clock.js | 2 +- apps/solarclock/solar_loc.Seoul.json | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 apps/solarclock/solar_loc.Seoul.json diff --git a/apps/solarclock/custom.html b/apps/solarclock/custom.html index 4e089a016..25fd52d7b 100644 --- a/apps/solarclock/custom.html +++ b/apps/solarclock/custom.html @@ -25,7 +25,8 @@ {name:"Honolulu", shortname:"Honolulu"}, {name: "Reykjavik", shortname:"Reykjavik"}, {name: "Rio", shortname:"Rio"}, - {name:"Tokyo", shortname:"Tokyo"} + {name:"Tokyo", shortname:"Tokyo"}, + {name:"Seoul", shortname:"Seoul"} ]; var selected_locations = ["local"]; try{ diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 310ec84bf..fbb8a94de 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -290,7 +290,7 @@ function write_location_name() { g.setFontAlign(-1, -1, 0); GraphicUtils.set_color(screen_info.screen_bg_color); - g.fillRect(DATE_X_COORD, LOCATION_Y_COORD, DATE_X_COORD + 95, LOCATION_Y_COORD + 20); + g.fillRect(DATE_X_COORD, LOCATION_Y_COORD, DATE_X_COORD + 105, LOCATION_Y_COORD + 20); if (new_location_name != "local") { GraphicUtils.set_color(time_color); diff --git a/apps/solarclock/solar_loc.Seoul.json b/apps/solarclock/solar_loc.Seoul.json new file mode 100644 index 000000000..a3ebbb463 --- /dev/null +++ b/apps/solarclock/solar_loc.Seoul.json @@ -0,0 +1,4 @@ +{ + "coordinates": [126.98705302359637, 37.542652407748214], + "utc_offset": 9 +} From 36772a6fa7d7e2cb2fe79a22e101fae76a91945c Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 28 Jul 2021 15:40:47 +0100 Subject: [PATCH 131/163] Solar Clock: added Soeld to apps index --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index d11554c2c..584878b95 100644 --- a/apps.json +++ b/apps.json @@ -301,7 +301,8 @@ {"name":"solar_loc.Hong_Kong.json","url":"solar_loc.Hong_Kong.json"}, {"name":"solar_loc.Honolulu.json","url":"solar_loc.Honolulu.json"}, {"name":"solar_loc.Rio.json","url":"solar_loc.Rio.json"}, - {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"} + {"name":"solar_loc.Tokyo.json","url":"solar_loc.Tokyo.json"}, + {"name":"solar_loc.Seoul.json","url":"solar_loc.Seoul.json"} ] }, { "id": "sweepclock", From d551e9d78c2960574fbc87f4923cd0cea5312455 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Jul 2021 16:30:16 +0100 Subject: [PATCH 132/163] Evaluate images before they get to Bangle.js --- bin/build_bangle2_c.js | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/bin/build_bangle2_c.js b/bin/build_bangle2_c.js index 5e086b980..5b4464691 100755 --- a/bin/build_bangle2_c.js +++ b/bin/build_bangle2_c.js @@ -30,6 +30,42 @@ global.Const = { SINGLE_APP_ONLY : false, }; + +function atob(input) { + // Copied from https://github.com/strophe/strophejs/blob/e06d027/src/polyfills.js#L149 + // This code was written by Tyler Akins and has been placed in the + // public domain. It would be nice if you left this header intact. + // Base64 code from Tyler Akins -- http://rumkin.com + var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + var output = []; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + // remove all characters that are not A-Z, a-z, 0-9, +, /, or = + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); + do { + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output.push(chr1); + + if (enc3 !== 64) { + output.push(chr2); + } + if (enc4 !== 64) { + output.push(chr3); + } + } while (i < input.length); + return new Uint8Array(output); + } + var AppInfo = require(ROOTDIR+"/core/js/appinfo.js"); var appjson = JSON.parse(fs.readFileSync(APPJSON).toString()); var appfiles = []; @@ -50,6 +86,28 @@ function fileGetter(url) { return Promise.resolve(fs.readFileSync(url).toString("binary")); } +// If file should be evaluated, try and do it... +function evaluateFile(file) { + var hsStart = 'require("heatshrink").decompress(atob("'; + var hsEnd = '"))'; + if (file.content.startsWith(hsStart) && file.content.endsWith(hsEnd)) { + var heatshrink = require(ROOTDIR+"/core/lib/heatshrink.js"); + var b64 = file.content.slice(hsStart.length, -hsEnd.length); + var decompressed = heatshrink.decompress(atob(b64)); + file.content = ""; + for (var i=0;i { var app = appjson.find(app=>app.id==appid); if (app===undefined) throw new Error(`App ${appid} not found`); @@ -63,6 +121,8 @@ Promise.all(APPS.map(appid => { // work out what goes in storage var storageContent = ""; appfiles.forEach((file) => { + //console.log(file); + if (file.evaluate) evaluateFile(file); var fileLength = file.content.length; console.log(file.name+" -> "+fileLength+"b"); // set up header From c169d42455d4868d47cb64f64ba51dc760707570 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Thu, 29 Jul 2021 02:10:23 +0100 Subject: [PATCH 133/163] Solar Clock: Added comments --- apps/solarclock/solar_clock.js | 65 ++++++++++++++++++++++++-- apps/solarclock/solar_controller.js | 18 ++++++- apps/solarclock/solar_date_utils.js | 2 + apps/solarclock/solar_graphic_utils.js | 2 +- 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index fbb8a94de..5772b59b5 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -1,3 +1,12 @@ +/** + * Adrian Kirk 2021-07 + * + * Solar Clock + * + * Using your current or chosen location the solar watch face shows the Sun's sky position, + * time and date. Also allows you to wind backwards and forwards in time to see the sun's position + **/ + const DateUtils = require("solar_date_utils.js"); const Math2 = require("solar_math_utils.js"); const GraphicUtils = require("solar_graphic_utils.js"); @@ -5,6 +14,11 @@ const Colors = require("solar_colors.js"); const LocationUtils = require("solar_location.js"); const Locale = require('locale'); +/** + * The screen info data structure stores all of the + * relevant screen information, such as the sun's position + * where the sunrise line is, etc + */ var screen_info = { screen_width : g.getWidth(), screen_start_x : 0, @@ -18,10 +32,16 @@ var screen_info = { sun_y : null, sunrise_y : null, } +// we set up the image buffer with which we draw the sun with const img_width=40; const img_height=30; var img_buffer = Graphics.createArrayBuffer(img_width,img_height,8); var img = {width:img_width,height:img_height,bpp:8,transparent:0,buffer:img_buffer.buffer}; +/** + * We use an image buffer to do the sun animation. + * We pass around the img_info structure with the + * image buffer data + */ var img_info = { x: null, y: null, @@ -36,6 +56,9 @@ var curr_mode = null; var last_sun_draw_time = null; var draw_full_cosine = true; +// The draw sun function is responsible for +// drawing the whole sun animation which includes the +// sun, the cosine curve and the sunrise line. function draw_sun(now, day_info) { var now_fraction = (now.getTime() - day_info.day_start.getTime())/DateUtils.DAY_MILLIS; @@ -110,6 +133,8 @@ function draw_sun(now, day_info) { return true; } +// clear sun is called when there is a large change in the sun's +// location, such as location change. function clear_sun(){ if(img_info.x != null && img_info.y != null) { GraphicUtils.set_color(screen_info.screen_bg_color); @@ -153,10 +178,14 @@ function write_date(now){ } } +// The info panels mid way down the screen on the left and right const INFO_PANEL_LINE_Y1 = 90; const INFO_PANEL_LINE_Y2 = 105; var gps_status_requires_update = true; +// The GPS status panel shows the status of the GPS +// when the location is know it shows the +// longitude and latitude. function write_GPS_status(){ if(!gps_status_requires_update) return; @@ -198,6 +227,8 @@ const TWILIGHT_X_COORD = 200; const NO_TIME = "--:--"; var twilight_times_requires_update = true; +// The right panel shows the sun rise and sunset times. +// we make provision for when there is no times available function write_twilight_times(){ if(!twilight_times_requires_update) return; @@ -314,8 +345,10 @@ location.addUpdateListener( } ); - - +// day info is responsible for populating the day_info structure +// The day_info structure holds the sun set and sunset times +// The function also has to detect when the end of the solar +// day has been reached and flip the day over. function dayInfo(now) { if (day_info == null || now > day_info.day_end) { var coords = location.getCoordinates(); @@ -342,7 +375,8 @@ function time_now() { } } - +// The main loop called everytime we want to refresh the +// clock function draw_clock(){ var start_time = Date.now(); var now = time_now(); @@ -370,6 +404,11 @@ function log_memory_used() { ); } +// Button has a short press action of resetting the offet +// and a long press set the GPS up for refreshing the current +// position. +// To accomodate the long and short press we record when the press +// starts and time to when it is released var button1pressStart = null; function button1pressed(){ if(button1pressStart == null) { @@ -377,6 +416,8 @@ function button1pressed(){ } //console.log("button 1 pressed for:" + (Date.now() - button1pressStart)); if(BTN1.read()){ + // we look every 100 ms to see if the button is still pressed + // (to makes the button responsive) setTimeout(button1pressed,100); } else { var buttonPressTime = Date.now() - button1pressStart; @@ -396,12 +437,18 @@ function button1pressed(){ } } +// button 3 kicks off a the change to the next location function button3pressed() { console.log("button 3 pressed"); time_offset = 0; location.nextLocation(); } +// button 4 moves the offset back +// keeping the button pressed repeats +// to give the sun the continuous animation +// to achieve this we put in a call back +// to see if its still presses after 50 ms. function button4pressed(){ time_offset -= DateUtils.HOUR_MILLIS/4; draw_clock(); @@ -414,6 +461,11 @@ function button4pressed(){ ) } +// button 5 moves the offset forward +// keeping the button pressed repeats +// to give the sun the continuous animation +// to achieve this we put in a call back +// to see if its still presses after 50 ms. function button5pressed(){ time_offset += DateUtils.HOUR_MILLIS/4; draw_clock(); @@ -485,6 +537,12 @@ Bangle.drawWidgets(); start_timers(); +// When button 2 is pressed we return to the +// launcher. We run through a shutdown sequence +// we shutdown the location object, which +// shut down the GPS (if running) +// we deference the location and controller to +// to free up memory before the jump is made. function button2pressed(){ controller = null; @@ -494,6 +552,7 @@ function button2pressed(){ Bangle.showLauncher(); } setWatch(button2pressed, BTN2,{repeat:false,edge:"falling"}); +// we are timing button 1 so we put a callback in the the rising edge. setWatch(button1pressed, BTN1,{repeat:true,edge:"rising"}); setWatch(button3pressed, BTN3,{repeat:true,edge:"falling"}); setWatch(button4pressed, BTN4,{repeat:true,edge:"rising"}); diff --git a/apps/solarclock/solar_controller.js b/apps/solarclock/solar_controller.js index 8c116ecd5..5908b82ef 100644 --- a/apps/solarclock/solar_controller.js +++ b/apps/solarclock/solar_controller.js @@ -75,6 +75,7 @@ function draw_partial_sun(time, day_info, screen_info,img_info){ ); } } + function draw_random_background(screen_info, img_info, rgb_init, @@ -106,6 +107,13 @@ function draw_random_background(screen_info, screen_info.sun_y - draw_info.offset_y, screen_info.sun_radius+1); } + +/** + * SolarControllerImpl to SolarMode is a Strategy pattern. + * The sun animation is very different through the different + * sectors of the day so the correct strategy is selected + * for the day sector + */ class SolarMode { test(time, day_info, screen_info){ throw "test undefined";} draw(time, day_info, screen_info, img_buffer_info){ @@ -136,10 +144,11 @@ class DayLightMode extends SolarMode { time > day_info.sunrise_date && sun_height >= screen_info.sun_radius * 2 + SUNSET_START_HEIGHT; } + // The corona is larger the closer you are to solar noon _calc_corona_radius(now, day_info){ if(now < day_info.sunset_date && now > day_info.sunrise_date){ - var now_fraction_of_day =DateUtils.now_fraction_of_day(now,day_info); + var now_fraction_of_day = DateUtils.now_fraction_of_day(now,day_info); var sunset_fraction = (day_info.sunset_date.getTime() - day_info.day_start.getTime())/DateUtils.DAY_MILLIS; var now_fraction_from_midday = 1 - Math.abs(now_fraction_of_day-0.5)/(sunset_fraction-0.5); @@ -227,18 +236,25 @@ class SolarControllerImpl { toString(){ return "SolarControllerImpl"; } + // The mode method is responsible for selecting the + // correct mode to the time given. mode(time, day_info, screen_info){ + // first we test the last selection + // to see if its still valid if(this.last != null){ if(this.last.test(time,day_info,screen_info)){ return this.last; } } + // next we step through the different modes and test then + // one by one. for(var i=0; i{ var sod_julian = _start_of_julian_day(now); diff --git a/apps/solarclock/solar_graphic_utils.js b/apps/solarclock/solar_graphic_utils.js index e2327df97..28bfc3ad7 100644 --- a/apps/solarclock/solar_graphic_utils.js +++ b/apps/solarclock/solar_graphic_utils.js @@ -31,7 +31,7 @@ const GraphicUtils = { draw_info.buff.reset(); draw_info.buff.setColor(line_colour[0],line_colour[1],line_colour[2]); - first = true; + var first = true; for(var x=from_x; x Date: Thu, 29 Jul 2021 12:43:29 +0100 Subject: [PATCH 134/163] Solar Clock: added GPS reset instructions --- apps/solarclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/solarclock/README.md b/apps/solarclock/README.md index e661b47c5..3fa25decc 100644 --- a/apps/solarclock/README.md +++ b/apps/solarclock/README.md @@ -72,7 +72,7 @@ Button 4 (left side of screen) will move the sun backwards in time and button 5 ### Button 1 A short press of Button 1 by itself will change the time offset back to 0, making the sun go back to its current position -A long press of Button 1 will request a GPS update to your current position +A long press (3 seconds+) of Button 1 will request a GPS update to your current position ## Further Details For further details of design and working please visit [The Project Page]( https://adrianwkirk.notion.site/Solar-Clock-a2b6268075a6481686b86ecc2094dc14) From 7ba2cb6a4d76982625d605495e400553eb09eb83 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 4 Aug 2021 00:10:02 +0100 Subject: [PATCH 135/163] Solar Clock: Sun sometimes not getting cleared at steapest part of slope. Change large sun movements detections to be in x and y directions --- apps/solarclock/solar_clock.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 5772b59b5..24244cfc6 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -53,7 +53,6 @@ const HORIZON_COLOUR = Colors.GREY; const SolarController = require("solar_controller.js"); var controller = new SolarController(); var curr_mode = null; -var last_sun_draw_time = null; var draw_full_cosine = true; // The draw sun function is responsible for @@ -64,19 +63,20 @@ function draw_sun(now, day_info) { var now_fraction = (now.getTime() - day_info.day_start.getTime())/DateUtils.DAY_MILLIS; var now_x = now_fraction * screen_info.screen_width; if(screen_info.sun_x != null && Math.abs(now_x- screen_info.sun_x) < 1){ - console.log("no sun movement"); + console.log("no sun movement now_x:" + now_x + " screen sun_x:" + screen_info.sun_x); return false; } // now calculate thew new sun coordinates var now_radians = Math2.TWO_PI *(now_x - screen_info.screen_centre_x)/screen_info.screen_width; var now_y = screen_info.screen_centre_y - (screen_info.screen_height * Math.cos(now_radians) / 2); - if(Math.abs(now_x - screen_info.sun_x) > 5){ + if(screen_info.sun_x != null && Math.abs(now_x - screen_info.sun_x) > 5.0){ + clear_sun(); + } else if(screen_info.sun_y != null && Math.abs(now_y - screen_info.sun_y) > 5.0){ clear_sun(); } // update the screen info with the new sun info screen_info.sun_x = now_x; screen_info.sun_y = now_y; - last_sun_draw_time = now; if(draw_full_cosine){ //console.log("drawing full cosine"); From 91a957adeb8e8ab9fbd1b72430876c06de5d5bc7 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Thu, 5 Aug 2021 20:36:58 +0100 Subject: [PATCH 136/163] Solar Clock: BUGFIX:Sun sometimes disappearing from view completely until button1 is pressed. --- apps/solarclock/solar_clock.js | 2 +- apps/solarclock/solar_controller.js | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/apps/solarclock/solar_clock.js b/apps/solarclock/solar_clock.js index 24244cfc6..924090f6e 100644 --- a/apps/solarclock/solar_clock.js +++ b/apps/solarclock/solar_clock.js @@ -350,7 +350,7 @@ location.addUpdateListener( // The function also has to detect when the end of the solar // day has been reached and flip the day over. function dayInfo(now) { - if (day_info == null || now > day_info.day_end) { + if (day_info == null || now > day_info.day_end || now < day_info.day_start) { var coords = location.getCoordinates(); if(coords != null) { day_info = DateUtils.sunrise_sunset(now, coords[0], coords[1], location.getUTCOffset()); diff --git a/apps/solarclock/solar_controller.js b/apps/solarclock/solar_controller.js index 5908b82ef..dd26d89e3 100644 --- a/apps/solarclock/solar_controller.js +++ b/apps/solarclock/solar_controller.js @@ -121,7 +121,6 @@ class SolarMode { } } class NightMode extends SolarMode { - toString(){return "NightMode";} test(time, day_info, screen_info, img_info) { return (time < day_info.sunrise_date || time > day_info.sunset_date); } @@ -130,9 +129,6 @@ class NightMode extends SolarMode { } } class DayLightMode extends SolarMode { - toString(){ - return "DayLightMode"; - } test(time, day_info, screen_info){ var sun_height = screen_info.sunrise_y - screen_info.sun_y; /*console.log("DayLightMode " + @@ -190,9 +186,6 @@ class DayLightMode extends SolarMode { } } class TwiLightMode extends SolarMode { - toString(){ - return "TwilightMode"; - } test(time, day_info, screen_info){ if(screen_info.sunrise_y == null) { console.log("warning no sunrise_defined"); @@ -233,9 +226,6 @@ class SolarControllerImpl { this.default_mode = new NightMode(); this.last = null; } - toString(){ - return "SolarControllerImpl"; - } // The mode method is responsible for selecting the // correct mode to the time given. mode(time, day_info, screen_info){ From 8bcf8887cc4aa19df8996d195352b7d753ca9f52 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Sun, 8 Aug 2021 16:16:05 +0100 Subject: [PATCH 137/163] Solar Clock: Memory footprint reduction. It appears that each object created is extremely expensive memorywise. Have merged together the night and data strategy which reduces the footprint by 5% --- apps/solarclock/solar_controller.js | 68 ++++++++++------------------- 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/apps/solarclock/solar_controller.js b/apps/solarclock/solar_controller.js index dd26d89e3..5e9a32509 100644 --- a/apps/solarclock/solar_controller.js +++ b/apps/solarclock/solar_controller.js @@ -120,25 +120,9 @@ class SolarMode { throw "sun drawing undefined"; } } -class NightMode extends SolarMode { - test(time, day_info, screen_info, img_info) { - return (time < day_info.sunrise_date || time > day_info.sunset_date); - } - draw(time, day_info, screen_info, img_info){ - draw_night_sun(screen_info.sun_x,screen_info.sun_y,screen_info.sun_radius, img_info); - } -} -class DayLightMode extends SolarMode { +class DayNightMode extends SolarMode { test(time, day_info, screen_info){ - var sun_height = screen_info.sunrise_y - screen_info.sun_y; - /*console.log("DayLightMode " + - "time=" + time.toISOString() + - " sunset_date=" + day_info.sunset_date.toISOString() + - " sunrise_date=" + day_info.sunrise_date.toISOString() - );*/ - return time < day_info.sunset_date && - time > day_info.sunrise_date && - sun_height >= screen_info.sun_radius * 2 + SUNSET_START_HEIGHT; + return true; } // The corona is larger the closer you are to solar noon _calc_corona_radius(now, day_info){ @@ -169,20 +153,24 @@ class DayLightMode extends SolarMode { } } draw(now, day_info, screen_info, img_info){ - var sun_color = daytime_sun_color(now,day_info); - var corona_radius = this._calc_corona_radius(now, day_info); - var draw_info = GraphicUtils.draw_info(img_info); - GraphicUtils.set_color(sun_color,draw_info.buff); - if(corona_radius > screen_info.sun_radius){ - this._drawCorona(corona_radius, - screen_info.sun_x, - screen_info.sun_y, - screen_info.sun_radius, - draw_info); + if(now < day_info.sunrise_date || now > day_info.sunset_date){ + draw_night_sun(screen_info.sun_x,screen_info.sun_y,screen_info.sun_radius, img_info); + } else { + var sun_color = daytime_sun_color(now, day_info); + var corona_radius = this._calc_corona_radius(now, day_info); + var draw_info = GraphicUtils.draw_info(img_info); + GraphicUtils.set_color(sun_color, draw_info.buff); + if (corona_radius > screen_info.sun_radius) { + this._drawCorona(corona_radius, + screen_info.sun_x, + screen_info.sun_y, + screen_info.sun_radius, + draw_info); + } + draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, + screen_info.sun_y - draw_info.offset_y, + screen_info.sun_radius); } - draw_info.buff.fillCircle(screen_info.sun_x - draw_info.offset_x, - screen_info.sun_y - draw_info.offset_y, - screen_info.sun_radius); } } class TwiLightMode extends SolarMode { @@ -222,32 +210,22 @@ class TwiLightMode extends SolarMode { } class SolarControllerImpl { constructor(){ - this.solar_modes = [new TwiLightMode(), new DayLightMode()]; - this.default_mode = new NightMode(); - this.last = null; + this.solar_modes = [new TwiLightMode()]; + this.default_mode = new DayNightMode() } // The mode method is responsible for selecting the // correct mode to the time given. mode(time, day_info, screen_info){ - // first we test the last selection - // to see if its still valid - if(this.last != null){ - if(this.last.test(time,day_info,screen_info)){ - return this.last; - } - } // next we step through the different modes and test then // one by one. for(var i=0; i Date: Tue, 10 Aug 2021 22:26:17 +0200 Subject: [PATCH 138/163] qmsched: Simplify scheduling logic Instead of keeping track when a schedule last fired, just check if the time is in the future. --- apps.json | 2 +- apps/qmsched/ChangeLog | 1 + apps/qmsched/app.js | 43 +++++++++++++++++++----------------------- apps/qmsched/boot.js | 27 +++++++++++--------------- 4 files changed, 32 insertions(+), 41 deletions(-) diff --git a/apps.json b/apps.json index 4ad53b1eb..35d7f2fb3 100644 --- a/apps.json +++ b/apps.json @@ -3245,7 +3245,7 @@ "name": "Quiet Mode Schedule", "shortName":"Quiet Mode", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Automatically turn Quiet Mode on or off at set times", "readme": "README.md", "tags": "tool", diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog index 7f837e50e..9665bdf0d 100644 --- a/apps/qmsched/ChangeLog +++ b/apps/qmsched/ChangeLog @@ -1 +1,2 @@ 0.01: First version +0.02: Simplify scheduling logic diff --git a/apps/qmsched/app.js b/apps/qmsched/app.js index 7761be31c..105e09ea6 100644 --- a/apps/qmsched/app.js +++ b/apps/qmsched/app.js @@ -5,18 +5,25 @@ const modeNames = ["Off", "Alarms", "Silent"]; let scheds = require("Storage").readJSON("qmsched.json", 1); /*scheds = [ { hr : 6.5, // hours + minutes/60 - last : 0, // last day of the month we fired on - so we don't switch twice in one day! mode : 1, // quiet mode (0/1/2) } ];*/ if (!scheds) { // set default schedule on first load of app scheds = [ - {"hr": 8, "mode": 0, "last": 25}, - {"hr": 22, "mode": 1, "last": 25}, + {"hr": 8, "mode": 0}, + {"hr": 22, "mode": 1}, ]; require("Storage").writeJSON("qmsched.json", scheds); } +if (scheds.length && scheds.some(s => "last" in s)) { + // cleanup: remove "last" values (used by old versions) + scheds = scheds.map(s => { + delete s.last; + return s; + }); + require("Storage").writeJSON("qmsched.json", scheds); +} function formatTime(t) { const hrs = 0|t; @@ -24,11 +31,6 @@ function formatTime(t) { return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2); } -function getCurrentHr() { - const time = new Date(); - return time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600); -} - function showMainMenu() { const menu = { "": {"title": "Quiet Mode"}, @@ -36,8 +38,8 @@ function showMainMenu() { value: (require("Storage").readJSON("setting.json", 1) || {}).quiet|0, format: v => modeNames[v], onchange: function(v) { - if (v<0) v = 2; - if (v>2) v = 0; + if (v<0) {v = 2;} + if (v>2) {v = 0;} require("qmsched").setMode(v); this.value = v; }, @@ -71,8 +73,8 @@ function showEditMenu(index) { "Hours": { value: hrs, onchange: function(v) { - if (v<0) v = 23; - if (v>23) v = 0; + if (v<0) {v = 23;} + if (v>23) {v = 0;} hrs = v; this.value = v; }, // no arrow fn -> preserve 'this' @@ -80,8 +82,8 @@ function showEditMenu(index) { "Minutes": { value: mins, onchange: function(v) { - if (v<0) v = 59; - if (v>59) v = 0; + if (v<0) {v = 59;} + if (v>59) {v = 0;} mins = v; this.value = v; }, // no arrow fn -> preserve 'this' @@ -90,24 +92,17 @@ function showEditMenu(index) { value: mode, format: v => modeNames[v], onchange: function(v) { - if (v<0) v = 2; - if (v>2) v = 0; + if (v<0) {v = 2;} + if (v>2) {v = 0;} mode = v; this.value = v; }, // no arrow fn -> preserve 'this' }, }; function getSched() { - const hr = hrs+(mins/60); - let day = 0; - // If schedule is for tomorrow not today (eg, in the past), set day - if (hr Save"] = function() { diff --git a/apps/qmsched/boot.js b/apps/qmsched/boot.js index 3c53ef3f7..2712cab30 100644 --- a/apps/qmsched/boot.js +++ b/apps/qmsched/boot.js @@ -1,24 +1,19 @@ // apply Quiet Mode schedules (function qm() { let scheds = require("Storage").readJSON("qmsched.json", 1) || []; - if (!scheds.length) return; - let next,idx; - scheds.forEach(function(s, i) { - if (!next || (s.hr+s.last*24)<(next.hr+next.last*24)) { - next = s; - idx = i; - } - }); + if (!scheds.length) { return;} const now = new Date(), - hr = now.getHours()+(now.getMinutes()/60)+(now.getSeconds()/3600); - let t = 3600000*(next.hr-hr); - if (next.last===now.getDate()) t += 86400000; + hr = now.getHours()+(now.getMinutes()/60)+(now.getSeconds()/3600); // current (decimal) hour + scheds.sort((a, b) => a.hr-b.hr); + const tday = scheds.filter(s => s.hr>hr), // scheduled for today + tmor = scheds.filter(s => s.hr<=hr); // scheduled for tomorrow + const next = tday.length ? tday[0] : tmor[0], + mode = next.mode; + let t = 3600000*(next.hr-hr); // timeout in milliseconds + if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day /* update quiet mode at the correct time. */ - setTimeout(function() { - let scheds = require("Storage").readJSON("qmsched.json", 1) || []; - require("qmsched").setMode(scheds[idx].mode); - scheds[idx].last = (new Date()).getDate(); - require("Storage").writeJSON("qmsched.json", scheds); + setTimeout(() => { + require("qmsched").setMode(mode); qm(); // schedule next update }, t); })(); From 7487ea5e081a92f0d38a4b52adda3e40c4709eb0 Mon Sep 17 00:00:00 2001 From: adrian w kirk Date: Wed, 11 Aug 2021 00:22:52 +0100 Subject: [PATCH 139/163] Solar clock: updating the version no and change log for next release --- apps.json | 2 +- apps/solarclock/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 4ad53b1eb..87c7a87b0 100644 --- a/apps.json +++ b/apps.json @@ -281,7 +281,7 @@ { "id": "solarclock", "name": "Solar Clock", "icon": "solar_clock.png", - "version":"0.01", + "version":"0.02", "description": "Using your current or chosen location the solar watch face shows the Sun's sky position, time and date. Also allows you to wind backwards and forwards in time to see the sun's position", "tags": "clock", "type":"clock", diff --git a/apps/solarclock/ChangeLog b/apps/solarclock/ChangeLog index d53df991b..983875aab 100644 --- a/apps/solarclock/ChangeLog +++ b/apps/solarclock/ChangeLog @@ -1 +1,2 @@ 0.01: Initial Release +0.02: Bug fixes From b21d432cce0c7dc3d62ad82bd31ad974e2b21cf5 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 11 Aug 2021 01:10:03 +0200 Subject: [PATCH 140/163] qmsched: add widget --- apps.json | 7 +++-- apps/qmsched/ChangeLog | 3 +- apps/qmsched/README.md | 8 ++++-- apps/qmsched/lib.js | 1 + apps/qmsched/screenshot_widget_alarms.png | Bin 0 -> 3965 bytes apps/qmsched/screenshot_widget_silent.png | Bin 0 -> 3890 bytes apps/qmsched/widget.js | 32 ++++++++++++++++++++++ 7 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 apps/qmsched/screenshot_widget_alarms.png create mode 100644 apps/qmsched/screenshot_widget_silent.png create mode 100644 apps/qmsched/widget.js diff --git a/apps.json b/apps.json index 35d7f2fb3..b0e7eb71d 100644 --- a/apps.json +++ b/apps.json @@ -3242,18 +3242,19 @@ ] }, { "id": "qmsched", - "name": "Quiet Mode Schedule", + "name": "Quiet Mode Schedule and Widget", "shortName":"Quiet Mode", "icon": "app.png", "version":"0.02", "description": "Automatically turn Quiet Mode on or off at set times", "readme": "README.md", - "tags": "tool", + "tags": "tool,widget", "storage": [ {"name":"qmsched","url":"lib.js"}, {"name":"qmsched.app.js","url":"app.js"}, {"name":"qmsched.boot.js","url":"boot.js"}, - {"name":"qmsched.img","url":"icon.js","evaluate":true} + {"name":"qmsched.img","url":"icon.js","evaluate":true}, + {"name":"qmsched.wid.js","url":"widget.js"} ], "data": [ {"name":"qmsched.json"} diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog index 9665bdf0d..8bae1dba0 100644 --- a/apps/qmsched/ChangeLog +++ b/apps/qmsched/ChangeLog @@ -1,2 +1,3 @@ 0.01: First version -0.02: Simplify scheduling logic +0.02: Add widget + diff --git a/apps/qmsched/README.md b/apps/qmsched/README.md index 1ccddbf8c..033014789 100644 --- a/apps/qmsched/README.md +++ b/apps/qmsched/README.md @@ -1,5 +1,9 @@ -# Quiet Mode Schedule +# Quiet Mode Schedule and Widget -Automatically turn Quiet Mode on or off at set times. +Automatically turn Quiet Mode on or off at set times, and display a widget when enabled. +### Edit Schedule: ![Main menu](screenshot_main.png) ![Edit Schedule menu](screenshot_edit.png) + +### Widget: +![Widget, quiet mode: silent](screenshot_widget_silent.png) ![Widget, quiet mode: alarms](screenshot_widget_alarms.png) diff --git a/apps/qmsched/lib.js b/apps/qmsched/lib.js index 6cdf4f181..a3d36ed34 100644 --- a/apps/qmsched/lib.js +++ b/apps/qmsched/lib.js @@ -14,4 +14,5 @@ exports.setMode = function(mode) { if (s.brightness && s.brightness!=1) Bangle.setLCDBrightness(s.brightness); } if (mode && s.qmTimeout) Bangle.setLCDTimeout(s.qmTimeout); + if (typeof (WIDGETS)!=="undefined" && "qmsched" in WIDGETS) {WIDGETS["qmsched"].draw();} }; \ No newline at end of file diff --git a/apps/qmsched/screenshot_widget_alarms.png b/apps/qmsched/screenshot_widget_alarms.png new file mode 100644 index 0000000000000000000000000000000000000000..52dbe246463d0e7d9567d37683f8ecd9535f5414 GIT binary patch literal 3965 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 E52Ui~sQ>@~ literal 0 HcmV?d00001 diff --git a/apps/qmsched/screenshot_widget_silent.png b/apps/qmsched/screenshot_widget_silent.png new file mode 100644 index 0000000000000000000000000000000000000000..38b133650f7f83ee1ca429652f9177f95af5159d GIT binary patch literal 3890 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 {return;} // no alarms + // alarms still on: draw alarm icon in bottom-right corner + x = this.x+18;y = this.y+17; // center of alarm + g.setColor(1, 1, 0) + .fillCircle(x, y, 3) // alarm body + .fillRect(x-5, y+2, x+5, y+3) // bottom ridge + .fillRect(x-1, y-5, x+1, y+5).drawLine(x, y-6, x, y+6) // top+bottom + .drawLine(x+5, y-3, x+3, y-5).drawLine(x-5, y-3, x-3, y-5); // wriggles + }, +}; \ No newline at end of file From 1aeed274c357173c3c8e6d177a40e73815948cdd Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 11 Aug 2021 01:14:44 +0200 Subject: [PATCH 141/163] settings: update Quiet Mode widget (if present) --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index b0e7eb71d..6476f6d47 100644 --- a/apps.json +++ b/apps.json @@ -185,7 +185,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.27", + "version":"0.28", "description": "A menu for setting up Bangle.js", "tags": "tool,system,b2", "readme": "README.md", diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 779a14ebd..5a96451f2 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -30,3 +30,4 @@ 0.25: Move boot.js code into 'boot' app itself 0.26: Use Bangle.softOff if available as this keeps the time 0.27: Add Theme menu +0.28: Update Quiet Mode widget (if present) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index f494a008d..1b1cc5478 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -387,6 +387,7 @@ function showQuietModeMenu() { settings.quiet = v%3; updateSettings(); updateOptions(); + if ("qmsched" in WIDGETS) {WIDGETS["qmsched"].draw();} }, }, "LCD Brightness": { From 642485c0b1dd87612b5a43dfd04a559b5d73240b Mon Sep 17 00:00:00 2001 From: Ivor Hewitt Date: Thu, 12 Aug 2021 09:55:50 +0100 Subject: [PATCH 142/163] Adjust hand lengths to be relative to tick marks --- apps/boldclk/bold_clock.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/boldclk/bold_clock.js b/apps/boldclk/bold_clock.js index 191b6ec4f..4358b2e29 100644 --- a/apps/boldclk/bold_clock.js +++ b/apps/boldclk/bold_clock.js @@ -23,6 +23,10 @@ tick5.fillRect(0,0,tick5.getWidth()-1, tick5.getHeight()-1); let tick1 = Graphics.createArrayBuffer(8,4,1,{msb:true}); tick1.fillRect(0,0,tick1.getWidth()-1, tick1.getHeight()-1); +// Adjust hand lengths to be within 'tick' points +minute_hand.width=radius-tick1.getWidth()-6; +hour_hand.width=radius-tick5.getWidth()-6; + function big_wheel_x(angle){ return clock_center.x + radius * Math.cos(angle*p180); } From 9e5b3fde7511300bc5b8ceb76a2697a3a009b161 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 12 Aug 2021 09:56:18 +0100 Subject: [PATCH 143/163] bump version after merge --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 548b56db8..8d334036d 100644 --- a/apps.json +++ b/apps.json @@ -1944,7 +1944,7 @@ "id": "largeclock", "name": "Large Clock", "icon": "largeclock.png", - "version": "0.08", + "version": "0.09", "description": "A readable and informational digital watch, with date, seconds and moon phase", "readme": "README.md", "tags": "clock", From 7e93e639e5a08b8de5d8a56500c6148bed38df8b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 12 Aug 2021 10:32:17 +0100 Subject: [PATCH 144/163] version for ac1ea15bd38f1a5a0a6c2df22b2bef5ed1500173 --- apps.json | 2 +- apps/boldclk/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 8d334036d..fe0c80019 100644 --- a/apps.json +++ b/apps.json @@ -1159,7 +1159,7 @@ { "id": "boldclk", "name": "Bold Clock", "icon": "bold_clock.png", - "version":"0.04", + "version":"0.05", "description": "Simple, readable and practical clock", "tags": "clock,b2", "type":"clock", diff --git a/apps/boldclk/ChangeLog b/apps/boldclk/ChangeLog index f5d1af878..c7a4ba7b4 100644 --- a/apps/boldclk/ChangeLog +++ b/apps/boldclk/ChangeLog @@ -1,3 +1,4 @@ 0.02: Modified for use with new bootloader and firmware 0.03: Tweak for more efficient rendering, and firmware 2v06 0.04: Work with themes, smaller screens +0.05: Adjust hand lengths to be within 'tick' points From 6afd7ae7f61872c621c848d7802b8be00ed66e70 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 16 Aug 2021 12:27:26 +0100 Subject: [PATCH 145/163] notifyfs 0.10: Ensure dismissing a notification dismissal doesn't enter launcher if in clock mode --- apps.json | 2 +- apps/notifyfs/ChangeLog | 1 + apps/notifyfs/notify.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index fe0c80019..12b09f6d1 100644 --- a/apps.json +++ b/apps.json @@ -107,7 +107,7 @@ "name": "Fullscreen Notifications", "shortName":"Notifications", "icon": "notify.png", - "version":"0.09", + "version":"0.10", "description": "A handler for displaying notifications that displays them fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notifications library.", "tags": "widget", "type": "notify", diff --git a/apps/notifyfs/ChangeLog b/apps/notifyfs/ChangeLog index 18adecb4f..ace651a0d 100644 --- a/apps/notifyfs/ChangeLog +++ b/apps/notifyfs/ChangeLog @@ -7,3 +7,4 @@ 0.07: Support background color 0.08: Don't turn on screen during Quiet Mode 0.09: Add onHide callback +0.10: Ensure dismissing a notification dismissal doesn't enter launcher if in clock mode diff --git a/apps/notifyfs/notify.js b/apps/notifyfs/notify.js index b6b8dc43b..cd8d108d5 100644 --- a/apps/notifyfs/notify.js +++ b/apps/notifyfs/notify.js @@ -127,7 +127,7 @@ exports.hide = function(options) { Bangle.setLCDPower(1); } // hack for E.showMenu/showAlert/showPrompt - can force a redraw by faking next/back - if (Bangle.btnWatches) { + if (!Bangle.CLOCK && Bangle.btnWatches && Bangle.btnWatches.length==3) { global["\xff"].watches[Bangle.btnWatches[0]].callback(); global["\xff"].watches[Bangle.btnWatches[1]].callback(); } From a10427e76bbb16c807330537beda97dd7c884903 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 16 Aug 2021 20:13:34 +0100 Subject: [PATCH 146/163] gpsrec 0.23: Fix issue where tracks wouldn't record when running from OpenStMap if a period hadn't been set up first --- apps.json | 2 +- apps/gpsrec/ChangeLog | 1 + apps/gpsrec/widget.js | 9 +++------ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/apps.json b/apps.json index 12b09f6d1..34e215230 100644 --- a/apps.json +++ b/apps.json @@ -497,7 +497,7 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.22", + "version":"0.23", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index 289fb38d6..8d13df000 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -24,3 +24,4 @@ 0.20: Add documentation to explain time needed for getting a time fix 0.21: Fix issue where a period of 1s recorded every 2s, 5s every 6s, and so on 0.22: Ensure Bangle.setGPSPower uses 'gpsrec' as a tag +0.23: Fix issue where tracks wouldn't record when running from OpenStMap if a period hadn't been set up first diff --git a/apps/gpsrec/widget.js b/apps/gpsrec/widget.js index 3d22373ec..6a47f04c5 100644 --- a/apps/gpsrec/widget.js +++ b/apps/gpsrec/widget.js @@ -4,7 +4,7 @@ var fixToggle = false; // toggles once for each reading var gpsTrack; // file for GPS track var gpsOn = false; - var lastFixTime; + var lastFixTime = Date.now(); // draw your widget function draw() { @@ -26,9 +26,7 @@ fixToggle = !fixToggle; WIDGETS["gpsrec"].draw(); if (hasFix) { - var period = 1000000; - if (lastFixTime!==undefined) - period = fix.time.getTime() - lastFixTime; + var period = fix.time.getTime() - lastFixTime; if (period+500 > settings.period*1000) { // round up lastFixTime = fix.time.getTime(); try { @@ -78,8 +76,7 @@ reload(); Bangle.drawWidgets(); // relayout all widgets },plotTrack:function(m) { // m=instance of openstmap module - settings = require("Storage").readJSON("gpsrec.json",1)||{}; - settings.file |= 0; + // if we're here, settings was already loaded var n = settings.file.toString(36); var f = require("Storage").open(".gpsrc"+n,"r"); var l = f.readLine(f); From 0e5be94ac36292a32864fa5c0ebb7fd11d7e7793 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 18 Aug 2021 09:21:54 +0100 Subject: [PATCH 147/163] pull in app tag changes - https://github.com/espruino/BangleApps/issues/788 --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 8d9a012d6..27f9a7125 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 8d9a012d62d40aae1b2304d0149440fb3c022393 +Subproject commit 27f9a7125146a38c4357d679ec783f6e98a983c6 From d6750129d6e852ac9267c1a9bd5445b7e775aa36 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 18 Aug 2021 11:17:01 +0100 Subject: [PATCH 148/163] welcome 0.11: Fix initial screen fill colour --- apps.json | 2 +- apps/welcome/ChangeLog | 1 + apps/welcome/app.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 34e215230..d41e3e928 100644 --- a/apps.json +++ b/apps.json @@ -118,7 +118,7 @@ { "id": "welcome", "name": "Welcome", "icon": "app.png", - "version":"0.10", + "version":"0.11", "description": "Appears at first boot and explains how to use Bangle.js", "tags": "start,welcome", "allow_emulator":true, diff --git a/apps/welcome/ChangeLog b/apps/welcome/ChangeLog index ce9194c5d..3e70af0ee 100644 --- a/apps/welcome/ChangeLog +++ b/apps/welcome/ChangeLog @@ -12,3 +12,4 @@ More useful app menu BTN2 now goes to menu on release 0.10: Tweaks to reduce memory usage +0.11: Fix initial screen fill colour diff --git a/apps/welcome/app.js b/apps/welcome/app.js index 1b413e080..ebe3e44e0 100644 --- a/apps/welcome/app.js +++ b/apps/welcome/app.js @@ -12,6 +12,7 @@ function animate(seq,period) { function fade(col, callback) { var n = 0; function f() {"ram" + g.setColor(col); for (var i=n;i<240;i+=10) g.drawLine(i,0,0,i).drawLine(i,240,240,i); g.flip(); n++; From 1592bcb1a56d014cc4de6fa5287f6b364987724b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 18 Aug 2021 16:10:04 +0100 Subject: [PATCH 149/163] calculator 0.03 - Support for different screen sizes and touchscreen --- apps.json | 4 +-- apps/calculator/ChangeLog | 1 + apps/calculator/app.js | 72 +++++++++++++++++++++++---------------- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/apps.json b/apps.json index d41e3e928..2b28509cf 100644 --- a/apps.json +++ b/apps.json @@ -1669,9 +1669,9 @@ "name": "Calculator", "shortName":"Calculator", "icon": "calculator.png", - "version":"0.02", + "version":"0.03", "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus.", - "tags": "app,tool", + "tags": "app,tool,b2", "storage": [ {"name":"calculator.app.js","url":"app.js"}, {"name":"calculator.img","url":"calculator-icon.js","evaluate":true} diff --git a/apps/calculator/ChangeLog b/apps/calculator/ChangeLog index 3b9b23270..c711731d7 100644 --- a/apps/calculator/ChangeLog +++ b/apps/calculator/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: fix precision rounding issue + no reset when equals pressed +0.03: Support for different screen sizes and touchscreen diff --git a/apps/calculator/app.js b/apps/calculator/app.js index a736b715d..89520ab94 100644 --- a/apps/calculator/app.js +++ b/apps/calculator/app.js @@ -6,13 +6,11 @@ */ g.clear(); -Graphics.prototype.setFont7x11Numeric7Seg = function() { - this.setFontCustom(atob("ACAB70AYAwBgC94AAAAAAAAAAB7wAAPQhhDCGELwAAAAhDCGEMIXvAAeACAEAIAQPeAA8CEMIYQwhA8AB70IYQwhhCB4AAAIAQAgBAB7wAHvQhhDCGEL3gAPAhDCGEMIXvAAe9CCEEIIQPeAA94EIIQQghA8AB70AYAwBgCAAAAHgQghBCCF7wAHvQhhDCGEIAAAPehBCCEEIAAAAA=="), 46, atob("AgAHBwcHBwcHBwcHAAAAAAAAAAcHBwcHBw=="), 11); -}; +require("Font7x11Numeric7Seg").add(Graphics); var DEFAULT_SELECTION = '5'; -var BOTTOM_MARGIN = 10; var RIGHT_MARGIN = 20; +var RESULT_HEIGHT = 40; var COLORS = { // [normal, selected] DEFAULT: ['#7F8183', '#A6A6A7'], @@ -123,7 +121,7 @@ function drawKey(name, k, selected) { var bMargin = 0; var color = k.color || COLORS.DEFAULT; g.setColor(color[selected ? 1 : 0]); - g.setFont('Vector', 20); + g.setFont('Vector', 20).setFontAlign(0,0); g.fillRect(k.xy[0], k.xy[1], k.xy[2], k.xy[3]); g.setColor(-1); // correct margins to center the texts @@ -141,7 +139,7 @@ function drawKey(name, k, selected) { } else if (name === '%') { rMargin = -3; } - g.drawString(k.val || name, k.xy[0] + RIGHT_MARGIN + rMargin, k.xy[1] + BOTTOM_MARGIN + bMargin); + g.drawString(k.val || name, (k.xy[0] + k.xy[2])/2, (k.xy[1] + k.xy[3])/2); } function getIntWithPrecision(x) { @@ -202,7 +200,7 @@ function displayOutput(num) { var len; var minusMarge = 0; g.setColor(0); - g.fillRect(0, 0, 240, 39); + g.fillRect(0, 0, g.getWidth(), RESULT_HEIGHT-1); g.setColor(-1); if (num === Infinity || num === -Infinity || isNaN(num)) { // handle division by 0 @@ -240,17 +238,12 @@ function displayOutput(num) { num = num.substr(1); } } - - len = (num + '').length; - if (numNumeric < 0 || (numNumeric === 0 && 1/numNumeric === -Infinity)) { - // minus is not available in font 7x11Numeric7Seg, we use Vector - g.setFont('Vector', 20); - g.drawString('-', 220 - (len * 15), 10); - minusMarge = 15; - } + num = num.toString(); + num = num.replace("-","- "); // fix padding for '-' g.setFont('7x11Numeric7Seg', 2); } - g.drawString(num, 220 - (len * 15) + minusMarge, 10); + g.setFontAlign(1,0); + g.drawString(num, g.getWidth()-20, RESULT_HEIGHT/2); } var wasPressedEquals = false; var hasPressedNumber = false; @@ -370,14 +363,6 @@ function buttonPress(val) { } } -for (var k in keys) { - if (keys.hasOwnProperty(k)) { - drawKey(k, keys[k], k == '5'); - } -} -g.setFont('7x11Numeric7Seg', 2.8); -g.drawString('0', 205, 10); - function moveDirection(d) { drawKey(selected, keys[selected]); prevSelected = selected; @@ -385,8 +370,37 @@ function moveDirection(d) { drawKey(selected, keys[selected], true); } -setWatch(_ => moveDirection(0), BTN1, {repeat: true, debounce: 100}); -setWatch(_ => moveDirection(2), BTN3, {repeat: true, debounce: 100}); -setWatch(_ => moveDirection(3), BTN4, {repeat: true, debounce: 100}); -setWatch(_ => moveDirection(1), BTN5, {repeat: true, debounce: 100}); -setWatch(_ => buttonPress(selected), BTN2, {repeat: true, debounce: 100}); +if (global.BTN4) { + setWatch(_ => moveDirection(0), BTN1, {repeat: true, debounce: 100}); + setWatch(_ => moveDirection(2), BTN3, {repeat: true, debounce: 100}); + setWatch(_ => moveDirection(3), BTN4, {repeat: true, debounce: 100}); + setWatch(_ => moveDirection(1), BTN5, {repeat: true, debounce: 100}); + setWatch(_ => buttonPress(selected), BTN2, {repeat: true, debounce: 100}); +} else { // touchscreen? + selected = "NONE"; + Bangle.on('touch',(n,e)=>{ + for (var key in keys) { + var r = keys[key].xy; + if (e.x>=r[0] && e.y>=r[1] && + e.x n*g.getWidth()/240); + } +} +// draw keys +for (var k in keys) { + if (keys.hasOwnProperty(k)) { + drawKey(k, keys[k], k == selected); + } +} +displayOutput(0); From 4e84c7c6d51a4ca6a325dbd2fd71ba2ce4d66277 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Sun, 22 Aug 2021 13:45:00 -0700 Subject: [PATCH 150/163] Create app.js --- apps/carcrazy/app.js | 232 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 apps/carcrazy/app.js diff --git a/apps/carcrazy/app.js b/apps/carcrazy/app.js new file mode 100644 index 000000000..82945011f --- /dev/null +++ b/apps/carcrazy/app.js @@ -0,0 +1,232 @@ +Bangle.setLCDPower(1); +Bangle.setLCDTimeout(0); +var numberofHearts = 3; + +Bangle.setLCDMode("doublebuffered"); + + +//var popUp = require("heatshrink").decompress(atob("isFwMBCJoA==")); + +var backgroundImage = require("heatshrink").decompress(atob("isZxH+woAB6YBBBodXAgYLCCIQUJAgoUOFP4p/FP4p/FP4p/FP4pYA==")); + +var heartImage = require("heatshrink").decompress(atob("hUKxH+ABckAAYIDpFstlIudzpARCtmQyGXz2luYVBkgIBBQXCy4JCCYQKCtgpCE4IJCFQIyFBAwKDBAw/CAogA==")); + +var gameOverImage = require("heatshrink").decompress(atob("kcV4MB+Nj/4AJwATBgfwDAV+AYUP4ADBgP4BAU/AYUHERMP+AiBgP+EQU/4AiBg/4EQX/EQUf8EH8ED/kAAIN/wEfEQ9/FwX+A==")); + +var RedCar = +require("heatshrink").decompress(atob("ol7xH+ABWBqwAqwI5LABKAtIf4AClZASq0rp9zudIDYNIABgSBABd5AAtPEoNPAoUrqxDPlcAkmXy9OIYVsABYSBABWdzwAFIYVzAoMkRSJDCNAJDBkhDiuckFQOevMqklPZBo7DZAUkHagAKIoyKCkl5IwIwBwJDLYYRDrWoMAAgJDCqxDZyxDXzoABIcpAXRRRD/If5D/If5D/If5D9uYASId9OBoIAPpxDvBoRD2AAlOADlPAAckIbJ0QABjeNIf4ACkhDUIgNIUQQEBAAtyIaOXvIAFp4lBp4FBIapFCA4wACyxCRzo2BAAlzEoNzA4ZDVQ4ZDGQyRDHQ4RDgHyQAHIf5DhklIHoRDrudzA4RDNIoRDtFYRD/Iac5rsykgABaANyILQACzudIgTGClcrrowBIZ9ktdkRQhCdRQ8rGAxD/If5D/If4ACzpD/Io5D/IbOI2eIIdowBwJDP1nX1hDtGAJD/Ialkx7eCZdgwDIZ1rIdwwEIf5D/If5DZmU5mRDtGAhDNAAhDrAAhD/IaM5rrLmzpCCIYYwEIZtktdkIcpBCIYgwEIf5DZAARD/If8ylcrpFIIcd5uYpBmRDUAAUyA4JECIb9zEoNdFoZDVnJDkp5DZx+z2YHCIbudAAJDFFYOPIanX65DgIAIACIYWBFYJD/IYSHBx5DQ1idCx5DFAAjITIIjLFFYIvBwJDQLINrtc5IZOWIbq1DIaJXBslkmUHg9IAA1yRCV5AAtPg8rnIrBQ6VkbwcyDQMrAoIAEpxCRpwaGmSwBmUAg4wEIZ1rIYYdBg5DZpBDLGAt6II+BwJ8CIY85mQAFp9OACFPDQ1dIZMrHYJCFLghDHAA4lCAB85DpgwEAARD9rpDHq0rp9zAAcrmTQCIZVkroAQGoNr2YABIY4wCHAlPldWBgMky4ADkhTDIZQAV2fXIZA4JlYABQ4pDCg8HIcePAAJDCFYJDCYAoABZoOBdw0HoFAVoQAdIASKFslkIgSMEIAIACIZBBgIonXZwpDHgBDE/1Wq0rIe8rHYJDFIoRD3IJBD6vRD1AASH/AA5DWoFkAARD9IgIADoA+hrooEGQhDQAAk5IcM5FpJDNkgAGnNAaQjTTC4gACmUklQAEkhDPpFsAAoYCR68yDQ1PzwAFvJD/IbNyuVOAA1WnIAQp4aGuedzpDauWXABFIOgwAKpwdJIghDgpxD/AAVzACRDvADpD/If5D/If5D/If5D/If5D/If5D/If5DGthD/AApD/If8kkhFGuVyIMJCDp4ABIZ5FCRIyKgQgmekgzDIf5DRp1zpzOIZ4I+dZAUqldzvLLQueXuaKiIQ2elYrBAgN5IaSHBRAIADIcOdp8klSSBOgRDNHIQiBpzjDRjDIEvMkEYdzBAIPBIbUAIboiEIaWBq1WYYVyy9yZwTQGAAVOp9OABlzAAdPAAlzzuduYeBGoJCJAAcrYYZFBAAReCADUkRgeezomBaYMrIJpD/Z496YoRFEUoIAaYoQgBEIMkp+BwJCQAARkCRQKJDAD2WEoKEBgBBTZw1zIcNyIYbIRAA1WRQQABEQIAbEAQlBY6hDIAARCcpAiEIbWBlYADpAAcEQhCZAAyrCADI+hAAhCbIc+BqwAawIwS")); + +var OrangeCar = require("heatshrink").decompress(atob("ol7xH+ABXGAFfHHJYAJQFpD/Ia1OgEkpwDBAAUqABYSBABd4AAskEgQFBAgOcQiQXBlQdCGhdyGowAFznGAAnHNQVO4/GRSQSCGIJDPIRhDH4xDD0SHCkhAMCAQ7BIAQbBHaYAKIoyEDKII1C45DJLIRDw0XHIYXGIa5BYZwWiIZKHDIeZFCIf5D/If5D/If5D/If4ADBQgAMIeEkBoQAOlRDvISJDnAAkklQAWDAQbGIcB0JABreNIf5DYIgJFEW4xCRJZYeBznGIagABIQYHDAAQ7SGwQAD44mCp3HBARD64xDDA4ZDbYzRDdPghDs45DQgEkHoRDrE4MkIaCKDIdYyEIf5DRzjeDaAZBaAAOcAAI9B0RmBlQqB0QwDIZvP5/ORQhCcRRAqCGAhD1Q4RD/If5D/ABOiIf6KHIf5DZ63X55DtGAhDN6/X6xDtGAPQIf5DT5/WZdwwB5xDQ54SCIdgwDIf5D/If5DZvHGAgRDrGAhDNAApDqAAhD/IaOc494Icui0RCBIYeiGAZDN5/P5xDkQgRDFGAhD/IbIABuRD/AAZD658qkkAlUqIcdyuUkkkqIaoABvAHBIgRDfFoXGFoZD+45DW6HX6+cIb+czmiIYnOFYJDU6wXB4xDfIAIACIYvQIf5DVCgPX63WZYoAEZCZBEIYnHFYLNCIaSKBvBDoFYKJCIafOIYUklQAFZKecAAsqEoOi5xDCQ6BYBCQVO5zjCAApESkgaGpwqBIwQEBFYRDPCQRD54/HDARDHzlOAAdyuTTHABd4CwIACp3HIZMAHYJCEPQpDHAAjYCTQQAPzgWCAAxDIAAJDXIgRDi5pDHpy0BXokAdoZDK56lBAB4UC64ABIY4wCHAkkkl4BgV4AAZTEIZYAUIZY4LI4IACuQUFITxDD6HQA4TpFIY7NB47vHQj4AE6yKG5w1HIAIACBpBDk6DOHIZn+lTdFIekqpxDFAALeFIeXGII5D/IeHP63X6xD/ABBD/IbIAE45Dh44tJIfHGIb9445FCaCzrGvBDXlVOAAodIISI7HknGAAtyIeQzCIZhTCIad4vEqkgAFp2cACAZGDQZDaIQIAIeZIAIlQdJ0RDkkhD/AAbbEABgcKIcwAcIf5D/If5D/If5D/If5D/If5D/If5D/If5DKI1BDVIQxD8AAMkIc+cAAJBCp0qGYRDPRVBBDAAIyEIf5DRlSbDZwtOuQ+eAAIrCNQIECIZofBRgaJfIQyED43HvBDPPYJDKRC6GD0WcAAUkFQILBIaB9EToRIJRqDIEzgiFBAR0DIZsqPgZDp46FBIZ3OGAMkkkqCogACBQIAFKwIATEQl4aIIJBD4RCJAAZ/EN4olEADCMDZAQlDIJpD/Z47pCZwQACYSgAIzg/CvEqeAPH5xCQRRoAdEoKETIdlyIbQABcgZIDADYiE45BXAAPGIcMqEQnPIbPOEAkqADgiEITIAGEogAYH0BD/ABHH4wAa5wwSA")); + +var PurpleCar = require("heatshrink").decompress(atob("ol74UBitg///BIP/7lVqtUDJUVBwIABq2qABOVCCkolQJC0AwDgWolAQD1EqwBCH0EqCCdKxQuEAAkKwGhCH4Q/CGD7ECDINEAAoQIwBACgQQYwQ+EAAcC1EACAeAlQfDAAheBCG2oCBUCCB8qCCiQBdp3+fxW/CH4Q/CH4QxgQQKwAQD1QQK1QQUmQQKxiH/CBGqCB3/5WACA+j/4Qf14Q/KhWqRI0CCAv+x4QBEYcC1Wo/SpFCBtUlQQBBgISBAAUAgYQB1fVr2qCAP//8qB4WoAwIQB1WVCCEoFwIQCAA36GwMo1AQOlQQM+QQCqWq1YPIAAPqKgYQOqwQOiqpBCBi6DCH4QDYoIOH/gKBCAs/CD2AZoISEBwUAgAQYAYIABgWqfIIQGAAISBAAQHCCDIAICH4Q/CH4Q/CAWoB5UKCB8qCCmK0AxJwQQDgQQKwAQE1Q0ICAuAlQQHlQrBCCdy1EK1QABCAmq0EKgoQBqofBIoIAFWYMqB4QQRuQ5BCAxlBxoQDqyHKyoQUZpLJDCBmq1oQFvRTGAAOlCApFBB4xBFCCdUIY3VBgY=")); + +var LightGreenCar = require("heatshrink").decompress(atob("ol74UBocF///BIP1z9VqtUDJUVBwIABq2qABOVCCkolQJC0AwDgWolAQD1EqwBCH0EqCCdKxQuEAAkKwGhCH4Q/CGD7ECDINEAAoQIwBACgQQYwQ+EAAcC1EACAeAlQfDAAheBCG2oCBUCCB8qCCiQBdp3+fxW/CH4Q/CH4QxgQQKwAQD1QQK1QQUmQQKxiH/CBGqCB3/5WACA+j/4Qf14QxKjGqRI0CCAv+x4QBEYcC1Wo/SpFCBtUlQQBBgISBAAQGBCAOo6te1QQB///lQPC1AGBCAOqyoQQlAuBCAXPAQIAD/Q2BlGoCAgAGCAUqCBnyCAVS1WrB5AAB9RUDCB1WCB0VVIIQMXQYQ/CAbFBBw/8BQIQFn4QewDNBCQgOCgEACDADBAAMC1T5BCAwABCQIACA4QQZABAQ/CH4Q/CH4QC1APKhQQPlQQUxWgGJOCCAcCCBWACAmqGhAQFwEqCA8qFYIQTuWohWqAAIQE1WghUFCANVD4JFBAAqzBlQPCCCNyHIIQGMoONCAdWQ5WVCCjNJZIYQM1WtCAt6KYwAB0oQFIoIPGIIoQTqhDG6oMDA")); + +function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min) + min); //The maximum is exclusive and the minimum is inclusive +} + +function moveEnemyPosition(){ + score += 1; + randomRoadPositionIndicator = getRandomInt(1, 4); + if ((randomRoadPositionIndicator == 1)) { + randomRoadPosition = 85; + }else if((randomRoadPositionIndicator == 2)){ + randomRoadPosition = 120; + }else { + randomRoadPosition = 155; + } +} + +function collision(){ + if(gameStatus == GAMEPLAYING){ + if + ( + (enemyCarFrontY > playerCarFrontY) + && + ( + (enemyCarLeftX > playerCarLeftX && enemyCarLeftX < playerCarRightX) + || + (enemyCarRightX > playerCarLeftX && enemyCarRightX < playerCarRightX) + ) + ){ + // hit + setTimeout(collision, 2500); // wait 2.5 second for the function to actiavte agian. + numberofHearts -= 1; + score -= 1; + Bangle.buzz(); + }else{ + // miss + setTimeout(collision, 1); // try again in 1 milliseconds. + } + } +} + +function storeMyData(data) { + // ensure there are less than 500 elements in the array + while (log.length >= 500) log.shift(); + // append a new item to the array + log.push(data); +} + + +var file = require("Storage").open("CarCrazy.csv","r"); +var currentHighScore = file.readLine(); +if (currentHighScore == undefined) currentHighScore = 0; +var BackgroundStartingPosition = 75; +var carScale = 0.5; +var accel = Bangle.getAccel(); +var playerCarPosition = 120-accel.x*40; +var BackgroundYPosition = BackgroundStartingPosition; +var randomRoadPositionIndicator = getRandomInt(1, 3); +var randomRoadPosition = 120; +var enemyPositonY = 30; +var carWidth = 30; +var carHeight = 60; +var playerCarY = 130; +var enemyCarLeftX; +var enemyCarRightX; +var playerCarLeftX; +var playerCarRightX; +var enemyCarFrontY; +var playerCarFrontY; +var GAMEPLAYING = 1; +var GAMEOVER = 2; +var GAMESTART = 3; +var gameStatus = GAMESTART; +var score = 0; + +moveEnemyPosition(); +collision(); + + +g.setFontAlign(-1,-1); + +function clearHighScore() { + currentHighScore = 0; + file = require("Storage").open("CarCrazy.csv","w"); + file.erase(); +} + +function draw(){ + if(gameStatus == GAMEPLAYING){ + BackgroundYPosition += 10; + accel = Bangle.getAccel(); + playerCarPosition = 120-accel.x*40; + g.flip(); + g.drawImage(backgroundImage,125,BackgroundYPosition, {scale:13,rotate:0}); + g.drawImage(RedCar,playerCarPosition,playerCarY, {scale:carScale,rotate:3.142}); + g.drawImage(OrangeCar,randomRoadPosition,enemyPositonY, {scale:carScale,rotate:0}); + + if(numberofHearts==3){ + g.drawImage(heartImage,10,10, {scale:2,rotate:0}); + g.drawImage(heartImage,10,50, {scale:2,rotate:0}); + g.drawImage(heartImage,10,30, {scale:2,rotate:0}); + }else if(numberofHearts==2){ + g.drawImage(heartImage,10,50, {scale:2,rotate:0}); + g.drawImage(heartImage,10,30, {scale:2,rotate:0}); + }else if(numberofHearts==1){ + g.drawImage(heartImage,10,50, {scale:2,rotate:0}); + }else{ + gameStatus = GAMEOVER; + //clearHighScore(); + if(score >= currentHighScore){ + currentHighScore = score; + file = require("Storage").open("CarCrazy.csv","w"); + file.erase(); + file = require("Storage").open("CarCrazy.csv","w"); + file.write(currentHighScore+"\n"); + } + } + + playerCarFrontY = playerCarY-carHeight/2; + playerCarBackY = playerCarY+carHeight/2; + playerCarLeftX = playerCarPosition-carWidth/2; + playerCarRightX = playerCarPosition+carWidth/2; + + enemyCarFrontY = enemyPositonY+carHeight/2; + enemyCarBackY = enemyPositonY-carHeight/2; + enemyCarLeftX = randomRoadPosition-carWidth/2; + enemyCarRightX = randomRoadPosition+carWidth/2; + + //g.drawRect(playerCarLeftX, playerCarFrontY, playerCarRightX, playerCarBackY); + //g.drawRect(enemyCarLeftX, enemyCarFrontY, enemyCarRightX, enemyCarBackY); + + g.setColor(0,0,0); + g.drawString("Score: "+score,180,5); + g.drawString("High Score: "+currentHighScore,180,15); + + if(BackgroundYPosition > 170){ + BackgroundYPosition = BackgroundStartingPosition; + } + + + }else if(gameStatus == GAMEOVER){ + + BackgroundYPosition += 10; + g.flip(); + g.drawImage(backgroundImage,125,BackgroundYPosition, {scale:13,rotate:0}); + g.drawImage(gameOverImage,125,80, {scale:8,rotate:0}); + if(BackgroundYPosition > 170){ + BackgroundYPosition = BackgroundStartingPosition; + } + g.setColor(255,0,0); + g.setFont("6x8",4); + g.drawString("Game Over",13,17); + g.setFont("6x8",1.5); + g.drawString("Score: "+score,10,75); + g.drawString("High",10,100); + g.drawString("Score: " + currentHighScore,10,110); + g.drawString("Hold Button",10,130); + g.drawString("2 To Play",10,140); + g.drawImage(LightGreenCar,180,115, {scale:0.5,rotate:3}); + g.drawImage(PurpleCar,215,115, {scale:0.5,rotate:3}); + }else if(gameStatus == GAMESTART){ + g.flip(); + g.drawImage(backgroundImage,125,BackgroundYPosition, {scale:13,rotate:0}); + g.setColor(255,0,0); + BackgroundYPosition += 10; + g.setFont("6x8",3); + g.drawImage(gameOverImage,125,80, {scale:8,rotate:0}); + g.drawString("Welcome to",13,11); + g.drawString("Car Crazy",13,31); + g.setFont("6x8",1.8); + g.drawString("High",10,80); + g.drawString("Score: "+currentHighScore,10,90); + g.drawString("Hold Button",10,120); + g.drawString("2 To Start",10,130); + g.drawImage(LightGreenCar,180,115, {scale:0.5,rotate:3}); + g.drawImage(PurpleCar,215,115, {scale:0.5,rotate:3}); + //setTimeout(displayPopup, 3000); + } +} +setInterval(draw ,10); + + +function moveEnemyCar(){ + if(gameStatus == GAMEPLAYING){ + enemyPositonY = enemyPositonY + 10; + if((enemyPositonY > 200)){ + enemyPositonY = 30; + moveEnemyPosition(); + } + } +} +setInterval(moveEnemyCar,10); + +setWatch(() => { + if(gameStatus == GAMESTART){ + gameStatus = GAMEPLAYING; + collision(); + enemyPositonY = 0; + score = 0; + }else if(gameStatus == GAMEOVER){ + gameStatus = GAMEPLAYING; + collision(); + enemyPositonY = 0; + numberofHearts = 3; + score = 0; + } +}, BTN2, {repeat:true}); From 7669df9dcc061482e0d84090917ef685e9b988d8 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Sun, 22 Aug 2021 13:48:28 -0700 Subject: [PATCH 151/163] Create app-icon.js --- apps/carcrazy/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/carcrazy/app-icon.js diff --git a/apps/carcrazy/app-icon.js b/apps/carcrazy/app-icon.js new file mode 100644 index 000000000..b3f122ea8 --- /dev/null +++ b/apps/carcrazy/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4Ay90A8AWT8HuhwXSCQPuAAIXShwWCC6YuDAAQwWGKQWWFwoJDxAAFF5gHChAXODAhHCxGDmYAE3YAC2AwKxAWFC4gABC4YBCIwYXGoNb2tUpYxDRYsIIw0zqoXBqtVDAIXVDAJiEUYYXNqhhDUYgWGC41VSYgXSjYXHAA4XGJAULDQQXQJALFDGBTXFAAuwgQXV3cP+coC6m////nAXYiIAEC5m4FIYXN2gKBpYXFwIXMkIKBiQXSFwQwCC4hIFC42xiMjmURlYXFDAgXImcziMbC4ynKC4uxC5MAAAsBI4cQAoMRC50AKYYdCDYIQHGBASCC6QwCDgwA/AH4AVA==")) From eebb7d65fc84038e205f9076d1361d9d74895691 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Sun, 22 Aug 2021 13:58:11 -0700 Subject: [PATCH 152/163] Update apps.json --- apps.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps.json b/apps.json index 2b28509cf..23620c6b2 100644 --- a/apps.json +++ b/apps.json @@ -3410,5 +3410,17 @@ {"name":"thermomF.app.js","url":"app.js"}, {"name":"thermomF.img","url":"app-icon.js","evaluate":true} ] +}, +{ "id": "carcrazy", + "name": "Car Crazy", + "shortName":"Car Crazy", + "icon": "app.png", + "version":"0.01", + "description": "A simple car game where you try to aviod the other cars by tilting your wrist left and right. Hold down button 2 to start.", + "tags": "game", + "storage": [ + {"name":"carcrazy.app.js","url":"app.js"}, + {"name":"carcrazy.img","url":"app-icon.js","evaluate":true} + ] } ] From a1f7913efe60d8bc922e39be5950f7921bcdec50 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Sun, 22 Aug 2021 14:08:40 -0700 Subject: [PATCH 153/163] Add files via upload --- apps/carcrazy/carcrash.png | Bin 0 -> 1788 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/carcrazy/carcrash.png diff --git a/apps/carcrazy/carcrash.png b/apps/carcrazy/carcrash.png new file mode 100644 index 0000000000000000000000000000000000000000..1678c54c8008bc3fb136aa1c8a6c4469b8ea3b10 GIT binary patch literal 1788 zcmVs(v=njf8tUa)^>SH#6swn3^)jdzC{iyq>P5Ag zw7V5sqH$6mPoaDZ@S^w-@_?TM7UR7-TJDxYQkO*S3`CUxfO;th4g>CaOfRGCl8s!B zHr8B3odAIP_%arMLs&n*F`omcFgS@twQM95OYBi%N&rB8+=p@z7Ch6mA?%d`{t#3mI2y?kc|p9cU1zE1(~;^TE-s}%4f099=GC?J&-;0pl5ZhHa6_)2Q}yyD~R zkehBXWI^8XAW+P%jUPc6`3HHXDt#P&Pj2}a(t-XV*y2@j;M zo;9w>@GxhhHFf8PyTO>Gi%w|#BX-k#kSAA5sega$5oNlZ7 zy_|XF{OtDfhM+$HUE%jAL*}rMmfjvJ&ecUDVT`CxWbJ`I>e{b@U?BRsqN1p1N#$NG zsqE5{%4RLA*apybsQAY>50xa|N{)OlZ0dYXFN&CslqYXA(;FTHVGCuIRg_j8VEAB@ z0&KvNziU~=BjeHJh1ldyN3^7JX&=dSy0N5G&b;#J(}&LoYMSrF_k|)$)_6?Y=>?L4 zp=Y(Y@+bcCocOS%oW0u1$xFBSpy@Vk{@Bhn_o4^J=s&r8(w0FLK5FUZ>xaEjw|Osm zV2r8z9TE7)b^oNgg63nm`#Tog<~>bd<$*?Ara_|9PQ2Y9IAqb%GdRhnGj-FwPvD$0 z$O*TfCUbbVofk5By5Ga*f%r*w;fT@`iO@4J`%8Q)DTg&}4LHJm3yK|c0&lPA;i!A^ zF!&^HkWb(%TLR7I_#9rkbqg++Yoz=r@BH}~08M7}^L)^mOwgG;`4ByY z*uGBd_`Ddgtg*7CA{=i0W9a0R}IDdbdQ`YN&gndd(QiUHPUWm5d;@DMuPaE|M( zZ2%}zf9lAgGJv9;-%x;%!-LPWAQ@f&0000 Date: Sun, 22 Aug 2021 14:09:36 -0700 Subject: [PATCH 154/163] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 23620c6b2..eb78ac3fc 100644 --- a/apps.json +++ b/apps.json @@ -3414,7 +3414,7 @@ { "id": "carcrazy", "name": "Car Crazy", "shortName":"Car Crazy", - "icon": "app.png", + "icon": "carcrash.png", "version":"0.01", "description": "A simple car game where you try to aviod the other cars by tilting your wrist left and right. Hold down button 2 to start.", "tags": "game", From 34b29d50da8f2da98e8d0506f196f6e1ff42c756 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Sun, 22 Aug 2021 14:10:51 -0700 Subject: [PATCH 155/163] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index eb78ac3fc..66d8ec9e9 100644 --- a/apps.json +++ b/apps.json @@ -3416,7 +3416,7 @@ "shortName":"Car Crazy", "icon": "carcrash.png", "version":"0.01", - "description": "A simple car game where you try to aviod the other cars by tilting your wrist left and right. Hold down button 2 to start.", + "description": "A simple car game where you try to avoid the other cars by tilting your wrist left and right. Hold down button 2 to start.", "tags": "game", "storage": [ {"name":"carcrazy.app.js","url":"app.js"}, From eb83ce4fad33412d97b2badc532d57841accc883 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Sun, 22 Aug 2021 14:15:59 -0700 Subject: [PATCH 156/163] Add files via upload --- apps/carcrazy/app.png | Bin 0 -> 1788 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/carcrazy/app.png diff --git a/apps/carcrazy/app.png b/apps/carcrazy/app.png new file mode 100644 index 0000000000000000000000000000000000000000..1678c54c8008bc3fb136aa1c8a6c4469b8ea3b10 GIT binary patch literal 1788 zcmVs(v=njf8tUa)^>SH#6swn3^)jdzC{iyq>P5Ag zw7V5sqH$6mPoaDZ@S^w-@_?TM7UR7-TJDxYQkO*S3`CUxfO;th4g>CaOfRGCl8s!B zHr8B3odAIP_%arMLs&n*F`omcFgS@twQM95OYBi%N&rB8+=p@z7Ch6mA?%d`{t#3mI2y?kc|p9cU1zE1(~;^TE-s}%4f099=GC?J&-;0pl5ZhHa6_)2Q}yyD~R zkehBXWI^8XAW+P%jUPc6`3HHXDt#P&Pj2}a(t-XV*y2@j;M zo;9w>@GxhhHFf8PyTO>Gi%w|#BX-k#kSAA5sega$5oNlZ7 zy_|XF{OtDfhM+$HUE%jAL*}rMmfjvJ&ecUDVT`CxWbJ`I>e{b@U?BRsqN1p1N#$NG zsqE5{%4RLA*apybsQAY>50xa|N{)OlZ0dYXFN&CslqYXA(;FTHVGCuIRg_j8VEAB@ z0&KvNziU~=BjeHJh1ldyN3^7JX&=dSy0N5G&b;#J(}&LoYMSrF_k|)$)_6?Y=>?L4 zp=Y(Y@+bcCocOS%oW0u1$xFBSpy@Vk{@Bhn_o4^J=s&r8(w0FLK5FUZ>xaEjw|Osm zV2r8z9TE7)b^oNgg63nm`#Tog<~>bd<$*?Ara_|9PQ2Y9IAqb%GdRhnGj-FwPvD$0 z$O*TfCUbbVofk5By5Ga*f%r*w;fT@`iO@4J`%8Q)DTg&}4LHJm3yK|c0&lPA;i!A^ zF!&^HkWb(%TLR7I_#9rkbqg++Yoz=r@BH}~08M7}^L)^mOwgG;`4ByY z*uGBd_`Ddgtg*7CA{=i0W9a0R}IDdbdQ`YN&gndd(QiUHPUWm5d;@DMuPaE|M( zZ2%}zf9lAgGJv9;-%x;%!-LPWAQ@f&0000 Date: Mon, 23 Aug 2021 09:41:35 -0700 Subject: [PATCH 157/163] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 66d8ec9e9..8f5f4141c 100644 --- a/apps.json +++ b/apps.json @@ -3418,6 +3418,7 @@ "version":"0.01", "description": "A simple car game where you try to avoid the other cars by tilting your wrist left and right. Hold down button 2 to start.", "tags": "game", + "readme": "README.md", "storage": [ {"name":"carcrazy.app.js","url":"app.js"}, {"name":"carcrazy.img","url":"app-icon.js","evaluate":true} From b9375375ba381cd80788865c92191296f59717cc Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 23 Aug 2021 09:42:38 -0700 Subject: [PATCH 158/163] Delete app.png --- apps/carcrazy/app.png | Bin 1788 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/carcrazy/app.png diff --git a/apps/carcrazy/app.png b/apps/carcrazy/app.png deleted file mode 100644 index 1678c54c8008bc3fb136aa1c8a6c4469b8ea3b10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1788 zcmVs(v=njf8tUa)^>SH#6swn3^)jdzC{iyq>P5Ag zw7V5sqH$6mPoaDZ@S^w-@_?TM7UR7-TJDxYQkO*S3`CUxfO;th4g>CaOfRGCl8s!B zHr8B3odAIP_%arMLs&n*F`omcFgS@twQM95OYBi%N&rB8+=p@z7Ch6mA?%d`{t#3mI2y?kc|p9cU1zE1(~;^TE-s}%4f099=GC?J&-;0pl5ZhHa6_)2Q}yyD~R zkehBXWI^8XAW+P%jUPc6`3HHXDt#P&Pj2}a(t-XV*y2@j;M zo;9w>@GxhhHFf8PyTO>Gi%w|#BX-k#kSAA5sega$5oNlZ7 zy_|XF{OtDfhM+$HUE%jAL*}rMmfjvJ&ecUDVT`CxWbJ`I>e{b@U?BRsqN1p1N#$NG zsqE5{%4RLA*apybsQAY>50xa|N{)OlZ0dYXFN&CslqYXA(;FTHVGCuIRg_j8VEAB@ z0&KvNziU~=BjeHJh1ldyN3^7JX&=dSy0N5G&b;#J(}&LoYMSrF_k|)$)_6?Y=>?L4 zp=Y(Y@+bcCocOS%oW0u1$xFBSpy@Vk{@Bhn_o4^J=s&r8(w0FLK5FUZ>xaEjw|Osm zV2r8z9TE7)b^oNgg63nm`#Tog<~>bd<$*?Ara_|9PQ2Y9IAqb%GdRhnGj-FwPvD$0 z$O*TfCUbbVofk5By5Ga*f%r*w;fT@`iO@4J`%8Q)DTg&}4LHJm3yK|c0&lPA;i!A^ zF!&^HkWb(%TLR7I_#9rkbqg++Yoz=r@BH}~08M7}^L)^mOwgG;`4ByY z*uGBd_`Ddgtg*7CA{=i0W9a0R}IDdbdQ`YN&gndd(QiUHPUWm5d;@DMuPaE|M( zZ2%}zf9lAgGJv9;-%x;%!-LPWAQ@f&0000 Date: Mon, 23 Aug 2021 09:43:24 -0700 Subject: [PATCH 159/163] Create README.md --- apps/carcrazy/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/carcrazy/README.md diff --git a/apps/carcrazy/README.md b/apps/carcrazy/README.md new file mode 100644 index 000000000..1c6e298c1 --- /dev/null +++ b/apps/carcrazy/README.md @@ -0,0 +1 @@ +Test![image (7)](https://user-images.githubusercontent.com/89286474/130485173-03155f4c-cb6e-4b12-9466-16b4310a6476.png) From 2bfce0b08dce7e3846a77417227209daa2b1444d Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 23 Aug 2021 09:45:29 -0700 Subject: [PATCH 160/163] Create ChangeLog --- apps/carcrazy/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/carcrazy/ChangeLog diff --git a/apps/carcrazy/ChangeLog b/apps/carcrazy/ChangeLog new file mode 100644 index 000000000..9a50abf42 --- /dev/null +++ b/apps/carcrazy/ChangeLog @@ -0,0 +1 @@ +0.01: Car Crazy is now avialable for testing in beta! From 47893eda83fa19e09cebd298484f2c8a58f18025 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 23 Aug 2021 10:02:44 -0700 Subject: [PATCH 161/163] Update app.js --- apps/carcrazy/app.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/carcrazy/app.js b/apps/carcrazy/app.js index 82945011f..c7476d18a 100644 --- a/apps/carcrazy/app.js +++ b/apps/carcrazy/app.js @@ -156,7 +156,8 @@ function draw(){ g.setColor(0,0,0); g.drawString("Score: "+score,180,5); - g.drawString("High Score: "+currentHighScore,180,15); + g.drawString("HighScore:",178,15); + g.drawString(currentHighScore,205,25); if(BackgroundYPosition > 170){ BackgroundYPosition = BackgroundStartingPosition; @@ -230,3 +231,10 @@ setWatch(() => { score = 0; } }, BTN2, {repeat:true}); + + + + + + + From 15d34b9f5d7b306a3b44bb6e129b0611f30ca0b5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 23 Aug 2021 10:27:26 -0700 Subject: [PATCH 162/163] Update README.md --- apps/carcrazy/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/carcrazy/README.md b/apps/carcrazy/README.md index 1c6e298c1..774061c58 100644 --- a/apps/carcrazy/README.md +++ b/apps/carcrazy/README.md @@ -1 +1,3 @@ -Test![image (7)](https://user-images.githubusercontent.com/89286474/130485173-03155f4c-cb6e-4b12-9466-16b4310a6476.png) +![Screenshot 2021-08-23 100720](https://user-images.githubusercontent.com/89286474/130490762-24915bfe-5368-4ef8-b164-38a0fcf3b814.png) + +Form Link: https://forms.office.com/r/HnwYzG9Sk7 From 35b334f8321d59e18c340e131dafe79f511d3c11 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 23 Aug 2021 11:30:50 -0700 Subject: [PATCH 163/163] Update README.md --- apps/carcrazy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/carcrazy/README.md b/apps/carcrazy/README.md index 774061c58..6eef6f8c7 100644 --- a/apps/carcrazy/README.md +++ b/apps/carcrazy/README.md @@ -1,3 +1,3 @@ -![Screenshot 2021-08-23 100720](https://user-images.githubusercontent.com/89286474/130490762-24915bfe-5368-4ef8-b164-38a0fcf3b814.png) +![Screenshot 2021-08-23 100720](https://user-images.githubusercontent.com/89286474/130498574-0b5246cb-8553-455c-b6c0-096e5ca1644c.png) Form Link: https://forms.office.com/r/HnwYzG9Sk7