From 128257c4bbf491688366c605dfe992db97cf9720 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 10:52:30 +0100 Subject: [PATCH 01/31] Create app.js --- apps/stressless/app.js | 303 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 apps/stressless/app.js diff --git a/apps/stressless/app.js b/apps/stressless/app.js new file mode 100644 index 000000000..b5e0ba8dd --- /dev/null +++ b/apps/stressless/app.js @@ -0,0 +1,303 @@ +var option = null; + +//debugging or analysis files +var logfile = require("Storage").open("HRV_log.csv", "w"); + +logfile = require("Storage").open("HRV_log.csv", "a"); + +var csv = [ + "time", + "sample count", + "HR", + "SDNN", + "RMSSD", + "Temp", + "movement" + ]; +logfile.write(csv.join(",")+"\n"); + +var debugging = true; +var samples = 0; // how many samples have we connected? +var collectData = false; // are we currently collecting data? + +var BPM_array = []; +var raw_HR_array = new Float32Array(1536); +var alternate_array = new Float32Array(3072); +var pulse_array = []; +var cutoff_threshold = 0.5; +var sample_frequency = 51.6; +var gap_threshold = 0.15; +var movement = 0; + +var px = g.getWidth()/2; +var py = g.getHeight()/2; +var accel; // interval for acceleration logging + +function storeMyData(data, file_type) { "ram" + log = raw_HR_array; + // shift elements backwards - note the 4, because a Float32 is 4 bytes + log.set(new Float32Array(log.buffer, 4 /*bytes*/)); + // add ad final element + log[log.length - 1] = data; +} + +function average(samples) { + return E.sum(samples) / samples.length; // faster builtin + /* var sum = 0; + for (var i = 0; i < samples.length; i++) { + sum += parseFloat(samples[i]); + } + var avg = sum / samples.length; + return avg;*/ +} + +function StandardDeviation (array) { + const n = array.length; + const mean = E.sum(array) / n; //array.reduce((a, b) => a + b) / n; + //return Math.sqrt(array.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n); + return Math.sqrt(E.variance(array, mean)); +} + +function turn_off() { + Bangle.setHRMPower(0); + + + g.clear(); + g.drawString("processing 1/5", px, py); + + rolling_average(raw_HR_array,5); + g.clear(); + g.drawString("processing 2/5", px, py); + + upscale(); + g.clear(); + g.drawString("processing 3/5", px, py); + + rolling_average(alternate_array,5); + g.clear(); + g.drawString("processing 4/5", px, py); + + apply_cutoff(); + find_peaks(); + + g.clear(); + g.drawString("processing 5/5", px, py); + + calculate_HRV(); +} + +function bernstein(A, B, C, D, E, t) { "ram" + s = 1 - t; + x = (A * Math.pow(s, 4)) + (B * 4 * Math.pow(s, 3) * t) + (C * 6 * s * s * t * t) + + (D * 4 * s * Math.pow(t, 3)) + (E * Math.pow(t, 4)); + return x; +} + +function upscale() { "ram" + var index = 0; + for (let i = raw_HR_array.length - 1; i > 5; i -= 5) { + p0 = raw_HR_array[i]; + p1 = raw_HR_array[i - 1]; + p2 = raw_HR_array[i - 2]; + p3 = raw_HR_array[i - 3]; + p4 = raw_HR_array[i - 4]; + for (let T = 0; T < 100; T += 10) { + x = T / 100; + D = bernstein(p0, p1, p2, p3, p4, x); + alternate_array[index] = D; + index++; + } + } +} + +function rolling_average(values, count) { "ram" + var temp_array = []; + + for (let i = 0; i < values.length; i++) { + temp_array = []; + for (let x = 0; x < count; x++) + temp_array.push(values[i + x]); + values[i] = average(temp_array); + } +} + +function apply_cutoff() { "ram" + var x; + for (let i = 0; i < alternate_array.length; i++) { + x = alternate_array[i]; + if (x < cutoff_threshold) + x = cutoff_threshold; + alternate_array[i] = x; + } +} + +function find_peaks() { "ram" + var previous; + var previous_slope = 0; + var slope; + var gap_size = 0; + var temp_array = []; + + for (let i = 0; i < alternate_array.length; i++) { + if (previous == null) + previous = alternate_array[i]; + slope = alternate_array[i] - previous; + if (slope * previous_slope < 0) { + if (gap_size > 30) { + pulse_array.push(gap_size); + gap_size = 0; + } + } + else { + gap_size++; + } + previous_slope = slope; + previous = alternate_array[i]; + } +} + +function RMSSD(samples){ "ram" + var sum = 0; + var square = 0; + var data = []; + var value = 0; + + for (let i = 0; i < samples.length-1; i++) { + value = Math.abs(samples[i]-samples[i+1])*((1 / (sample_frequency * 2)) * 1000); + data.push(value); + } + + for (let i = 0; i < data.length; i++) { + square = data[i] * data[i]; + Math.round(square); + sum += square; + } + + var meansquare = sum/data.length; + var RMS = Math.sqrt(meansquare); + RMS = parseInt(RMS); + return RMS; +} + +function calculate_HRV() { + var gap_average = average(pulse_array); + var temp_array = []; + var gap_max = (1 + gap_threshold) * gap_average; + var gap_min = (1 - gap_threshold) * gap_average; + for (let i = 0; i < pulse_array.length; i++) { + if (pulse_array[i] > gap_min && pulse_array[i] < gap_max) + temp_array.push(pulse_array[i]); + } + gap_average = average(temp_array); + var calculatedHR = (sample_frequency*60)/(gap_average/2); + if(option == 0) + Bangle.setLCDPower(1); + g.clear(); + //var display_stdv = StandardDeviation(pulse_array).toFixed(1); + var SDNN = (StandardDeviation(temp_array) * (1 / (sample_frequency * 2) * 1000)).toFixed(0); + var RMS_SD = RMSSD(temp_array); + g.drawString("SDNN:" + SDNN + +"\nRMSSD:" + RMS_SD + + "\nHR:" + calculatedHR.toFixed(0) + +"\nSample Count:" + temp_array.length, px, py); + Bangle.setLCDPower(1); + if(option == 0) { // single run + Bangle.buzz(500,1); + option = null; + drawButtons(); + } else { + var csv = [ + 0|getTime(), + temp_array.length, + calculatedHR.toFixed(0), + SDNN, + RMS_SD, + E.getTemperature(), + movement.toFixed(5) + ]; + logfile.write(csv.join(",")+"\n"); + + + // for (let i = 0; i < raw_HR_array.length; i++) { + // raw_HR_array[i] = null; + //} + + turn_on(); + } +} + +function btn1Pressed() { + if(option === null){ + g.clear(); + g.drawString("one-off assessment", px, py); + option = 0; + + turn_on(); + } +} + +function btn3Pressed() { + if(option === null){ + logfile.write(""); //reset HRV log + g.clear(); + g.drawString("continuous mode", px, py); + option = 1; + + turn_on(); + } +} + +function turn_on() { + BPM_array = []; + pulse_array = []; + samples = 0; + if (accel) clearInterval(accel); + movement = 0; + accel = setInterval(function () { + movement = movement + Bangle.getAccel().diff; + }, 1000); + Bangle.setHRMPower(1); + collectData = true; +} + +function drawButtons() { + g.setColor("#00ff7f"); + g.setFont("6x8", 2); + g.setFontAlign(-1,1); + g.drawString("continuous", 120, 210); + g.drawString("one-time", 140, 50); + g.setColor("#ffffff"); + g.setFontAlign(0, 0); +} + +g.clear(); + +drawButtons(); + +g.setFont("6x8", 2); +g.setColor("#ffffff"); +g.setFontAlign(0, 0); // center font +g.drawString("check app README\nfor more info", px, py); + +setWatch(btn1Pressed, BTN1, {repeat:true}); +setWatch(btn3Pressed, BTN3, {repeat:true}); + + + +Bangle.on('HRM-raw', function (e) { + if (!collectData) return; + storeMyData(e.raw, 0); + if (!(samples & 7)) { + Bangle.setLCDPower(1); + g.clearRect(0, py-10, g.getWidth(), py+22); + if (samples < 100) + g.drawString("setting up...\nremain still " + samples + "%", px, py, true); + else + g.drawString("logging: " + (samples*100/raw_HR_array.length).toFixed(0) + "%", px, py, true); + } + if (samples > raw_HR_array.length) { + collectData = false; + turn_off(); + } + samples++; +}); From fc28c7306f9aeaf041bf92024d26afb832681084 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 10:59:05 +0100 Subject: [PATCH 02/31] add png --- apps/stressless/stressless.png | Bin 0 -> 1838 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/stressless/stressless.png diff --git a/apps/stressless/stressless.png b/apps/stressless/stressless.png new file mode 100644 index 0000000000000000000000000000000000000000..6f79d7c838d5807b01f379c196c9e280a645b099 GIT binary patch literal 1838 zcmV+}2hsS6P)j z3jVg|@-`{BCtZe8u#-~ow>-h0z{dC&quRsqe3U2HQfp5Nekx;&ds*AIZ81!UeSW~e zRU^Mq3ic~0Sjuxb^{2r%f^X|@VCx9aWi3(dNtbO>qW*KWffszb=Q3Gopkig+(v96) zXitvg->%i38W*2d6?iG)%~J55>Ichu&*f<;_`^ASE_>9r)of4j9_g|rkv$(7{FJZv zPr{AeD@FXifq?h&NK}l3&H1QdR@29m|IG4=;m_#6zhxR0LWJKZJSr5S=|w z@W8inZMd{K0G)dG&y;-g^|Ez@K*~zOtx$Z0GgKHECfSM?Ofu&9C&aO;*qL{!X_YjuL^NI_1RQ^x`daqCK56*xE|o#4*9& z;5nNX{>rCw2K_ZZ&XC&idZumC9h5%No&mmob+4VtcLtFwCU8D7f#B5E$VNE*i4tsK zVMpu1`~lUhNx640w{IQb4<8Ahd-m@O(k!f*aK`F6aG-ArJ+>%F9}6BI{XwPNf5@pM z!r)u^9_X4r`hz2BI98l1d*~cmyObWQ;W!_KR6jIgw+#Zr>j2XD^bVoZ9(CphRsby z1B7*uK7Jy%$dx3&_1D!;nS$%?M7*IY@Vz8rcS)BeLu0A8c9A!+p=gk>4suiO+Esnu z+x4PgMUM!+#~w+Yfru2bIpG;u&74s2d_ZSDBsHV>JN?qnssr!xv~uH30|MV02|hhP zol0p~2dO<}_CJYu6`p4)Pq6vUV2X6(W9=@m+@N6{_^X!HHp{rVwDG(I|Hhz#&yg4( z`&!}b)Ta(Q&h)!&sHlRS?-~~y<6KO!cc7lj4weFtziX{Q+qx3*o1LK$YHa+tC-}xv zcSW^%p1)={lg?0!H;&KE-YVCc@4mgpbcR!8qW)HULaHTYJW+qUb14Yb)qPC5Y(=DN z^Wfr_y-ee8`=oQJiAwPLz_Vouu%k6^3x+frBHo;Ty0iNkTlCiJ2C+#4-0uvv7=Yy( zaeX!aMv^XnQwqKl-Plcec3#$qt1lYRPz=CQ1JI@s_azZsjo6_P&-%W9mjQTR1MKyE zf0{;IXAn;qfH#Qf69(X^Y`?!C;wX*yJp=GBgZOvtdAElI$n$Q{0B;+_cB9lIMD!^Q zu-o=E0Go;EDucK!`yAMIsu6?uf${xjU#WYv*0*WIH5%Y0BKovJBn|M*Bw|7XbQ-0& zLHwHrn5z*_8N@~Qz1I3xjksSUuCio}QuQH$Kmm3q5yxr(lSG`T5ziTbF$Qs=@B3fL zwvW|_^GV9@y3SW>rUvM?psXelCmE&U261b)-)IZO0KB3R zPy4=qcSyh>witkeVPBH+vlggEe8&L%!$!bYYL*7rWg|}A-JgjJo`^n@O^Y8{V;b?n zY-+SxG9dwL)TUJc3Segd)}{o&G6V2W4KPn5{?*n_7TB^}1Z;#5Piw@V7{u)cpwR#v zv+1M(JOglteQ&csBc9hOzkmrrihz}%ve+m&@K}1(uBEIi`*$!?!WWQ5Njns(W zwV}@TyCK_ea?r1{^I8os$5(0w5q;DsRcBKx8)a^51QEZKeU53w1=bPv*@CuFvF%lX c|9_JI0mlPN+v_lqkpKVy07*qoM6N<$f>$k$_W%F@ literal 0 HcmV?d00001 From 5c17492486879d8e4bc933b7b69bdbfbf27cfb28 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:02:37 +0100 Subject: [PATCH 03/31] Create app-icon.js --- apps/stressless/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/stressless/app-icon.js diff --git a/apps/stressless/app-icon.js b/apps/stressless/app-icon.js new file mode 100644 index 000000000..7eabcf2e9 --- /dev/null +++ b/apps/stressless/app-icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("mEwwhC/AH4AVhnM5nABJ4ACBYIADBJojFAAYnCBJIkJEwYJJFw/NEwYuGGAwJE6gSHGBAkFoYXNNZEzC60/7gXPA4nN/8sMB4GE4f/ngXqIYPf+f9AwPEC53NCYNPmfyVZoXD4fzRwMyAYKTMU4fT+fcn9NC4ZjJX4kv/8tGIXc4n/nr4DmgXGgf//5FDn8sSYPyAQIABHAQXEgE/+ZgB+g0BnnT+Xz6YXHCwRIC4X/SIPfnlPnk/MIRHEFwYXC5oPC4f9JIJoBph2IAASJE4fyPIKYCUo4wF74nB4XzLALICFxQwC4b0CRoL4DFxQwC5oMCn4UCbAouHMIbtLCxBhCAAMvRYwuKGAnfRYwuKGAh7CFyAwDPYYuPPQwWSPQhFQGBIWQDAoWSDAZFPh5iFCwP/Cpnw/4CC+ADBBAkPAYIdG+AmBGAPwAAItC/4JBBQI9FF4oRBF4oABDoYvGCAIXDAAIDBIYQLBBoQAxA")) From f6231de549559fd4375ca1088661b18e98439945 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:04:58 +0100 Subject: [PATCH 04/31] Create metadata.json --- apps/stressless/metadata.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 apps/stressless/metadata.json diff --git a/apps/stressless/metadata.json b/apps/stressless/metadata.json new file mode 100644 index 000000000..5d9786b4c --- /dev/null +++ b/apps/stressless/metadata.json @@ -0,0 +1,12 @@ +{ "id": "stressless", + "name": "Stressless", + "shortName":"Stressless", + "icon": "stressless.png", + "version":"0.01", + "description": "This is a heart activity tracker for PIIS stressless project", + "tags": "", + "storage": [ + {"name":"stressless.app.js","url":"app.js"}, + {"name":"stressless.img","url":"app-icon.js","evaluate":true} + ] +} From e0f9b5695aa51833235ca493d49e9f8c3fd62547 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:30:06 +0100 Subject: [PATCH 05/31] Update metadata.json --- apps/stressless/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/stressless/metadata.json b/apps/stressless/metadata.json index 5d9786b4c..8c27620d3 100644 --- a/apps/stressless/metadata.json +++ b/apps/stressless/metadata.json @@ -4,7 +4,8 @@ "icon": "stressless.png", "version":"0.01", "description": "This is a heart activity tracker for PIIS stressless project", - "tags": "", + "tags": "health", + "supports": ["BANGLEJS"], "storage": [ {"name":"stressless.app.js","url":"app.js"}, {"name":"stressless.img","url":"app-icon.js","evaluate":true} From 221138a98127a412b73e7486d65716d98e9079f6 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:34:34 +0100 Subject: [PATCH 06/31] Update app-icon.js --- apps/stressless/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/stressless/app-icon.js b/apps/stressless/app-icon.js index 7eabcf2e9..0dd5ec32a 100644 --- a/apps/stressless/app-icon.js +++ b/apps/stressless/app-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("mEwwhC/AH4AVhnM5nABJ4ACBYIADBJojFAAYnCBJIkJEwYJJFw/NEwYuGGAwJE6gSHGBAkFoYXNNZEzC60/7gXPA4nN/8sMB4GE4f/ngXqIYPf+f9AwPEC53NCYNPmfyVZoXD4fzRwMyAYKTMU4fT+fcn9NC4ZjJX4kv/8tGIXc4n/nr4DmgXGgf//5FDn8sSYPyAQIABHAQXEgE/+ZgB+g0BnnT+Xz6YXHCwRIC4X/SIPfnlPnk/MIRHEFwYXC5oPC4f9JIJoBph2IAASJE4fyPIKYCUo4wF74nB4XzLALICFxQwC4b0CRoL4DFxQwC5oMCn4UCbAouHMIbtLCxBhCAAMvRYwuKGAnfRYwuKGAh7CFyAwDPYYuPPQwWSPQhFQGBIWQDAoWSDAZFPh5iFCwP/Cpnw/4CC+ADBBAkPAYIdG+AmBGAPwAAItC/4JBBQI9FF4oRBF4oABDoYvGCAIXDAAIDBIYQLBBoQAxA")) +E.toArrayBuffer(atob("mEwxH+AH4A/AH4A/AFW7AAgThDBQeNCaYaSDg4TTFygcFCaYuWDgYTTFyHB5AmRGCARK4XJF7bXR5PQF9vQ6/CF8COL6/XYDgwERxYvBYEKOM67AhLQwEDFwTAGYywvIXIIhCAgPQSILAE4RmWF5AnBMAQECA4gJDMCovDGAfBQ4PR4K+C4RiCZAr3UFwgvDJ4IAB5IrEYAgJBHwaoF6HQNRIvFEQItDXYaTEYAQ+EAogADZZIvFGAYTBAgIBBFQg0CRwQREF5wuGeQpNDQYSUDAYYyFR5guIF4jyCdQ3CMYY+DNwTtRMBSJCAwgyBNAI+HFygwEQoJ4EQwQpEHwwuVGAhPFGwIABFIY+GFywwDdoTAFe4ZgCFzjDFSAy4NFyowIF4PIF0gwHXAKYGFz4wHXBgubGAxeOFzT1KFsowQF0AwNF0QxKFsoxIEj/XGBgQDCJYrODQICHEgQDGAQoSECwhaNCoYJDAwgoHBxBfVJgpfJGIgOHL5haGPgoBDTxIBHAH4AkA==")) From dd82b80b86fa8fc7eaac5c29e4da82f7f77a00a0 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:35:39 +0100 Subject: [PATCH 07/31] Update app-icon.js --- apps/stressless/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/stressless/app-icon.js b/apps/stressless/app-icon.js index 0dd5ec32a..0d9739661 100644 --- a/apps/stressless/app-icon.js +++ b/apps/stressless/app-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("mEwxH+AH4A/AH4A/AFW7AAgThDBQeNCaYaSDg4TTFygcFCaYuWDgYTTFyHB5AmRGCARK4XJF7bXR5PQF9vQ6/CF8COL6/XYDgwERxYvBYEKOM67AhLQwEDFwTAGYywvIXIIhCAgPQSILAE4RmWF5AnBMAQECA4gJDMCovDGAfBQ4PR4K+C4RiCZAr3UFwgvDJ4IAB5IrEYAgJBHwaoF6HQNRIvFEQItDXYaTEYAQ+EAogADZZIvFGAYTBAgIBBFQg0CRwQREF5wuGeQpNDQYSUDAYYyFR5guIF4jyCdQ3CMYY+DNwTtRMBSJCAwgyBNAI+HFygwEQoJ4EQwQpEHwwuVGAhPFGwIABFIY+GFywwDdoTAFe4ZgCFzjDFSAy4NFyowIF4PIF0gwHXAKYGFz4wHXBgubGAxeOFzT1KFsowQF0AwNF0QxKFsoxIEj/XGBgQDCJYrODQICHEgQDGAQoSECwhaNCoYJDAwgoHBxBfVJgpfJGIgOHL5haGPgoBDTxIBHAH4AkA==")) +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AFW7AAgThDBQeNCaYaSDg4TTFygcFCaYuWDgYTTFyHB5AmRGCARK4XJF7bXR5PQF9vQ6/CF8COL6/XYDgwERxYvBYEKOM67AhLQwEDFwTAGYywvIXIIhCAgPQSILAE4RmWF5AnBMAQECA4gJDMCovDGAfBQ4PR4K+C4RiCZAr3UFwgvDJ4IAB5IrEYAgJBHwaoF6HQNRIvFEQItDXYaTEYAQ+EAogADZZIvFGAYTBAgIBBFQg0CRwQREF5wuGeQpNDQYSUDAYYyFR5guIF4jyCdQ3CMYY+DNwTtRMBSJCAwgyBNAI+HFygwEQoJ4EQwQpEHwwuVGAhPFGwIABFIY+GFywwDdoTAFe4ZgCFzjDFSAy4NFyowIF4PIF0gwHXAKYGFz4wHXBgubGAxeOFzT1KFsowQF0AwNF0QxKFsoxIEj/XGBgQDCJYrODQICHEgQDGAQoSECwhaNCoYJDAwgoHBxBfVJgpfJGIgOHL5haGPgoBDTxIBHAH4AkA==")) From 8a4be166af798326319ccd7139ae7017561c4e96 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:48:26 +0100 Subject: [PATCH 08/31] Create ChangeLog --- apps/stressless/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/stressless/ChangeLog diff --git a/apps/stressless/ChangeLog b/apps/stressless/ChangeLog new file mode 100644 index 000000000..55ebb3e4b --- /dev/null +++ b/apps/stressless/ChangeLog @@ -0,0 +1 @@ +0.01: New App From 0b2dfae94fe353880b72d25ffea69946367a64f9 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:54:24 +0100 Subject: [PATCH 09/31] Update app.js --- apps/stressless/app.js | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/apps/stressless/app.js b/apps/stressless/app.js index b5e0ba8dd..2caf7ac40 100644 --- a/apps/stressless/app.js +++ b/apps/stressless/app.js @@ -1,9 +1,9 @@ var option = null; //debugging or analysis files -var logfile = require("Storage").open("HRV_log.csv", "w"); +//var logfile = require("Storage").open("HRV_log.csv", "w"); -logfile = require("Storage").open("HRV_log.csv", "a"); +var logfile = require("Storage").open("HRV_log.csv", "a"); var csv = [ "time", @@ -16,11 +16,9 @@ var csv = [ ]; logfile.write(csv.join(",")+"\n"); -var debugging = true; var samples = 0; // how many samples have we connected? var collectData = false; // are we currently collecting data? -var BPM_array = []; var raw_HR_array = new Float32Array(1536); var alternate_array = new Float32Array(3072); var pulse_array = []; @@ -43,12 +41,6 @@ function storeMyData(data, file_type) { "ram" function average(samples) { return E.sum(samples) / samples.length; // faster builtin - /* var sum = 0; - for (var i = 0; i < samples.length; i++) { - sum += parseFloat(samples[i]); - } - var avg = sum / samples.length; - return avg;*/ } function StandardDeviation (array) { @@ -216,25 +208,11 @@ function calculate_HRV() { movement.toFixed(5) ]; logfile.write(csv.join(",")+"\n"); - - - // for (let i = 0; i < raw_HR_array.length; i++) { - // raw_HR_array[i] = null; - //} - turn_on(); } } -function btn1Pressed() { - if(option === null){ - g.clear(); - g.drawString("one-off assessment", px, py); - option = 0; - turn_on(); - } -} function btn3Pressed() { if(option === null){ @@ -248,7 +226,7 @@ function btn3Pressed() { } function turn_on() { - BPM_array = []; + pulse_array = []; samples = 0; if (accel) clearInterval(accel); @@ -265,7 +243,6 @@ function drawButtons() { g.setFont("6x8", 2); g.setFontAlign(-1,1); g.drawString("continuous", 120, 210); - g.drawString("one-time", 140, 50); g.setColor("#ffffff"); g.setFontAlign(0, 0); } @@ -277,13 +254,10 @@ drawButtons(); g.setFont("6x8", 2); g.setColor("#ffffff"); g.setFontAlign(0, 0); // center font -g.drawString("check app README\nfor more info", px, py); -setWatch(btn1Pressed, BTN1, {repeat:true}); setWatch(btn3Pressed, BTN3, {repeat:true}); - Bangle.on('HRM-raw', function (e) { if (!collectData) return; storeMyData(e.raw, 0); From a8ddde48dbee7baadcfcb30eb6a859eabf7c3ea2 Mon Sep 17 00:00:00 2001 From: hanna0616 <64650462+hanna0616@users.noreply.github.com> Date: Thu, 4 Jan 2024 16:14:02 +0100 Subject: [PATCH 10/31] Update app.js --- apps/stressless/app.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/stressless/app.js b/apps/stressless/app.js index 2caf7ac40..b27c79a0d 100644 --- a/apps/stressless/app.js +++ b/apps/stressless/app.js @@ -3,7 +3,7 @@ var option = null; //debugging or analysis files //var logfile = require("Storage").open("HRV_log.csv", "w"); -var logfile = require("Storage").open("HRV_log.csv", "a"); +var logfile = require("Storage").open("HRV_logs.csv", "a"); var csv = [ "time", @@ -16,9 +16,11 @@ var csv = [ ]; logfile.write(csv.join(",")+"\n"); +var debugging = true; var samples = 0; // how many samples have we connected? var collectData = false; // are we currently collecting data? +var BPM_array = []; var raw_HR_array = new Float32Array(1536); var alternate_array = new Float32Array(3072); var pulse_array = []; @@ -41,6 +43,12 @@ function storeMyData(data, file_type) { "ram" function average(samples) { return E.sum(samples) / samples.length; // faster builtin + /* var sum = 0; + for (var i = 0; i < samples.length; i++) { + sum += parseFloat(samples[i]); + } + var avg = sum / samples.length; + return avg;*/ } function StandardDeviation (array) { @@ -208,12 +216,13 @@ function calculate_HRV() { movement.toFixed(5) ]; logfile.write(csv.join(",")+"\n"); + + turn_on(); } } - function btn3Pressed() { if(option === null){ logfile.write(""); //reset HRV log @@ -226,7 +235,7 @@ function btn3Pressed() { } function turn_on() { - + BPM_array = []; pulse_array = []; samples = 0; if (accel) clearInterval(accel); @@ -242,7 +251,7 @@ function drawButtons() { g.setColor("#00ff7f"); g.setFont("6x8", 2); g.setFontAlign(-1,1); - g.drawString("continuous", 120, 210); + g.drawString("start recording HRV", 120, 210); g.setColor("#ffffff"); g.setFontAlign(0, 0); } @@ -258,6 +267,7 @@ g.setFontAlign(0, 0); // center font setWatch(btn3Pressed, BTN3, {repeat:true}); + Bangle.on('HRM-raw', function (e) { if (!collectData) return; storeMyData(e.raw, 0); From 7ab3fe2f37de68b802dcab074b3e00e4cfa1b45c Mon Sep 17 00:00:00 2001 From: Paul Spenke Date: Fri, 5 Jan 2024 12:15:31 +0100 Subject: [PATCH 11/31] Add new Line Clock application This commit introduces the Line Clock application. The Line Clock is a readable analog clock that is customizable via the theme configuration. It includes a JavaScript logic file, an app icon, a metadata JSON file, a README, and a ChangeLog file. This also includes the MIT license file. --- apps/line_clock/ChangeLog | 1 + apps/line_clock/LICENSE | 21 +++ apps/line_clock/README.md | 11 ++ apps/line_clock/app-icon.js | 1 + apps/line_clock/app-icon.png | Bin 0 -> 3511 bytes apps/line_clock/app-screenshot.png | Bin 0 -> 2653 bytes apps/line_clock/app.js | 273 +++++++++++++++++++++++++++++ apps/line_clock/metadata.json | 17 ++ 8 files changed, 324 insertions(+) create mode 100644 apps/line_clock/ChangeLog create mode 100644 apps/line_clock/LICENSE create mode 100644 apps/line_clock/README.md create mode 100644 apps/line_clock/app-icon.js create mode 100644 apps/line_clock/app-icon.png create mode 100644 apps/line_clock/app-screenshot.png create mode 100644 apps/line_clock/app.js create mode 100644 apps/line_clock/metadata.json diff --git a/apps/line_clock/ChangeLog b/apps/line_clock/ChangeLog new file mode 100644 index 000000000..0f7cf828d --- /dev/null +++ b/apps/line_clock/ChangeLog @@ -0,0 +1 @@ +0.1 init app diff --git a/apps/line_clock/LICENSE b/apps/line_clock/LICENSE new file mode 100644 index 000000000..404cbc7a0 --- /dev/null +++ b/apps/line_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Paul Spenke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/apps/line_clock/README.md b/apps/line_clock/README.md new file mode 100644 index 000000000..5789acbbc --- /dev/null +++ b/apps/line_clock/README.md @@ -0,0 +1,11 @@ +# Line Clock + +This app displays a simple, different looking, analog clock. It considers the +currently configured "theme" (and may therefore look different than shown in +the screenshot on your watch depending on which theme you prefer). + +![](app-screenshot.png) + +## License + +[MIT License](LICENSE) diff --git a/apps/line_clock/app-icon.js b/apps/line_clock/app-icon.js new file mode 100644 index 000000000..eaaf719b4 --- /dev/null +++ b/apps/line_clock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgYMJh/4AgUD+AeKgIRDj/+n41O/4RQABcfIJYAEKZgAkL4U/8ARNBwIRP/+AGx6YBPSH/4ASPh/A/hfDAAZAHg/8gP/LguSoARHEwIRFiVJkDCFjgRHgEJkg4CcwQjIAAMEHAUDCoIRB46kIHAkH//xLIw4I8eAnCNKHAYAO/xxEABg4ByASPHAkBKAbUE/5xGhP//wRFv4RDOIYIB//ACQr1FHAIRJAA0TCAP/ZwIALgYRJVowRCj/4BIkBLIgABgRHC/KqFaI4RC5MkJBlPR4UECJizJJwoAKCKImVQAwAJv0HL5S6CbwIjLCKMAn4RDh0/LMKMhWaYAKA=")) diff --git a/apps/line_clock/app-icon.png b/apps/line_clock/app-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2753538122d298ede31a6526c23ac519dee6d1e7 GIT binary patch literal 3511 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 literal 0 HcmV?d00001 diff --git a/apps/line_clock/app.js b/apps/line_clock/app.js new file mode 100644 index 000000000..0596b865e --- /dev/null +++ b/apps/line_clock/app.js @@ -0,0 +1,273 @@ +const handWidth = 6; +const hourRadius = 4; +const hourWidth = 8; +const hourLength = 40; +const hourSLength = 20; +const radius = 220; +const lineOffset = 115; +const hourOffset = 32; +const numberOffset = 85; +const numberSize = 22; + +let settings = { + showLock: true +}; + +let gWidth = g.getWidth(), gCenterX = gWidth/2; +let gHeight = g.getHeight(), gCenterY = gHeight/2; + +let currentTime = new Date(); +let currentHour = currentTime.getHours(); +let currentMinute = currentTime.getMinutes(); + +let drawTimeout; + +function imgLock() { + return { + width : 16, height : 16, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("A8AH4A5wDDAYGBgYP/w//D/8Pnw+fD58Pnw//D/8P/w=")) + }; +} + +/** + * Retrieves the angle of the hour hand for the current time. + * + * @returns {number} The angle of the hour hand in degrees. + */ +function getHourHandAngle() { + let hourHandAngle = 30 * currentHour; + hourHandAngle += 0.5 * currentMinute; + return hourHandAngle; +} + +let hourAngle = getHourHandAngle(); + +/** + * Converts degrees to radians. + * + * @param {number} degrees - The degrees to be converted to radians. + * @return {number} - The equivalent value in radians. + */ +function degreesToRadians(degrees) { + return degrees * (Math.PI / 180); +} + +/** + * Rotates an array of points around a given angle and radius. + * + * @param {Array} points - The array of points to be rotated. + * @param {number} angle - The angle in degrees to rotate the points. + * @param {number} rad - The radius to offset the rotation. + * @returns {Array} - The array of rotated points. + */ +function rotatePoints(points, angle, rad) { + const ang = degreesToRadians(angle); + const hAng = degreesToRadians(hourAngle); + const rotatedPoints = []; + points.map(function(point) { + return { + x: point.x * Math.cos(ang) - point.y * Math.sin(ang), + y: point.x * Math.sin(ang) + point.y * Math.cos(ang) + }; + }).forEach(function(point) { + rotatedPoints.push(point.x + gCenterX - (rad * Math.sin(hAng))); + rotatedPoints.push(point.y + gCenterY + (rad * Math.cos(hAng))); + }); + return rotatedPoints; +} + +/** + * Draws a hand on the canvas. + * + * @function drawHand + * + * @returns {void} + */ +function drawHand() { + g.setColor(0xF800); + const halfWidth = handWidth / 2; + + const points = [{ + x: -halfWidth, + y: -gHeight + }, { + x: halfWidth, + y: -gHeight + }, { + x: halfWidth, + y: gHeight + }, { + x: -halfWidth, + y: gHeight + }]; + + g.fillPolyAA(rotatePoints(points, hourAngle, 0)); +} + +/** + * Retrieves the hour coordinates for a given small flag. + * @param {boolean} small - Determines if the flag is small. + * @returns {Array} - An array of hour coordinates. + */ +function getHourCoordinates(small) { + const dist = small ? (hourSLength - hourLength) : 0; + const halfWidth = hourWidth / 2; + const gh = gHeight + lineOffset; + return [{ + x: -halfWidth, + y: -gh - dist + }, { + x: halfWidth, + y: -gh - dist + }, { + x: halfWidth, + y: -gh + hourLength + }, { + x: -halfWidth, + y: -gh + hourLength + }]; +} + +/** + * Assign the given time to the hour dot on the clock face. + * + * @param {number} a - The time value to assign to the hour dot. + * @return {void} + */ +function hourDot(a) { + const h = gHeight + lineOffset; + const rotatedPoints = rotatePoints( + [{ + x: 0, + y: -h + hourLength - (hourRadius / 2) + }], a, radius + ); + g.fillCircle(rotatedPoints[0], rotatedPoints[1], hourRadius); +} + +/** + * Convert an hour into a number and display it on the clock face. + * + * @param {number} a - The hour to be converted (between 0 and 360 degrees). + */ +function hourNumber(a) { + const h = gHeight + lineOffset; + const rotatedPoints = rotatePoints( + [{ + x: 0, + y: -h + hourLength + hourOffset + }], a, radius + ); + g.drawString(String(a / 30), rotatedPoints[0], rotatedPoints[1]); +} + +/** + * Draws a number on the display. + * + * @param {number} n - The number to be drawn. + * @return {void} + */ +function drawNumber(n) { + const h = gHeight + lineOffset; + const halfWidth = handWidth / 2; + const rotatedPoints = rotatePoints( + [{ + x: 0, + y: -h + hourLength + numberOffset + }], hourAngle, radius + ); + g.setColor(0xF800); + g.fillCircle(rotatedPoints[0], rotatedPoints[1], numberSize+ halfWidth); + g.setColor(g.theme.bg); + g.fillCircle(rotatedPoints[0], rotatedPoints[1], numberSize - halfWidth); + g.setColor(g.theme.fg); + g.setFont("Vector:"+numberSize); + g.drawString(String(n), rotatedPoints[0], rotatedPoints[1]); +} + +const hourPoints = getHourCoordinates(false); +const hourSPoints = getHourCoordinates(true); + +/** + * Draws an hour on a clock face. + * + * @param {number} h - The hour to be drawn on the clock face. + * @return {undefined} + */ +function drawHour(h) { + if (h === 0) { h= 12; } + if (h === 13) { h= 1; } + g.setColor(g.theme.fg); + g.setFont("Vector:32"); + const a = h * 30; + g.fillPolyAA(rotatePoints(hourPoints, a, radius)); + g.fillPolyAA(rotatePoints(hourSPoints, a + 15, radius)); + hourNumber(a); + hourDot(a + 5); + hourDot(a + 10); + hourDot(a + 20); + hourDot(a + 25); +} + +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +function lockListenerBw(isLocked) { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + draw(); +} +Bangle.on('lock', lockListenerBw); + +Bangle.setUI({ + mode : "clock", + remove : function() { + Bangle.removeListener('lock', lockListenerBw); + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +/** + * Draws a clock on the canvas using the current time. + * + * @return {undefined} + */ +function draw() { + queueDraw(); + currentTime = new Date(); + currentHour = currentTime.getHours(); + if (currentHour > 12) { + currentHour -= 12; + } + currentMinute = currentTime.getMinutes(); + + hourAngle = getHourHandAngle(); + + g.clear(); + g.setFontAlign(0, 0); + + g.setColor(g.theme.bg); + g.fillRect(0, 0, gWidth, gHeight); + + if(settings.showLock && Bangle.isLocked()){ + g.setColor(g.theme.fg); + g.drawImage(imgLock(), gWidth-16, 2); + } + + drawHour(currentHour); + drawHour(currentHour-1); + drawHour(currentHour+1); + + + drawHand(); + drawNumber(currentMinute); +} + +draw(); diff --git a/apps/line_clock/metadata.json b/apps/line_clock/metadata.json new file mode 100644 index 000000000..a2aad5f58 --- /dev/null +++ b/apps/line_clock/metadata.json @@ -0,0 +1,17 @@ +{ "id": "line_clock", + "name": "Line Clock", + "shortName":"Line Clock", + "version":"0.1", + "description": "a readable analog clock", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"line_clock.app.js","url":"app.js"}, + {"name":"line_clock.img","url":"app-icon.js","evaluate":true} + ] +} From a54d37dbfc33f8f088bc75146c89289243c69b67 Mon Sep 17 00:00:00 2001 From: Paul Spenke Date: Fri, 5 Jan 2024 19:15:55 +0100 Subject: [PATCH 12/31] Implement showMinute setting in Line Clock app The commit adds 'showMinute' configuration in both app and settings file for the Line Clock app, allowing users to choose whether to display the minute. An additional property within the settings JSON file is now read at application start to adjust behavior accordingly. --- apps/line_clock/app.js | 17 ++++++++++++--- apps/line_clock/metadata.json | 6 ++++-- apps/line_clock/settings.js | 39 +++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 apps/line_clock/settings.js diff --git a/apps/line_clock/app.js b/apps/line_clock/app.js index 0596b865e..4d243b736 100644 --- a/apps/line_clock/app.js +++ b/apps/line_clock/app.js @@ -9,10 +9,18 @@ const hourOffset = 32; const numberOffset = 85; const numberSize = 22; +const SETTINGS_FILE = "line_clock.setting.json"; + let settings = { - showLock: true + showLock: true, + showMinute: true, }; +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +for (const key in saved_settings) { + settings[key] = saved_settings[key]; +} + let gWidth = g.getWidth(), gCenterX = gWidth/2; let gHeight = g.getHeight(), gCenterY = gHeight/2; @@ -218,7 +226,7 @@ function queueDraw() { }, 60000 - (Date.now() % 60000)); } -function lockListenerBw(isLocked) { +function lockListenerBw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; draw(); @@ -267,7 +275,10 @@ function draw() { drawHand(); - drawNumber(currentMinute); + + if(settings.showMinute){ + drawNumber(currentMinute); + } } draw(); diff --git a/apps/line_clock/metadata.json b/apps/line_clock/metadata.json index a2aad5f58..01393efdf 100644 --- a/apps/line_clock/metadata.json +++ b/apps/line_clock/metadata.json @@ -12,6 +12,8 @@ "readme": "README.md", "storage": [ {"name":"line_clock.app.js","url":"app.js"}, - {"name":"line_clock.img","url":"app-icon.js","evaluate":true} - ] + {"name":"line_clock.img","url":"app-icon.js","evaluate":true}, + {"name":"line_clock.settings.js","url":"settings.js"} + ], + "data":[{"name":"line_clock.setting.json"}] } diff --git a/apps/line_clock/settings.js b/apps/line_clock/settings.js new file mode 100644 index 000000000..5a793ed0f --- /dev/null +++ b/apps/line_clock/settings.js @@ -0,0 +1,39 @@ +(function(back) { + const SETTINGS_FILE = "line_clock.setting.json"; + + // initialize with default settings... + const storage = require('Storage') + let settings = { + showLock: true, + showMinute: true, + }; + let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; + for (const key in saved_settings) { + settings[key] = saved_settings[key] + } + + function save() { + storage.write(SETTINGS_FILE, settings) + } + + E.showMenu({ + '': { 'title': 'Line Clock' }, + '< Back': back, + 'Show Lock': { + value: settings.showLock, + format: () => (settings.showLock ? 'Yes' : 'No'), + onchange: () => { + settings.showLock = !settings.showLock; + save(); + }, + }, + 'Show Minute': { + value: settings.showMinute, + format: () => (settings.showMinute ? 'Yes' : 'No'), + onchange: () => { + settings.showMinute = !settings.showMinute; + save(); + }, + } + }); + }) From e62d3fd2198965e29add4407559da7ada84ea0a1 Mon Sep 17 00:00:00 2001 From: Paul Spenke Date: Sat, 6 Jan 2024 15:00:52 +0100 Subject: [PATCH 13/31] Add Storage requirement to Line Clock app --- apps/line_clock/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/line_clock/app.js b/apps/line_clock/app.js index 4d243b736..67ad742f5 100644 --- a/apps/line_clock/app.js +++ b/apps/line_clock/app.js @@ -9,6 +9,8 @@ const hourOffset = 32; const numberOffset = 85; const numberSize = 22; +const storage = require('Storage'); + const SETTINGS_FILE = "line_clock.setting.json"; let settings = { From 651d08de5316a282deb8c319c4b474b21de4507c Mon Sep 17 00:00:00 2001 From: Paul Spenke Date: Sat, 6 Jan 2024 15:06:25 +0100 Subject: [PATCH 14/31] Update changelog --- apps/line_clock/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/line_clock/ChangeLog b/apps/line_clock/ChangeLog index 0f7cf828d..504dc0efe 100644 --- a/apps/line_clock/ChangeLog +++ b/apps/line_clock/ChangeLog @@ -1 +1 @@ -0.1 init app +0.1: init app From 6e3066d444912275999cc747cd76ba8e128e6950 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 8 Jan 2024 21:45:50 +0000 Subject: [PATCH 15/31] sanitycheck: warn on boolean-formatters --- bin/sanitycheck.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index f1e795156..945bb8bff 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -256,9 +256,17 @@ apps.forEach((app,appIdx) => { if (a>=0 && b>=0 && a !d.name || !d.name.endsWith(".json")))) { - WARN(`App ${app.id} has a setting file but no corresponding data entry (add \`"data":[{"name":"${app.id}.settings.json"}]\`)`, {file:appDirRelative+file.url}); + // if settings + if (/\.settings?\.js$/.test(file.name)) { + // suggest adding to datafiles + if (!app.data || app.data.every(d => !d.name || !d.name.endsWith(".json"))) { + WARN(`App ${app.id} has a setting file but no corresponding data entry (add \`"data":[{"name":"${app.id}.settings.json"}]\`)`, {file:appDirRelative+file.url}); + } + // check for manual boolean formatter + const m = fileContents.match(/format: *\(\) *=>.*["']Yes["']/); + if (m) { + WARN(`Settings for ${app.id} has a boolean formatter - this is handled automatically, the line can be removed`, {file:appDirRelative+file.url, line: fileContents.substr(0, m.index).split("\n").length}); + } } } for (const key in file) { From b5b65406c000881afdd56f88992d0578375bcc71 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 8 Jan 2024 21:46:46 +0000 Subject: [PATCH 16/31] Update apps to remove default boolean formatters --- apps/90sclk/settings.js | 1 - apps/banglexercise/settings.js | 1 - apps/bwclk/settings.js | 2 -- apps/bwclklite/settings.js | 2 -- apps/circlesclock/settings.js | 5 +---- apps/clicompleteclk/settings.js | 4 ---- apps/fuzzyw/fuzzyw.settings.js | 1 - apps/health/settings.js | 1 - apps/lcars/lcars.settings.js | 4 ---- apps/limelight/limelight.settings.js | 5 +---- apps/linuxclock/settings.js | 2 -- apps/mosaic/mosaic.settings.js | 1 - apps/pebble/pebble.settings.js | 3 +-- apps/slopeclockpp/settings.js | 8 -------- apps/weather/settings.js | 1 - apps/widbgjs/settings.js | 1 - apps/widpedom/settings.js | 3 --- 17 files changed, 3 insertions(+), 42 deletions(-) diff --git a/apps/90sclk/settings.js b/apps/90sclk/settings.js index 8f97cd317..74241d603 100644 --- a/apps/90sclk/settings.js +++ b/apps/90sclk/settings.js @@ -21,7 +21,6 @@ '< Back': back, 'Full Screen': { value: settings.fullscreen, - format: () => (settings.fullscreen ? 'Yes' : 'No'), onchange: () => { settings.fullscreen = !settings.fullscreen; save(); diff --git a/apps/banglexercise/settings.js b/apps/banglexercise/settings.js index 3208c6eca..0b52acd72 100644 --- a/apps/banglexercise/settings.js +++ b/apps/banglexercise/settings.js @@ -11,7 +11,6 @@ '< Back': back, 'Buzz': { value: "buzz" in settings ? settings.buzz : false, - format: () => (settings.buzz ? 'Yes' : 'No'), onchange: () => { settings.buzz = !settings.buzz; save('buzz', settings.buzz); diff --git a/apps/bwclk/settings.js b/apps/bwclk/settings.js index 116253fda..8bcf0ae0f 100644 --- a/apps/bwclk/settings.js +++ b/apps/bwclk/settings.js @@ -32,7 +32,6 @@ }, 'Show Lock': { value: settings.showLock, - format: () => (settings.showLock ? 'Yes' : 'No'), onchange: () => { settings.showLock = !settings.showLock; save(); @@ -40,7 +39,6 @@ }, 'Hide Colon': { value: settings.hideColon, - format: () => (settings.hideColon ? 'Yes' : 'No'), onchange: () => { settings.hideColon = !settings.hideColon; save(); diff --git a/apps/bwclklite/settings.js b/apps/bwclklite/settings.js index 2d3916a3d..4c59198c6 100644 --- a/apps/bwclklite/settings.js +++ b/apps/bwclklite/settings.js @@ -32,7 +32,6 @@ }, 'Show Lock': { value: settings.showLock, - format: () => (settings.showLock ? 'Yes' : 'No'), onchange: () => { settings.showLock = !settings.showLock; save(); @@ -40,7 +39,6 @@ }, 'Hide Colon': { value: settings.hideColon, - format: () => (settings.hideColon ? 'Yes' : 'No'), onchange: () => { settings.hideColon = !settings.hideColon; save(); diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 63a2b0f93..ae090c1d7 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -30,7 +30,6 @@ }, /*LANG*/'show widgets': { value: !!settings.showWidgets, - format: () => (settings.showWidgets ? 'Yes' : 'No'), onchange: x => save('showWidgets', x), }, /*LANG*/'update interval': { @@ -45,7 +44,6 @@ }, /*LANG*/'show big weather': { value: !!settings.showBigWeather, - format: () => (settings.showBigWeather ? 'Yes' : 'No'), onchange: x => save('showBigWeather', x), }, /*LANG*/'colorize icons': ()=>showCircleMenus() @@ -87,8 +85,7 @@ const colorizeIconKey = circleName + "colorizeIcon"; menu[/*LANG*/'circle ' + circleId] = { value: settings[colorizeIconKey] || false, - format: () => (settings[colorizeIconKey]? /*LANG*/'Yes': /*LANG*/'No'), - onchange: x => save(colorizeIconKey, x), + onchange: x => save(colorizeIconKey, x), }; } E.showMenu(menu); diff --git a/apps/clicompleteclk/settings.js b/apps/clicompleteclk/settings.js index 2df20ed3e..0213ead6e 100644 --- a/apps/clicompleteclk/settings.js +++ b/apps/clicompleteclk/settings.js @@ -9,7 +9,6 @@ '': { 'title': 'CLI complete clk' }, 'Show battery': { value: "battery" in settings ? settings.battery : false, - format: () => (settings.battery ? 'Yes' : 'No'), onchange: () => { settings.battery = !settings.battery; save('battery', settings.battery); @@ -27,7 +26,6 @@ }, 'Show weather': { value: "weather" in settings ? settings.weather : false, - format: () => (settings.weather ? 'Yes' : 'No'), onchange: () => { settings.weather = !settings.weather; save('weather', settings.weather); @@ -35,7 +33,6 @@ }, 'Show steps': { value: "steps" in settings ? settings.steps : false, - format: () => (settings.steps ? 'Yes' : 'No'), onchange: () => { settings.steps = !settings.steps; save('steps', settings.steps); @@ -43,7 +40,6 @@ }, 'Show heartrate': { value: "heartrate" in settings ? settings.heartrate : false, - format: () => (settings.heartrate ? 'Yes' : 'No'), onchange: () => { settings.heartrate = !settings.heartrate; save('heartrate', settings.heartrate); diff --git a/apps/fuzzyw/fuzzyw.settings.js b/apps/fuzzyw/fuzzyw.settings.js index 8feb30bfb..535f91d67 100644 --- a/apps/fuzzyw/fuzzyw.settings.js +++ b/apps/fuzzyw/fuzzyw.settings.js @@ -23,7 +23,6 @@ '< Back': back, 'Show Widgets': { value: settings.showWidgets, - format: () => (settings.showWidgets ? 'Yes' : 'No'), onchange: () => { settings.showWidgets = !settings.showWidgets; save(); diff --git a/apps/health/settings.js b/apps/health/settings.js index 88c8061c6..4d6e1a067 100644 --- a/apps/health/settings.js +++ b/apps/health/settings.js @@ -43,7 +43,6 @@ /*LANG*/"Step Goal Notification": { value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false, - format: () => (settings.stepGoalNotification ? 'Yes' : 'No'), onchange: () => { settings.stepGoalNotification = !settings.stepGoalNotification; setSettings(); diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index db583741f..2ce3e4fc9 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -76,7 +76,6 @@ var bg_code = [ }, 'Full Screen': { value: settings.fullscreen, - format: () => (settings.fullscreen ? 'Yes' : 'No'), onchange: () => { settings.fullscreen = !settings.fullscreen; save(); @@ -120,7 +119,6 @@ var bg_code = [ }, 'Disable alarm functionality': { value: settings.disableAlarms, - format: () => (settings.disableAlarms ? 'Yes' : 'No'), onchange: () => { settings.disableAlarms = !settings.disableAlarms; save(); @@ -128,7 +126,6 @@ var bg_code = [ }, 'Disable data pages functionality': { value: settings.disableData, - format: () => (settings.disableData ? 'Yes' : 'No'), onchange: () => { settings.disableData = !settings.disableData; save(); @@ -136,7 +133,6 @@ var bg_code = [ }, 'Random colors on open': { value: settings.randomColors, - format: () => (settings.randomColors ? 'Yes' : 'No'), onchange: () => { settings.randomColors = !settings.randomColors; save(); diff --git a/apps/limelight/limelight.settings.js b/apps/limelight/limelight.settings.js index aacea2f86..fa1d857d2 100644 --- a/apps/limelight/limelight.settings.js +++ b/apps/limelight/limelight.settings.js @@ -27,13 +27,12 @@ } var font_options = ["Limelight","GochiHand","Grenadier","Monoton"]; - + E.showMenu({ '': { 'title': 'Limelight Clock' }, '< Back': back, 'Full Screen': { value: s.fullscreen, - format: () => (s.fullscreen ? 'Yes' : 'No'), onchange: () => { s.fullscreen = !s.fullscreen; save(); @@ -50,7 +49,6 @@ }, 'Vector Font': { value: s.vector, - format: () => (s.vector ? 'Yes' : 'No'), onchange: () => { s.vector = !s.vector; save(); @@ -68,7 +66,6 @@ }, 'Second Hand': { value: s.secondhand, - format: () => (s.secondhand ? 'Yes' : 'No'), onchange: () => { s.secondhand = !s.secondhand; save(); diff --git a/apps/linuxclock/settings.js b/apps/linuxclock/settings.js index 116253fda..8bcf0ae0f 100644 --- a/apps/linuxclock/settings.js +++ b/apps/linuxclock/settings.js @@ -32,7 +32,6 @@ }, 'Show Lock': { value: settings.showLock, - format: () => (settings.showLock ? 'Yes' : 'No'), onchange: () => { settings.showLock = !settings.showLock; save(); @@ -40,7 +39,6 @@ }, 'Hide Colon': { value: settings.hideColon, - format: () => (settings.hideColon ? 'Yes' : 'No'), onchange: () => { settings.hideColon = !settings.hideColon; save(); diff --git a/apps/mosaic/mosaic.settings.js b/apps/mosaic/mosaic.settings.js index dcf725b84..ee80cf950 100644 --- a/apps/mosaic/mosaic.settings.js +++ b/apps/mosaic/mosaic.settings.js @@ -25,7 +25,6 @@ '< Back': back, 'Show Widgets': { value: settings.showWidgets, - format: () => (settings.showWidgets ? 'Yes' : 'No'), onchange: () => { settings.showWidgets = !settings.showWidgets; save(); diff --git a/apps/pebble/pebble.settings.js b/apps/pebble/pebble.settings.js index f1c065db4..83032270a 100644 --- a/apps/pebble/pebble.settings.js +++ b/apps/pebble/pebble.settings.js @@ -23,7 +23,7 @@ var color_options = ['Green','Orange','Cyan','Purple','Red','Blue']; var bg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f']; var theme_options = ['System', 'Light', 'Dark']; - + E.showMenu({ '': { 'title': 'Pebble Clock' }, /*LANG*/'< Back': back, @@ -48,7 +48,6 @@ }, /*LANG*/'Show Lock': { value: settings.showlock, - format: () => (settings.showlock ? /*LANG*/'Yes' : /*LANG*/'No'), onchange: () => { settings.showlock = !settings.showlock; save(); diff --git a/apps/slopeclockpp/settings.js b/apps/slopeclockpp/settings.js index 3c0e0a6e9..2c2d2c463 100644 --- a/apps/slopeclockpp/settings.js +++ b/apps/slopeclockpp/settings.js @@ -21,42 +21,34 @@ }, /*LANG*/'Red': { value: !!settings.colorRed, - format: () => (settings.colorRed ? 'Yes' : 'No'), onchange: x => save('colorRed', x), }, /*LANG*/'Green': { value: !!settings.colorGreen, - format: () => (settings.colorGreen ? 'Yes' : 'No'), onchange: x => save('colorGreen', x), }, /*LANG*/'Blue': { value: !!settings.colorBlue, - format: () => (settings.colorBlue ? 'Yes' : 'No'), onchange: x => save('colorBlue', x), }, /*LANG*/'Magenta': { value: !!settings.colorMagenta, - format: () => (settings.colorMagenta ? 'Yes' : 'No'), onchange: x => save('colorMagenta', x), }, /*LANG*/'Cyan': { value: !!settings.colorCyan, - format: () => (settings.colorCyan ? 'Yes' : 'No'), onchange: x => save('colorCyan', x), }, /*LANG*/'Yellow': { value: !!settings.colorYellow, - format: () => (settings.colorYellow ? 'Yes' : 'No'), onchange: x => save('colorYellow', x), }, /*LANG*/'Black': { value: !!settings.colorBlack, - format: () => (settings.colorBlack ? 'Yes' : 'No'), onchange: x => save('colorBlack', x), }, /*LANG*/'White': { value: !!settings.colorWhite, - format: () => (settings.colorWhite ? 'Yes' : 'No'), onchange: x => save('colorWhite', x), } }; diff --git a/apps/weather/settings.js b/apps/weather/settings.js index 7e2c043b9..7e0bb24c8 100644 --- a/apps/weather/settings.js +++ b/apps/weather/settings.js @@ -21,7 +21,6 @@ }, 'Hide Widget': { value: "hide" in settings ? settings.hide : false, - format: () => (settings.hide ? 'Yes' : 'No'), onchange: () => { settings.hide = !settings.hide save('hide', settings.hide); diff --git a/apps/widbgjs/settings.js b/apps/widbgjs/settings.js index e480c8cf9..c599183dc 100644 --- a/apps/widbgjs/settings.js +++ b/apps/widbgjs/settings.js @@ -43,7 +43,6 @@ }, 'Hide Widget': { value: s.hide, - format: () => (s.hide ? 'Yes' : 'No'), onchange: () => { s.hide = !s.hide; save(); diff --git a/apps/widpedom/settings.js b/apps/widpedom/settings.js index 4455ce7d7..24e8c9b35 100644 --- a/apps/widpedom/settings.js +++ b/apps/widpedom/settings.js @@ -37,7 +37,6 @@ }, 'Show Progress': { value: s.progress, - format: () => (s.progress ? 'Yes' : 'No'), onchange: () => { s.progress = !s.progress save(); @@ -45,7 +44,6 @@ }, 'Large Digits': { value: s.large, - format: () => (s.large ? 'Yes' : 'No'), onchange: () => { s.large = !s.large save(); @@ -53,7 +51,6 @@ }, 'Hide Widget': { value: s.hide, - format: () => (s.hide ? 'Yes' : 'No'), onchange: () => { s.hide = !s.hide save(); From 8b7ee2390d63f14c2f8a568889226327f6d181be Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sat, 13 Jan 2024 09:11:54 +0100 Subject: [PATCH 17/31] calendar: Load holidays before events Previously events were loaded and as result painted first and a following draw on a holiday would overwrite the event indicator --- apps/calendar/ChangeLog | 1 + apps/calendar/calendar.js | 29 +++++++++++++++++------------ apps/calendar/metadata.json | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/apps/calendar/ChangeLog b/apps/calendar/ChangeLog index 6edb54f65..bd8e6117b 100644 --- a/apps/calendar/ChangeLog +++ b/apps/calendar/ChangeLog @@ -17,3 +17,4 @@ 0.15: Edit holidays on device in settings 0.16: Add menu to fast open settings to edit holidays Display Widgets in menus +0.17: Load holidays before events so the latter is not overpainted diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js index 7477775ca..555a068ba 100644 --- a/apps/calendar/calendar.js +++ b/apps/calendar/calendar.js @@ -43,24 +43,24 @@ const dowLbls = function() { }(); const loadEvents = () => { + // add holidays & other events + events = (require("Storage").readJSON("calendar.days.json",1) || []).map(d => { + const date = new Date(d.date); + const o = {date: date, msg: d.name, type: d.type}; + if (d.repeat) { + o.repeat = d.repeat; + } + return o; + }); // all alarms that run on a specific date - events = (require("Storage").readJSON("sched.json",1) || []).filter(a => a.on && a.date).map(a => { + events = events.concat((require("Storage").readJSON("sched.json",1) || []).filter(a => a.on && a.date).map(a => { const date = new Date(a.date); const time = timeutils.decodeTime(a.t); date.setHours(time.h); date.setMinutes(time.m); date.setSeconds(time.s); return {date: date, msg: a.msg, type: "e"}; - }); - // add holidays & other events - (require("Storage").readJSON("calendar.days.json",1) || []).forEach(d => { - const date = new Date(d.date); - const o = {date: date, msg: d.name, type: d.type}; - if (d.repeat) { - o.repeat = d.repeat; - } - events.push(o); - }); + })); }; const loadSettings = () => { @@ -141,6 +141,7 @@ const calcDays = (month, monthMaxDayMap, dowNorm) => { }; const drawCalendar = function(date) { + d1 = new Date(); g.setBgColor(bgColor); g.clearRect(0, 0, maxX, maxY); g.setBgColor(bgColorMonth); @@ -281,7 +282,11 @@ const showMenu = function() { }, /*LANG*/"Exit": () => load(), /*LANG*/"Settings": () => { - const appSettings = eval(require('Storage').read('calendar.settings.js')); + const appSettings = () => eval(require('Storage').read('calendar.settings.js'))(() => { + loadSettings(); + loadEvents(); + showMenu(); + }); appSettings(() => { loadSettings(); loadEvents(); diff --git a/apps/calendar/metadata.json b/apps/calendar/metadata.json index e263efe35..895f8f7aa 100644 --- a/apps/calendar/metadata.json +++ b/apps/calendar/metadata.json @@ -1,7 +1,7 @@ { "id": "calendar", "name": "Calendar", - "version": "0.16", + "version": "0.17", "description": "Monthly calendar, displays holidays uploaded from the web interface and scheduled events.", "icon": "calendar.png", "screenshots": [{"url":"screenshot_calendar.png"}], From a75338efae5b0c5610c42d9c243ae7c9b91538eb Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 13 Jan 2024 11:50:22 +0000 Subject: [PATCH 18/31] fwupdate: don't reset the watch after upload Closes #3153. Trace: ``` apps/fwupdate/custom.html:423: calls `sendCustomizedApp()` core/lib/customize.js:63: send customised app core/js/index.js:340: handle `"app"` message core/js/index.js:356: call `uploadApp()` core/js/comms.js:166: call `showUploadFinished()` core/js/comms.js:24: reset watch (if autoReload is set) ``` --- apps/fwupdate/custom.html | 2 +- core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/fwupdate/custom.html b/apps/fwupdate/custom.html index 066d658be..3feab6591 100644 --- a/apps/fwupdate/custom.html +++ b/apps/fwupdate/custom.html @@ -426,7 +426,7 @@ function handleUpload() { storage:[ {name:"RAM", content:hexJS}, ] - }); + }, true); } document.getElementById('fileLoader').addEventListener('change', handleFileSelect, false); diff --git a/core b/core index c97b7851f..3bbca52f3 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit c97b7851f50cfff4e898c2264a337a17085ce463 +Subproject commit 3bbca52f36237e92265749ee86069468460488a1 From ae25c46690a00b6170af724a0bf319a82699bfee Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Mon, 15 Jan 2024 07:06:34 +0100 Subject: [PATCH 19/31] calendar: remove debug statement --- apps/calendar/calendar.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js index 555a068ba..a6e78aab7 100644 --- a/apps/calendar/calendar.js +++ b/apps/calendar/calendar.js @@ -141,7 +141,6 @@ const calcDays = (month, monthMaxDayMap, dowNorm) => { }; const drawCalendar = function(date) { - d1 = new Date(); g.setBgColor(bgColor); g.clearRect(0, 0, maxX, maxY); g.setBgColor(bgColorMonth); From ef7695bc769ec2a0b8e89d09f733ed031f9eabe8 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Mon, 15 Jan 2024 07:15:30 +0100 Subject: [PATCH 20/31] calendar: remove duplicate settings call --- apps/calendar/calendar.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js index a6e78aab7..f9fd43de8 100644 --- a/apps/calendar/calendar.js +++ b/apps/calendar/calendar.js @@ -280,18 +280,12 @@ const showMenu = function() { setUI(); }, /*LANG*/"Exit": () => load(), - /*LANG*/"Settings": () => { - const appSettings = () => eval(require('Storage').read('calendar.settings.js'))(() => { + /*LANG*/"Settings": () => + eval(require('Storage').read('calendar.settings.js'))(() => { loadSettings(); loadEvents(); showMenu(); - }); - appSettings(() => { - loadSettings(); - loadEvents(); - showMenu(); - }); - }, + }), }; if (require("Storage").read("alarm.app.js")) { menu[/*LANG*/"Launch Alarms"] = () => { From 99bb9a2d2e8fc5767952b968e18d5eff0aa7e147 Mon Sep 17 00:00:00 2001 From: Flaparoo <629229+flaparoo@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:25:25 +0800 Subject: [PATCH 21/31] dragboard: fix touch region for letters --- apps/dragboard/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dragboard/lib.js b/apps/dragboard/lib.js index 78ef11bd4..2e40f3a77 100644 --- a/apps/dragboard/lib.js +++ b/apps/dragboard/lib.js @@ -107,7 +107,7 @@ exports.input = function(options) { "ram"; // ABCDEFGHIJKLMNOPQRSTUVWXYZ // Choose character by draging along red rectangle at bottom of screen - if (event.y >= ( (R.y+R.h) - 12 )) { + if (event.y >= ( (R.y+R.h) - 26 )) { // Translate x-position to character if (event.x < ABCPADDING) { abcHL = 0; } else if (event.x >= 176-ABCPADDING) { abcHL = 25; } @@ -139,7 +139,7 @@ exports.input = function(options) { // 12345678901234567890 // Choose number or puctuation by draging on green rectangle - else if ((event.y < ( (R.y+R.h) - 12 )) && (event.y > ( (R.y+R.h) - 52 ))) { + else if ((event.y < ( (R.y+R.h) - 26 )) && (event.y > ( (R.y+R.h) - 52 ))) { // Translate x-position to character if (event.x < NUMPADDING) { numHL = 0; } else if (event.x > 176-NUMPADDING) { numHL = NUM.length-1; } From 33c5bd1b7986e9e7a4dfbbd4bded453f445334fe Mon Sep 17 00:00:00 2001 From: Flaparoo <629229+flaparoo@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:27:03 +0800 Subject: [PATCH 22/31] dragboard: update version for fix --- apps/dragboard/ChangeLog | 1 + apps/dragboard/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/dragboard/ChangeLog b/apps/dragboard/ChangeLog index 68cd82cfa..77cc63c98 100644 --- a/apps/dragboard/ChangeLog +++ b/apps/dragboard/ChangeLog @@ -8,3 +8,4 @@ 0.08: Catch and discard swipe events on fw2v19 and up (as well as some cutting edge 2v18 ones), allowing compatability with the Back Swipe app. 0.09: Fix colors settings, where color was stored as string instead of the expected int. +0.10: Fix touch region for letters diff --git a/apps/dragboard/metadata.json b/apps/dragboard/metadata.json index 090c37a01..c4596d7bd 100644 --- a/apps/dragboard/metadata.json +++ b/apps/dragboard/metadata.json @@ -1,6 +1,6 @@ { "id": "dragboard", "name": "Dragboard", - "version":"0.09", + "version":"0.10", "description": "A library for text input via swiping keyboard", "icon": "app.png", "type":"textinput", From fd0c46608af5221d8246630aab30013a30bf64b6 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 15 Jan 2024 20:53:10 +0000 Subject: [PATCH 23/31] fwupdate: pass { noFinish: true } for app --- apps/fwupdate/custom.html | 2 +- core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/fwupdate/custom.html b/apps/fwupdate/custom.html index 3feab6591..a5f96d98d 100644 --- a/apps/fwupdate/custom.html +++ b/apps/fwupdate/custom.html @@ -426,7 +426,7 @@ function handleUpload() { storage:[ {name:"RAM", content:hexJS}, ] - }, true); + }, { noFinish: true }); } document.getElementById('fileLoader').addEventListener('change', handleFileSelect, false); diff --git a/core b/core index 3bbca52f3..41e586e3b 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 3bbca52f36237e92265749ee86069468460488a1 +Subproject commit 41e586e3bb1025253ebdaa27a6be32e19619837f From 9175d5cc0e903c90a7ce394407be1ddeabf28e69 Mon Sep 17 00:00:00 2001 From: shansou504 <123512155+shansou504@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:26:28 -0500 Subject: [PATCH 24/31] added settings for fullscreen --- apps/binaryclk/ChangeLog | 1 + apps/binaryclk/app.js | 24 +++++++++++++++++------- apps/binaryclk/metadata.json | 4 +++- apps/binaryclk/settings.js | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 apps/binaryclk/settings.js diff --git a/apps/binaryclk/ChangeLog b/apps/binaryclk/ChangeLog index a78cbe479..7b6810faa 100644 --- a/apps/binaryclk/ChangeLog +++ b/apps/binaryclk/ChangeLog @@ -1,2 +1,3 @@ 0.01: Added app 0.02: Removed unneeded squares +0.03: Added settings with fullscreen option diff --git a/apps/binaryclk/app.js b/apps/binaryclk/app.js index 8b030ccff..988d2ec3f 100644 --- a/apps/binaryclk/app.js +++ b/apps/binaryclk/app.js @@ -1,3 +1,7 @@ +var settings = require('Storage').readJSON("binaryclk.json", true) || {}; +var full = settings.fullscreen || false; +delete settings; + function draw() { var dt = new Date(); var h = dt.getHours(), m = dt.getMinutes(); @@ -11,9 +15,14 @@ function draw() { g.clearRect(Bangle.appRect); let i = 0; + if (full) { + const gap = 12; + const mgn = 0; + } else { + const gap = 8; + const mgn = 20; + } const sq = 29; - const gap = 8; - const mgn = 20; const pos = sq + gap; for (let r = 3; r >= 0; r--) { @@ -26,14 +35,15 @@ function draw() { } i++; } - g.clearRect(mgn/2 + gap, mgn + gap, mgn/2 + gap + sq, mgn + 2 * gap + 2 * sq); - g.clearRect(mgn/2 + 3 * gap + 2 * sq, mgn + gap, mgn/2 + 3 * gap + 3 * sq, mgn + gap + sq); + g.clearRect(mgn/2 + gap, mgn + gap, mgn/2 + gap + sq, mgn + 2 * gap + 2 * sq); + g.clearRect(mgn/2 + 3 * gap + 2 * sq, mgn + gap, mgn/2 + 3 * gap + 3 * sq, mgn + gap + sq); } - g.clear(); draw(); var secondInterval = setInterval(draw, 60000); Bangle.setUI("clock"); -Bangle.loadWidgets(); -Bangle.drawWidgets(); +if (!full) { + Bangle.loadWidgets(); + Bangle.drawWidgets(); +} diff --git a/apps/binaryclk/metadata.json b/apps/binaryclk/metadata.json index a81a39b7a..37a8c8c0d 100644 --- a/apps/binaryclk/metadata.json +++ b/apps/binaryclk/metadata.json @@ -11,6 +11,8 @@ "allow_emulator": true, "storage": [ {"name":"binaryclk.app.js","url":"app.js"}, + {"name":"binaryclk.settings.js","url":"settings.js"}, {"name":"binaryclk.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"binaryclk.json"}] } diff --git a/apps/binaryclk/settings.js b/apps/binaryclk/settings.js new file mode 100644 index 000000000..3ae758de2 --- /dev/null +++ b/apps/binaryclk/settings.js @@ -0,0 +1,20 @@ +(function(back) { + var FILE = "binaryclk.json"; + var settings = Object.assign({ + fullscreen: false, + }, require('Storage').readJSON(FILE, true) || {}); + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + E.showMenu({ + "" : { "title" : "Bin Clock" }, + "< Back" : () => back(), + 'Fullscreen': { + value: settings.fullscreen, + onchange: v => { + settings.fullscreen = !v; + writeSettings(); + } + }, + }); +}) From 3deef94948c21d09bfa84a91e59f86649111f708 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 00:31:10 +0000 Subject: [PATCH 25/31] build(deps): bump core from `41e586e` to `e6a65a8` Bumps [core](https://github.com/espruino/EspruinoAppLoaderCore) from `41e586e` to `e6a65a8`. - [Commits](https://github.com/espruino/EspruinoAppLoaderCore/compare/41e586e3bb1025253ebdaa27a6be32e19619837f...e6a65a8cb20a730f75bbbab549c602300e69e8c4) --- updated-dependencies: - dependency-name: core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 41e586e3b..e6a65a8cb 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 41e586e3bb1025253ebdaa27a6be32e19619837f +Subproject commit e6a65a8cb20a730f75bbbab549c602300e69e8c4 From c06612b4005254c8792dc1719e08743cf7e1373d Mon Sep 17 00:00:00 2001 From: shansou504 <123512155+shansou504@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:34:29 -0500 Subject: [PATCH 26/31] add fullscreen option --- apps/binaryclk/app.js | 21 ++++++------ apps/binaryclk/binaryclk.app.js | 49 ++++++++++++++++++++++++++++ apps/binaryclk/binaryclk.info | 15 +++++++++ apps/binaryclk/binaryclk.settings.js | 20 ++++++++++++ apps/binaryclk/metadata.json | 2 +- apps/binaryclk/settings.js | 34 ++++++++++--------- 6 files changed, 113 insertions(+), 28 deletions(-) create mode 100644 apps/binaryclk/binaryclk.app.js create mode 100644 apps/binaryclk/binaryclk.info create mode 100644 apps/binaryclk/binaryclk.settings.js diff --git a/apps/binaryclk/app.js b/apps/binaryclk/app.js index 988d2ec3f..94c906104 100644 --- a/apps/binaryclk/app.js +++ b/apps/binaryclk/app.js @@ -1,6 +1,6 @@ -var settings = require('Storage').readJSON("binaryclk.json", true) || {}; -var full = settings.fullscreen || false; -delete settings; +var settings = Object.assign({ + fullscreen: false, +}, require('Storage').readJSON("binaryclk.json", true) || {}); function draw() { var dt = new Date(); @@ -15,15 +15,14 @@ function draw() { g.clearRect(Bangle.appRect); let i = 0; - if (full) { - const gap = 12; - const mgn = 0; - } else { - const gap = 8; - const mgn = 20; + var gap = 8; + var mgn = 20; + if (settings.fullscreen) { + gap = 12; + mgn = 0; } const sq = 29; - const pos = sq + gap; + var pos = sq + gap; for (let r = 3; r >= 0; r--) { for (let c = 0; c < 4; c++) { @@ -43,7 +42,7 @@ g.clear(); draw(); var secondInterval = setInterval(draw, 60000); Bangle.setUI("clock"); -if (!full) { +if (!settings.fullscreen) { Bangle.loadWidgets(); Bangle.drawWidgets(); } diff --git a/apps/binaryclk/binaryclk.app.js b/apps/binaryclk/binaryclk.app.js new file mode 100644 index 000000000..02e6172f5 --- /dev/null +++ b/apps/binaryclk/binaryclk.app.js @@ -0,0 +1,49 @@ +var settings = Object.assign({ + fullscreen: false, +}, require('Storage').readJSON("binaryclk.json", true) || {}); +var full = settings.fullscreen; + +function draw() { + var dt = new Date(); + var h = dt.getHours(), m = dt.getMinutes(); + const t = []; + t[0] = Math.floor(h/10); + t[1] = Math.floor(h%10); + t[2] = Math.floor(m/10); + t[3] = Math.floor(m%10); + + g.reset(); + g.clearRect(Bangle.appRect); + + let i = 0; + var gap = 8; + var mgn = 20; + if (full) { + gap = 12; + mgn = 0; + } + const sq = 29; + const pos = sq + gap; + + for (let r = 3; r >= 0; r--) { + for (let c = 0; c < 4; c++) { + if (t[c] & Math.pow(2, r)) { + g.fillRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq); + } else { + g.drawRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq); + } + } + i++; + } + g.clearRect(mgn/2 + gap, mgn + gap, mgn/2 + gap + sq, mgn + 2 * gap + 2 * sq); + g.clearRect(mgn/2 + 3 * gap + 2 * sq, mgn + gap, mgn/2 + 3 * gap + 3 * sq, mgn + gap + sq); +} + +g.clear(); +draw(); +var secondInterval = setInterval(draw, 60000); +Bangle.setUI("clock"); +if (!full) { + Bangle.loadWidgets(); + Bangle.drawWidgets(); +} diff --git a/apps/binaryclk/binaryclk.info b/apps/binaryclk/binaryclk.info new file mode 100644 index 000000000..6dcdcb435 --- /dev/null +++ b/apps/binaryclk/binaryclk.info @@ -0,0 +1,15 @@ +require("Storage").write("binaryclk.info",{ + "id": "binaryclk", + "name": "Bin Clock", + "version": "0.03", + "description": "Clock face to show binary time in 24 hr format", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"binaryclk.app.js","url":"app.js"}, + {"name":"binaryclk.settings.js","url":"settings.js"} + ], + "data": [{"name":"binaryclk.json"}] +}); diff --git a/apps/binaryclk/binaryclk.settings.js b/apps/binaryclk/binaryclk.settings.js new file mode 100644 index 000000000..3ae758de2 --- /dev/null +++ b/apps/binaryclk/binaryclk.settings.js @@ -0,0 +1,20 @@ +(function(back) { + var FILE = "binaryclk.json"; + var settings = Object.assign({ + fullscreen: false, + }, require('Storage').readJSON(FILE, true) || {}); + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + E.showMenu({ + "" : { "title" : "Bin Clock" }, + "< Back" : () => back(), + 'Fullscreen': { + value: settings.fullscreen, + onchange: v => { + settings.fullscreen = !v; + writeSettings(); + } + }, + }); +}) diff --git a/apps/binaryclk/metadata.json b/apps/binaryclk/metadata.json index 37a8c8c0d..b4ddc6544 100644 --- a/apps/binaryclk/metadata.json +++ b/apps/binaryclk/metadata.json @@ -1,7 +1,7 @@ { "id": "binaryclk", "name": "Bin Clock", - "version": "0.02", + "version": "0.03", "description": "Clock face to show binary time in 24 hr format", "icon": "app-icon.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/binaryclk/settings.js b/apps/binaryclk/settings.js index 3ae758de2..0ef30e19d 100644 --- a/apps/binaryclk/settings.js +++ b/apps/binaryclk/settings.js @@ -1,20 +1,22 @@ (function(back) { - var FILE = "binaryclk.json"; - var settings = Object.assign({ + var FILE = "binaryclk.json"; + var settings = Object.assign({ fullscreen: false, }, require('Storage').readJSON(FILE, true) || {}); - function writeSettings() { - require('Storage').writeJSON(FILE, settings); - } - E.showMenu({ - "" : { "title" : "Bin Clock" }, - "< Back" : () => back(), - 'Fullscreen': { - value: settings.fullscreen, - onchange: v => { - settings.fullscreen = !v; - writeSettings(); - } - }, - }); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + "" : { "title" : "Bin Clock" }, + "< Back" : () => back(), + 'Fullscreen': { + value: settings.fullscreen, + onchange: v => { + settings.fullscreen = v; + writeSettings(); + } + }, + }); }) From 657c8898cc7760ccde7418901f85bfcbfb0a1954 Mon Sep 17 00:00:00 2001 From: shansou504 <123512155+shansou504@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:45:14 -0500 Subject: [PATCH 27/31] remove extra files --- apps/binaryclk/binaryclk.app.js | 49 ---------------------------- apps/binaryclk/binaryclk.info | 15 --------- apps/binaryclk/binaryclk.settings.js | 20 ------------ 3 files changed, 84 deletions(-) delete mode 100644 apps/binaryclk/binaryclk.app.js delete mode 100644 apps/binaryclk/binaryclk.info delete mode 100644 apps/binaryclk/binaryclk.settings.js diff --git a/apps/binaryclk/binaryclk.app.js b/apps/binaryclk/binaryclk.app.js deleted file mode 100644 index 02e6172f5..000000000 --- a/apps/binaryclk/binaryclk.app.js +++ /dev/null @@ -1,49 +0,0 @@ -var settings = Object.assign({ - fullscreen: false, -}, require('Storage').readJSON("binaryclk.json", true) || {}); -var full = settings.fullscreen; - -function draw() { - var dt = new Date(); - var h = dt.getHours(), m = dt.getMinutes(); - const t = []; - t[0] = Math.floor(h/10); - t[1] = Math.floor(h%10); - t[2] = Math.floor(m/10); - t[3] = Math.floor(m%10); - - g.reset(); - g.clearRect(Bangle.appRect); - - let i = 0; - var gap = 8; - var mgn = 20; - if (full) { - gap = 12; - mgn = 0; - } - const sq = 29; - const pos = sq + gap; - - for (let r = 3; r >= 0; r--) { - for (let c = 0; c < 4; c++) { - if (t[c] & Math.pow(2, r)) { - g.fillRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq); - } else { - g.drawRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq); - } - } - i++; - } - g.clearRect(mgn/2 + gap, mgn + gap, mgn/2 + gap + sq, mgn + 2 * gap + 2 * sq); - g.clearRect(mgn/2 + 3 * gap + 2 * sq, mgn + gap, mgn/2 + 3 * gap + 3 * sq, mgn + gap + sq); -} - -g.clear(); -draw(); -var secondInterval = setInterval(draw, 60000); -Bangle.setUI("clock"); -if (!full) { - Bangle.loadWidgets(); - Bangle.drawWidgets(); -} diff --git a/apps/binaryclk/binaryclk.info b/apps/binaryclk/binaryclk.info deleted file mode 100644 index 6dcdcb435..000000000 --- a/apps/binaryclk/binaryclk.info +++ /dev/null @@ -1,15 +0,0 @@ -require("Storage").write("binaryclk.info",{ - "id": "binaryclk", - "name": "Bin Clock", - "version": "0.03", - "description": "Clock face to show binary time in 24 hr format", - "type": "clock", - "tags": "clock", - "supports": ["BANGLEJS2"], - "allow_emulator": true, - "storage": [ - {"name":"binaryclk.app.js","url":"app.js"}, - {"name":"binaryclk.settings.js","url":"settings.js"} - ], - "data": [{"name":"binaryclk.json"}] -}); diff --git a/apps/binaryclk/binaryclk.settings.js b/apps/binaryclk/binaryclk.settings.js deleted file mode 100644 index 3ae758de2..000000000 --- a/apps/binaryclk/binaryclk.settings.js +++ /dev/null @@ -1,20 +0,0 @@ -(function(back) { - var FILE = "binaryclk.json"; - var settings = Object.assign({ - fullscreen: false, - }, require('Storage').readJSON(FILE, true) || {}); - function writeSettings() { - require('Storage').writeJSON(FILE, settings); - } - E.showMenu({ - "" : { "title" : "Bin Clock" }, - "< Back" : () => back(), - 'Fullscreen': { - value: settings.fullscreen, - onchange: v => { - settings.fullscreen = !v; - writeSettings(); - } - }, - }); -}) From 3f16edcaf83f90fef746c69bc36f2e1f41564fde Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Thu, 18 Jan 2024 19:09:54 +0100 Subject: [PATCH 28/31] forge: Compatibility with Fastload Utils ... by adding the string `"Bangle.loadWidget()";`. This way Fastload Utils thinks widgets would be present and so fastloads. But in the absence of Fastload Utils no widgets will be loaded, and so no overhead is added for the usual case. --- apps/forge/ChangeLog | 1 + apps/forge/forge.app.js | 2 ++ apps/forge/metadata.json | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/forge/ChangeLog b/apps/forge/ChangeLog index 263d4078d..0c651c90b 100644 --- a/apps/forge/ChangeLog +++ b/apps/forge/ChangeLog @@ -1 +1,2 @@ 0.01: attempt to import +0.02: Make it possible for Fastload Utils to fastload into this app. diff --git a/apps/forge/forge.app.js b/apps/forge/forge.app.js index b972e13bb..b179fb540 100644 --- a/apps/forge/forge.app.js +++ b/apps/forge/forge.app.js @@ -1,5 +1,7 @@ // App Forge +"Bangle.loadWidgets()"; // Facilitates fastloading to this app via Fastload Utils, while still not loading widgets on standard `load` calls. + st = require('Storage'); l = /^a\..*\.js$/; diff --git a/apps/forge/metadata.json b/apps/forge/metadata.json index 03671a647..6e13a4df3 100644 --- a/apps/forge/metadata.json +++ b/apps/forge/metadata.json @@ -1,6 +1,6 @@ { "id": "forge", "name": "App Forge", - "version":"0.01", + "version":"0.02", "description": "Easy way to run development versions of your apps", "icon": "app.png", "readme": "README.md", From fa88a3edc00776aa0f418bca2ac6d3cd17f4c2a5 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 18 Jan 2024 18:43:14 +0000 Subject: [PATCH 29/31] sanitycheck: improve boolean formatter regex check for "on", and make case-insensitive --- bin/sanitycheck.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 945bb8bff..4e6662e4a 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -263,7 +263,7 @@ apps.forEach((app,appIdx) => { WARN(`App ${app.id} has a setting file but no corresponding data entry (add \`"data":[{"name":"${app.id}.settings.json"}]\`)`, {file:appDirRelative+file.url}); } // check for manual boolean formatter - const m = fileContents.match(/format: *\(\) *=>.*["']Yes["']/); + const m = fileContents.match(/format: *\(\) *=>.*["'](yes|on)["']/i); if (m) { WARN(`Settings for ${app.id} has a boolean formatter - this is handled automatically, the line can be removed`, {file:appDirRelative+file.url, line: fileContents.substr(0, m.index).split("\n").length}); } From c21ea99724bcfab50d0b6b593f28c329ef59ad6c Mon Sep 17 00:00:00 2001 From: Paul Spenke Date: Sat, 20 Jan 2024 19:48:33 +0100 Subject: [PATCH 30/31] Refactor settings in line_clock app The `settings` object has been renamed to `initialSettings` for better clarity as these values represent the initial, default settings. Also, the code to remove the clock UI has been commented out, possibly signaling future work on applying the Fast Load system, but this needs to be confirmed. Lastly, calling settings to draw locking and minute indicators has been updated to call the renamed `initialSettings` object. --- apps/line_clock/app.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/line_clock/app.js b/apps/line_clock/app.js index 67ad742f5..eadc46fad 100644 --- a/apps/line_clock/app.js +++ b/apps/line_clock/app.js @@ -13,14 +13,14 @@ const storage = require('Storage'); const SETTINGS_FILE = "line_clock.setting.json"; -let settings = { +let initialSettings = { showLock: true, showMinute: true, }; -let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || initialSettings; for (const key in saved_settings) { - settings[key] = saved_settings[key]; + initialSettings[key] = saved_settings[key]; } let gWidth = g.getWidth(), gCenterX = gWidth/2; @@ -237,11 +237,12 @@ Bangle.on('lock', lockListenerBw); Bangle.setUI({ mode : "clock", - remove : function() { - Bangle.removeListener('lock', lockListenerBw); - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - } + // TODO implement https://www.espruino.com/Bangle.js+Fast+Load + // remove : function() { + // Bangle.removeListener('lock', lockListenerBw); + // if (drawTimeout) clearTimeout(drawTimeout); + // drawTimeout = undefined; + // } }); /** @@ -266,7 +267,7 @@ function draw() { g.setColor(g.theme.bg); g.fillRect(0, 0, gWidth, gHeight); - if(settings.showLock && Bangle.isLocked()){ + if(initialSettings.showLock && Bangle.isLocked()){ g.setColor(g.theme.fg); g.drawImage(imgLock(), gWidth-16, 2); } @@ -278,7 +279,7 @@ function draw() { drawHand(); - if(settings.showMinute){ + if(initialSettings.showMinute){ drawNumber(currentMinute); } } From ef94eab3633458920c8a1f2f7e8ed639b8e93cb6 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sat, 20 Jan 2024 22:58:30 +0100 Subject: [PATCH 31/31] Update settings.js Delete custom formatting for booleans in settings, falling back on the default checkboxes. --- apps/line_clock/settings.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/line_clock/settings.js b/apps/line_clock/settings.js index 5a793ed0f..5da04e959 100644 --- a/apps/line_clock/settings.js +++ b/apps/line_clock/settings.js @@ -21,7 +21,6 @@ '< Back': back, 'Show Lock': { value: settings.showLock, - format: () => (settings.showLock ? 'Yes' : 'No'), onchange: () => { settings.showLock = !settings.showLock; save(); @@ -29,7 +28,6 @@ }, 'Show Minute': { value: settings.showMinute, - format: () => (settings.showMinute ? 'Yes' : 'No'), onchange: () => { settings.showMinute = !settings.showMinute; save();