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 01/97] 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 02/97] 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 03/97] 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 04/97] 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 05/97] 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 zw}9X6?+!QAU!*IMT~uT?{!ysQ`&1_=fT1j3RKe+mbIpumq%5ZZO%KX0;o zz90}KNaCrGl8esjlye;6{8;POjD1yU6bcmTPD|phTBru%BcUQ%g;23g(TL&`5<&@L z=(Lrdwy*|a-H(BWptP_CpuFpIR&U?it{-_or_dZz&S&4v!7+2vv0|4}=dnH}xM$RT zC*$3zgNL1FeBqjs`k3g00nyJD;gyy&mEomD1~SyQ=f5OekFca<6g%8%vZvv~xQFR^ z*9QbaqrCVB7k8979^Mus&J-;j_?jhLIq&rpv-z;N2BW@;?Yz<|LnEfEJ~BiQGqOj zeVBqnvmdq`2y~YYsxlaVj5v&eoV(JNV@H3E$iXtV@TYd@xLvdi2|Da{TN(*&j`s~{~ zJ#>0fODA_(r?fyx`zC%5jmUCpc%BR=v1WK``DZ@<^C=hzfrhE(c{s<8OjsB!G(eEA zXe=f8X=3{9*=sP}^U8b88tsr~t~U5zO<^q1$6>2Cq76F-3yh13T6P)V)0|-XY?F7X zJd<5WJzW%3h8s!p(xd-j`+p2|ilHR_1Lby?yiVI4f#J%|8HXV;xfw{>$-VgYX_qVm z>zE2pUfeGs|FMiu4`impamUD+%EKnm;-e#zw$7-Ex|uEkPB{ySW_NlyTuf5vT*A7a zLF`QgT3e`4l09ZrCtDHg`}800!ziO5qL@k~e5xfWmBTBi^}3*>hwc>02|WBiH+FLa z{Qs{xac~hOQO|n%F&8|R4V$J}L9(tt)LK@{BNE)yX-fY<)jwwqh(lg)>56w-T1C;> zU7LcW4XjETc5zCK=@5$D`M+oaL#deM>Ga)A)_L~bpUrlie>T1B$8|Ogs_Xwn0@|^# zUce8>#?nT*U0slahugc%#1&1n1>7r8|NB##Btnz3#QxjH2JhLRHMrMwkFe}V3a{}3 z13?ehaj(spf8~M`wuY)3=fX&5BPI7LsGs;BTsJ~*n) zRAZN@A^H!Xz)*g|fR1ICu8pJv(gqd5O2C3i6XHz2jeniRa+WPJ=cb?Zh;#|3)?ll819&k#l2Jr?O3{4h7a~ydTLVm@fk>{%;6?5Cj;X z*1&E{NhD`RCFi&pU~A7;#OR-AeZG0P`}qVU&3B-g~a zBre#GhyPb_z?n7^emGj40moG&x6D_QMPwFvaOp{6(%k;b@`Ji*N?ZNIZh0$yPjk;s zOJ}y0FloB-y*;QdvxbYK`H(_N?YTAz$C@-i{2c0Ks&xvK%71+dc7oDL(8X6bQbGjs zIBhz8_w>JvhGaxkbCzr?oN0q@klz^~MYWEIT2YE8_&XMNaYqX?i04f=XAhdD!M(QK z)9~Z+!>8Yw|2jqu1I|&=kL1dO925{6$iepM;LHDnmJcd~*i2`^|Ev~GL-Hdz+$<_=!30_?u;v)8UiSHYw zDfo{y8+JPGhKfS}g1ikJIgT3`3Yw%}VyDN<{5#Axh4n-MR?W}EuMZHt@%QucNE0jI z_t}}$WXz!ve;a`mQH_V`vrkL5D8v8uFG%_LLMUj6K*6+Y^Ln;X|8*<~GL6P8;em-{ zzg-^8y%q4{uk&@ItJU#uL6MRYMalQxy!iX|_Ylf~D6sU*Y#kArn}1pN5&gTnr67jz zs5vcDg1_IcgMM5CdZ!~o{r`B9QNA65YS{no! z(IvqWiA72=wDHUmrJRFul7A%MFX)jFN*9id=THa(&e;gXQAp6BWhxhm{TF+)81tz3 zt@zBJynB&%TlV|6S7dw5b&Z$av{+_xvCu|lP;jFj|Cxv**`R75nM4wvENx$wtvr6w{GA6tmJFaPFucj<&1BvRJ%Sd&Nyl0=c_8AiVg|! zIReVN2x9T$;HI%OLRIM@*{)b|Nq#U+8pXY?lb_IJ-ns$;bG)>VjD%O^7oryP9VoYs zj2<^24fc)Wl(ZskrJ2`A43%P6&WS4eJ^O%l_`|A$rF$rmSjgQ!4J8H`%Em|}3oTQX zvQgs68+Q?Jo@3K};5oP%plHQ@=Q^C3tu0dP%~hboYyb~Ija8I_U~W*0_^5K7s#bAE zW9?1y{gNUL*ObmrAK-=^<0-See?SC63qVAE?yVXW&agR`c*1S6Maxm4S|Ac3@oe28 zs|>!O$~Ka@|7MOFyp#ZT{lgFVfFDR%5V&aXU>+IdJadeWQ!5+k?vqUq6Gjyv7+i=L;-QN(h{PSTsvH})ExMC<&O z9d800U}M7&^%AxW#nWA>Rc`O)R^3C^xM)<9>Q2-F=K z0KwgqpllS0B|CVt&bRc8QNLVH;v?=}2N$YI&(V>1w$LMzx0siPM2G{g3iv*1%G(dA z5)LBFtx;_x`R+w*8f1`=dZz5|nB-~5F7|)=m^pyA9&z0a5<(3{ofhXE?C0@cXPyo9bbDJ#9@0;|*q;C2*weD>7TSnWC;OJm1mfrh%6(z@n03b@( z`f$Y?06?s-?G&=k>|67%Z)BWOr#cOyu<5MoUl;zP-#A+Y!US0h1p2`ap%!^jnhX>A zxlxtj-n;wmcq;63qEgW;$K6joE^Q1neQ|+Tpi>Lsh-bjQ*?KGHa!t|a8cq|NGSj@s z>)1B<9P&K_gnLJT|i1B5yD+;lyp~81K4PO7X%Y z|LCA0G6A>Hw6wIKJ)+W+a{Su3v6y}nTk>`y86(qMLz>4JVS)ckhUfG_D`o|MzK%6y!E(U5n}y%9 zCK%_6HC^teHFLb>yf7E#GK3lQ)(f?_sSZ-5)y^b;yv%1{H@sETR2O-eSH_R!QWX5T z(f#dqG@SCXIRWEDQ3E}-Uw2rm^co;zyJ}kpKiYa~3M?DMnr{D%$x5iU38F%wD9~HT=D_cDy0&MkTsbACPoTBOg zin3uezZQCgYHW9=Xqv^N6`#QxKFEyJmgl|F>K35YOWXV%f;(VM#yt4~cWL>8dbSse z+|erc?z=7RlI(PnN3@Az{Gpfexn3L?7=bacZ{{Ztm&dy0mR}3#EZCm)VtJFsOH_-u z$UGUjjde92g{q!&uCds>5Mh9IUz??1pOo<=wV~BbGvYyQU*u6@-O{W?t5m60;T7g_ zY=nJKeDL+t0>sfqF&I_SWCU9C6f&%TC3!>rtc+wLy}ks(aw-BYNg4+Vu!~R}9@lj( z%B>pjaGj0Aus737GHuX$vi6cnXQ1p?0TXwb@81!Dn>svP^z4|;Y@Of4lUyYB{dL3DXkg)=PDIW9Y0pesD zHod*b+s>6r-I(CW);Z{oR@ zCvV3Dzo)o5e?Jp&dlVhhU`N9|BD0-cR8-f`@IsIL&EDy7M$&TV*H;v$6MqOmT%O+t zmJB#%Ffil^+Oae;Mgj}N!2NYt8Rmhix7C{>jKbnaGDWRPEG;f~DXY;gRRiubHBe@2 za^W)^asKrZ;iA>Y>P3lOA1F?r#pU$~IQ(i|bNiW0=GiUmashv!abCp=T-$ut5VdHZ zxXol2S{;6nTW{8QYahRL`+SFiBfCzi4HKNSfpnTKZX{FX3AZz9SuyDL0(YAF)IBL}W zl#to-#-F`nM&Qa0V>iP?5kKAH9GQE0DBx)*z+I;E(5*?=t%_cq9Y!fDDT%*SPrlyF^9i>ORYzqLg(4j z3VO?7%PVr>seWp}&;siQGKt8h#^H@{jvu)z)7vzWRl?%0k>1d%(YZl}rUHWl22l0Y zfXc@kaPDzAZJ9Y_>p5BN%5#=gkCG_mMGeP6d|O15mqUhM_k;-h7;bEu=ao~N0K6X1 zN@+PmEnXR5DEH2>a+&{(=5tg)hcw}g%Kj)`$zpFL3M0L`5s(xB^iFH=hS2{_25hF8 z$;vwflXC;8aB^j5cRzMGu1>9GsO%!!kjbJ~SU{CT$U)Mh*>$^4~6q8-6c#s8?%$GV6^p ztdf+iqTe0!JY@Edi6>GKP%p&}kGTl41@ZLQ@*J=3dRq}AWCvZow|Rupyz^;-Z;<=O zpVRAuSHSgd6)=nWDVS^NJI}J?EI*?P(XrPe2u#Mrv1gYTQG)W_=xPA7DGN}kbIeo8 zN*|W!pN+8%4uw(WkB7$E{C!Fw<&C7d!A2)4L0p?$*dMO4(6{G44lTiVDNlMOP#5o2vSiFl8q)QxE!y4)}DBOcG4@e$NBDzo5WsmiJeOC2K& z!@^;EIsUz_M%FrlNWPXSlzY+)c6>%Ier|aps-aa1RW>$POZPT=K5G7A_96e@(Sih7RXF)X)*kNys$H?2qRg2eh6-x!JBU3KC&cl)I5C52TAUyx;&f@#d&zk(;BUzd=sf%8*N%C5$lY3 zZdfVU8f{9P%WPHLDWNY=Fc*m_W|F%0c#B!*)-}tjwV_AnM4{qyzdJVNl98IuS&v2f zxCj%dYx~`_n}61kId8}wagAt~%DStTzk zHo405Co7O}+`A*Ih)GcP=X{P%@4y0{@wOS{3~3(sXL z0)lvVn^PuYq_X8#+@yOS${Y|+rG*^*qHSGyy-=HzwJNf(u#!ghI3nuc3!0!N{^%|1 zlKNv-cp)R~5Aqw71Oyeu)i5w3QUN-*)+Qg3sACadW+2Yd)sy+qJ-#=6cZubbm5O0% zdeFQ_;xzA_9G-0Gf!iak5E(nraNOvDg@CEKwS9-;wB4 zr=7I@b?T~gD)*hOBtLRK-F`P?GrN+oHN(%^^vayhC7euGQ+k_o4zs65HxUYKJ<&&D z+TfCmfA3MG+nfF9S3|i&SHZ%2X|B_lUF4MPno)P%sL0~%0o>wM9anZk8FT!S zeil~9fDSs!A3|6FA#1;Cw3Au-HuV=)YMWC5a9fQ?IyMn7SWmPV zG?P&cpNVoF?$(!!ejd`V4Edwlhfo4M3wmN#{8W>UON-ilJ{f*9wa3Zo@em;ackQyZ z>QYMR8*JGzr$~#YyYS)t4|zOT(WiUAY&Gg@)JfPQ@h%7eM#%uc`vp5A@p1)W1WRw( zy=?PXqT}E~Olpa2zv>u@{EU>v)J|OE;$*L%PilW6xoHV`6(h}Ged>DFe#z)8bgBS3)v%+FtOQv1M%}a@+V(M~opUQ4+_y)3>na+wY0uTm7{x1UaI4VZJY^pB zJkUC6=s;a=Z`})j&hyxqivN-dU^wTgj;&c<;aE(r2mtZD;|FjfTPBXkf<_3Tx|v{3 zsLs*h?4hXLoX0wLnW|jG^Nz{f);6YuHtF{=)eLK9^WL{8^Sx+p=K3fle=3>ZjvJOLV0d z8gRsydI2fbIBfmLGXifFozDCh($N=7kohmP2Y*aY9Lq!uFOnJ_VMVjM-qmx|zaKiy z;+dE{ED?U^((Fh9-~wOoqVXgg!vjcMxNF&lLU$#$k#Ug4Uj167$7-lXb-v|PH|pZx z>cED=LIXY~_wa&Vkd}Zzs~&o;A=<`aHkI569qQ=F zI(9Cewr}ysoqajg{aCh5=9F!OMQPOzdG@5%G>ZIGp`VwN@9E+3dc;==(87i(#^oX( zoCW}xNUv;mX>`O?+CE!C-nDA)kv2TWd^5zn`MB9gJhx~hgY_$m{iTS;H%4cb%e9rA zFPp@(&MT#wn#-Ms03YD;M7!Zy!19@UDOBwAiSr%4;F4X;aRK@9r$!%NrYWzvHVA6j zCXRFJF1t?NNAbv6gp)nky~P+qnq9ScRobS#0UWrDMm(xtrPQv?GU53$N}FKxA(gtz zq{(KYwqr-4@zb)CGs{}>sxur$-_Rl@&nE@|<0)u#L40(t)}auenogWN#v!<11Vz(u ziTpj*)a+yp4x7_n>BdktT_8Jic7m?wXVX&ex;wb$OUK?PJo zdXMO(RWFDSwg#YdaGI$`^>Z+1Wi#foEz+KUo#Gv1jFoBn^+++)!exRO^XlCCp0)N) z_3)3GAEbu%r!*Z$3i!n7?zyxmKDY#yk1=pU{tSovVJrjIPFinin-ZxEf&PFmetvCc zyY%kKQA@3Pp9F%5kF4c%esh8IdyTjF;bXF;YZ3PD@wOupgk9I*Y=%@9TO?=)Kq`gA z9&%`vuAiE*=sjH5AL0+K&dhPY)AqxAt-#4l@F>9`ROH|gUbOZ=m?gmj_nB{krni-& zb+YT35WG;Ri};V#Fc<@H(wAn1DnZu3rsm^(MQ87j){|=wCw57l;K55zuBlW~&nN7b zorsB-Qruzu(!yS5uzvd<;X|j=M`l-)ERHzOrYLi0Ua|DGxqB7Hb|=vp66Da(O7P<` z^eE&kl=RiJVQ(?$aW*rrJNfUKo!D|FmKcuA#HOZ`eNJI)AsPA!jlHb8&|XRa*G_Lv zJW$W5q_H%JGI7WDz)&rd_PuOsi;pKzgzimrxvkNSc|FNw_QK95?e(&6U5b=Tc+c}B z|4OS(W#FPHsrR}r$G_gBV6A&!(SPG0CN(f%%@?_FZ+}<^dusN{cN70R-XG_d?M=Sz zKU1!_o4Q z9Ww$MtV;$kulUXHY2D{RC>{IO7wCHA%yHB{Z*qkfQi(`N%)NsBim{CHoY8fioWblg z(5KNs8$A>`wW!^ZQOR`6R=*HM*$#-(N^bnOykyXAAOCI^Jy^+wsOg*E zb~pJ<-})_56p_;tS6uGBU2Jf0l4o`!(bAoZ+_RCUk?4L%HB;VYULA!FBv!W_S?~es zlM~Sxnq#$0tgeXhujwR2#Ku%9`tyv`z-22|-nESPyT{qt$BIm(`>k6aY?hGh^;_S+ zg26dkfnxpc%w)PQ@E6{6Kb^|T&&?u&tZ=Vp673%=m%Xp7Nsxlmg;fjh<>y7HhnGbm zqzv{V-xtIx0j-#8+e%dqZOM}NOUx%tVMer2CcOT|C(jzkd*VR3dB{yAYV8%wF`M!Y|r0cz{-~I=8F`r^T*OMim9|Wn!a2lj}5kjW&`jz>V>bY=j3mW1H*HiJ9hIL!$P* zTJ3gq&HYD7(hWY*q7B=8C(l0cn?n}nFG$s30k zFYg{0j2Yz7g#Ha)FD}KFoGnm&@@3zGW>ZD)Yml$w!Q8b5EXj%;v{87``U7~;&zMYl zZ&+Dl**a6Q!v-z@e9G;&(iexMynU{h39Y-OM=)LTalISaK|Mi%_#Wp-jzXG+6z04% z2~)hEY2k~(6ikES@HGzMprSo~2N#IZmr3_nrCtVpmcC1h@Ii(G*gvkpwRrDUKKGpE z*AxL`!I#h*pLV1utsH(GlP7Gom3kRcS|y-7es2@CH@5D}sruFFaHE6I+`lwO@<9y9 zN-k*mBIiPU2NDvR1?A=;+cvA-LvsB={ta_EYWz-b1a~Y&wv*h>wjl29{(E}d9eZ^$ z?T3#W93Q2egt^XDF6uYpBDWqWkYC(EVNn1%XV&D`KH94EO5FV(FSk6|paV2)`5(w= zhhd3KH!(+pwO^I*0AI~j2kCH~X+%+C*e)QC6hcLnrJ#3FO26CYoIP|BWl59g#I*le&&oWTD@)lg%3;Lc*-xcK7&%sp+}m{ujj8h z{L(*?EWKlFo_YVm2Oz{aP(bB246&6|L`N|8#+aXzy;$H%dt9+Sws*e}ad!ia_EOu* z3t0DlS;IDMGbXrzT#O?=?@5-7j8@z&uB$|R@Vx5L2F-~a8jr;Dn&nixOg6E4neuNp z*J@Xuyw)601LsZQ=Jx*V5H(pK0&*Hhj$dWp`PW=WfTF%PnKV}N;*bd5^Qz9TJ7#&j zS$E)zeo7cSa24IItX6emJ+X6qvw@a zqItFAf5l3Ed*vgG<@fwjDVp=F1WLr#e>7#Zh+Lb_Tar9&(uYWSjjFo$)OMHVGqm!6 zHQ#nMSgSTq8g@tjfD1V@H|mTCRQns0X)^_DTu1_jtiXUvo=in2eRZB&GM+Soa=zaI zQ^{gXR6Vjav+l-EREe~{>M{X($sZGx%E{j}sw3lFe3d>bf*Aei$u5pJ8xH`>jDe!T zBEH+)Hqv+$`coai`qyBA-OX?M9ZHM{&h9h%?t3VC-UAXq zP6-X5txSEk0=cMop>V+Wj{4;-Wu8_Mb}A@#H3|%FbDxLX6P=6+G_qO=&^p)nmC5#9 zq~NX?Whfji{|*5}*j+zZ_~c(+I%wx$e0GrRz3pd|%ER-qIv}G+)gbRA>9O0|iZ2;U zSQ&&-FIahO;bDuN3o*=byUwYvtKHkxxXl2?u9M*MD@9L%)B`3HS#3BzxkATf@oE3% z$kXWjv$HR)^eZo1W3!mZT;J05e!Dl;kuCYnxpBE~gO0;1O=+6h%o+9MGTB1_-DmlN zEy6E1SJ~nA=>=KJJpBzpz8J@|Xsoj0kyEPP^a5i0acRg(Q@<^M2I^sq#RZ3MGm2f8o_MDoB z=!o`j+3iV>q}f9vAGKtm9Z>h`)v+miJOe_A8Jth__#Y;-T<*aM2)aNFVB{EX z-=m0HWh^cMdPqA9D8#0pKFV@wx1EVmzJg?FOnF9W%(KWo>z>VW+e`%49)trnklhT* zxy+v^g#qG^Agd}GbSIYX{lLd8y+<>mdUx}88)?qhClR77@~^Z zd9inmT93PJuTHsL<91xcfI_aTS^kcruR|ss{Y7N^0N=d>w1Jow#E#;PdHH4*$~cDL zwAqJxc$BfmIjhsS=Pc=A@_Q_w@Or0K({ADQ=F_PcXGA5>$l$R-Z|qIUUMyPRr~r5D zZoI`DVVS_0Mk-o3&(YNQROQ@>FZBRhh@U*r$erV&9<2Eqd)K17E=H8)y^gnw6Ly<{ zJ8_iwRjQkE4ngb;mXV(wVrC0OsYCRVi#=8hW*J7#Gq{J3P47b>A&t=uZv48KYHPWg z9n!T5Ox?jqETP~F8L)TfCvw)Ql6R69Y#Zd3ujy%BZ<26YOZjRQvHp=wuVZ&j+1bS3 zNb2K^xd5+L#TFhJ`}{2(G&SreZ!RO!3(#W|wu^XEK4{rQ%pXAT4QHN*eJ}DRG}LDfQV}x#QZ4 z8UHFllHfN;^99+#t-1!bJQ`jZ`Z3c|%N)O7#FE+S5%ll>Xf&_^RwZw%GHG~fUWc{I zpyARS*OrmR!t!x~GFjvalBl4fN8WIuFhI1)arLJh#f{-)wzV$+s1{ovTmS`W4#?06 z9A_ug@k|89XY0zJPEc*uY#gUOa2`4E)75HU zr{9E$R5+J$lMd)Kn;*H}eh^hEefm@)Z|t$I!24(bb&7GW0XcQY&ux%?*ps>Vp_KKgBzy^YvDL ztzTcg$l_(Q+eREH@RutfFVYows2s>>2pFm~r@TvrT9tAWr2L zGZUGs8`NW7mWhwoD#P8jrYz0fc}A}4)&rn}heTBxV^`j36uSN1L(avq-kO!~=~~L2 z*;Z&kAWRbFXQ;dIHEeIi{`{yPSW4{nVV!XWneEvKro`u$x6plnv^UKYj2c#9r!_@^ zBd-$}ZUaD!#6O#{1#9Lz3Ty!VT!3jEBNKL~K-!$el{U3OdVp6`jw=?T{B zRqV}pg@@jLK~d{qe~&AUo#`N?7YvCvH$0kTZ1FKvIufKgKy zog!C}UiCQduFqknZlwDYQ!Fgd1cbmOp^dc$HBRQcrjm9jTy16j_LUO{Z-C@F_gbda zZ+M|q07X}7EBEHR*eLJglgGyBE(bN?w<7_qosgvI$6qjMV!TfL#MJ@uweHUndGM9r zMTMR|J>5qE{T3nq9uU#gW*KPFBm^I(YvMrRJ&jByD`91Gz;?hU2!#pHrYIUM1zkI3 z%)<#|f-*VAv2U|Q58n9W>LNI=Vo;pEm467N1qlve#3@A54&cy2U$E#&RpjljnMKw8 z+pmnv;x?J(sFUy`h8#-ETu!)W1p#h{+j5NB71elTI+<;$GnJt{Y^{BfJos}u9Z{6} z5%(Yz*1TchE*t$^*B71z;{etkBw9RJD6hH)VN5`j?b3yRqBm> z`1kp0WVPyzzMEZwsF@@PY;N7$YxK#KEiOO(NiQ2^;=q{CM~UGqYA!{QypIr-KlbBm zu(WbGEr*pG2s6h3>c#R-q3VnU{@KhVANM}CTx8>dK4_BWlKhwe^2-$dHN#_3YH+g5 z_l7tPvBk&x{eWs0HB+tqX&MQ*T(;^Ajj;+Zn+XNzgHf;*&69#_BrZAR--)!Q;^YC* zn2=|tnuv_5=;7H+OR`>9!zj+Kw`S}{QXbV6iNglnw&Y)7KvqHfD4)lI+~P#oaj57?uZSS>5j4zZ?R&kVpF4vs^Blp zHiMBRe*a6TK~L`iS4~#k2Njd8mbnVmm3{5}_V*eX+^cCn2K;$ciBax`Rls~H3`%aZ z#al-{CP}^)Vn~M_S;ZM5+u?AT1Rnqs0VMq>uYV<}0qU-dhY+>k5L$)%^RQ_xFC0-c zs8*Wry^>q`!(B}`TqsUs&cC>g^O3k1{`OVs;9+2l1}|s>=Mi$*tLXleL;^@?)JTzA(2!I`x7reR9qrJHK;3j%8$-ym^pm0~6cVk8SYhkh|FksuhN=z5{^( zBD=$&PA;064O-}SFwrsT*lU6*)^0CIt_Lbd#o z(BC;yCa-sd*3Qy2GTYt*9rk3JqT~8<^4O9VdUxw1A?osGYYCQc-rzZ_yf13%jj>Xs zDH6_S0s|S+Xh9~14%!!)%P*Y{ssM$gWmdmuvN{`|4Xn1n=5f<)E?{Rgxg-*To2!$i zwBmkKb^Eg}L^%YBFSs+XK`|*8#Dzq^U;$Vf5#VDp#P@bu>lAJwvGtvpd-IRf#ae)N zH<#<{$VvqQhy=Ppal{&jbWoApvRVbJ6(xsfR7JW(#dx;ng-w3XuVQ2LFH@!Cfz2kqviPe9w$vO(qVL?(+@N?6Ctr)Eboj6&e?IQ$e#_S3j^Z>5@(+UmahyhXcjUB* zC46n0o-wDlvOOu^czr=^Wzg82M;X6`Ql1zQPiD0I?F66VgfYKkOFSuW@L79jlM=jK zd`Bws0{k%T^Ey3zqe$AtLx7gJH)7<9{47k4Xa$v z5Cnf)W3!!l18Gb4j`JgI$qcMiV3tx(($muhqCfGh~ z3++pc`LB8EO8ej*WUlCJbJvu^Z020nExA*hjLWv5CNOWonLT>`Gca^{**6u-29=Sa zflA6~a)*G13I*~Qb5wZjlsdC>!$X$f`{r%-Q0ef-j+=J)gO~JnaK0tLJx&0vYAHJ@ zjxKwcMX7G1IN7ksx$83jarPl>9_^TBbLaMel@y660=#PkKZ$D%R!VoA>i z>+KXM+97k^#rAytd1_x|yqqy+N4Qh3+?BvA=eZ6tJhoa}AKyCt0M3tt@tln@X$N!F?qm+08w_4u|g*8NlE>%wK%%0<`D(d5^>Z{^r(zael}2_CO>*gL(%^ z`(*S%tfChVS}oFT?9^HO_6%wRF2zbun5*8~iUe!uCT@K1ZxJ~6flLrgsun%}x%$h^ zI}C;d{#n$zhc)xN#U#hW@r|G87$A8BYCr*ZbNsx3%abO})k4{dtdQ{{W*nxGcT~Lm zBL%au=hcG208Vu?IVM-hb`7V&O%=&VK^eI0yP#|hAVdBqX;N-K1t*$8Sv|L%x;z>x z4a%-yOT`9|lXSHYi=z4lX;gF_ue7%7bVuvVTEPj$`|j-;=u^shNKs={1I<=xj54Df zS=`GX^6{myQiMP&S3FXVVGxu0VUaQ!VC!_JsEG@x_O#1yU z8xTBngabfLz&rvTw58yaFV+kDk>ZgTW(}4Yv6R&L%}q8>fZK=EezPj*ld&)AUi5Rq z>Caf|6)9}mS*8>zIKVa(eGo*7jr@Fq!W>jIQoAre-!xFH&j+kVR6cHgb;$>#0PDZB zd@HzXzxHgK^XCDo@OZMAWlKnB+--6c>KhPKf_I4qM_A!y2O7xb?B2ciwujFp$~kWa z4PJ_H11KePWTt7g>S@&mC8K+!H;*um>vX@CWF3-7!#9?{FQoX=%mdVY8ET}^9@KzGmBUDO|m|-$R@A1t3BpuZ_ub z`jUQdp*KhSUPqA|Q<=eM8Rr7Je4#X12(W50MPpc8Ft8+khu!_l>sl2&UCdj7t^+i` zQ|sgNW-5V|-zQA)5mrPQ5b2I{UW*x#Lzbt83N_S=557an<(kBj_r2uc3San&+}(2; zoN{zLsvW1U*<23i(9(d+8g#QrmbUr;zE`HX?7%7M-er*;p=a}cmjqVUhoZnbOdkF}Ey>3gSYI^_8X>HV_l>37)$@~PDyGc$w zw|@oScu*8966gTpQJDYYgP^upL?nFr0$f+(n zJ(a6v2dZ^{t+KmlnRCL;a37YDL-Hqs{Gli?WkpXf8H(fw+xI0(aj;TUE_p2=YR@;{2(B*?$nLA40f*e1Mlqe?%weCyX82xYr=oRR6bRPqYr zQUbww^#v|dWc=1rcI`;wc9v}Pyv76P#xZqow~SzOLj`Pz1ZI7oVbb{8PekU=%pTFN zKJi@Ihj;H`6!lYI6h4$hAl!QNy|FEQ&;H#vXih0w9Y#9@Z9jj_ejltE=KpNNZO~T5s&N)n{tFk8E7&1lU!&5)&F++$VG+R9xS7lQ;btf~ce}jo*qpfFK%?H#mq1tR5^SccSgW9c=o_99D z;_vycV`ht5@DSyyY+L2W3Mpr2Y$Q+^YT&&{rH^hkwZo>CqaTqjYrfx~!o#CzxF z7H)ZP=a)p<$lKrOOtCH!Kk@p#nz;d@05r@|_}F9bC_4=5*Yfr&C0?$XvL1(LW{qL@ zaBQ^n;79&LD`DI;TYP8R3h{l;QZd9}Uauqg#ZdL1QKJC(i7mfAupcOtZqm|2*O}WE zVY+CH@tk@VSg;4!2-j?QQR>Vdg~2zTQ=6$9L%t>IvhbogzieE~HhNa?H1lTIM%=K+!2%{b$$&W*&%@=a%Aho7FHYN*^j$* z_xhx#1XG>A`R%CWu>8i^0kH7{s{Y7^lE56fW{b}>gce1-k+~YkEtw6LMT2T0iOdx@ zzM4fHIlepEOgro|C+|&*x5cKyz3e300ADTgsVkR|Gpy1osKp+rl4%l`JB1l^4J6U} zFRm^W-*{R{5C~KkAx+V14;0vEL`lqq_8NGt9#Mb;c4T1N|I*M?7;qe@Uy?&G(DKlo z5M0s^=aughHCmO4FujvkW%@7)GNbL9SY=(snbb8@RuJ9gXHu8wR6IYV<##b!f}Y=0 z_ZNP+4`HVs`gG42r);>sNYWb{pE0XGD#5nH9DIY6gNT%!_&+^-<)fK^C7+Ra^Xr?- z#8>$I`X8Jt60@&TtMV3PEUzFJ687S3Ebsi@2$ukGDe10&bFi?{x|EwN7^X!2%IPe% zVH*^g|7Cnrb1L$d-`(~wnjoLIX}M_2Bp#8}q|W%w28 zew zy>5B%b!{o#q$l>O3E-k==kl3{(LVV{5)mHSlQQfV?H}*pX`s0zo*PR0?C1MXg7k9H z7i>z6TRL|L19dQ6NEd5$9N1E@s5j?_B6-sL7X04x)+dXWFh6f~GX=TiFFsd6Ljy11 z1Q0y&RP!)oGUmn}@JR3@`{`U}k3l0TO+|?XxZgBAc16y^{}nOwyZgRJPpsQ`!n1=# z!FH5sM+Hl^sI@o(Zd5dG-J{!~2>Y zHrkg3;eL8u$Y7azSSCK?2Y%RfpI=;WLY`;`kw>FQAVxoNuuD=8_LDx7lcJsqWVFV0 zNn6>T?3-ulJ?iAv$+&0M9)hzOzoC2wuA`Q21elz*)&Eo=uATmbWh*o1mN}3u9CCA z%IN2g>&f^bl6zG068`>r@A32CC%`+t$x{!T8 z44=MNMD~CyKKa8O>YCb(_Y4zn4=>y5dB1YV%^^Y#XJT}Pe*k`eCjr2afum9!@`>?r z@&s>5{w6=0%xJXz4J@LmHQJ7ELrM_GCNb=q9wle_HRyG3H&RU9H*qTpN&g-~gz`?> z{8j=5TZ+okltIfOcBX72hLT&omblJcJp!;P=$5i&LXoo^E<|L%z?$2+*jPN zSrg(Q;x^$~ZbVL-_8Vb6s1n~zvl^k3KY)1Edek!Tt`paWjw33a%AfZ?(l)OEv5Wozx!pCCUW zt<3sW+8s0#-3PRhdFP%sGql{?wLkMWQL%2oil0oNN>=seN38c?I~IWZ)=VLHtF+JV zhnRU9bG`~Sd;DZ!tIs`W9t6w4WcdLc<6Vr;%_lUlo`GQ3)57=2?6`%a`ZNmqu62l) zDqSROiF5DuO`CGUo+*Lv2JD$EhND6)tsSFVhG)NsI?7M zewZj*m+LP%>3C>hXC1_HG~Vm5rM6FkGfz%~V|0{;YN~eRUfwYB2({7#bWEj7)5Tg* zgAWl#;z9b%Pw+5ZR%%Ng)$IvO!H?zSJ@1(H%Wn=<(We^VLayThFF=S?4#6{T2^ig= zA(%)QR&JwWkuUdua=%%*Or$Ut{d-#LZA*!hB8it_}hHj)gq#K5iZlp`4L!^-q7^FL- z8x)Z4PLb{gN$Kv+@A5qF`+k35?!D)nz1P}nuYD%v)Iv%SGN!#3H$)3$&NshO9nU7} zPIc^d&aKj`nrS}Sf3UR~y+tp?b4MXaprD8RE7+&V?^Y*`u&n601`~>rfa#8(NlolH z8NmTiJCuO)oY3g1;_disu}I}1G}(UWa0Bju86h-qydO*jy*NBP8XX*ruEHylfhNWA z+fnaM4~sIj*!bmE@1Ncf7QETHv@N1gphkgbLESNQ*)m!ktmaaDFfDM+861?-yRYPU z(wBz4U|7d4ICtSO9{tvCHP}VT0NcH`{D@rgx>pr3OGG!+i&NTf|7E{j>70vJ$y{cJ zRq(e_jG7LtyeIQ!LHUA`(IF7fvm)hhov#ezZU1z7x|pmTIHr$A{BRocCvQH6O90u4 zSrr=W=iT${$blP`g(|Q)T_HV{yBnj~dbVtq4>@6c35=Q(?Kz*kS&@-X)`z?0+BQrChju*q0 z25bf=lt2owLr%6fodpWI^$SqLTQh6K$Icoh?CvyFo})z#LxG*~+eel5kI^0qfPpMH@V$~{AKSOhV_LmMNW`Az$#Z`SiCsm?;9C?S*KQoS2j+^qr1sY%WLd$PH>GKEO^IPPnrQ0lwsTyG_ zR%DP+yLRpv)64IFS4hs4LLR62{LQSOg=R~-;!s_&++TD!gHeUYBhGK@IEi(2g74V# z_hVjjlGFYKm*C?H?leI>kU_tPLj|CN>%8K|T;vx$PRfo0+3lZR%O7tt_^FP#I4USh z2Unv4yFGvDSRhnOn31xna>(~93Y@k&N`cHgogWb=gF+VM#}18dLXJCV9TcSCMdfeE z2$0qPZ7e7#MDajZ0GugI8VD0C^{3r#dk}p;hk%ly$0ltqff5Yr>A}z^K(%TOM97KD zEgM&Pm$%cUk`V9HpIk6~fbzyV8@a%zX)D~J5M&+PF{RtC6(Z*WMd;kL$^eaz#6PZ} zA@=VKZ#Q9dra+>4ljO&aU?Nsr_O~w~lHeP&L+z}QIpO&Gz3$Z{?nFZ)Iqc8qz`>gH zpZ_LL?XhDZ13SyUKGVm19hvGTtd`fpZI%uR5rsFB-aSE*=b}FD(?-ROTHW#R`hVt;=D1t zZ;za#O8^#4g$ly%7l9Hu%T6mpNeC7Rh0cp z3j-x=GTc-CIS{LlpGZR4!N5tD>sQ8=E2|s+BDV6nHi8fLjFM5LqDSU)f1YH+_}avF6Bl{Kv=so=0)jl7`NHfd7WIdnELIZ3VlaZ%yT!1* zYI{Vwf>{a=iT;pe9JwVJ#nqelcctW^52tyE59^{H3{3g^vi<)UyTi{b{}Q%GlA+F-s^?$44L~{7I}~ z&DlH%QpgH#B=e+v9hcbDScPrKeLR`Uvdi;9d}pt0oK^BaG*^on!sL$><2xMx<94}B zgRx$DS2feJXf4HZ^p-%G+#qgt|ln4OoC6uW%A;4GY%%Aw7hpfbyaFcQA-g>hWiqSG|C ziZ9&%cmZCyA5ta+d0GhBDL9lOVza-XmH;)(0ZyMTha(Hk<`FyC%e>>y=cA1y9ew|} z3^?OojW?{Xfd_t%j*kdKg#BpUF);RDwXF=XFpKd2oj8^3EX>%LKhy^j{{1e*h+hQy zm?|zH8JR$B{DG73k=OGus|DGH&N388#L#q<|71ukgq3Wq0cS^?f2%b`*v$8CC^JqK za&G*h_O9hi-11626f#4k)S?1d?!y}3SPTb%p&1S@?$6BK|&gAjH^%ENj5&0#38 z6>K0VS&_X^rJX!3>;4)-+D4XJ><6?HVX0!qm|z#pVZ%J$p&5zm$%eXH)n`I{_Vv4Y z#Iv8HytbMF0B=`g2mKR?5|pSsjn;%ee`e<(jHkiSP#p?1a+-Ex)m6aYeu2dZp{BuZ z^|w0`la#bN2oyyQr0(Rsm8yL(za#xQd$s1*qFWT}Sx=>P$o3s`0g>ml)KHXWugeJ#kW_ZM^qgw=CP)!mB?j+f&vr3 z9W!4YwA9LqG@Q4hQp2&7I8qX~S!y+FpC)>jEBq?Nh6*ADq?ZsXB~&eVkbL8TH)UkR z;jGU4xcZ;J42^E;*X=&Zz6@(zpAmSda~-v+|WW ztMrC7f?j644K125-g!*)Wzg#>m39@|FiZ$?3SYP6@BID&CW4<|CgyR-6 zM`*T7T1^PJms%})a6<4nZRK9s7cn)%Vd{lA&`i}-LL+Zx z6snrz{n%xqNs#5e7Js#;7l{`>(ON1E!A}ebN(KF=@*#r))uFO?z}-mq=r$(AtSvz7 zwOEJdYct@SZYAlHQTV?UR@Q&Apf(iuN2>WFiKOf0-8pD(8#O=2bA`!^RLlfZItI`Q zou^Na;mlPM^>{yB%4QR|`A4E^h0|33Coj8Uk4eZetyROnp5XixXrxCs3J)SKw04)& z#RPvx{HOc^`W8zWn?g80Rs#E3h5sQ{`^x`9b6vuz-SO=Eq@TdZHERoYLG_$6iZQ!# zoAA9!JnfY|m+1G(Fg93Q(?My7^23COr#Gz0I_-U1e}C+rfrtx!{&X+r$sw+e3FgU3 zUd#Cn5G1t^W?Y>lAVF{5N{U104J|*ZQ#N*ciM^5qiTP5G|#o1^> z+}CM&YTugW(*I)AF%a*oM*u7K9_9aM%T}uVMH?FI+V^PSjWOMNZ8aC2OklN`M^!9( z;-ED&%SbMx?a)65@dGT;Y=PJOuB$_qc{&UOvM6LQKTHiSZ|eSOA5N0#-?^I@nfP#7 zi{C%EAO=PH{<|{^*K3E!24nfIb%xm38!)S zWy-Aj5YZJ^T&M44idynaoyu!D*4Y5nMmtodLD?L$H*67I>d zM0DHhDIZhiw)m#7>f;6UzDZxxaMqpxzsdj7%G&)IXP-k46&;ql0r_mXthbl_trGn( zzfEcSE<*(<2^>3HI)j;Pn8$jMYdVX#A(qjRobyzT_&1g7KXH)wU>eBB1;1eHch|zs zoaT!W`g7QA*J=ONZC33-u_7`V%~`t{7VypKrCL*3$sGZokG3*(QeVgmeh>q$p%n0l zGNuICK>E#WSy43o6XmjLNiaq|qqD|00SM8_=QqhgCy~hjIEqsix*w)u%&o^rc zxd&Ow0{p5`rNgqR@GgvGTvxnCW|;Si0E>*xmMEmeD3FLt3q{~XyG%EFtzMwmSbT4B zB>Ew@LI4kbnxM9Xash|~#*R>B z2tDVbBy>CXb0!L^*J5tNZy|<5y@4!3LRh(e;PwC*kP8B!ji}Nq=jGUD=N-H}%088g zlV;f|V42e9q=R~rZ*e-KLnRgNM)C+9&9&}X=Tn9k%D56~_u(p9;Z+P{sdwj}<0oy4 z(I$A$d9yAuRSNQ6`H0g0lYVyNs5nKZLl;1ldhWMAYuC>d(N`OX~YkmXWt`^_^%mMZRVC|LWLLL!=u zypuuvTe|M+@ppp2Lkh|GQ}Fpgf;%N19sG`(s~3NM0_v}2G$P%?&kW<@qCKz1UeMFr zT}Dxm-!3vviV(Hf^q zM`%w2|L=I=;ev$z$TNU%YVMPh1Gu^6&^|x8aBYk74=H)A?dgD;h(vA3XjASKBC@K* zzC>KlF#l?J$%&M1FUkZin(p+y7myUy>h61^N-ATo0-Mx7+o+yQ^UUNCof81b_e=4z zMZ+uPIgu^iRC+PXpw}#h0nw7mX>d~&)J=a};9!m0Wve~$#)t!C+4NU9Xx>R`>*Yys zPFT(dy9&}&tH4T&c)GK#{wm}4JERDttYeW{EyAKOn+}%kCss^=F*uXS0>K`|5{kl1 z2qS^Nh;fA4HwJk*jwPno@ff)j5SFGL>m@;mJqVdSl5&i3e?1R~T$LoCJt)!P~A4|588IJCM_goY{N#3rAF5WXWi#6T?qk{CCPc;fE z9rK{SajpN(MoZV}QmM+ihJdI?^M+8N@wz67>|5Y4K>eW8I zEAuq>d&3pbk&U~&QE5L)a(_3tGDtAytWSKivD;3isBH(Nm6z0*lbe04QFOmt&0lZE zo!K$-UNtInnfze_{HARViS#>?UuXAaK&>2wS5J#lYe167hk6ZqsYvxnpyxF3!6spC z`-gnf_tleATCIgGS}o40xG;S#;;a0gH~9fLfB=aLc7bSw-R?B03h;gnWngXYG^=Rf z><@Yz+H0_2Hu2WN{hqG59>mK?@|^U-Q?(khpskWF&#`CrD<7C|*E81zEOrl%%4=uI z->rmE+=W!CK8v$8M5#EBfK7PIb@U&Aid)SXBm~}YUg>ToUa;q@Xm8;*Pd5i^eDT?) z^c0=O3FF1(Sn6t6e_hL(_6S=5v==y=`7C`dG#C*CC|fWn6+#4F>ae|RS3@;-|5f82=)CG+)8Ay>A{$9 zfzw{aH$)ke{Egy~ai`Scrm~|us^gR=Rb0kLSFd9xF($NmJnsk*RQID=xWCvdc+T1h6IcBoBF8ewJ=U1Tlh$X~PX`a$24&yVeg8gw22{cym0k;@ZCBL?d@tENHoN5=tcHwK)} z>sds%i{l+1e2AmIS6Hm}x)k%Tpca|t{%c+MCHbD(_8(XeW;k zdr@~!3lAT@mZ_8kwJ>@-6&_6El{v|8wA^wySv=|7XZ}>Kzi&>SXXMnN7q4#t{b$t% z^bd|)DBz~$-thgm;?iWQHq3Jb%|=HLxLjY3Buf@=NtgPqt`0YDh_r8$h$xni%6A0# z$X|v05kRn!x?V*MMo>1bI5^iO>!~#!yVVvP;@0a!^d$AADEnq4;;jtt4QzjVQQM$- z#g*l#oQk6c*v7st>ujrX@nI?%K8kx+hd;fVC5 z@_3DqWflML`PqmBBU4xABbOMMnog}cBI~|grg~!szwj)SA67d}FmCQh)5H5>{M#6~k>uQCsx9qnkoK zL=9@95Kl<&3>!WqzV}d^BMicMT^O)J0w&l@sF0*Q0#if!x8p`6w6l28-&}0PH#nDt z_~D5SH7Ay-y7;ZxXg$B>&%3E#N*yoNruUAL9Bx7PcVf#%oxbo#25>KD!1%mSF=c$; zK&I}lcs5<9<1>;?zj8&rIpS8I+5*as$dltdT2uWZoS3!Qe9zKpD9$|2K~Dfj)7f0p zUp1mu3zols;xj-|92qFAuVHdjQ_(Ri$MO>o#|fXKBC5W3JoN=meLYjHkos1xZ|C$j z%)_@&ziGx0FYOCv$k_*D-=-098n+0tRe9QEMPP-tW@gq$oW}IV8IV^z(z|jFgZ-7| zhuWk7>1zUQoDSpghMjxFJMGVgN%{|^8i5$U83w1(yUfLNZ3IS@I14`nTiUn*d1#V^ z2K;B^d&KQ2xFg0FtbNl>sU2le1)Z|J-tgjD& zC`Wb>59lC=U5{Cc(hyGB`@3zRO3?lNu0DYR3j^K<+MUvm!H->t4aI6(dbpn~R*N6@iq5-@ zTPTJ|8RoZvR zrl;2pN&IeM`6*{4eL1bu8H979SF!Z$U`3jcTTWpId5|gGt(TGmM3Tb79=%v3KSw%z zsb>jFjo)X*0LSTn2k*=XYT~tdqGYt9jyRxnST&jz#an(8KQ*<(@nr61mOw^9cjA14 zrZ3{dzESYtCgUe75psBg8*=o8x}%lwc&p3}-OuQBcEc61h|Srj;d`2Py?@0pzq&cFSD!OQuP0XQLZ@&-=b!G7Y%U!7~`@;80MeZ1j;ZnC+xZaniYQq&Da@qsO zm^ZO&bfASn_MFp)@N8*g)Dw-R^*vqhqd@!5y^Vi&T{c6?!vjB?Hd{G zXA`}(o6wFqssuUCmqrZ{?E4#bO0{}8QA$s?>_ramLYq&2oypje24H?##>2?VuEQUC zFRQK8yxI--bYN!laugSYk< zHUtV^)MBe`(xCdzw3AIoa0Y3md`(CE|Yhv=ZrJ;6iq@r<Rx>blnE^seLr_g;CvZ4(*Gb3f>QDef#?nQ9wXkR-Hp(ORx` zzXypY8g_D4Kf%f2cC2z4*s^(6%S*x+dw$*+kQtwR+|**Qg(cB6J-@Rza>tHtTZVkc zt-pWWBNgd=vAQrM$fyIdbB4-8{F8sp64w|z%aH3kdU3fJAg zj;a}uvSfpM3{>1dZLczD{XVQpsv$u~v@Rdf@WS*L4TRN=^+4kV1j_z9VqMInow(<1 zE7O^Ls*8K5<@kKR!W$23_`ejM8^qKU|DH7Whd5BfE(5;`__*nu$m4c|UOEQQ8==Vu zw)hP5r|Y=qkQMFwt|ee4q_B@j^%1rbqpDi$+lgCYV= zO(hnVI57?PlX|gcNAjlCg*ypb|Eh{fb|`^N+grksXUNzJwA1vK!ILg$@WwzLmwMWu0V^@6q1QfO z&oS}Cl8tw}?!p1O$Fxxmv)$EwlvmAji12Vlvusfj< zyh322+9?qwq42h9Jjia!)rnV^pa%Odkh- z(ySMEjn6-NUku8-JQ=u%(#dU0Vy7#&g=Z(zwT&TDUw`kzU6sSro zQ(!1O*_Xoc5|jLITW(VWs7TUe+9l36EDdcskmg@_%Xl>$Mtc_@&gw0N>Ui}ulH8mr zg04IjI9>VuNVMMKg&pa&3Cot<(5Vg~lRt?BAC{ri*@{m^;sEC17J)&r**#;-A9C4~q=Jcz31Cm|z4~`HxAR zSrRyd_&Ic@!*md)fBj-B4wvJTLzlYdmZj?FND>n9%(6}@eml)&f(K0>_%3Z_>hA`d z%SL`hGCHEcxW1CeYnCBygcoVr;NX%2MV)ZaP051Nds8Jzg_t7jo2DBQ72QRAwD`@U zhG!XKrmZY~pAPHY@M5HSiR#&{tAas)ZnNNoZ#HZAOaL$_{OsP2MJ;^X8L~onKN;KW z=^`yL&N-F*NT@cws0!UayTVsJ3AR}A=NNtT`2&Mg#B@wWy2ssmJ6D&JRmWuINy;i@ zYZDtFwL$ zJt<)R(5#g%t_4JfZTEroTIZ^g;q|>8CXwgE-3!lM&+Dc!x<$9WeG!+t=9n6xbP&`3 zdI6SN#Q^hYMFLdF=IJqp!yxWcH^rbCpm(AovbLWw-0|sCE!HAOeHj+sPrn+~Wn3|HUNdiazPF>_r6qGjlt7&F| z%5U4saBKY^W1o>h%t_=Zg@cqI#9^KDQ-u^?*EkC9)9QG-qiex#iAK_0zX-pXv=!qI$5kLf2B+)`x()ppCPU*X_j>@0IA*Y zbGxE+xDwT>2*|QsFvVT0l*!~>hED1?7BoUAg0fG0f!ulPA;C1#{>6Dy<}jkF)m&)H zz0te^Kl|HjV#E3Qk+g#UO2dMd-5%YXnz6u>ONtwc&|q?$K>Cub_dGAg={{(TB`BQl zqDuZ}m(`R!zb!Uef%}Y#djHb4K!w+VSOulVp*BUaOnGYmU=REux!iK4IP&YUfv1MN z0y6NhJ?S=F3jh;p;U1>i#z)jx>Net2f?h3ye;;w5nI1Qnq#D1-GXQUp94537^532W zAqNOmaAzC~;VkMVN1=k{S%74S6oHw}SW8H0S);HnJQwC%m>5TM+$2;XN!{NHCiqOz z)uGkQt`-c`Z&Qaw2I)GXby+hsn)eAh`71^no2rH!WcmFtZ zv0~R@XY>2&<55Mr|2F%Z+4Ws4b}2=e>qbNOg0UNMWWgi0_XIe^09zzZmjsT2sb;PO z43nck)MNQ|3{kG%oR5N7?kMSf-L(~aWA0H(JbmS;u@3L>+`#MDXTZB zMRwUW(u9t-x)74I-V%H4&}@>qvF*yk^1i{L+f-VfrMO~K)A9Axa_vpbB-MqB7bg@9(Sw9<`)v1 zQW|n#9$i2KvIQhEA0aZ zXpb=wPxV8`gh-!a+&SlgA!V#2U!=YifH#LjHr8c74Y+pO&wvr}M2#yq2jH`tpVrz$ zz#2~DT?~C3$-y6LdFw@GIa-LnD+l}UN-j4$VOx?tlHZs$`+6i+Mqq=qAq~D=x;?E^ zi*4ff+Q|-@LvpA;5>D1T_^neuj&O+BGk5yhT%KG1U3byfM-opQVBtJvHuDs_3tGSs zI^iehJ(gfB#OBD2n{@z4!JC$jj~qxq@rz|t6}s?u`SrK=`9XcFBiAGUI-}Vu=iWp1 zKG95AvNLO}!i)`rR8FXz$k z1zFl!eCfT`3~z5N>+Qx!O9!YO2Nj{@-9wAk5#CPXc=UruNoP*gp6TLPU(cymHH*3D z2~0$VvG@c}i_8}wa@653z)W3%GxG)@$Q-5qJI4IP7OaVG58gFDX)<({$Of|^{p;s# z;X7jvxHnE8NeyxVX9ENmWV1^)7f%wei?hN1Vsxujm={|$C!ud+)Lm2Q7&Tt{mY3Ot zR~PW(AO5xHL%AQf@WJ}hIX8J>iBsI~y>~eDM#z1FED1D>)&C<+2S7bg0}$*;9+3ds zJJT`7aU}Yzta3AMp{DC`Q^2lexy8F)cPa^=({drTP)cwKO@;VWWYZ+Odrw04%zO<) z75ldU@67#k@+97n%p(&ERpWjqD^T0y?!%R`_l0`w+vY{Ej}nSB+Pver4GGcIo3y4= z6)qDiR0Vs((0-CwN@QRqpalMqLKN7Z$4-vv=Hp=3n}wQVu)Y|DD5RoFyhJjlCi?e& zwY+kq{dLmhBTJREc?l$h5GHmk{zvoK4zK*;Xq2>dMs<6#z?O=oX#}pWc_n_I{KtvP zk!yNu3BvdM=H*BRj45`&>i0=)y#&+dN>q(?Tj|Tk$G>J8ByfDNM4li>2-xGH=oN;Q z&^$y+d(O&V{|z2!n3=+GyTW``DRm0y+unA!ufYK>#}EeCRpG7_6|KoT7Q;XXcpkq8 z9~SxZR-=ErTvS)!t3dYLtL-{WV*q?s&hSYFi|k3v;TD+(jp zJt`p-C=GBIgxVIBymk7GaCKU4mOo21=u*&M&LQGkoX`=Pv8x*qK0|>4kKbf@jIq-z z?m4}CoxwVIUuStgF_=GE#>T{1j*+)TF$JJtgZOaeq}kGuJgoV)UG2^ zg7uuLLum$df~T9ya(V~qAaRFJQH=8V(uT9nkA!@u4mKP05>DXk1R(A zG@PV%Gj|q1G+nSaR;KxenHuWBBsr`;Sp_BExcK{`Fb8bKPXRla-_0x(uOR_C47zwV&T_mFuqBmn z(riR--E49mzM-pqQfxa83zez}%jbJL^~a;)|Z4KfbAzCYK|% z$lmX%_TM?e!9LrF$pmkPodn@n>k4L5a3;mPP-QZdUJ(~>kVSS?ujDU7bfVW!TV@GJ zeuA}l3~oT5s=DcU+fc)|ZYgCcUX?#@I^K7!AcGv5|+WmDlz?J@7u&GAT^@*i%b49G9a_o?{gd#D^OA)i{4Sam(`*n7Jlx1I2W*3 z?)M(|Wn-YIH7>j4uABI%gz~@u+cc0F|GbI1ysSY!^3C*dCo^8+ky4R%8T`%&03_4@ z020W=sRdu&rx=wMag1gg&IIU^=HK{CO{7#XOy_&Y^+>-ULS@lfzZhWbiQTp{mnk^C z+Wf90*&zwCx%HkS7PS@tF=L=o$ze+IzLFO!DhS#&X2^2eg})jLv9OjH5!^#gr9Y+~ zHj!@nEbdc_i1Ku|7knlq;2E9hEg}o_(YHiV0x7(IlQ6+Z=pIB)TvO@9j~ge1#~pHx zB_}eE5CFV#wNYV>2~4dTxet{mXV6XVTpqiPb(YI|U^wwOIo9@4Crwi(f$K@sj+mFB zj8pX4Vg`i$zlj>aeFnO?x)mN6Qki16kPnx>kI!286VC*S)+f(bsvwA{JIgDTU!+?b zo)Ri039<{R%>wy)rRZI`;dY8xq-)h%}uqMafbla%XmL4|8L%C;$jnax5rwv z6_pzbQNv;@!pA!MkejoV*?q#G8lV)zdKa6mR4xPyQhNLVN#WoDZxH4eox6Mh8_7{R zoT= z^OtN)jBq`K4?lM}pzpIVL2fgF&nHG6MXeiLoL}*A(EBDat_eKZSrkofURbq;_>Z#B z9M+yJ0rk)tCiTpG|8V(ksV4nexVkT^PkRm&1?hPI*6ruB`Fjv*Hy*G+K4L5fz5R-+ z-+to>3NGyz=Q%PpjbfM4yW!_q0Kzs@ZbZ*fYo3f+n*((BwJihH}yNZ_jGxE z-G7x*j+7=gY=>Lhg_@SywV4)xvQ4Uygl}fBK;zVjhEU`F*K!4K6OGhzLK&X)B>mg4 z8_yd9GC(6DvgA0X=;>Be0j8mVw%}J8pwIu>w%<$$wqbY?vLkHaRM5Kn)2+7shw0A4 z9=UhT$dt*$VY!Ogl~)M%|0LZ#U%2h`8TB~4%I zfT4}ews3yVx~0dNKS_m>*P&Z5%Gb(yL!Eu~#R|%$*&c-0TQ{#mO{Weq>r#!rV)0 zNzldyOAu1wzt|#X2t3^ceoed%?1FihxZ}!A`jJ#87Zt{gqc%w>(Pz@l$n~fOW>$ z(D4D4=gEt2fqwv(Q#dhnWbd;q3E}ohUS=|4v*C?m>VL|z_9O158PCOT-ZyehjGPju)ed4=((u1L$Cd0s3ZuvBC{2N0jr%Tx36FgV*CRbw@ z>-(hrWKss*f=bV8sAq{CI+e9OiH?ad##^*`9-CJH$Eu}CV-rlY>;Kp>;IfX1cv^A;Yv076Tl_}20&iH0Bw&S$DA6tI7f z-6Dhj1A1y%f;YD!6oc|kPlT{i^Cahssv`jP+VK7X?FH3r88Od3a-^@Sin7CA5Hy>2 znV~}$7%#28{Hc#q+JH0a+{<@x)nbc`$CO1}UfU7$gj9Ho1ubhq&~^M$nT{=C`6|L3 ziePGP5)38tzIDM#{#-tV!z+BlX}+`}93EPZ|aH4!8xxU>?8?~=J87qhA3 zE44zenNd(07siL|HSX=nf1-$+9fu;y4W!acrdp!f48H*hOBvq^yDHII+6w~M(DC*g zSJ#VH8{k(^6S9`i(PhYKhTDPvL5XbTcX(Pa5ZoWD+aYELCr>z&n(B}8?-adZc=%QL z11X_1j%}9fy_WMB(juk0JOOvk3b~3>5`>({)n4UMr2R|3FYfwJ z)fL8P?;{ZR<@Q(`SIt^Pk0;VLF#&2E*D`Cz`x&eESt|Hz%U7R#3Gm+>dMpI8rmg|X z3Hv(gS8)6~sx`t{P}+`>G!tr?Q@U+i{JBTJ z#vK0sJYAX~2T)7GhvJ50cw<$YffZe>xXmv<>2|eOtTi|;DrcY6{p_FYS$O-T zg7X{ED)iMpt-Z6qcr!kF*L?`4qSQ@GD@mgdEIuC`s(0L;p(WgMEnzq(_3L}8$L}}y zJ^bvh%NfOpO%Oq~=;PmHNH0W7|I4a~b6DA8wqRHBi_S$+We zGP6YX-_w#;hB8USpEg9F6;{I+@bG0UF~bZz-D$;$dCe)UNXrp1kOgW@lcSr=5lEL{ z{ZkO)%9A<4h;)=A0ZtuBFvf!b(iCsW=UcEpI72`(P;R?!ZjT9_c{1o)s@q;Mr$4p_t=itcDne8|X z0-Uj(5_p0he##mZsbOCfw24yAyg|wwzwJBkLGxDxL^Z>+B!*YgpZ4GUgxG859)1Y(6T%S6DjsEA>t_cl zN&~iWb_o_q%2@Yvq?2HC21)sgqN*QZN{N+{9r~cAm{$IF=u$vZ>9DEkMRPkz?;l<^ zXnz-&v{G0sfd`Jvgc{ol4|ex<$5s~ZL!Mn|3K6#4j(@5PO~4~38smp_Nhl^*#EEW- z+j(`H=o13g3r_q4aN@F5)X9nXgCH!u&tpn&8QBfgW|O!b50=c<0PiI|T!{{U|CUCY zTXh_uF>kH;>+<~$EudcM>sD^6fnq<35mhC!^AZZa%kB$9hy5Wa?CtGj-yQ1>Y$un; zmE0M3Vq5*E7Az3>r~eVgOomdZNcAh`y8J$(td^oauPSa`4*U-J&es87QM~XK^Pybc zW;;6UWn|-gdDYiRrnGmhm?mice>CMErvy^@_E>bU;OceME}EmE8tk4M;P>tKHQ{S> zIC3^UMk`N&_nFl@OWSir307LPYJ5&0RC#eN&anB(*LU`;?j=$7I;E>KC;z`}+KFUo z9zxngb7v}9{)!-~T@x51^3~;Szw|~qI1aQE>x>};8H?5z!oB)q1Ssjw5;%Yy$W+3fzTSo!>Th?&?N3pS>Waa~qb+9Ud^Yudvg?u5A;{|pwh?nzM} zFKPt3YSTCUc2sJDKwBq+_w{$d+2MDX0sNM~8qsqAW2sl=o$oH?nIq^uM^_BX>WAzZu1Wz($*`l6{|s@Z~aouTpeuT(TdyXoBp!-~U=KBH(#; z@{qqgEMWkn*~wwr%YbD1GPi*S8vr^II-iV#o+cv`qN%uzWLKlgd(Ov-OAQMQz`con zz~u#InKqkbbE#nFf4<23fVEnGv^2t=ymf}-x)0tw0FdHIRPA36@%q}L{zE%huFy`9 zCIkWZJ_3_KmJZV&1#H~7r!EXAX?$7Z|a+-}QDx?cl zT5|XlxTp#!iCRWB>ymIJv62wru?7{hLQ;89yj^|yS)Epom7|oQ*XiKBU?-X+*bMfK z;1@x*L_;`_P@py!8p08z08_v97JXog;I4fO^N8;KN3U79N@PJc0x60>-;=+UGqO|lHws9f6zn0|I3SC zr-g;`HV{tjdd~aGSV&U0AsOm(+4)1<0V&{--HmGEke(75^jF#NOe@_l3kzqXUIVqc2|l%H*MOm@aaLtS8?iln#3$$U%W082f(DhCw-5=1!)86qRL~6 zB$Zy=)|?>p6E=M91?L>i!Xw*nTemq9stX8kj1Q=r=Q7&S3)%!DRK?hVO9L>P8{(*2 zi@?-@4?KHXfcHdmS}rQ3-As`HLAx$~NhIo5$XCh#Rv@%sOjSzJ*P;TR;$K2zoKRsp zZYHB|2S*YQpV)sTX_^nP!xd=v3^q-8xXkj{8)>2Z+%-m`S`O@JN1bAXVl^(Me@k;E zv3crJQ-~=e=iEd|i**8>ag)c{cM;l5y?U2LqtdRkdWV0tZCI(LpE>eNM9ZPYd zd_OIr5TFa0BW(Nbse0v?(WmvH5{{X3hzf#Q^|1GOXThw9GxPtmypH7D#4aFO2jJy{ zP~aC(Zk)&X#nJ3)*?!U%5yA8NQf)A3+r>o?fMh8vKJ;<@or&2$G|TxD3&>WkuP-d- zkzJu$(RmPgHZYk|M^-RJHK1H!66kSS59?S~-!|`MZ(!tw#X28b0YkR+Zn=xnfOJ4Q zvN+;DGA?YnxlRkxGg<8YKAR>aA7{lG<|kwM>dioGvLh;dM$d{n){pH0K1k6n&N#Iu z%Ae>CJ@V_*5s#EpT*&#*p?Z8U9PqhA<3c>y0GR0$#cqB8=AzHIvgntd>w>8S`aBB- zZSDegjCGMiahPOqtcawqBYjZgqahXFpv=Wm+&h&ucvpa7=%cJgKNWaUl~SWGD$V4F z#G1{u*X?lU_el4cOGy?r`JOL0G{Jyr2u_b&vLh56#Vlz;*h=u`K-x8P{D*}Yk_144 zxe?v{)PYk2|MtW$0LN8qTKoFjE4tPA$wyH&r%EDQkSqE)f((LrWfWP#7gx3FW7x-e zM7#pfTq;mX*R3U*NoJ=5R-6|8FKm`m`tL?ixmXjyDju#v`)x(|gE2UYDBppr=!rx< z)oyzR7^&3MK}EdIz6YHZ+tKiB?Ke7jSrLSwXJBk=s}}a!(Wf=A2dZZ>7rbuyC;@oU z@^gdv0Ah=Ur^nj#{XZc1*ukDe;*fQ))X8o()YAX;_uEQ!Fq*80oXr_ho=9lQ4elIX zi+^G`hac#+Tl{Gnf+z!#8wsDvl24q0#kOt`n5djq# zL>lSt2I-KlK}14n=@#iONnrqKB&18aQ$SMSx4EC^ec$6dzW?XAW?y@+IM=z(wXdL- zH9l0@j%AuAajgrDU0g?bnkHHK&YK0%sPe|Bqi2|ZjF_NqNsZ1AlLH*FdVIcXykv_D zMrC7dLQkW-B4_+v%bcmN#tmLn-Y%doVVBlf^od@wuhxX2nGh8?5#Cb@$GP{S#EMVxw3(Nd-)|I3Y z?US{|b)ft6=&8+GEBr2h7b$atiKb~D;SXAM^who4+hfB^{x)26nv=&31Gfw6$mqQ6 zeur?u5?Q{~eii$WhF-ayTwPBX|J!>YUn7__1=gO7_?i^u;G3y7n)pLUX7?A*1ydZP zI5N=|Viq!{5(B_%flKH^dM7MsVZ)}$3KB_I1clTZ)5FZ=^+@ph)WKa#d_iqmHm;ho z8_%FE>k8-F&-T4?MOlF`yzw&3_>4$qP$H^+C@UzHUwPU?{7vJPEd%b&U8C1r1q&hw zNcLo}&a?ZD7X_4K&lFdFJn(Qn>o29wmxsXv8Hhr&sxfK2l0JbeMZ{<^F^ApWNVCeu z=eyAuV3^KAK*#9Js5$KUtfZskEpmIKSV)|kLqiMDlsjKtpDSI2+%>;9KG+$8tPi~6*nxia5ULCZSjd>yI z(uWBojDK3_nfaARyTrBKNyt@)1EvAedP71Ywhpu;iqGg#`SaaLJA5Ao$C@vc=|YS; z@eALFQ$iX@c^x*>leDRoZt==Yw(ix6=L)N2TN6TmGYx+w_8T`g`-gXPE>7AqD}$@> zH1A6*1+Z@u43g&`h_LQWJzFQCU@3b#XFa}K2yU_WnryWpw)mEVwaV%l^?$SgUxSAQ zfqpNtC~VJ^Q0M!Vly`|WN51Rqpdlf4pbJPomHy{?HSz{3gYZF`JU40IIEPpRsX=bF z;Bi^>to9!Bcle?FfhTC*hnaz~LO9M2mob@C0h1k9~ffKW2n{J_S`Nu+d4Vcn=SM-Azs!4RXk=6YI+q-x?S)a1C{zO}~ z`hTW$lOz^%#D|=1_N)f@7!`3}BZ5+H=-yM}FoF3ReQCNxGMWyK$DNgCNLXZ z!!x+!GpSgj;DTQHG*K5td>h%h8zhrLG~fF@ZF zb@jUx_(45Q{{vbPl-YrR^LISHLk<8kdgSn-4$R8s`11jb`0mv>^0mbzt|m=$G4^cc zaEIrR^znt$wAf*PsEHdpJgy8K%)jVAzPqTv4Jy4SX_Tn(SI9ZCqVOvjmz4qc2HKAX z+)6o~2T1Lh&q6Qh00ix9cIyxmZaOvl)3cwF2JT(6m1BC@FOQ;?S^(GAB#1<{ZFsxYoBrB;39rgZE_`N71nLhC- zU$m(;XZ(G8f#I5M-<{BLIq4V$pEopYT=~pRoN95w1$(KjnlBO$&V4g7C2U27 zH?BJ0>#IO8bgGfR(T0g0LF#al(giha3hHFWN zL12ZiA0P|)vxPdQ-PGR_7UUvvVI@pS@*#;+={?k=4>7k?45+m*wU*s+NJ$ecND zj@yLi8=l=}s#<(&)Ab~?tNN}fX|$e$iR9@o`zpd_oOraaQSNG<X5N!9QqF7NZnPM`UFHtuv5wF*- z!%LF%$@EW*nybMDELxv}f4Ip535u<1G}FA;g|-Yr_Zsszn!0 zo=XY&r5B{W*FrY&enh#j4o#J*%#ZO9Cva-#hO21GecHvnUwex-ZQyCz*`RiYp~hxr znn+q9P?m6)sUBw|3l{^ATbE|85B``O{mHjm`-yo%t@qEAVoN(Pk3iuT68S(WkjZc{ z!pZ2F;&TY}0by&s=4T|#o!j^kKKuG~#?Dsr)qT2Up2C5rpQdVdfz=e1OKI zt|Bb6NCw47QmMRk{q@&)T=d}xv$k3HPD2dR2ZNK6zbeybMQimhK9=cEpNHSJq>$cp zHbt;yB3>0 ze@^?#O8Ghqt0f^;FN48pmglVJ>!J?jGOdKX>N*R5YhMY=WC?i_Ms(@lhk)bFs$wNB zhfj4@)JaMXO`Bu>KGJos?PsZekiJ0Cam+(D>5w7yTov&EO*%nRTsA8MI`Zf#Za~aa zov3kFdPk+nTIBDt@{Ow5{QIL4A=h4IWo`=AQ_t%jo4DChV`)o^y^aHSk>(Lr$?Hs7 zaY+lL@DwB=EGeN%3n3Tvsx&nC%IGL`Np)<(sX|1~%K?(fpj-!gH>I9lo`|K|Grdhn zEV3Hooyq_f_0h)eqg?uD#Uv9`V&WRrPwdLLm=?wFPL|kNZNq-fdGi%@!M_D2+-pqR z8~a0v;h^9%BRLzi^YZn+DITc1aMa1a_lBiimrN_q)(UMQJ3sPd*$8+)-*5PsR>GrN zmHN~<6XiNvww@*|y^TPe#VZm#e@&+g+k2Vxks0|nd-RLzs}~bv$;u^4EYvEWyfL#e z5h4%)185{E*1DP03z(hL+oY}g+^P*c$wUsXt*~bFptlSax8fMSBNp}Mj1@S6bQ2|i zqBA+z;4)d<&^)M1pU%R80Ip5NS8k4T%SZu#%vUd4dMEqCiXe+?+w6kyB&-dZxS>%N z1D1~z;1RdBZKS zaY)dzizzF8Npn)%Z!{-UHyg@03bb01QBQdNYZPwvO3K=ke$Ns6nEWS()L2QX4)&*F zP)vSPR@g^#hCp4Mv`X*$JT0Tz_n;HHibTG^vwxi9dX^!{+QRkZa1`+`#z0l`1Z#^lJh{s zAf7tGGwm$ui6mRpCIWGfOg1}L4^@WjiuWBolbqQ~_^PX6_UnTf|M?#YTLI~ybPn)z zSKFK(#%Li()2DIt-(S?Klf(2zgE+Pj2t3m9UN(V(_WQqfZWOs=QcY8@=4CFqMPX1K z2W-7cIl2pI9`@sK9j6h&69)n6;XRpJ$vRSn5U%9f^t?Z~B)|l-gH^N%W$F>EwEVlG z#;)y&r+x2?NYlF@qnBPx)N4!HkRbADEl1U7-$WfAaFW?>`zg=$l)_mZ;EaYS?yvoP zYbBdc-~*FkMhkcxDf%TLG_X+=-t^@oX#q4}6-y>I2uj^$erv(ymZ0uq4kpBQz>XI} zE=$J-T^aJp%)Z)Svasi34=nF*`ZEi+LeNP+1Oz(L0F%q^o5872lSRo%ouo+hZN=(i z+)Q5z?Pr_~8J{DQ%P^56Q`Z!Cs_b!*my~EG-VAgk9^VtfEGAUr#RHl1v>W|M5N6AsX?N0sf9h zqE;wF#~mor&-eXam%vzgP{|wqY#FWj^V%Eu&)INODZ`9mrrIQ!4PmIRbljgs3xt}u zEJ_T@jGY&1lE2Ph)?vOVeY=`5rf`O$aOFt)AUiMlF<%q$06FGuD+vE;gyLRHFP%l%z3q@xI zOO%Y8MNK9d?3BCvWK8d=A#1LWt97`*7B1_kZPR{f_M?SdWa0Z=)rr44{VEYB@(~8! z2P+4T!1 zlB~EWjS;^bG3zoA?5)wj%x$}@z&aU-{3ELBPwBBpZz8($V!-hYhfyNd=l=%+Vq@6` zwqd*2JzQ3P3zI?xZG^&1I*Sc^3_?~D2Pd<)jL-9Jy#&yHF_rr zayv3L^8+vCBYr2j9D|gHopz--1>KnaW*S#bx@E%WS`Fc%&I@*JWM5IRkuXXC)~*?O|xV;Ju2phbg9VF^E>8R;vlV z9JQL%Z!w5v*l*TN>F%v=i7fGD(s4OLnFPeH8~7%)-EMXGQ=R^}+K&_SVW^r|>4!pZ z?!hSfyE}mOc-Gg;y@opDXkR3$te||U&xl(eloZV+4!_sCPWW~d0bhN^tA!UG4AbYt z|B-UWYuE4WjEg;g46U5J=Kr4v_S@>2c4vmtv@HCFcvrGNL=hQkct)A!}sDs~o<0 z`r#)k@;20PM#cYP8A-_|anpoS>n9m1J6{eB^P8C6ErUfCgA20Eq$cS?$m0GboA-Y| zHlGzxs?zJ~`%${p7XOwm>)yx4xX)dgXQC2kL&wrpeZK^uK?^PEvgNxujy`^B&SZ=> ziQ+h^dx;`a$DcH~v8H_JQwG%FFJ{PE?tAhGThypQ1kg^5Wf0I?p5YRh>xE2~KDZ-Y zTRsnUb{RQQjVCjTmDg%`c4p`2mpNsqy;2rZWZ9C4k4V8#fW7Q2*}dko+J8zEnkP(` z=|KD99fM)>2fW|oc(?xE&@r?_wc7Y%m^(npl|={72Caqtv>5!Z&w$$ot<`-=ib?e0 z<;!IZG{SySw`Vh$JZgC6v(qLMg$#SgX1ZC3@#%mUe$FT2Y^{Yw)ApyheCem#<j26O$&AmU_iA;91*W^4LHcin{#hjYjCM4lYK>ip*TgsK>T zi0Dhm&FIrO7~o$u>2&XxLe)>x6nng%*ZSDj8DYOyT$&=gtU684GWTT#nGf${*=Hu@ z9Ap^p?q}MElS`!H<8;Om$rw_%-CNrs<_9hcLxE+A;%)K(RxC)}$fQuh>6<>ET{ia;M9>t@>qjWoBQy$dd_+gm_cFIyO$Z}*Vll?ioMf|!^I)p%#vyFv zwMl8Hl+O-3-+qE4on=3DZ6?=9TDmr%Xl_qHn8I-V{HZd1zfeL5a|$)w+3zCSONWE1 z_*A^e@B6J1%5O+n@Bhu}-Q_otw@hIeIo%>wMyE@^1aL@^bgKIPs80p%dSSNI#7VMp zfh{Ec-^1I-PbF@mU!++2EoMZM6vAQ|jrF7n26k|yJp5V0rWX38J{q^8t-q5s_S3uY|s3XM{w|AxxALYC+J zZ-d$a2-8l>5m12M;3w6-A-+zezOR`eMyQ$4OU6qwT#@$I&uAqJQ$Dse(|xKIvFUOD z;@q2A)Br7k!oLag_y!BqWJYEdtbvU<=48g03mA5VR}?gv!nP~CmtyWU-PLcMy^}SP zvc2aQI!V+wWl2C{S>t9MafHS7?S^!|CefBuXjs(4{FZt;q;>n3WgaU2O=o`UI%ag~ z-rHm8#{Q+OYj6t6e8k}}DsW~ES91^MoRmx8Sz_aGZ8OWD5rJoe-Y@M24r8KY4oWJB zBVbg_hi+bi{?C{0W338tJ`P@?2((Vh0R!awpPW&GW$@Y2zz@%c&%P537?5M0=mjWE zHsbacLX_`4c^!i+hbf3!j;U9O{?VAJm772cSUQyESvwuUK4dh;{E^-!{kRIZwJ3*c zM=1q9c+i}Xa3uQ;X@L8hh64v{|ji_gu;V`ehnP#EFrbbvma*b9ee7GK+n>OCVcua3u=HrpbvC{%SkIlu8LAP4Y7gpM#8 zRfh2;*p8wle8F6#a;H+1CL0|xs_xt0^=UUT?`Lf(teO6BF;UQIKJF?occ-mcWrWef zBxK9~C7--v(tSI*U(CASoBxtf0^AWAV@I+8dX z(TeLQ)UF>dwNKJ6{;6|6lW&adaa|AIsc+u%l>YIBj∾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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 06/97] 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 07/97] 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 08/97] 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 09/97] 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 zcmV;V4O{YwP)=m zrl&^Cnh9b?XK2IT!M{p?17p4chSzM(r*3u>`-4U({6}mcIyLsG6R$P|QuP4}17p{K zI<+>|d+OFuS*9>B=4)U?^@LNU7po3sQ6WVc?AkgVAX>mAM^!P zU*gHn*sCxw`U)sMmEKEe%VGk(1&`)Qw0Ftm#LYI4(EyBjm0srec~LnlOf(f}Q2vIh z%=`I{pz3gKc8Sd|hV!3oPH2fG^)57uTm`?j1Ji@wNA}9?a;0K`iV6jeV0HxWWIlR6 ziupY^gDYSLtbhxgyxbPw%_~4V3rpp;fAVjY2T(|=K&~5@atZFXpGCf((Xug+UyR5J zEQON)ghs!^rubptnEjALJb4V|?obXu;b#^j9b2DeO`r9=*!qHGrvi)~&RlE5hD$*# zd?5@EcZuhICb<1`J7jr+L8!ORqiZPu3ym^5)=y?#-_887OSELCHee4j;m`4}6ZT^e zWO?(}OB-1}WEF_`VuJsPAIY?D-?nM7j`at{0V>je9L&7d=`c(D!tnI8`Iuh%+xEl& z#vKcR)Rr=0S`FZmLBfQobZ&MB3P8<=##_E1^;#Ej&Z_GiSqz}n2>N^ukDgDzj%THx z3I9^zRB{{MJ@F@wB>94_5RAD+=9lA6V2}O8j`~m@kP!}E>d8x67t6_YYpRcE(Bi;` zmp^A>uUHV#-U;?3_9Ae{Um(vJoHIcYVbktgDik_s$v$@MJOVo%m!_=1n6E!z=jp*x zi*@IU#Q=(QAOeeXCaIIh&_I|ckevzjzS;!8HMVKv5x)|EbKRj?5^C^NS#X))`fVp# zZQ2Cco^?q8N(nM%S4RCImYpL$m3ht)b|v^TI&yybg66sM$)JBQx8Ei?&l%<)oXEoc zlfWSt!~y>PqZEK5aOf-?d}S^J+9ya;H9-IEi#VLv51h&f9Kwg4vPqvb8gJ3P5tb}! z>&fe2omIoCuJJX`|d9IJ2rGXPZlys{h?Zel}6e5Hzt%5K+6V&Yh(W4j1 zAms>~P7ftC>K$8PssTXZ3W8CIeKpQoDaS4&(F-jWm{|4l-ZL3uqk`EDyl!$Q zBp5Fda1{706THGVL3%SV-GBTPRlP>Y7Y;t7@!$>r9jqK2CUc?*)}9#7)EHs9`Hz!o5rymD=0QjZPW6FY zaNqJJS=ZZE-3LYbu^7QKh1GuBnbv)mmbL`0;N5eHI2BkKB2fWALEH3jHh2czTV9rd zqX2xigmLv+cbgV%)+&4>uO9CQ{DZ#?*q}Z9Yg`ELN4+TzL!7qWQhp@XQk8@BHRntw zcRj@CeoOJNS&&8~R7kx8jW$L?R(%?3VQmjwRbk|E6I)=uCasB5`MJI137u?@516(3jk$alRrP zLvVAG8)syK=ekH*c%~82{|o${`&Wr_%6{_Nug$cD(8)LTG!2i02QHv1fP5Ft9Ow3m z=DnV4ardxk!V0H<@!|DjQ#pO*4^Su=KhQD}_0>1Q4WiEbF(T5&flKcRRT7|PKCaB@ zyNwlrD`jb~5~h+DVxsUfmuwOyOs8|R6bVwKJz+)$D9nM?31gWN_lj&l*-5#@0G?@FpE#Bl zjS3|J$OXTcPnh2J7@^%`rJo6Kxe)QMAp{=@g|ug-8H>PFd=(*M9b- z^;a9f>?AFs`OK~i>U5az zN6s&LEV=^%l#t&7$8U9EW_&1TetKS}pW-FiqhjZH5Y+tu(PBMEcyI3%mK+&h8e6Ig zKznIqVE5P$8P@5D6i$5F*tw7cCxf7VicO`(Bof*Y6@_aCiJ_C}&^%Q#BLPqxkWF*S zKO^8)E6G+$lw^;rB}~?;XI$4G*gAB9=8JdJz-8r6elmr;YK z$Vg{|gd0uix^)FSaF-gi50OVLCK|U$Wc`a97}D~TG;5pYAHHXRWhcimYtM9WD5LEt zXrO3YHoeAu(<6TT5kOJg@x1SljD8p(CzL znm$YL^0rM<;NQt^EI%`qg}s;JF4#%&_~8KOZ}`xC*I(hD=tJ9*zcC;GcJXZNzmOJ< z#A!-!_wK=h_*ty@F%Sw2Wig~`XwVMQ?98C9Kk)sSkEKtUVB5I>J~=azuzsr;(DuSZ z7LuC=UCPwK*aEw-NsGXHxsc>tG|?&4j<5`y-1lyo9r34iPVIVtD(b56d=D zpRT_+f^uf{Iw=cdVK&0_ggJ^)0N?!7kEwCNq~GWu zqpQ}0(sN?MY{~{j8}ZV#j&BygsqT%2i}N#pUCt6GT&+WQS>M)EP898L4jVY|C|U5T*-g; z*)C004||e&6S!*u?w&2_rta6&hI{_$6=o?UY(Hz`ZP}ziyY7u$T4Oj$gxz ze0Q@q^G^w7xr79cU|z9bx71 zQOt;$DSgiVwMhsld^gWUYf!z~^$;ujEuo%^)ZpDa;Jq#ias~gi^?fR|!g94)8vsR- zYSd2qT<}b~i5gC%utI1Z5yrKv-M}PjHlb}1eRTA0dz!Ep*5UiyCHbz%g9^<0{wnKyo}d+**b9!FlP50cAg!`Y`OTMxf)n6qHPsVRJVItcE0OJE`u zJTY+E{hdg0(`h-VZ`B$=u~3c&gS#GL&nth{B4ot>4kkEmg8W7y0!UdUQLPH0`T7!Z z%i>*NNv*D3C<;%NIsJC=V_Gu~B)$Mvo%A(3U8~g%%UVpCsW9l6ZMAhRZYwSf ziH{|=ue?=fAvKky5WT*gOs4@ct5KO&(-ohp`3h^;7c|{|A+`Zl%Z>jBw|(troP|;G z;k%*fMTF?3*u^O7dry@XsxQo3_6Lbu5XBf@{~rwKbAnNnkAN1{U%O6c-az3)3Y@>< z&;YF=QaYs#h#8NnbVN}bVWkNQ;sTf8{7=)!LFG0&l2Mfu6g823L0cXb@c#h9k`aVp S@FYF}0000 Date: Fri, 25 Jun 2021 19:56:38 +0200 Subject: [PATCH 10/97] 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 11/97] 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 12/97] 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 13/97] 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 14/97] 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 zcmV;V4O{YwP)=m zrl&^Cnh9b?XK2IT!M{p?17p4chSzM(r*3u>`-4U({6}mcIyLsG6R$P|QuP4}17p{K zI<+>|d+OFuS*9>B=4)U?^@LNU7po3sQ6WVc?AkgVAX>mAM^!P zU*gHn*sCxw`U)sMmEKEe%VGk(1&`)Qw0Ftm#LYI4(EyBjm0srec~LnlOf(f}Q2vIh z%=`I{pz3gKc8Sd|hV!3oPH2fG^)57uTm`?j1Ji@wNA}9?a;0K`iV6jeV0HxWWIlR6 ziupY^gDYSLtbhxgyxbPw%_~4V3rpp;fAVjY2T(|=K&~5@atZFXpGCf((Xug+UyR5J zEQON)ghs!^rubptnEjALJb4V|?obXu;b#^j9b2DeO`r9=*!qHGrvi)~&RlE5hD$*# zd?5@EcZuhICb<1`J7jr+L8!ORqiZPu3ym^5)=y?#-_887OSELCHee4j;m`4}6ZT^e zWO?(}OB-1}WEF_`VuJsPAIY?D-?nM7j`at{0V>je9L&7d=`c(D!tnI8`Iuh%+xEl& z#vKcR)Rr=0S`FZmLBfQobZ&MB3P8<=##_E1^;#Ej&Z_GiSqz}n2>N^ukDgDzj%THx z3I9^zRB{{MJ@F@wB>94_5RAD+=9lA6V2}O8j`~m@kP!}E>d8x67t6_YYpRcE(Bi;` zmp^A>uUHV#-U;?3_9Ae{Um(vJoHIcYVbktgDik_s$v$@MJOVo%m!_=1n6E!z=jp*x zi*@IU#Q=(QAOeeXCaIIh&_I|ckevzjzS;!8HMVKv5x)|EbKRj?5^C^NS#X))`fVp# zZQ2Cco^?q8N(nM%S4RCImYpL$m3ht)b|v^TI&yybg66sM$)JBQx8Ei?&l%<)oXEoc zlfWSt!~y>PqZEK5aOf-?d}S^J+9ya;H9-IEi#VLv51h&f9Kwg4vPqvb8gJ3P5tb}! z>&fe2omIoCuJJX`|d9IJ2rGXPZlys{h?Zel}6e5Hzt%5K+6V&Yh(W4j1 zAms>~P7ftC>K$8PssTXZ3W8CIeKpQoDaS4&(F-jWm{|4l-ZL3uqk`EDyl!$Q zBp5Fda1{706THGVL3%SV-GBTPRlP>Y7Y;t7@!$>r9jqK2CUc?*)}9#7)EHs9`Hz!o5rymD=0QjZPW6FY zaNqJJS=ZZE-3LYbu^7QKh1GuBnbv)mmbL`0;N5eHI2BkKB2fWALEH3jHh2czTV9rd zqX2xigmLv+cbgV%)+&4>uO9CQ{DZ#?*q}Z9Yg`ELN4+TzL!7qWQhp@XQk8@BHRntw zcRj@CeoOJNS&&8~R7kx8jW$L?R(%?3VQmjwRbk|E6I)=uCasB5`MJI137u?@516(3jk$alRrP zLvVAG8)syK=ekH*c%~82{|o${`&Wr_%6{_Nug$cD(8)LTG!2i02QHv1fP5Ft9Ow3m z=DnV4ardxk!V0H<@!|DjQ#pO*4^Su=KhQD}_0>1Q4WiEbF(T5&flKcRRT7|PKCaB@ zyNwlrD`jb~5~h+DVxsUfmuwOyOs8|R6bVwKJz+)$D9nM?31gWN_lj&l*-5#@0G?@FpE#Bl zjS3|J$OXTcPnh2J7@^%`rJo6Kxe)QMAp{=@g|ug-8H>PFd=(*M9b- z^;a9f>?AFs`OK~i>U5az zN6s&LEV=^%l#t&7$8U9EW_&1TetKS}pW-FiqhjZH5Y+tu(PBMEcyI3%mK+&h8e6Ig zKznIqVE5P$8P@5D6i$5F*tw7cCxf7VicO`(Bof*Y6@_aCiJ_C}&^%Q#BLPqxkWF*S zKO^8)E6G+$lw^;rB}~?;XI$4G*gAB9=8JdJz-8r6elmr;YK z$Vg{|gd0uix^)FSaF-gi50OVLCK|U$Wc`a97}D~TG;5pYAHHXRWhcimYtM9WD5LEt zXrO3YHoeAu(<6TT5kOJg@x1SljD8p(CzL znm$YL^0rM<;NQt^EI%`qg}s;JF4#%&_~8KOZ}`xC*I(hD=tJ9*zcC;GcJXZNzmOJ< z#A!-!_wK=h_*ty@F%Sw2Wig~`XwVMQ?98C9Kk)sSkEKtUVB5I>J~=azuzsr;(DuSZ z7LuC=UCPwK*aEw-NsGXHxsc>tG|?&4j<5`y-1lyo9r34iPVIVtD(b56d=D zpRT_+f^uf{Iw=cdVK&0_ggJ^)0N?!7kEwCNq~GWu zqpQ}0(sN?MY{~{j8}ZV#j&BygsqT%2i}N#pUCt6GT&+WQS>M)EP898L4jVY|C|U5T*-g; z*)C004||e&6S!*u?w&2_rta6&hI{_$6=o?UY(Hz`ZP}ziyY7u$T4Oj$gxz ze0Q@q^G^w7xr79cU|z9bx71 zQOt;$DSgiVwMhsld^gWUYf!z~^$;ujEuo%^)ZpDa;Jq#ias~gi^?fR|!g94)8vsR- zYSd2qT<}b~i5gC%utI1Z5yrKv-M}PjHlb}1eRTA0dz!Ep*5UiyCHbz%g9^<0{wnKyo}d+**b9!FlP50cAg!`Y`OTMxf)n6qHPsVRJVItcE0OJE`u zJTY+E{hdg0(`h-VZ`B$=u~3c&gS#GL&nth{B4ot>4kkEmg8W7y0!UdUQLPH0`T7!Z z%i>*NNv*D3C<;%NIsJC=V_Gu~B)$Mvo%A(3U8~g%%UVpCsW9l6ZMAhRZYwSf ziH{|=ue?=fAvKky5WT*gOs4@ct5KO&(-ohp`3h^;7c|{|A+`Zl%Z>jBw|(troP|;G z;k%*fMTF?3*u^O7dry@XsxQo3_6Lbu5XBf@{~rwKbAnNnkAN1{U%O6c-az3)3Y@>< z&;YF=QaYs#h#8NnbVN}bVWkNQ;sTf8{7=)!LFG0&l2Mfu6g823L0cXb@c#h9k`aVp 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 15/97] 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: Sun, 11 Jul 2021 21:07:20 +0200 Subject: [PATCH 16/97] 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 17/97] 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 18/97] 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 19/97] 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 20/97] 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 21/97] 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 22/97] 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 23/97] 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 24/97] 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 25/97] 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 26/97] 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 27/97] 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 28/97] 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 29/97] 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 30/97] 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 31/97] 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 32/97] 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 33/97] 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 34/97] 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 35/97] 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 36/97] 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 37/97] 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 38/97] 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 39/97] 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 40/97] 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 41/97] 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 42/97] 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 43/97] 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 44/97] 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 45/97] 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 46/97] 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 47/97] 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 48/97] 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 49/97] 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 50/97] 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 51/97] 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 52/97] 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 53/97] 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 54/97] 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 ba63388a0939de6fd17fab74eef8710f889bfebe Mon Sep 17 00:00:00 2001 From: numerist Date: Sun, 18 Jul 2021 06:31:23 -0400 Subject: [PATCH 55/97] 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 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 56/97] 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 57/97] 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 58/97] 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 59/97] 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 60/97] 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 61/97] 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 62/97] 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 63/97] 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 64/97] 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 65/97] 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 66/97] 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 67/97] 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 68/97] 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 69/97] 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 70/97] 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 71/97] 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 72/97] 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 73/97] 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 74/97] 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 75/97] 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 76/97] 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 77/97] 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 78/97] 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 79/97] 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 80/97] 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 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 81/97] 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 82/97] 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 83/97] 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 8c5b0e4c362512781984269f353b212d6ebc09ba Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 26 Jul 2021 09:10:22 +0100 Subject: [PATCH 84/97] 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 6168782cf5c1335c149b99c4e29c06cab6c52a17 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 26 Jul 2021 15:53:46 +0100 Subject: [PATCH 85/97] 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 86/97] 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 2dda299cabf308507c1f5ca6e16dc6b1937adced Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 27 Jul 2021 10:22:41 +0100 Subject: [PATCH 87/97] 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 88/97] 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 89/97] 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 90/97] 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 91/97] 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 92/97] 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 93/97] 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 04b7af4a6a87e25fbf54edb323022c071563f53a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Jul 2021 09:41:27 +0100 Subject: [PATCH 94/97] 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 95/97] 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 96/97] 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 d551e9d78c2960574fbc87f4923cd0cea5312455 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Jul 2021 16:30:16 +0100 Subject: [PATCH 97/97] 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