From 80403150795bb04cc76d739e880083100dae2e2e Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:25:01 -0400 Subject: [PATCH 01/29] Create app.js --- apps/g26/app.js | 345 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 apps/g26/app.js diff --git a/apps/g26/app.js b/apps/g26/app.js new file mode 100644 index 000000000..6e2bdf037 --- /dev/null +++ b/apps/g26/app.js @@ -0,0 +1,345 @@ +g.clear(); + +require("FontHaxorNarrow7x17").add(Graphics); +g.setFont("HaxorNarrow7x17", 1); // bitmap font, 8x magnified + +g.setFontAlign(0,0); // center font + +let interval = null; +let stepCounter = 0; + +let fgColor = "#FFFFFF"; +let bgColor = "#000000"; + +let fillDigits = true; +let myHeartRate = 123; +let hrmPower = false; + +const startX = [ 24, 90, 24, 90 ]; +const startY = [ 14, 14, 120, 120 ]; + +const hht = 60; +const vht = 40; +const w = 60; +const h = 90; + +let lastHour = 99; +let lastMinute = 99; + + +function pad0(n) { + return (n > 9) ? n : ("0"+n); +} + +function setFG() { + g.setColor(fgColor); +} + +function setBG() { + g.setColor(bgColor); +} + +function ellipse(x1, y1, x2, y2, fill) { + if (fill) g.fillEllipse(x1, y1, x2, y2); + else g.drawEllipse(x1, y1, x2, y2); +} + +function poly(arr, fill) { + if (fill) g.fillPoly(arr, true); + else g.drawPoly(arr, true); +} + +function rect(x1, y1, x2, y2, fill) { + if (fill) g.fillRect(x1, y1, x2, y2); + else g.drawRect(x1, y1, x2, y2); +} + +setBG(); +rect(0, 0, 240, 240, true); + + +/** DIGITS **/ + +/* zero */ +function draw0(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+w, yOrig+h, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+15, yOrig+15, xOrig+w-15, yOrig+h-15, fillDigits); +} + +/* one */ +function draw1(xOrig, yOrig) { + setFG(); + poly([xOrig+w/2-6, yOrig, + xOrig+w/2-12, yOrig, + xOrig+w/2-20, yOrig+12, + xOrig+w/2-6, yOrig+12 + ], fillDigits); + rect(xOrig+w/2-6, yOrig, xOrig+w/2+6, yOrig+h-3, fillDigits); + +} + +/* two */ +function draw2(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); + + setBG(); + rect(xOrig, yOrig+27, xOrig+40, yOrig+61, true); + + setFG(); + poly([xOrig, yOrig+88, + xOrig+56, yOrig+88, + xOrig+56, yOrig+75, + xOrig+25, yOrig+75, + xOrig+46, yOrig+50, + xOrig+42, yOrig+36 + ], fillDigits); +} + +/* three */ +function draw8(xOrig, yOrig) { + setFG(); + ellipse(xOrig+3, yOrig, xOrig+53, yOrig+48, fillDigits); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+17, yOrig+13, xOrig+40, yOrig+35, fillDigits); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); +} + +function draw3(xOrig, yOrig) { + draw8(xOrig, yOrig); + setBG(); + rect(xOrig, yOrig+24, xOrig+24, yOrig+61, true); +} + +/* four */ +function draw4(xOrig, yOrig) { + setFG(); + rect(xOrig+8, yOrig+54, xOrig+w-4, yOrig+67, fillDigits); + rect(xOrig+36, yOrig+12, xOrig+49, yOrig+88, fillDigits); + poly([xOrig, yOrig+67, + xOrig+12, yOrig+67, + xOrig+49, yOrig+12, + xOrig+49, yOrig+1, + xOrig+42, yOrig+1 + ], fillDigits); +} + +function draw5(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); + + setBG(); + rect(xOrig, yOrig+24, xOrig+20, yOrig+61, true); + + setFG(); + poly([xOrig+20, yOrig+1, + xOrig+7, yOrig+47, + xOrig+19, yOrig+47, + xOrig+32, yOrig+1 + ], fillDigits); + rect(xOrig+20, yOrig+1, xOrig+53, yOrig+13, fillDigits); +} + +/* six */ +function draw6(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + poly([xOrig+2, yOrig+48, + xOrig+34, yOrig, + xOrig+46, yOrig+7, + xOrig+14, yOrig+56 + ], fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); +} + +/* seven */ +function draw7(xOrig, yOrig) { + setFG(); + poly([xOrig+4, yOrig+1, + xOrig+w-1, yOrig+1, + xOrig+w-7, yOrig+13, + xOrig+4, yOrig+13 + ], fillDigits); + poly([xOrig+w-1, yOrig+1, + xOrig+15, yOrig+88, + xOrig+5, yOrig+81, + xOrig+w-19, yOrig+9 + ], fillDigits); +} + +function draw9(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); + poly([xOrig+54, yOrig+41, + xOrig+22, yOrig+89, + xOrig+10, yOrig+82, + xOrig+42, yOrig+33 + ], fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); +} + +/** END DIGITS **/ +function getRandomColor() { + const digits = "0123456789ABCDEF"; + let r1 = digits[Math.floor(Math.random() * 16)]; + let r2 = digits[Math.floor(Math.random() * 16)]; + let g1 = digits[Math.floor(Math.random() * 16)]; + let g2 = digits[Math.floor(Math.random() * 16)]; + let b1 = digits[Math.floor(Math.random() * 16)]; + let b2 = digits[Math.floor(Math.random() * 16)]; + let str = "#"+r1+r2+g1+g2+b1+b2; + /* console.log(str); */ + return str; +} + +function drawDigit(pos, dig) { + let x = startX[pos]; + let y = startY[pos]; + + setBG(); + rect(x, y, x+w, y+h, true); + switch(dig) { + case 0: + draw0(x, y); + break; + case 1: + draw1(x, y); + break; + case 2: + draw2(x, y); + break; + case 3: + draw3(x, y); + break; + case 4: + draw4(x, y); + break; + case 5: + draw5(x, y); + break; + case 6: + draw6(x, y); + break; + case 7: + draw7(x, y); + break; + case 8: + draw8(x, y); + break; + case 9: + draw9(x, y); + break; + } +} + + +function drawTime() { + let d = new Date(); + let hour = d.getHours(); + let minute = d.getMinutes(); + let month = d.getMonth(); + let date = d.getDate(); + + if(hour == lastHour && minute == lastMinute) { + return; + } + + fgColor = "#FFFFFF"; + if(hour != lastHour) { + drawDigit(0, Math.floor(hour / 10)); + drawDigit(1, hour % 10); + } + + fgColor = "#00FFFF"; + if(minute != lastMinute) { + drawDigit(2, Math.floor(minute / 10)); + drawDigit(3, minute % 10); + } + lastHour = hour; + lastMinute = minute; + + setBG(); + rect(0, 226, 240, 240, true); + for(let c = 0; c <= 240; c++) { + g.setColor(0, 0, 1-c/240); + g.fillRect(180, c, 240, c); + } + g.setColor("#C0C0C0"); + + g.setFontAlign(-1,-1); + g.drawString("DT", 184, 10); + g.drawString("STP", 184, 70); + g.drawString("BPM", 184, 140); + g.drawString("BTY", 184, 210); + + g.setFontAlign(1,-1); + g.drawString(month + "/" + date, 236, 10); + g.drawString(stepCounter, 236, 70); + g.drawString(myHeartRate, 236, 140); + g.drawString(E.getBattery(), 236, 210); + +} + +function stop () { + if (interval) { + clearInterval(interval); + } +} + +function start () { + if (interval) { + clearInterval(interval); + } + // first time init + interval = setInterval(drawTime, 10000); + drawTime(); +} + +start(); + +// Bangle.loadWidgets(); +// Bangle.drawWidgets(); + +Bangle.on('lcdPower', function (on) { + if (on) { + start(); + } else { + stop(); + } +}); + +function btn1Func() { + fillDigits = !fillDigits; + g.clear(); + lastHour = 99; + lastMinute = 99; + drawTime(); +} + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + +setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); + +Bangle.on('step', function(cnt) { + stepCounter = cnt; +}); + +Bangle.on('swipe', function(dir) { + Bangle.buzz(); + hrmPower = ! hrmPower; + Bangle.setHRMPower(hrmPower); +}); + +Bangle.on('HRM', function(hrm) { + myHeartRate = hrm.bpm; +}); From 2bb279c5a360695d4febba10a535a820b356476f Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:26:51 -0400 Subject: [PATCH 02/29] Create g26.js --- apps/g26/g26.js | 345 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 apps/g26/g26.js diff --git a/apps/g26/g26.js b/apps/g26/g26.js new file mode 100644 index 000000000..6e2bdf037 --- /dev/null +++ b/apps/g26/g26.js @@ -0,0 +1,345 @@ +g.clear(); + +require("FontHaxorNarrow7x17").add(Graphics); +g.setFont("HaxorNarrow7x17", 1); // bitmap font, 8x magnified + +g.setFontAlign(0,0); // center font + +let interval = null; +let stepCounter = 0; + +let fgColor = "#FFFFFF"; +let bgColor = "#000000"; + +let fillDigits = true; +let myHeartRate = 123; +let hrmPower = false; + +const startX = [ 24, 90, 24, 90 ]; +const startY = [ 14, 14, 120, 120 ]; + +const hht = 60; +const vht = 40; +const w = 60; +const h = 90; + +let lastHour = 99; +let lastMinute = 99; + + +function pad0(n) { + return (n > 9) ? n : ("0"+n); +} + +function setFG() { + g.setColor(fgColor); +} + +function setBG() { + g.setColor(bgColor); +} + +function ellipse(x1, y1, x2, y2, fill) { + if (fill) g.fillEllipse(x1, y1, x2, y2); + else g.drawEllipse(x1, y1, x2, y2); +} + +function poly(arr, fill) { + if (fill) g.fillPoly(arr, true); + else g.drawPoly(arr, true); +} + +function rect(x1, y1, x2, y2, fill) { + if (fill) g.fillRect(x1, y1, x2, y2); + else g.drawRect(x1, y1, x2, y2); +} + +setBG(); +rect(0, 0, 240, 240, true); + + +/** DIGITS **/ + +/* zero */ +function draw0(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+w, yOrig+h, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+15, yOrig+15, xOrig+w-15, yOrig+h-15, fillDigits); +} + +/* one */ +function draw1(xOrig, yOrig) { + setFG(); + poly([xOrig+w/2-6, yOrig, + xOrig+w/2-12, yOrig, + xOrig+w/2-20, yOrig+12, + xOrig+w/2-6, yOrig+12 + ], fillDigits); + rect(xOrig+w/2-6, yOrig, xOrig+w/2+6, yOrig+h-3, fillDigits); + +} + +/* two */ +function draw2(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); + + setBG(); + rect(xOrig, yOrig+27, xOrig+40, yOrig+61, true); + + setFG(); + poly([xOrig, yOrig+88, + xOrig+56, yOrig+88, + xOrig+56, yOrig+75, + xOrig+25, yOrig+75, + xOrig+46, yOrig+50, + xOrig+42, yOrig+36 + ], fillDigits); +} + +/* three */ +function draw8(xOrig, yOrig) { + setFG(); + ellipse(xOrig+3, yOrig, xOrig+53, yOrig+48, fillDigits); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+17, yOrig+13, xOrig+40, yOrig+35, fillDigits); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); +} + +function draw3(xOrig, yOrig) { + draw8(xOrig, yOrig); + setBG(); + rect(xOrig, yOrig+24, xOrig+24, yOrig+61, true); +} + +/* four */ +function draw4(xOrig, yOrig) { + setFG(); + rect(xOrig+8, yOrig+54, xOrig+w-4, yOrig+67, fillDigits); + rect(xOrig+36, yOrig+12, xOrig+49, yOrig+88, fillDigits); + poly([xOrig, yOrig+67, + xOrig+12, yOrig+67, + xOrig+49, yOrig+12, + xOrig+49, yOrig+1, + xOrig+42, yOrig+1 + ], fillDigits); +} + +function draw5(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); + + setBG(); + rect(xOrig, yOrig+24, xOrig+20, yOrig+61, true); + + setFG(); + poly([xOrig+20, yOrig+1, + xOrig+7, yOrig+47, + xOrig+19, yOrig+47, + xOrig+32, yOrig+1 + ], fillDigits); + rect(xOrig+20, yOrig+1, xOrig+53, yOrig+13, fillDigits); +} + +/* six */ +function draw6(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + poly([xOrig+2, yOrig+48, + xOrig+34, yOrig, + xOrig+46, yOrig+7, + xOrig+14, yOrig+56 + ], fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); +} + +/* seven */ +function draw7(xOrig, yOrig) { + setFG(); + poly([xOrig+4, yOrig+1, + xOrig+w-1, yOrig+1, + xOrig+w-7, yOrig+13, + xOrig+4, yOrig+13 + ], fillDigits); + poly([xOrig+w-1, yOrig+1, + xOrig+15, yOrig+88, + xOrig+5, yOrig+81, + xOrig+w-19, yOrig+9 + ], fillDigits); +} + +function draw9(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); + poly([xOrig+54, yOrig+41, + xOrig+22, yOrig+89, + xOrig+10, yOrig+82, + xOrig+42, yOrig+33 + ], fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); +} + +/** END DIGITS **/ +function getRandomColor() { + const digits = "0123456789ABCDEF"; + let r1 = digits[Math.floor(Math.random() * 16)]; + let r2 = digits[Math.floor(Math.random() * 16)]; + let g1 = digits[Math.floor(Math.random() * 16)]; + let g2 = digits[Math.floor(Math.random() * 16)]; + let b1 = digits[Math.floor(Math.random() * 16)]; + let b2 = digits[Math.floor(Math.random() * 16)]; + let str = "#"+r1+r2+g1+g2+b1+b2; + /* console.log(str); */ + return str; +} + +function drawDigit(pos, dig) { + let x = startX[pos]; + let y = startY[pos]; + + setBG(); + rect(x, y, x+w, y+h, true); + switch(dig) { + case 0: + draw0(x, y); + break; + case 1: + draw1(x, y); + break; + case 2: + draw2(x, y); + break; + case 3: + draw3(x, y); + break; + case 4: + draw4(x, y); + break; + case 5: + draw5(x, y); + break; + case 6: + draw6(x, y); + break; + case 7: + draw7(x, y); + break; + case 8: + draw8(x, y); + break; + case 9: + draw9(x, y); + break; + } +} + + +function drawTime() { + let d = new Date(); + let hour = d.getHours(); + let minute = d.getMinutes(); + let month = d.getMonth(); + let date = d.getDate(); + + if(hour == lastHour && minute == lastMinute) { + return; + } + + fgColor = "#FFFFFF"; + if(hour != lastHour) { + drawDigit(0, Math.floor(hour / 10)); + drawDigit(1, hour % 10); + } + + fgColor = "#00FFFF"; + if(minute != lastMinute) { + drawDigit(2, Math.floor(minute / 10)); + drawDigit(3, minute % 10); + } + lastHour = hour; + lastMinute = minute; + + setBG(); + rect(0, 226, 240, 240, true); + for(let c = 0; c <= 240; c++) { + g.setColor(0, 0, 1-c/240); + g.fillRect(180, c, 240, c); + } + g.setColor("#C0C0C0"); + + g.setFontAlign(-1,-1); + g.drawString("DT", 184, 10); + g.drawString("STP", 184, 70); + g.drawString("BPM", 184, 140); + g.drawString("BTY", 184, 210); + + g.setFontAlign(1,-1); + g.drawString(month + "/" + date, 236, 10); + g.drawString(stepCounter, 236, 70); + g.drawString(myHeartRate, 236, 140); + g.drawString(E.getBattery(), 236, 210); + +} + +function stop () { + if (interval) { + clearInterval(interval); + } +} + +function start () { + if (interval) { + clearInterval(interval); + } + // first time init + interval = setInterval(drawTime, 10000); + drawTime(); +} + +start(); + +// Bangle.loadWidgets(); +// Bangle.drawWidgets(); + +Bangle.on('lcdPower', function (on) { + if (on) { + start(); + } else { + stop(); + } +}); + +function btn1Func() { + fillDigits = !fillDigits; + g.clear(); + lastHour = 99; + lastMinute = 99; + drawTime(); +} + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + +setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); + +Bangle.on('step', function(cnt) { + stepCounter = cnt; +}); + +Bangle.on('swipe', function(dir) { + Bangle.buzz(); + hrmPower = ! hrmPower; + Bangle.setHRMPower(hrmPower); +}); + +Bangle.on('HRM', function(hrm) { + myHeartRate = hrm.bpm; +}); From cbdde8b5cfa79e0e2468b15a472413174de124e2 Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:27:44 -0400 Subject: [PATCH 03/29] Delete app.js --- apps/g26/app.js | 345 ------------------------------------------------ 1 file changed, 345 deletions(-) delete mode 100644 apps/g26/app.js diff --git a/apps/g26/app.js b/apps/g26/app.js deleted file mode 100644 index 6e2bdf037..000000000 --- a/apps/g26/app.js +++ /dev/null @@ -1,345 +0,0 @@ -g.clear(); - -require("FontHaxorNarrow7x17").add(Graphics); -g.setFont("HaxorNarrow7x17", 1); // bitmap font, 8x magnified - -g.setFontAlign(0,0); // center font - -let interval = null; -let stepCounter = 0; - -let fgColor = "#FFFFFF"; -let bgColor = "#000000"; - -let fillDigits = true; -let myHeartRate = 123; -let hrmPower = false; - -const startX = [ 24, 90, 24, 90 ]; -const startY = [ 14, 14, 120, 120 ]; - -const hht = 60; -const vht = 40; -const w = 60; -const h = 90; - -let lastHour = 99; -let lastMinute = 99; - - -function pad0(n) { - return (n > 9) ? n : ("0"+n); -} - -function setFG() { - g.setColor(fgColor); -} - -function setBG() { - g.setColor(bgColor); -} - -function ellipse(x1, y1, x2, y2, fill) { - if (fill) g.fillEllipse(x1, y1, x2, y2); - else g.drawEllipse(x1, y1, x2, y2); -} - -function poly(arr, fill) { - if (fill) g.fillPoly(arr, true); - else g.drawPoly(arr, true); -} - -function rect(x1, y1, x2, y2, fill) { - if (fill) g.fillRect(x1, y1, x2, y2); - else g.drawRect(x1, y1, x2, y2); -} - -setBG(); -rect(0, 0, 240, 240, true); - - -/** DIGITS **/ - -/* zero */ -function draw0(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+w, yOrig+h, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+15, yOrig+15, xOrig+w-15, yOrig+h-15, fillDigits); -} - -/* one */ -function draw1(xOrig, yOrig) { - setFG(); - poly([xOrig+w/2-6, yOrig, - xOrig+w/2-12, yOrig, - xOrig+w/2-20, yOrig+12, - xOrig+w/2-6, yOrig+12 - ], fillDigits); - rect(xOrig+w/2-6, yOrig, xOrig+w/2+6, yOrig+h-3, fillDigits); - -} - -/* two */ -function draw2(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); - - setBG(); - rect(xOrig, yOrig+27, xOrig+40, yOrig+61, true); - - setFG(); - poly([xOrig, yOrig+88, - xOrig+56, yOrig+88, - xOrig+56, yOrig+75, - xOrig+25, yOrig+75, - xOrig+46, yOrig+50, - xOrig+42, yOrig+36 - ], fillDigits); -} - -/* three */ -function draw8(xOrig, yOrig) { - setFG(); - ellipse(xOrig+3, yOrig, xOrig+53, yOrig+48, fillDigits); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+17, yOrig+13, xOrig+40, yOrig+35, fillDigits); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); -} - -function draw3(xOrig, yOrig) { - draw8(xOrig, yOrig); - setBG(); - rect(xOrig, yOrig+24, xOrig+24, yOrig+61, true); -} - -/* four */ -function draw4(xOrig, yOrig) { - setFG(); - rect(xOrig+8, yOrig+54, xOrig+w-4, yOrig+67, fillDigits); - rect(xOrig+36, yOrig+12, xOrig+49, yOrig+88, fillDigits); - poly([xOrig, yOrig+67, - xOrig+12, yOrig+67, - xOrig+49, yOrig+12, - xOrig+49, yOrig+1, - xOrig+42, yOrig+1 - ], fillDigits); -} - -function draw5(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); - - setBG(); - rect(xOrig, yOrig+24, xOrig+20, yOrig+61, true); - - setFG(); - poly([xOrig+20, yOrig+1, - xOrig+7, yOrig+47, - xOrig+19, yOrig+47, - xOrig+32, yOrig+1 - ], fillDigits); - rect(xOrig+20, yOrig+1, xOrig+53, yOrig+13, fillDigits); -} - -/* six */ -function draw6(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - poly([xOrig+2, yOrig+48, - xOrig+34, yOrig, - xOrig+46, yOrig+7, - xOrig+14, yOrig+56 - ], fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); -} - -/* seven */ -function draw7(xOrig, yOrig) { - setFG(); - poly([xOrig+4, yOrig+1, - xOrig+w-1, yOrig+1, - xOrig+w-7, yOrig+13, - xOrig+4, yOrig+13 - ], fillDigits); - poly([xOrig+w-1, yOrig+1, - xOrig+15, yOrig+88, - xOrig+5, yOrig+81, - xOrig+w-19, yOrig+9 - ], fillDigits); -} - -function draw9(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); - poly([xOrig+54, yOrig+41, - xOrig+22, yOrig+89, - xOrig+10, yOrig+82, - xOrig+42, yOrig+33 - ], fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); -} - -/** END DIGITS **/ -function getRandomColor() { - const digits = "0123456789ABCDEF"; - let r1 = digits[Math.floor(Math.random() * 16)]; - let r2 = digits[Math.floor(Math.random() * 16)]; - let g1 = digits[Math.floor(Math.random() * 16)]; - let g2 = digits[Math.floor(Math.random() * 16)]; - let b1 = digits[Math.floor(Math.random() * 16)]; - let b2 = digits[Math.floor(Math.random() * 16)]; - let str = "#"+r1+r2+g1+g2+b1+b2; - /* console.log(str); */ - return str; -} - -function drawDigit(pos, dig) { - let x = startX[pos]; - let y = startY[pos]; - - setBG(); - rect(x, y, x+w, y+h, true); - switch(dig) { - case 0: - draw0(x, y); - break; - case 1: - draw1(x, y); - break; - case 2: - draw2(x, y); - break; - case 3: - draw3(x, y); - break; - case 4: - draw4(x, y); - break; - case 5: - draw5(x, y); - break; - case 6: - draw6(x, y); - break; - case 7: - draw7(x, y); - break; - case 8: - draw8(x, y); - break; - case 9: - draw9(x, y); - break; - } -} - - -function drawTime() { - let d = new Date(); - let hour = d.getHours(); - let minute = d.getMinutes(); - let month = d.getMonth(); - let date = d.getDate(); - - if(hour == lastHour && minute == lastMinute) { - return; - } - - fgColor = "#FFFFFF"; - if(hour != lastHour) { - drawDigit(0, Math.floor(hour / 10)); - drawDigit(1, hour % 10); - } - - fgColor = "#00FFFF"; - if(minute != lastMinute) { - drawDigit(2, Math.floor(minute / 10)); - drawDigit(3, minute % 10); - } - lastHour = hour; - lastMinute = minute; - - setBG(); - rect(0, 226, 240, 240, true); - for(let c = 0; c <= 240; c++) { - g.setColor(0, 0, 1-c/240); - g.fillRect(180, c, 240, c); - } - g.setColor("#C0C0C0"); - - g.setFontAlign(-1,-1); - g.drawString("DT", 184, 10); - g.drawString("STP", 184, 70); - g.drawString("BPM", 184, 140); - g.drawString("BTY", 184, 210); - - g.setFontAlign(1,-1); - g.drawString(month + "/" + date, 236, 10); - g.drawString(stepCounter, 236, 70); - g.drawString(myHeartRate, 236, 140); - g.drawString(E.getBattery(), 236, 210); - -} - -function stop () { - if (interval) { - clearInterval(interval); - } -} - -function start () { - if (interval) { - clearInterval(interval); - } - // first time init - interval = setInterval(drawTime, 10000); - drawTime(); -} - -start(); - -// Bangle.loadWidgets(); -// Bangle.drawWidgets(); - -Bangle.on('lcdPower', function (on) { - if (on) { - start(); - } else { - stop(); - } -}); - -function btn1Func() { - fillDigits = !fillDigits; - g.clear(); - lastHour = 99; - lastMinute = 99; - drawTime(); -} - -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); - -setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); - -Bangle.on('step', function(cnt) { - stepCounter = cnt; -}); - -Bangle.on('swipe', function(dir) { - Bangle.buzz(); - hrmPower = ! hrmPower; - Bangle.setHRMPower(hrmPower); -}); - -Bangle.on('HRM', function(hrm) { - myHeartRate = hrm.bpm; -}); From 0da1a4d7251a4d35cf26c4db4ae60ee1808a62e9 Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:37:25 -0400 Subject: [PATCH 04/29] Create g26.json --- apps/g26/g26.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 apps/g26/g26.json diff --git a/apps/g26/g26.json b/apps/g26/g26.json new file mode 100644 index 000000000..e037c8f17 --- /dev/null +++ b/apps/g26/g26.json @@ -0,0 +1,13 @@ +}, +{ "id": "g26", + "name": "G26 Watch", + "shortName":"G26 Watch", + "type": "clock", + "version":"0.01", + "description": "This is a watchface loosely based on a $5 step tracker", + "tags": "", + "storage": [ + {"name":"g26.app.js","url":"g26.js"} + ] +} +] From e9a20f90f3628140228d27a7a8b7d3621f06cf43 Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:51:35 -0400 Subject: [PATCH 05/29] Create apps.json --- apps/g26/apps.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 apps/g26/apps.json diff --git a/apps/g26/apps.json b/apps/g26/apps.json new file mode 100644 index 000000000..e037c8f17 --- /dev/null +++ b/apps/g26/apps.json @@ -0,0 +1,13 @@ +}, +{ "id": "g26", + "name": "G26 Watch", + "shortName":"G26 Watch", + "type": "clock", + "version":"0.01", + "description": "This is a watchface loosely based on a $5 step tracker", + "tags": "", + "storage": [ + {"name":"g26.app.js","url":"g26.js"} + ] +} +] From 17e920d7e569d341dc32044f74c47183e3978f8b Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:55:33 -0400 Subject: [PATCH 06/29] Create app.js --- apps/g26/app.js | 336 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 apps/g26/app.js diff --git a/apps/g26/app.js b/apps/g26/app.js new file mode 100644 index 000000000..b96422f4c --- /dev/null +++ b/apps/g26/app.js @@ -0,0 +1,336 @@ +g.clear(); + +require("FontHaxorNarrow7x17").add(Graphics); +g.setFont("HaxorNarrow7x17", 1); // bitmap font, 8x magnified + +g.setFontAlign(0,0); // center font + +let interval = null; +let stepCounter = 0; + +let fgColor = "#FFFFFF"; +let bgColor = "#000000"; + +let fillDigits = true; +let myHeartRate = 123; +let hrmPower = false; + +const startX = [ 24, 90, 24, 90 ]; +const startY = [ 14, 14, 120, 120 ]; + +const hht = 60; +const vht = 40; +const w = 60; +const h = 90; + +let lastHour = 99; +let lastMinute = 99; + + +function pad0(n) { + return (n > 9) ? n : ("0"+n); +} + +function setFG() { + g.setColor(fgColor); +} + +function setBG() { + g.setColor(bgColor); +} + +function ellipse(x1, y1, x2, y2, fill) { + if (fill) g.fillEllipse(x1, y1, x2, y2); + else g.drawEllipse(x1, y1, x2, y2); +} + +function poly(arr, fill) { + if (fill) g.fillPoly(arr, true); + else g.drawPoly(arr, true); +} + +function rect(x1, y1, x2, y2, fill) { + if (fill) g.fillRect(x1, y1, x2, y2); + else g.drawRect(x1, y1, x2, y2); +} + +setBG(); +rect(0, 0, 240, 240, true); + + +/** DIGITS **/ + +/* zero */ +function draw0(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+w, yOrig+h, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+15, yOrig+15, xOrig+w-15, yOrig+h-15, fillDigits); +} + +/* one */ +function draw1(xOrig, yOrig) { + setFG(); + poly([xOrig+w/2-6, yOrig, + xOrig+w/2-12, yOrig, + xOrig+w/2-20, yOrig+12, + xOrig+w/2-6, yOrig+12 + ], fillDigits); + rect(xOrig+w/2-6, yOrig, xOrig+w/2+6, yOrig+h-3, fillDigits); + +} + +/* two */ +function draw2(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); + + setBG(); + rect(xOrig, yOrig+27, xOrig+40, yOrig+61, true); + + setFG(); + poly([xOrig, yOrig+88, + xOrig+56, yOrig+88, + xOrig+56, yOrig+75, + xOrig+25, yOrig+75, + xOrig+46, yOrig+50, + xOrig+42, yOrig+36 + ], fillDigits); +} + +/* three */ +function draw8(xOrig, yOrig) { + setFG(); + ellipse(xOrig+3, yOrig, xOrig+53, yOrig+48, fillDigits); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+17, yOrig+13, xOrig+40, yOrig+35, fillDigits); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); +} + +function draw3(xOrig, yOrig) { + draw8(xOrig, yOrig); + setBG(); + rect(xOrig, yOrig+24, xOrig+24, yOrig+61, true); +} + +/* four */ +function draw4(xOrig, yOrig) { + setFG(); + rect(xOrig+8, yOrig+54, xOrig+w-4, yOrig+67, fillDigits); + rect(xOrig+36, yOrig+12, xOrig+49, yOrig+88, fillDigits); + poly([xOrig, yOrig+67, + xOrig+12, yOrig+67, + xOrig+49, yOrig+12, + xOrig+49, yOrig+1, + xOrig+42, yOrig+1 + ], fillDigits); +} + +function draw5(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); + + setBG(); + rect(xOrig, yOrig+24, xOrig+20, yOrig+61, true); + + setFG(); + poly([xOrig+20, yOrig+1, + xOrig+7, yOrig+47, + xOrig+19, yOrig+47, + xOrig+32, yOrig+1 + ], fillDigits); + rect(xOrig+20, yOrig+1, xOrig+53, yOrig+13, fillDigits); +} + +/* six */ +function draw6(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); + poly([xOrig+2, yOrig+48, + xOrig+34, yOrig, + xOrig+46, yOrig+7, + xOrig+14, yOrig+56 + ], fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); +} + +/* seven */ +function draw7(xOrig, yOrig) { + setFG(); + poly([xOrig+4, yOrig+1, + xOrig+w-1, yOrig+1, + xOrig+w-7, yOrig+13, + xOrig+4, yOrig+13 + ], fillDigits); + poly([xOrig+w-1, yOrig+1, + xOrig+15, yOrig+88, + xOrig+5, yOrig+81, + xOrig+w-19, yOrig+9 + ], fillDigits); +} + +function draw9(xOrig, yOrig) { + setFG(); + ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); + poly([xOrig+54, yOrig+41, + xOrig+22, yOrig+89, + xOrig+10, yOrig+82, + xOrig+42, yOrig+33 + ], fillDigits); + if(fillDigits) setBG(); + ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); +} + +/** END DIGITS **/ +function getRandomColor() { + const digits = "0123456789ABCDEF"; + let r1 = digits[Math.floor(Math.random() * 16)]; + let r2 = digits[Math.floor(Math.random() * 16)]; + let g1 = digits[Math.floor(Math.random() * 16)]; + let g2 = digits[Math.floor(Math.random() * 16)]; + let b1 = digits[Math.floor(Math.random() * 16)]; + let b2 = digits[Math.floor(Math.random() * 16)]; + let str = "#"+r1+r2+g1+g2+b1+b2; + /* console.log(str); */ + return str; +} + +function drawDigit(pos, dig) { + let x = startX[pos]; + let y = startY[pos]; + + setBG(); + rect(x, y, x+w, y+h, true); + switch(dig) { + case 0: + draw0(x, y); + break; + case 1: + draw1(x, y); + break; + case 2: + draw2(x, y); + break; + case 3: + draw3(x, y); + break; + case 4: + draw4(x, y); + break; + case 5: + draw5(x, y); + break; + case 6: + draw6(x, y); + break; + case 7: + draw7(x, y); + break; + case 8: + draw8(x, y); + break; + case 9: + draw9(x, y); + break; + } +} + + +function drawTime() { + let d = new Date(); + let hour = d.getHours(); + let minute = d.getMinutes(); + let month = d.getMonth(); + let date = d.getDate(); + + if(hour == lastHour && minute == lastMinute) { + return; + } + + fgColor = "#FFFFFF"; + if(hour != lastHour) { + drawDigit(0, Math.floor(hour / 10)); + drawDigit(1, hour % 10); + } + + fgColor = "#00FFFF"; + if(minute != lastMinute) { + drawDigit(2, Math.floor(minute / 10)); + drawDigit(3, minute % 10); + } + lastHour = hour; + lastMinute = minute; + + setBG(); + rect(0, 226, 240, 240, true); + for(let c = 0; c <= 240; c++) { + g.setColor(0, 0, 1-c/240); + g.fillRect(180, c, 240, c); + } + g.setColor("#C0C0C0"); + + g.setFontAlign(-1,-1); + g.drawString("DT", 184, 10); + g.drawString("STP", 184, 70); + g.drawString("BPM", 184, 140); + g.drawString("BTY", 184, 210); + + g.setFontAlign(1,-1); + g.drawString(month + "/" + date, 236, 10); + g.drawString(stepCounter, 236, 70); + g.drawString(myHeartRate, 236, 140); + g.drawString(E.getBattery(), 236, 210); + +} + +function stop () { + if (interval) { + clearInterval(interval); + } +} + +function start () { + if (interval) { + clearInterval(interval); + } + // first time init + interval = setInterval(drawTime, 10000); + drawTime(); +} + +start(); + +// Bangle.loadWidgets(); +// Bangle.drawWidgets(); + +Bangle.on('lcdPower', function (on) { + if (on) { + start(); + } else { + stop(); + } +}); + +function btn1Func() { + fillDigits = !fillDigits; + g.clear(); + lastHour = 99; + lastMinute = 99; + drawTime(); +} + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + +setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); + +Bangle.on('step', function(cnt) { + stepCounter = cnt; +}); + From 5ad73b28fa58a213c2833d6de334791c5f2960d5 Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:55:50 -0400 Subject: [PATCH 07/29] Delete g26.js --- apps/g26/g26.js | 345 ------------------------------------------------ 1 file changed, 345 deletions(-) delete mode 100644 apps/g26/g26.js diff --git a/apps/g26/g26.js b/apps/g26/g26.js deleted file mode 100644 index 6e2bdf037..000000000 --- a/apps/g26/g26.js +++ /dev/null @@ -1,345 +0,0 @@ -g.clear(); - -require("FontHaxorNarrow7x17").add(Graphics); -g.setFont("HaxorNarrow7x17", 1); // bitmap font, 8x magnified - -g.setFontAlign(0,0); // center font - -let interval = null; -let stepCounter = 0; - -let fgColor = "#FFFFFF"; -let bgColor = "#000000"; - -let fillDigits = true; -let myHeartRate = 123; -let hrmPower = false; - -const startX = [ 24, 90, 24, 90 ]; -const startY = [ 14, 14, 120, 120 ]; - -const hht = 60; -const vht = 40; -const w = 60; -const h = 90; - -let lastHour = 99; -let lastMinute = 99; - - -function pad0(n) { - return (n > 9) ? n : ("0"+n); -} - -function setFG() { - g.setColor(fgColor); -} - -function setBG() { - g.setColor(bgColor); -} - -function ellipse(x1, y1, x2, y2, fill) { - if (fill) g.fillEllipse(x1, y1, x2, y2); - else g.drawEllipse(x1, y1, x2, y2); -} - -function poly(arr, fill) { - if (fill) g.fillPoly(arr, true); - else g.drawPoly(arr, true); -} - -function rect(x1, y1, x2, y2, fill) { - if (fill) g.fillRect(x1, y1, x2, y2); - else g.drawRect(x1, y1, x2, y2); -} - -setBG(); -rect(0, 0, 240, 240, true); - - -/** DIGITS **/ - -/* zero */ -function draw0(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+w, yOrig+h, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+15, yOrig+15, xOrig+w-15, yOrig+h-15, fillDigits); -} - -/* one */ -function draw1(xOrig, yOrig) { - setFG(); - poly([xOrig+w/2-6, yOrig, - xOrig+w/2-12, yOrig, - xOrig+w/2-20, yOrig+12, - xOrig+w/2-6, yOrig+12 - ], fillDigits); - rect(xOrig+w/2-6, yOrig, xOrig+w/2+6, yOrig+h-3, fillDigits); - -} - -/* two */ -function draw2(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); - - setBG(); - rect(xOrig, yOrig+27, xOrig+40, yOrig+61, true); - - setFG(); - poly([xOrig, yOrig+88, - xOrig+56, yOrig+88, - xOrig+56, yOrig+75, - xOrig+25, yOrig+75, - xOrig+46, yOrig+50, - xOrig+42, yOrig+36 - ], fillDigits); -} - -/* three */ -function draw8(xOrig, yOrig) { - setFG(); - ellipse(xOrig+3, yOrig, xOrig+53, yOrig+48, fillDigits); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+17, yOrig+13, xOrig+40, yOrig+35, fillDigits); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); -} - -function draw3(xOrig, yOrig) { - draw8(xOrig, yOrig); - setBG(); - rect(xOrig, yOrig+24, xOrig+24, yOrig+61, true); -} - -/* four */ -function draw4(xOrig, yOrig) { - setFG(); - rect(xOrig+8, yOrig+54, xOrig+w-4, yOrig+67, fillDigits); - rect(xOrig+36, yOrig+12, xOrig+49, yOrig+88, fillDigits); - poly([xOrig, yOrig+67, - xOrig+12, yOrig+67, - xOrig+49, yOrig+12, - xOrig+49, yOrig+1, - xOrig+42, yOrig+1 - ], fillDigits); -} - -function draw5(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); - - setBG(); - rect(xOrig, yOrig+24, xOrig+20, yOrig+61, true); - - setFG(); - poly([xOrig+20, yOrig+1, - xOrig+7, yOrig+47, - xOrig+19, yOrig+47, - xOrig+32, yOrig+1 - ], fillDigits); - rect(xOrig+20, yOrig+1, xOrig+53, yOrig+13, fillDigits); -} - -/* six */ -function draw6(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - poly([xOrig+2, yOrig+48, - xOrig+34, yOrig, - xOrig+46, yOrig+7, - xOrig+14, yOrig+56 - ], fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); -} - -/* seven */ -function draw7(xOrig, yOrig) { - setFG(); - poly([xOrig+4, yOrig+1, - xOrig+w-1, yOrig+1, - xOrig+w-7, yOrig+13, - xOrig+4, yOrig+13 - ], fillDigits); - poly([xOrig+w-1, yOrig+1, - xOrig+15, yOrig+88, - xOrig+5, yOrig+81, - xOrig+w-19, yOrig+9 - ], fillDigits); -} - -function draw9(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); - poly([xOrig+54, yOrig+41, - xOrig+22, yOrig+89, - xOrig+10, yOrig+82, - xOrig+42, yOrig+33 - ], fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); -} - -/** END DIGITS **/ -function getRandomColor() { - const digits = "0123456789ABCDEF"; - let r1 = digits[Math.floor(Math.random() * 16)]; - let r2 = digits[Math.floor(Math.random() * 16)]; - let g1 = digits[Math.floor(Math.random() * 16)]; - let g2 = digits[Math.floor(Math.random() * 16)]; - let b1 = digits[Math.floor(Math.random() * 16)]; - let b2 = digits[Math.floor(Math.random() * 16)]; - let str = "#"+r1+r2+g1+g2+b1+b2; - /* console.log(str); */ - return str; -} - -function drawDigit(pos, dig) { - let x = startX[pos]; - let y = startY[pos]; - - setBG(); - rect(x, y, x+w, y+h, true); - switch(dig) { - case 0: - draw0(x, y); - break; - case 1: - draw1(x, y); - break; - case 2: - draw2(x, y); - break; - case 3: - draw3(x, y); - break; - case 4: - draw4(x, y); - break; - case 5: - draw5(x, y); - break; - case 6: - draw6(x, y); - break; - case 7: - draw7(x, y); - break; - case 8: - draw8(x, y); - break; - case 9: - draw9(x, y); - break; - } -} - - -function drawTime() { - let d = new Date(); - let hour = d.getHours(); - let minute = d.getMinutes(); - let month = d.getMonth(); - let date = d.getDate(); - - if(hour == lastHour && minute == lastMinute) { - return; - } - - fgColor = "#FFFFFF"; - if(hour != lastHour) { - drawDigit(0, Math.floor(hour / 10)); - drawDigit(1, hour % 10); - } - - fgColor = "#00FFFF"; - if(minute != lastMinute) { - drawDigit(2, Math.floor(minute / 10)); - drawDigit(3, minute % 10); - } - lastHour = hour; - lastMinute = minute; - - setBG(); - rect(0, 226, 240, 240, true); - for(let c = 0; c <= 240; c++) { - g.setColor(0, 0, 1-c/240); - g.fillRect(180, c, 240, c); - } - g.setColor("#C0C0C0"); - - g.setFontAlign(-1,-1); - g.drawString("DT", 184, 10); - g.drawString("STP", 184, 70); - g.drawString("BPM", 184, 140); - g.drawString("BTY", 184, 210); - - g.setFontAlign(1,-1); - g.drawString(month + "/" + date, 236, 10); - g.drawString(stepCounter, 236, 70); - g.drawString(myHeartRate, 236, 140); - g.drawString(E.getBattery(), 236, 210); - -} - -function stop () { - if (interval) { - clearInterval(interval); - } -} - -function start () { - if (interval) { - clearInterval(interval); - } - // first time init - interval = setInterval(drawTime, 10000); - drawTime(); -} - -start(); - -// Bangle.loadWidgets(); -// Bangle.drawWidgets(); - -Bangle.on('lcdPower', function (on) { - if (on) { - start(); - } else { - stop(); - } -}); - -function btn1Func() { - fillDigits = !fillDigits; - g.clear(); - lastHour = 99; - lastMinute = 99; - drawTime(); -} - -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); - -setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); - -Bangle.on('step', function(cnt) { - stepCounter = cnt; -}); - -Bangle.on('swipe', function(dir) { - Bangle.buzz(); - hrmPower = ! hrmPower; - Bangle.setHRMPower(hrmPower); -}); - -Bangle.on('HRM', function(hrm) { - myHeartRate = hrm.bpm; -}); From f367b1a662dcfa9f1696469ab6427a7b43206195 Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Thu, 21 May 2020 15:56:00 -0400 Subject: [PATCH 08/29] Delete g26.json --- apps/g26/g26.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 apps/g26/g26.json diff --git a/apps/g26/g26.json b/apps/g26/g26.json deleted file mode 100644 index e037c8f17..000000000 --- a/apps/g26/g26.json +++ /dev/null @@ -1,13 +0,0 @@ -}, -{ "id": "g26", - "name": "G26 Watch", - "shortName":"G26 Watch", - "type": "clock", - "version":"0.01", - "description": "This is a watchface loosely based on a $5 step tracker", - "tags": "", - "storage": [ - {"name":"g26.app.js","url":"g26.js"} - ] -} -] From 4fa0d1b204e997425887272215615b6f4de0102d Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Fri, 17 Jul 2020 14:37:15 -0400 Subject: [PATCH 09/29] Create readme.md --- apps/nixie/readme.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 apps/nixie/readme.md diff --git a/apps/nixie/readme.md b/apps/nixie/readme.md new file mode 100644 index 000000000..68af873a6 --- /dev/null +++ b/apps/nixie/readme.md @@ -0,0 +1,3 @@ +This watch face emulates nixie tube characters and is a bit fun to watch draw. Also displays date, "steps" (the stepcounter / 10 until I really train the accelerometer) and remaining battery. + +Also supports alarms from a JSON file named "yngv.alarms.json". From a33b203780c5bedccc7711ca46e8c1c191ee7404 Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Fri, 17 Jul 2020 14:38:24 -0400 Subject: [PATCH 10/29] Add files via upload --- apps/nixie/nixie.app.js | 392 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 apps/nixie/nixie.app.js diff --git a/apps/nixie/nixie.app.js b/apps/nixie/nixie.app.js new file mode 100644 index 000000000..c9fa068fe --- /dev/null +++ b/apps/nixie/nixie.app.js @@ -0,0 +1,392 @@ + +g.clear(); + +require("Font8x12").add(Graphics); +g.setFont("8x12", 1); +let interval = null; +let stepCounter = 0; + +let msgs = require("Storage").readJSON('yngv27.msgs.json'); +let alarms = require("Storage").readJSON('yngv27.alarm.json'); + +function showMsg(msg) { + g.setFontAlign(0,-1); + g.setColor(1,1,1); + g.drawString("<< ALARM >>", 120, 180, true); + g.drawString(msg, 120, 200, true); + Bangle.buzz(); + setTimeout(Bangle.buzz, 800); + setTimeout(Bangle.buzz, 1600); + setTimeout(Bangle.buzz, 2400); + setTimeout(Bangle.buzz, 3200); +} + +function checkMsgs() { + for(let idx=0; idx < alarms.length; idx++) { + let tdiff = Date.now() - Date.parse(alarms[idx].time); + // 10 sec margin of error + if(tdiff > 0 && tdiff < 10000) { + showMsg(alarms[idx].msg); + } + } +} + +for(let idx=0; idx < alarms.length; idx++) { + let tdiff = Date.parse(alarms[idx].time) - Date.now(); + let msg = alarms[idx].msg; + if(tdiff > 0) { + /*console.log(`will alarm ${msg} in ${tdiff}`);*/ + setTimeout(checkMsgs, tdiff); + } +} + +let xs = 0.5; +let ys = 0.75; + +let prevH1 = -1; +let prevH2 = -1; +let prevM1 = -1; +let prevM2 = -1; + + +let points0 = [ + 0, 40, + 1, 35, + 7, 20, + 16, 8, + 28, 2, + 40, 0, + + 51, 2, + 63, 10, + 72, 20, + 77, 35, + 78, 40, + + 78, 59, + 77, 64, + 72, 79, + 63, 89, + 51, 97, + + 40, 99, + 28, 97, + 16, 91, + 7, 79, + 1, 64, + 0, 59, + 0, 40 +]; + +let points1 = [ 40, 99, 40, 0]; + +let points2 = [ 0, 25, + 2, 22, + 6, 13, + 17, 5, + 28, 2, + 40, 0, + 52, 2, + 63, 5, + 74, 13, + 79, 23, + 79, 28, + 74, 38, + 63, 46, + 51, 54, + 40, 58, + 29, 62, + 17, 68, + 8, 80, + 0, 99, + 79, 99 + ]; + +let points4 = [ 60, 99, 60, 0, 0, 75, 79, 75 ]; + +let points8 = [ + 40, 40, + 26, 42, + 15, 46, + 4, 56, + 1, 66, + 1, 77, + 6, 87, + 17, 94, + 28, 97, + 38, 99, + 42, 99, + 52, 97, + 63, 94, + 74, 87, + 79, 77, + 79, 66, + 75, 56, + 64, 46, + 54, 42, + 40, 40, + + 52, 39, + 62, 34, + 69, 29, + 72, 23, + 72, 19, + 69, 12, + 62, 6, + 52, 2, + 40, 0, + + 28, 2, + 18, 6, + 11, 12, + 8, 19, + 8, 23, + 11, 29, + 18, 34, + 28, 39, + 40, 40, + ]; + +let points6 = [ + 50, 0, + 4, 56, + 1, 66, + 1, 77, + 6, 87, + 17, 94, + 28, 97, + 40, 99, + 52, 97, + 63, 94, + 74, 87, + 79, 77, + 79, 66, + 75, 56, + 64, 46, + 52, 42, + 40, 40, + 26, 42, + 15, 46, + 4, 56, + ]; + +let points3 = [ + 1, 77, + 6, 87, + 17, 94, + 28, 97, + 40, 99, + 52, 97, + 63, 94, + 74, 87, + 79, 77, + 79, 66, + 75, 56, + 64, 46, + 52, 42, + 39, 40, + 79, 0, + 1, 0 + ]; + +let points7 = [ 0, 0, 79, 0, 30, 99 ]; + +let points9 = []; +let points5 = [ + 1, 77, + 6, 87, + 17, 94, + 28, 97, + 38, 99, + 42, 99, + 52, 97, + 63, 94, + 74, 87, + 79, 77, + 79, 66, + 75, 56, + 64, 46, + 54, 42, + 40, 40, + 26, 42, + 15, 46, + 27, 0, + 79, 0, + ]; + + +function drawPoints(points, x0, y0) { + + let x = points[0]*xs+x0, y = points[1]*ys+y0; + //g.drawEllipse(x-2, y-2, x+2, y+2); + g.moveTo(x, y); + for(let idx=1; idx*2 < points.length; idx ++) { + let x = points[idx*2]*xs+x0; + let y = points[idx*2+1]*ys+y0; + //g.drawEllipse(x-2, y-2, x+2, y+2); + g.lineTo(x, y); + } +} + +/* create 5 from 2 , and 9 from 6 */ +/* nope, we have a better 5; less authentic, but whatev +for (let idx=0; idx*2 < points2.length; idx++) { + points5[idx*2] = points2[idx*2]; + points5[idx*2+1] = 99-points2[idx*2+1]; +} +*/ +for (let idx=0; idx*2 < points6.length; idx++) { + points9[idx*2] = 79-points6[idx*2]; + points9[idx*2+1] = 99-points6[idx*2+1]; +} + +pointsArray = [points0, points1, points2, points3, points4, points5, points6, points7, points8, points9]; + +function eraseDigit(d, x, y) { + // first time draw + if(d < 0) return; + g.setColor("#000000"); + drawPoints(pointsArray[d], x-2, y-2); + drawPoints(pointsArray[d], x+2, y-2); + drawPoints(pointsArray[d], x-2, y+2); + drawPoints(pointsArray[d], x+2, y+2); + drawPoints(pointsArray[d], x-1, y-1); + drawPoints(pointsArray[d], x+1, y-1); + drawPoints(pointsArray[d], x-1, y+1); + drawPoints(pointsArray[d], x+1, y+1); +} + +function drawDigit(d, x, y) { + //g.drawEllipse(20+4*xs, 20, 20+(72 * xs), 20+(40*ys)); + //g.drawEllipse(20, 20+(40*ys), 20+(80 * xs), 20+(99*ys)); + //g.drawEllipse(20, 20, 20+(79 * xs), 20+(99*ys)); + g.setColor("#202020"); + for (let idx = pointsArray.length - 1; idx >= 0 ; idx--) { + if(idx == d) { + + g.setColor("#FF0000"); + drawPoints(pointsArray[d], x-2, y-2); + drawPoints(pointsArray[d], x+2, y-2); + drawPoints(pointsArray[d], x-2, y+2); + drawPoints(pointsArray[d], x+2, y+2); + g.setColor("#FF6000"); + drawPoints(pointsArray[d], x-1, y-1); + drawPoints(pointsArray[d], x+1, y-1); + drawPoints(pointsArray[d], x-1, y+1); + drawPoints(pointsArray[d], x+1, y+1); + + g.setColor("#FFC000"); + drawPoints(pointsArray[d], x, y); + + g.setColor("#202020"); + } else { + drawPoints(pointsArray[idx], x, y); + } + } + +} + +function drawTime() { + const mstr="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; + + let d = new Date(); + let hour = d.getHours(); + let minute = d.getMinutes(); + let month = d.getMonth(); + let date = d.getDate(); + + let h1 = Math.floor(hour / 10); + let h2 = hour % 10; + let m1 = Math.floor(minute / 10); + let m2 = minute % 10; + + if(h1 == prevH1 && h2 == prevH2 && m1 == prevM1 && m2 == prevM2) { + return; + } + + if(h1 != prevH1) { + eraseDigit(prevH1, 10, 80); + drawDigit(h1, 10, 80); + } + if(h2 != prevH2) { + eraseDigit(prevH2, 65, 80); + drawDigit(h2, 65, 80); + } + if(m1 != prevM1) { + eraseDigit(prevM1, 135, 80); + drawDigit(m1, 135, 80); + } + if(m2 != prevM2) { + eraseDigit(prevM2, 190, 80); + drawDigit(m2, 190, 80); + } + + g.setColor("#000000"); + g.fillRect(0, 10, 240, 24); + g.fillRect(0, 222, 240, 240); + g.setColor("#202020"); + g.drawLine(0, 24, 239, 24); + g.drawLine(0, 226, 239, 226); + g.setColor("#C06000"); + g.setFontAlign(0, -1); + g.drawString(mstr.slice(month*3,month*3+3) + " " + date, 120, 10); + g.setFontAlign(-1,-1); + g.drawString("STEP " + stepCounter, 0, 230); + g.setFontAlign(1,-1); + g.drawString("BTY "+E.getBattery(), 240, 230); + + + prevH1 = h1; + prevH2 = h2; + prevM1 = m1; + prevM2 = m2; + +} + +function stop () { + if (interval) { + clearInterval(interval); + } +} + +function start () { + if (interval) { + clearInterval(interval); + } + // first time init + interval = setInterval(drawTime, 10000); + drawTime(); +} + +start(); + + +Bangle.on('lcdPower', function (on) { + if (on) { + start(); + } else { + stop(); + } +}); + +function btn1Func() { + g.clear(); + prevH1 = -1; + prevH2 = -1; + prevM1 = -1; + prevM2 = -1; + drawTime(); +} + +function btn3Func() { + showMsg("This is a test message"); +} + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// redraw +setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); +setWatch(btn3Func, BTN3, {repeat:true,edge:"falling"}); +Bangle.on('step', function(cnt) { + stepCounter = cnt / 10; +}); From 229fd1c672e1c81d9852d1534e45318ddb980fc2 Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Fri, 17 Jul 2020 14:42:25 -0400 Subject: [PATCH 11/29] Create nixie.info --- apps/nixie/nixie.info | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/nixie/nixie.info diff --git a/apps/nixie/nixie.info b/apps/nixie/nixie.info new file mode 100644 index 000000000..d9ac5129b --- /dev/null +++ b/apps/nixie/nixie.info @@ -0,0 +1 @@ +{"id":"jvNixie","name":"Nixie Clock","type":"clock","src":"nixie.app.js","sortorder":-1,"version":"0.1","files":"nixie.info,nixie.app.js"} From 8babc1ecf4c195ad0b4ca63afed725594a2c93cb Mon Sep 17 00:00:00 2001 From: yngv27 <61598758+yngv27@users.noreply.github.com> Date: Fri, 17 Jul 2020 14:58:08 -0400 Subject: [PATCH 12/29] Add files via upload Added night mode --- apps/nixie/nixie.app.js | 97 +++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/apps/nixie/nixie.app.js b/apps/nixie/nixie.app.js index c9fa068fe..f1cd245f1 100644 --- a/apps/nixie/nixie.app.js +++ b/apps/nixie/nixie.app.js @@ -1,4 +1,3 @@ - g.clear(); require("Font8x12").add(Graphics); @@ -9,7 +8,11 @@ let stepCounter = 0; let msgs = require("Storage").readJSON('yngv27.msgs.json'); let alarms = require("Storage").readJSON('yngv27.alarm.json'); +let alarming = false; +let nightMode = false; + function showMsg(msg) { + alarming = true; g.setFontAlign(0,-1); g.setColor(1,1,1); g.drawString("<< ALARM >>", 120, 180, true); @@ -214,9 +217,7 @@ let points5 = [ 79, 0, ]; - function drawPoints(points, x0, y0) { - let x = points[0]*xs+x0, y = points[1]*ys+y0; //g.drawEllipse(x-2, y-2, x+2, y+2); g.moveTo(x, y); @@ -228,13 +229,14 @@ function drawPoints(points, x0, y0) { } } -/* create 5 from 2 , and 9 from 6 */ -/* nope, we have a better 5; less authentic, but whatev +/* create 5 from 2 */ +/* uncomment if you want the 5 to look more authentic (but uglier) for (let idx=0; idx*2 < points2.length; idx++) { points5[idx*2] = points2[idx*2]; points5[idx*2+1] = 99-points2[idx*2+1]; } */ +/* create 9 from 6 */ for (let idx=0; idx*2 < points6.length; idx++) { points9[idx*2] = 79-points6[idx*2]; points9[idx*2+1] = 99-points6[idx*2+1]; @@ -243,10 +245,13 @@ for (let idx=0; idx*2 < points6.length; idx++) { pointsArray = [points0, points1, points2, points3, points4, points5, points6, points7, points8, points9]; function eraseDigit(d, x, y) { - // first time draw if(d < 0) return; g.setColor("#000000"); - drawPoints(pointsArray[d], x-2, y-2); + if(nightMode) { + drawPoints(pointsArray[d], x, y); + return; + } + drawPoints(pointsArray[d], x-2, y-2); drawPoints(pointsArray[d], x+2, y-2); drawPoints(pointsArray[d], x-2, y+2); drawPoints(pointsArray[d], x+2, y+2); @@ -257,13 +262,14 @@ function eraseDigit(d, x, y) { } function drawDigit(d, x, y) { - //g.drawEllipse(20+4*xs, 20, 20+(72 * xs), 20+(40*ys)); - //g.drawEllipse(20, 20+(40*ys), 20+(80 * xs), 20+(99*ys)); - //g.drawEllipse(20, 20, 20+(79 * xs), 20+(99*ys)); + if(nightMode) { + g.setColor("#206040"); + drawPoints(pointsArray[d], x, y); + return; + } g.setColor("#202020"); for (let idx = pointsArray.length - 1; idx >= 0 ; idx--) { if(idx == d) { - g.setColor("#FF0000"); drawPoints(pointsArray[d], x-2, y-2); drawPoints(pointsArray[d], x+2, y-2); @@ -274,7 +280,7 @@ function drawDigit(d, x, y) { drawPoints(pointsArray[d], x+1, y-1); drawPoints(pointsArray[d], x-1, y+1); drawPoints(pointsArray[d], x+1, y+1); - + g.setColor("#FFC000"); drawPoints(pointsArray[d], x, y); @@ -283,12 +289,11 @@ function drawDigit(d, x, y) { drawPoints(pointsArray[idx], x, y); } } - } - + function drawTime() { const mstr="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; - + let d = new Date(); let hour = d.getHours(); let minute = d.getMinutes(); @@ -303,7 +308,7 @@ function drawTime() { if(h1 == prevH1 && h2 == prevH2 && m1 == prevM1 && m2 == prevM2) { return; } - + if(h1 != prevH1) { eraseDigit(prevH1, 10, 80); drawDigit(h1, 10, 80); @@ -315,32 +320,47 @@ function drawTime() { if(m1 != prevM1) { eraseDigit(prevM1, 135, 80); drawDigit(m1, 135, 80); - } + } if(m2 != prevM2) { eraseDigit(prevM2, 190, 80); drawDigit(m2, 190, 80); - } - - g.setColor("#000000"); - g.fillRect(0, 10, 240, 24); - g.fillRect(0, 222, 240, 240); - g.setColor("#202020"); - g.drawLine(0, 24, 239, 24); - g.drawLine(0, 226, 239, 226); - g.setColor("#C06000"); - g.setFontAlign(0, -1); - g.drawString(mstr.slice(month*3,month*3+3) + " " + date, 120, 10); - g.setFontAlign(-1,-1); - g.drawString("STEP " + stepCounter, 0, 230); - g.setFontAlign(1,-1); - g.drawString("BTY "+E.getBattery(), 240, 230); + } + if(!nightMode) { + g.setColor("#000000"); + g.fillRect(0, 10, 240, 24); + g.fillRect(0, 222, 240, 240); + g.setColor("#202020"); + g.drawLine(0, 24, 239, 24); + g.drawLine(0, 226, 239, 226); + g.setColor("#C06000"); + g.setFontAlign(0, -1); + g.drawString(mstr.slice(month*3,month*3+3) + " " + date, 120, 10); + g.setFontAlign(-1,-1); + g.drawString("STEP " + stepCounter, 0, 230); + g.setFontAlign(1,-1); + g.drawString("BTY "+E.getBattery(), 240, 230); + } - prevH1 = h1; prevH2 = h2; prevM1 = m1; prevM2 = m2; - + +} + +function btn1Func() { + if(alarming) { + alarming = false; + } else { + nightMode = !nightMode; + g.setRotation(nightMode ? 1 : 0, 0); + } + g.clear(); + prevH1 = -1; + prevH2 = -1; + prevM1 = -1; + prevM2 = -1; + drawTime(); } function stop () { @@ -353,7 +373,6 @@ function start () { if (interval) { clearInterval(interval); } - // first time init interval = setInterval(drawTime, 10000); drawTime(); } @@ -369,14 +388,6 @@ Bangle.on('lcdPower', function (on) { } }); -function btn1Func() { - g.clear(); - prevH1 = -1; - prevH2 = -1; - prevM1 = -1; - prevM2 = -1; - drawTime(); -} function btn3Func() { showMsg("This is a test message"); From 9d33283bc8be69a73f7e743fb218aaf3d48b5796 Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:36:36 -0400 Subject: [PATCH 13/29] Create README.md --- apps/nixie/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 apps/nixie/README.md diff --git a/apps/nixie/README.md b/apps/nixie/README.md new file mode 100644 index 000000000..7280800e9 --- /dev/null +++ b/apps/nixie/README.md @@ -0,0 +1,16 @@ +Nixie clock + +This clock displays the time in nixie-inspired numerals. + +The app makes use of a module called "m_vatch" which manages all the timers, and makes calls to functions in the 'main' file +to manage drawing the background, time, and any data like sensor info, step counters, battery, etc. The idea is that it is +reusable if you write many watch apps... you just need to implement functions to draw the background (called on start, and every +time the 'mode' changes (regular and night mode), the time (which gets a call every second), and the data (also every second, +except not in night mode)). + +Night mode is a mode that can be set manually or automatically, allowing the watch code to adjust colors and detail. Mainly, +used as a night clock, you can draw no background, and use dim colors for your digits. If set to auto, the accelerometer is used so +when the watch is placed on its side, it switches to night mode (your watch may need a tweak... and Bangle 2 is a different story!) + +It also handles step counting so that it's stored on a daily +basis - survives a system reset, zeroes when the date changes and keeps a record in a history file by day. From f17f4e61481b508fd0ee0fbedbe668ed3f490d04 Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:37:12 -0400 Subject: [PATCH 14/29] Delete readme.md from an old version --- apps/nixie/readme.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 apps/nixie/readme.md diff --git a/apps/nixie/readme.md b/apps/nixie/readme.md deleted file mode 100644 index 68af873a6..000000000 --- a/apps/nixie/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -This watch face emulates nixie tube characters and is a bit fun to watch draw. Also displays date, "steps" (the stepcounter / 10 until I really train the accelerometer) and remaining battery. - -Also supports alarms from a JSON file named "yngv.alarms.json". From d34faf8a2b2d12652cd1923d600fe9938ed3506e Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:38:14 -0400 Subject: [PATCH 15/29] Update nixie.app.js Works on both Bangle 1 and Bangle 2 --- apps/nixie/nixie.app.js | 318 ++++++++++++++++++++++------------------ 1 file changed, 172 insertions(+), 146 deletions(-) diff --git a/apps/nixie/nixie.app.js b/apps/nixie/nixie.app.js index f1cd245f1..a62590f75 100644 --- a/apps/nixie/nixie.app.js +++ b/apps/nixie/nixie.app.js @@ -1,50 +1,47 @@ +const EMULATOR = false; +// which Bangle? +const isB2 = g.getWidth() < 200; + +// global coordinate system +const wX = g.getWidth(); +const wY = g.getHeight(); +const midX = wX/2, midY = wY/2; +// relative positioning: send 0 <= coord < 1 +function relX(x) { return Math.floor(x*wX); } +function relY(y) { return Math.floor(y*wY); } + +// colors +const col_bg = 0; +const col_nm =isB2 ? 1 :"#206040"; +const col_sep = isB2 ? 6 :"#202020"; +const col_off = isB2 ? 1 : "#202020"; +const col_shad1 = isB2 ? 4 :"#FF0000"; +const col_shad2 = isB2 ? 6 :"#FF6000"; +const col_hi =isB2 ? 7 : "#FFC000"; +const col_data = isB2 ? 6 :"#C06000"; + +g.setBgColor(col_bg); g.clear(); +var imgTube = { + width : 64, height : 128, bpp : 2, + buffer : require("heatshrink").decompress(atob("AE9AB7sQD54AOiFQB5tVsgPN0uoBxkByEFB5kGyIPNhVVB5tpLwKAMoJuOgNQggMJgtVDhsVqtEZ5cVrWlEBcFtWq1WlJxUaBwOq1IgJgIdCqoABEBEC1WVBwTkGKgUGFYIOCgIRDC4kaFoVUOQQKCQ4IgCB4YKDCYIgCq2QgEqHwJLIEoOkgFqB4KaIEoNkB4Z7JHQVqquqD5EVDYQPCVRIPE1IPKgsAtJTCAA8GyEBD4TrKqAPOgNRB5sRB5wfPgAPOiA/RP4IPaiD6BB5oCBB5kAdQIPNH5wPCvIPMBgIPMR4QPcL4QPNgIPQvS/MqtAB59+B9cVB91VL91BF91RF79RB4OVD5wPsH59BB51FB5sQB/0AD7xvPV4elD5wPLqIPOgJPeX/6//X8YPMH5wPPL74PfN55PQB6TfPB5afDB51/D57P/Z/7P/B97vOB5kAB58VoAA=")) +}; +var imgTubeBW = { + width : 46, height : 92, bpp : 1, + buffer : require("heatshrink").decompress(atob("AD0EAomAAgcCBQkQEykwAgcP/gFD/wKECok4AgcB4A7DgwQEjAFEsYWExg2DhkgAoVAE4kA8AEDgZqEhw+JgA+DCwIKEhhrJCyJELFqBbQIiByLIk6gWZyC3WOSItWOVq3nCywA=")) +}; + require("Font8x12").add(Graphics); g.setFont("8x12", 1); let interval = null; -let stepCounter = 0; - -let msgs = require("Storage").readJSON('yngv27.msgs.json'); -let alarms = require("Storage").readJSON('yngv27.alarm.json'); let alarming = false; let nightMode = false; -function showMsg(msg) { - alarming = true; - g.setFontAlign(0,-1); - g.setColor(1,1,1); - g.drawString("<< ALARM >>", 120, 180, true); - g.drawString(msg, 120, 200, true); - Bangle.buzz(); - setTimeout(Bangle.buzz, 800); - setTimeout(Bangle.buzz, 1600); - setTimeout(Bangle.buzz, 2400); - setTimeout(Bangle.buzz, 3200); -} - -function checkMsgs() { - for(let idx=0; idx < alarms.length; idx++) { - let tdiff = Date.now() - Date.parse(alarms[idx].time); - // 10 sec margin of error - if(tdiff > 0 && tdiff < 10000) { - showMsg(alarms[idx].msg); - } - } -} - -for(let idx=0; idx < alarms.length; idx++) { - let tdiff = Date.parse(alarms[idx].time) - Date.now(); - let msg = alarms[idx].msg; - if(tdiff > 0) { - /*console.log(`will alarm ${msg} in ${tdiff}`);*/ - setTimeout(checkMsgs, tdiff); - } -} - -let xs = 0.5; -let ys = 0.75; +// our scale factor +let xs = 0.5 * wX/240; +let ys = 0.75 * wY/240; let prevH1 = -1; let prevH2 = -1; @@ -52,7 +49,7 @@ let prevM1 = -1; let prevM2 = -1; -let points0 = [ +let points0 = new Uint8Array([ 0, 40, 1, 35, 7, 20, @@ -79,11 +76,11 @@ let points0 = [ 1, 64, 0, 59, 0, 40 -]; +]); -let points1 = [ 40, 99, 40, 0]; +let points1 = new Uint8Array([ 40, 99, 40, 0]); -let points2 = [ 0, 25, +let points2 = new Uint8Array([ 0, 25, 2, 22, 6, 13, 17, 5, @@ -103,11 +100,11 @@ let points2 = [ 0, 25, 8, 80, 0, 99, 79, 99 - ]; + ]); -let points4 = [ 60, 99, 60, 0, 0, 75, 79, 75 ]; +let points4 = new Uint8Array([ 60, 99, 60, 0, 0, 75, 79, 75 ]); -let points8 = [ +let points8 = new Uint8Array([ 40, 40, 26, 42, 15, 46, @@ -148,9 +145,9 @@ let points8 = [ 18, 34, 28, 39, 40, 40, - ]; + ]); -let points6 = [ +let points6 = new Uint8Array([ 50, 0, 4, 56, 1, 66, @@ -171,9 +168,9 @@ let points6 = [ 26, 42, 15, 46, 4, 56, - ]; + ]); -let points3 = [ +let points3 = new Uint8Array([ 1, 77, 6, 87, 17, 94, @@ -190,12 +187,12 @@ let points3 = [ 39, 40, 79, 0, 1, 0 - ]; + ]); -let points7 = [ 0, 0, 79, 0, 30, 99 ]; +let points7 = new Uint8Array([ 0, 0, 79, 0, 30, 99 ]); -let points9 = []; -let points5 = [ +let points9 = new Uint8Array(points6.length); +let points5 = new Uint8Array([ 1, 77, 6, 87, 17, 94, @@ -215,7 +212,7 @@ let points5 = [ 15, 46, 27, 0, 79, 0, - ]; +]); function drawPoints(points, x0, y0) { let x = points[0]*xs+x0, y = points[1]*ys+y0; @@ -245,8 +242,8 @@ for (let idx=0; idx*2 < points6.length; idx++) { pointsArray = [points0, points1, points2, points3, points4, points5, points6, points7, points8, points9]; function eraseDigit(d, x, y) { - if(d < 0) return; - g.setColor("#000000"); + if(d < 0 || d > 9) return; + g.setColor(col_bg); if(nightMode) { drawPoints(pointsArray[d], x, y); return; @@ -263,84 +260,101 @@ function eraseDigit(d, x, y) { function drawDigit(d, x, y) { if(nightMode) { - g.setColor("#206040"); + g.setColor(col_nm); drawPoints(pointsArray[d], x, y); return; } - g.setColor("#202020"); + g.setColor(col_off); for (let idx = pointsArray.length - 1; idx >= 0 ; idx--) { if(idx == d) { - g.setColor("#FF0000"); + g.setColor(col_shad1); drawPoints(pointsArray[d], x-2, y-2); drawPoints(pointsArray[d], x+2, y-2); drawPoints(pointsArray[d], x-2, y+2); drawPoints(pointsArray[d], x+2, y+2); - g.setColor("#FF6000"); + g.setColor(col_shad2); drawPoints(pointsArray[d], x-1, y-1); drawPoints(pointsArray[d], x+1, y-1); drawPoints(pointsArray[d], x-1, y+1); drawPoints(pointsArray[d], x+1, y+1); - g.setColor("#FFC000"); + g.setColor(col_hi); drawPoints(pointsArray[d], x, y); - g.setColor("#202020"); + g.setColor(col_off); } else { drawPoints(pointsArray[idx], x, y); } } } -function drawTime() { - const mstr="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; +function drawBkgd(nm) { + g.clear(); + prevH1=-1;prevH2=-1;prevM1=-1;prevM2=-1; + if(nm) return; + + if(!isB2) { + // tube images + g.setColor(col_shad2); - let d = new Date(); - let hour = d.getHours(); - let minute = d.getMinutes(); - let month = d.getMonth(); - let date = d.getDate(); + [relX(0),relX(0.25),relX(0.5),relX(0.75)].forEach((v,i,a) => { + g.drawImage(imgTube,v,relY(0.225)); + }); + // something to sit on + g.setColor(col_shad2); + g.fillRect(0, relY(0.76),wX,relY(0.76)); + } else { + // simple tubes + [1,45,89,133].forEach((v,i,a) => { + g.setColor(col_shad1); + g.drawEllipse(v, 52, v+41, 90); + g.drawRect(v,66,v+41,125); + g.clearRect(v+1,66,v+40,124); + }); + } + g.setColor(col_shad2); + g.moveTo(relX(0.125), 0); + g.lineTo(relX(0.25), relY(0.125)); + g.lineTo(relX(0.75), relY(0.125)); + g.lineTo(relX(0.875),0); + + g.moveTo(relX(0.125), wY); + g.lineTo(relX(0.25), relY(0.875)); + g.lineTo(relX(0.75), relY(0.875)); + g.lineTo(relX(0.875), wY); - let h1 = Math.floor(hour / 10); - let h2 = hour % 10; - let m1 = Math.floor(minute / 10); - let m2 = minute % 10; +} + +function drawTime(d,nm) { + const dx = [relX(0.042), relX(0.29), relX(0.55), relX(0.791)]; //[ 10, 65, 135, 190]; + const dy = [relY(0.38),relY(0.38),relY(0.38),relY(0.38)]; + + let h1 = Math.floor(d.hour / 10); + let h2 = d.hour % 10; + let m1 = Math.floor(d.min / 10); + let m2 = d.min % 10; if(h1 == prevH1 && h2 == prevH2 && m1 == prevM1 && m2 == prevM2) { return; } + nightMode = nm; if(h1 != prevH1) { - eraseDigit(prevH1, 10, 80); - drawDigit(h1, 10, 80); + eraseDigit(prevH1, dx[0], dy[0]); + drawDigit(h1, dx[0], dy[0]); } if(h2 != prevH2) { - eraseDigit(prevH2, 65, 80); - drawDigit(h2, 65, 80); + eraseDigit(prevH2, dx[1], dy[1]); + drawDigit(h2, dx[1], dy[1]); } if(m1 != prevM1) { - eraseDigit(prevM1, 135, 80); - drawDigit(m1, 135, 80); + eraseDigit(prevM1, dx[2], dy[2]); + drawDigit(m1, dx[2], dy[2]); } if(m2 != prevM2) { - eraseDigit(prevM2, 190, 80); - drawDigit(m2, 190, 80); + eraseDigit(prevM2, dx[3], dy[3]); + drawDigit(m2, dx[3], dy[3]); } - if(!nightMode) { - g.setColor("#000000"); - g.fillRect(0, 10, 240, 24); - g.fillRect(0, 222, 240, 240); - g.setColor("#202020"); - g.drawLine(0, 24, 239, 24); - g.drawLine(0, 226, 239, 226); - g.setColor("#C06000"); - g.setFontAlign(0, -1); - g.drawString(mstr.slice(month*3,month*3+3) + " " + date, 120, 10); - g.setFontAlign(-1,-1); - g.drawString("STEP " + stepCounter, 0, 230); - g.setFontAlign(1,-1); - g.drawString("BTY "+E.getBattery(), 240, 230); - } - prevH1 = h1; prevH2 = h2; prevM1 = m1; @@ -348,56 +362,68 @@ function drawTime() { } -function btn1Func() { - if(alarming) { - alarming = false; - } else { - nightMode = !nightMode; - g.setRotation(nightMode ? 1 : 0, 0); - } - g.clear(); - prevH1 = -1; - prevH2 = -1; - prevM1 = -1; - prevM2 = -1; - drawTime(); -} - -function stop () { - if (interval) { - clearInterval(interval); +function drawData(d) { + if(!nightMode) { + g.setColor(col_data); + g.setFontAlign(0, -1); + g.drawString(` ${d.dow}, ${d.mon3} ${d.date} `, wX/2, relX(0.042), true); + g.setFontAlign(-1,-1); + g.drawString("STEP ", 0, relY(0.82), true); + g.drawString(`${d.steps} `,0, relY(0.875), true); + g.setFontAlign(1,-1); + g.drawString(" BTY", relX(0.999), relY(0.82), true); + g.drawString(` ${d.batt}`, relX(0.999), relY(0.875), true); + g.setFontAlign(0,-1); + g.setColor(col_shad2); + g.drawString('BANGLE.JS', wX/2, relY(0.925)); } } -function start () { - if (interval) { - clearInterval(interval); - } - interval = setInterval(drawTime, 10000); - drawTime(); +//setWatch(E.showLauncher, BTN1, {repeat:true,edge:"falling"}); +if(EMULATOR) { + let d = new Date(); + + let hour = d.getHours(); + let minute = d.getMinutes(); + + let h1 = Math.floor(hour / 10); + let h2 = hour % 10; + let m1 = Math.floor(minute / 10); + let m2 = minute % 10; + + let data = { + h1: h1, + h2: h2, + m1: m1, + m2: m2, + hour: hour, + min: minute, + }; + + drawBkgd(nightMode); + + drawTime(data, nightMode); + const mstr="JanFebMarAprMayJunJulAugSepOctNovDec"; + const dowstr = "SunMonTueWedThuFriSat"; + + let month = d.getMonth(); + let dow = d.getDay(); + data.month = month; + data.date = d.getDate(); + + data.mon3 = mstr.slice(month*3,month*3+3); + data.dow = dowstr.substr(dow*3,3); + data.dateStr = data.dow + " " + data.mon3 + " " + data.date; + data.steps = 12345; + data.batt = E.getBattery() + (Bangle.isCharging() ? "+" : ""); + data.charging = Bangle.isCharging(); + + drawData(data); +} else { + Bangle.setUI("clock"); + let v = require("m_vatch.js"); + v.setDrawTime(drawTime); + v.setDrawBackground(drawBkgd); + v.setDrawData(drawData); + v.begin(); } - -start(); - - -Bangle.on('lcdPower', function (on) { - if (on) { - start(); - } else { - stop(); - } -}); - - -function btn3Func() { - showMsg("This is a test message"); -} - -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); -// redraw -setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); -setWatch(btn3Func, BTN3, {repeat:true,edge:"falling"}); -Bangle.on('step', function(cnt) { - stepCounter = cnt / 10; -}); From 9d912be5b6623d9bb5a715dc1b73869dae71fc09 Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:38:52 -0400 Subject: [PATCH 16/29] Update nixie.info --- apps/nixie/nixie.info | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/nixie/nixie.info b/apps/nixie/nixie.info index d9ac5129b..66f5ff2a5 100644 --- a/apps/nixie/nixie.info +++ b/apps/nixie/nixie.info @@ -1 +1,10 @@ -{"id":"jvNixie","name":"Nixie Clock","type":"clock","src":"nixie.app.js","sortorder":-1,"version":"0.1","files":"nixie.info,nixie.app.js"} +{ +"id":"jvNixie", +"name":"Nixie Clock", +"type":"clock", +"src":"nixie.app.js", +"icon": "nixie.img", +"sortorder":1, +"version":"1.1", +"files":"nixie.info,nixie.app.js,nixie.img, m_vatch.js" +} From 8bbfabfb77ace876d27deee1d393a6d5a982891f Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:39:24 -0400 Subject: [PATCH 17/29] Create m_vatch.js The watch engine, step manager --- apps/nixie/m_vatch.js | 317 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 apps/nixie/m_vatch.js diff --git a/apps/nixie/m_vatch.js b/apps/nixie/m_vatch.js new file mode 100644 index 000000000..430892424 --- /dev/null +++ b/apps/nixie/m_vatch.js @@ -0,0 +1,317 @@ +const _Storage = require('Storage'); + +let interval = null; + +let nightMode = false; + +let stepFile = 'v.steps.json'; +let stepArchiveFile = 'v.stephist.json'; + +let _Options = {}; +let optsFile = 'm_vatch.opts.json'; + +let _Alarm = { + inAlarm: false, + reload: () => {}, + scheduleAlarms: () => {}, + showMsg: (title, msg) => {}, + showNotes: () => {}, +}; + +let _StepData = {}; + +const pad0 = (n) => (n > 9) ? n : ("0"+n); + +const getToday = () => { + let d = new Date(); + return d.getFullYear()+'-'+ pad0(d.getMonth()+1) + '-' + pad0(d.getDate()); +}; + +function reload() { + _StepData = _Storage.readJSON(stepFile); + if(!_StepData) { + _StepData = { + lastDate: '2020-01-01', + stepCache: 0, + lastStepCount: 0, + updated: true, + }; + } + if(getToday() === _StepData.lastDate) { + _StepData.stepCache += _StepData.lastStepCount; + _StepData.lastStepCount = 0; + } +} + +function stringFromArray(data) +{ + var count = data.length; + var str = ""; + + for(var index = 0; index < count; index += 1) + str += String.fromCharCode(data[index]); + + return str; +} + +function logD(str) { + if(_Options.debug) console.log(str); +} + + +let lastH1 = -1; +let lastH2 = -1; +let lastM1 = -1; +let lastM2 = -1; + + +let drawBackground = () => {}; +let drawTime = () => {}; +let drawData = () => {}; + + +function timeCheck() { + + if(_Alarm.inAlarm) return; + + logD('Again, ' + JSON.stringify(_Options)); + logD('opt.nm = '+_Options.autoNightMode); + if(_Options.autoNightMode) { + // this may vary by Bangle.. adjust to taste + let a = Bangle.getAccel(); + a.x = Math.floor(a.x * 100); + logD('a.x = ' + a.x); + if(a.x <= 101 && a.x >= 99) { + if(!nightMode) { + nightMode = ! nightMode; + redrawScreen(); + } + } else { + if(nightMode) { + nightMode = ! nightMode; + redrawScreen(); + } + } + } + + let d = new Date(); + + let hour = d.getHours(); + let minute = d.getMinutes(); + + let h1 = Math.floor(hour / 10); + let h2 = hour % 10; + let m1 = Math.floor(minute / 10); + let m2 = minute % 10; + + logD("lastH1 = "+lastH1+": lastM2 = "+lastM2); + if(h1 == lastH1 && h2 == lastH2 && m1 == lastM1 && m2 == lastM2) { + return; + } + + logD("drawing time"); + let data = { + h1: h1, + h2: h2, + m1: m1, + m2: m2, + hour: hour, + min: minute, + }; + drawTime(data, nightMode); + + lastH1 = h1; + lastH2 = h2; + lastM1 = m1; + lastM2 = m2; + + if(!nightMode && !_Alarm.inAlarm) { + logD("drawing data..."); + const mstr="JanFebMarAprMayJunJulAugSepOctNovDec"; + const dowstr = "SunMonTueWedThuFriSat"; + + let month = d.getMonth(); + let dow = d.getDay(); + data.month = month; + data.date = d.getDate(); + + data.mon3 = mstr.slice(month*3,month*3+3); + data.dow = dowstr.substr(dow*3,3); + data.dateStr = data.dow + " " + data.mon3 + " " + data.date; + data.steps = _StepData.stepCache + _StepData.lastStepCount; + data.batt = E.getBattery() + (Bangle.isCharging() ? "+" : ""); + data.charging = Bangle.isCharging(); + + drawData(data); + } + + if(_StepData.updated) { + _Storage.writeJSON(stepFile, _StepData); + logD(JSON.stringify(_StepData)); + _StepData.updated = false; + } +} + +function stop () { + if (interval) { + clearInterval(interval); + } +} + +function start () { + if (interval) { + clearInterval(interval); + } + // first time init + interval = setInterval(timeCheck, 1000); + timeCheck(); +} + + +function btn1Func() { + logD("btn1Func"); + + if(_Alarm.inAlarm ) { + _Alarm.inAlarm = false; + } else { + if( ! _Options.autoNightMode) { + nightMode = ! nightMode; + logD('nm is '+nightMode); + } + } + redrawScreen(); +} + +function redrawScreen() { + logD("redrawScreen"); + + if(nightMode) { + g.setRotation(1,0); + } else { + g.setRotation(0,0); + } + lastM1 = -1; + lastM2 = -1; + lastH1 = -1; + lastH2 = -1; + drawBackground(nightMode); + timeCheck(); +} + +function btn2Func() { + _Alarm.reload(); + _Alarm.scheduleAlarms(); + _Alarm.showNotes(); +} + +Bangle.on('step', function(cnt) { + if(!_StepData.lastDate) return; + if(_StepData.lastDate !== getToday()) { + // save previous day's step count + try { + let sf = _Storage.readJSON(stepArchiveFile); + if(!sf) sf = []; + logD('sf is '+ (typeof sf) +':'+sf); + // trim to 30 + if(sf.length >= 30 ) sf.shift(); + let steps = _StepData.stepCache +_StepData.lastStepCount; + let sd = `${_StepData.lastDate},${steps}`; + sf.push(sd); + _Storage.writeJSON(stepArchiveFile, sf); + } catch (err) { + _Storage.write('err.txt',err); + } + /* individual step files by date + _Storage.write(_StepData.lastDate +'.steps', JSON.stringify( + _StepData.stepCache +_StepData.lastStepCount + )); + */ + _StepData.stepCache = 0 - cnt; + _StepData.lastDate = getToday(); + } + _StepData.lastStepCount = cnt; + _StepData.updated = true; +}); + +/* +** Advertise a writeable characteristic. Accepts text (in 20 char +** chunks) terminated with __EOM__ by itself. If there's text, show +** it (as an alarm), otherwise reload the alarm & msg files (empty +** string signals another BLE process updated those files) +*/ +/* +var BLEMessage = ""; +NRF.setServices({ + "feb10001-f00d-ea75-7192-abbadabadebb": { + "feb10002-f00d-ea75-7192-abbadabadebb": { + value : [0], + maxLen : 20, + writable : true, + onWrite : function(evt) { + let str = stringFromArray(evt.data); + if(str === "__EOM__") { + if(BLEMessage) { + showMsg('Message',BLEMessage); + } else { + reload(); + scheduleAlarms(); + showMsg('', 'Reloading...'); + } + BLEMessage = ''; + } else { + BLEMessage += str; + } + } + } + } +}, { }); +*/ + +exports.setDrawBackground = function(dBkgd) { + drawBackground = dBkgd; +}; +exports.setDrawTime = function(dTime) { + drawTime = dTime; +}; +exports.setDrawData = function( dData) { + drawData = dData; +}; +exports.begin = function() { + _Options = _Storage.readJSON(optsFile); + if(!_Options) _Options = { + autoNightMode: true, + useAlarms: false, + stepManager: true, + debug: true, + }; + + console.log(JSON.stringify(_Options)); + + if(_Options.useAlarms) { + _Alarm = require('m_alarms'); + _Alarm.reload(); + _Alarm.scheduleAlarms(); + } + // separate the Bangles now + const isB2 = g.getWidth() < 200; + + if(!isB2) { + Bangle.on('lcdPower', function (on) { + if (on) { + start(); + } else { + stop(); + } + }); + setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); + + if(_Options.useAlarms) { + setWatch(btn2Func, BTN2, {repeat:true,edge:"falling"}); + } + setWatch(Bangle.showLauncher, BTN3, {repeat:false,edge:"falling"}); + } + reload(); + drawBackground(nightMode); + start(); +}; + From d50d8c296b492c0600c2ce0a72cc1267094917d0 Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:40:06 -0400 Subject: [PATCH 18/29] Add files via upload for the launcher --- apps/nixie/nixie.png | Bin 0 -> 401 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/nixie/nixie.png diff --git a/apps/nixie/nixie.png b/apps/nixie/nixie.png new file mode 100644 index 0000000000000000000000000000000000000000..d21714191843d684e332a135789fde57d5f1e173 GIT binary patch literal 401 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDB3?!H8JlO)I7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O=*!;1lA?$jGSA$>t}_7OpOoAj*XtIhfUbd z1Ta2{0qS80Pt>pmQk(@Ik;M!Qe1}1p@p%4<6rkWMPZ!4!i_^&xtjsJDtP&CyR#Dbc zk`hW*HdZnXPD}}$(^wtetWfzlq0#YZfZ;YqjS@kniww(l$Q+nr=8?j*sm1)r9d8Gx zCsI$U%(mdD7Z>bgvAL#cv$b%_q+PMsvS35SI) mt~t=a$0Ff&P=SSqhv8p=?&)(Pb4`K1X7F_Nb6Mw<&;$S@*?AEF literal 0 HcmV?d00001 From 97938355be5cfbc8aea885f8732f6941e4f6255f Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:42:28 -0400 Subject: [PATCH 19/29] Update README.md --- apps/nixie/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/nixie/README.md b/apps/nixie/README.md index 7280800e9..17a49ebad 100644 --- a/apps/nixie/README.md +++ b/apps/nixie/README.md @@ -1,6 +1,7 @@ -Nixie clock +## Nixie clock -This clock displays the time in nixie-inspired numerals. +This clock displays the time in nixie-inspired numerals and works on both Bangle versions (1 and 2). It uses a generic +coordinate system (0 <= width < 1) and has helper functions to use inline. The app makes use of a module called "m_vatch" which manages all the timers, and makes calls to functions in the 'main' file to manage drawing the background, time, and any data like sensor info, step counters, battery, etc. The idea is that it is From 5001e793bc98a9c4bcbd986ce555fb715d6d3222 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 24 Aug 2021 09:35:36 -0700 Subject: [PATCH 20/29] Update README.md Made the image into text. --- apps/carcrazy/README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/apps/carcrazy/README.md b/apps/carcrazy/README.md index 6eef6f8c7..25fa23b25 100644 --- a/apps/carcrazy/README.md +++ b/apps/carcrazy/README.md @@ -1,3 +1,18 @@ -![Screenshot 2021-08-23 100720](https://user-images.githubusercontent.com/89286474/130498574-0b5246cb-8553-455c-b6c0-096e5ca1644c.png) +# Car Crazy +Car crazy is a fun game where you tilt your wrist left and right to avoid incoming cars. If you get hit by a car you lose a heart. In the game you have three hearts, if you get hit 3 times you are sent to the game over screen. Your goal is to try to last as long as you can. Because this game is still in beta please report any bugs here: https://forms.office.com/r/HnwYzG9Sk7. -Form Link: https://forms.office.com/r/HnwYzG9Sk7 +### Images: +(Coming Soon) + +### Instructions: + +BNT2: Hold down this button to start the game if you are on the starting page and game over page. + +Tilting Left-Right: Tilt your wrist left and right to steer your car and try not to get hit by the enemy car. + +### Feautures Coming Soon: +0.02: Levels are creating making the game get harder as it goes along. + +0.03: Optional soundtrack in settings. More levels. + +0.04: With higher scores you can now unlock different colors of cars. From 56269a668b71db80c4360489b69c7bc006cea11d Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:15:04 -0400 Subject: [PATCH 21/29] Delete app.js old app --- apps/g26/app.js | 336 ------------------------------------------------ 1 file changed, 336 deletions(-) delete mode 100644 apps/g26/app.js diff --git a/apps/g26/app.js b/apps/g26/app.js deleted file mode 100644 index b96422f4c..000000000 --- a/apps/g26/app.js +++ /dev/null @@ -1,336 +0,0 @@ -g.clear(); - -require("FontHaxorNarrow7x17").add(Graphics); -g.setFont("HaxorNarrow7x17", 1); // bitmap font, 8x magnified - -g.setFontAlign(0,0); // center font - -let interval = null; -let stepCounter = 0; - -let fgColor = "#FFFFFF"; -let bgColor = "#000000"; - -let fillDigits = true; -let myHeartRate = 123; -let hrmPower = false; - -const startX = [ 24, 90, 24, 90 ]; -const startY = [ 14, 14, 120, 120 ]; - -const hht = 60; -const vht = 40; -const w = 60; -const h = 90; - -let lastHour = 99; -let lastMinute = 99; - - -function pad0(n) { - return (n > 9) ? n : ("0"+n); -} - -function setFG() { - g.setColor(fgColor); -} - -function setBG() { - g.setColor(bgColor); -} - -function ellipse(x1, y1, x2, y2, fill) { - if (fill) g.fillEllipse(x1, y1, x2, y2); - else g.drawEllipse(x1, y1, x2, y2); -} - -function poly(arr, fill) { - if (fill) g.fillPoly(arr, true); - else g.drawPoly(arr, true); -} - -function rect(x1, y1, x2, y2, fill) { - if (fill) g.fillRect(x1, y1, x2, y2); - else g.drawRect(x1, y1, x2, y2); -} - -setBG(); -rect(0, 0, 240, 240, true); - - -/** DIGITS **/ - -/* zero */ -function draw0(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+w, yOrig+h, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+15, yOrig+15, xOrig+w-15, yOrig+h-15, fillDigits); -} - -/* one */ -function draw1(xOrig, yOrig) { - setFG(); - poly([xOrig+w/2-6, yOrig, - xOrig+w/2-12, yOrig, - xOrig+w/2-20, yOrig+12, - xOrig+w/2-6, yOrig+12 - ], fillDigits); - rect(xOrig+w/2-6, yOrig, xOrig+w/2+6, yOrig+h-3, fillDigits); - -} - -/* two */ -function draw2(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); - - setBG(); - rect(xOrig, yOrig+27, xOrig+40, yOrig+61, true); - - setFG(); - poly([xOrig, yOrig+88, - xOrig+56, yOrig+88, - xOrig+56, yOrig+75, - xOrig+25, yOrig+75, - xOrig+46, yOrig+50, - xOrig+42, yOrig+36 - ], fillDigits); -} - -/* three */ -function draw8(xOrig, yOrig) { - setFG(); - ellipse(xOrig+3, yOrig, xOrig+53, yOrig+48, fillDigits); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+17, yOrig+13, xOrig+40, yOrig+35, fillDigits); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); -} - -function draw3(xOrig, yOrig) { - draw8(xOrig, yOrig); - setBG(); - rect(xOrig, yOrig+24, xOrig+24, yOrig+61, true); -} - -/* four */ -function draw4(xOrig, yOrig) { - setFG(); - rect(xOrig+8, yOrig+54, xOrig+w-4, yOrig+67, fillDigits); - rect(xOrig+36, yOrig+12, xOrig+49, yOrig+88, fillDigits); - poly([xOrig, yOrig+67, - xOrig+12, yOrig+67, - xOrig+49, yOrig+12, - xOrig+49, yOrig+1, - xOrig+42, yOrig+1 - ], fillDigits); -} - -function draw5(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); - - setBG(); - rect(xOrig, yOrig+24, xOrig+20, yOrig+61, true); - - setFG(); - poly([xOrig+20, yOrig+1, - xOrig+7, yOrig+47, - xOrig+19, yOrig+47, - xOrig+32, yOrig+1 - ], fillDigits); - rect(xOrig+20, yOrig+1, xOrig+53, yOrig+13, fillDigits); -} - -/* six */ -function draw6(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig+33, xOrig+56, yOrig+89, fillDigits); - poly([xOrig+2, yOrig+48, - xOrig+34, yOrig, - xOrig+46, yOrig+7, - xOrig+14, yOrig+56 - ], fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+46, xOrig+43, yOrig+76, fillDigits); -} - -/* seven */ -function draw7(xOrig, yOrig) { - setFG(); - poly([xOrig+4, yOrig+1, - xOrig+w-1, yOrig+1, - xOrig+w-7, yOrig+13, - xOrig+4, yOrig+13 - ], fillDigits); - poly([xOrig+w-1, yOrig+1, - xOrig+15, yOrig+88, - xOrig+5, yOrig+81, - xOrig+w-19, yOrig+9 - ], fillDigits); -} - -function draw9(xOrig, yOrig) { - setFG(); - ellipse(xOrig, yOrig, xOrig+56, yOrig+56, fillDigits); - poly([xOrig+54, yOrig+41, - xOrig+22, yOrig+89, - xOrig+10, yOrig+82, - xOrig+42, yOrig+33 - ], fillDigits); - if(fillDigits) setBG(); - ellipse(xOrig+13, yOrig+13, xOrig+43, yOrig+43, fillDigits); -} - -/** END DIGITS **/ -function getRandomColor() { - const digits = "0123456789ABCDEF"; - let r1 = digits[Math.floor(Math.random() * 16)]; - let r2 = digits[Math.floor(Math.random() * 16)]; - let g1 = digits[Math.floor(Math.random() * 16)]; - let g2 = digits[Math.floor(Math.random() * 16)]; - let b1 = digits[Math.floor(Math.random() * 16)]; - let b2 = digits[Math.floor(Math.random() * 16)]; - let str = "#"+r1+r2+g1+g2+b1+b2; - /* console.log(str); */ - return str; -} - -function drawDigit(pos, dig) { - let x = startX[pos]; - let y = startY[pos]; - - setBG(); - rect(x, y, x+w, y+h, true); - switch(dig) { - case 0: - draw0(x, y); - break; - case 1: - draw1(x, y); - break; - case 2: - draw2(x, y); - break; - case 3: - draw3(x, y); - break; - case 4: - draw4(x, y); - break; - case 5: - draw5(x, y); - break; - case 6: - draw6(x, y); - break; - case 7: - draw7(x, y); - break; - case 8: - draw8(x, y); - break; - case 9: - draw9(x, y); - break; - } -} - - -function drawTime() { - let d = new Date(); - let hour = d.getHours(); - let minute = d.getMinutes(); - let month = d.getMonth(); - let date = d.getDate(); - - if(hour == lastHour && minute == lastMinute) { - return; - } - - fgColor = "#FFFFFF"; - if(hour != lastHour) { - drawDigit(0, Math.floor(hour / 10)); - drawDigit(1, hour % 10); - } - - fgColor = "#00FFFF"; - if(minute != lastMinute) { - drawDigit(2, Math.floor(minute / 10)); - drawDigit(3, minute % 10); - } - lastHour = hour; - lastMinute = minute; - - setBG(); - rect(0, 226, 240, 240, true); - for(let c = 0; c <= 240; c++) { - g.setColor(0, 0, 1-c/240); - g.fillRect(180, c, 240, c); - } - g.setColor("#C0C0C0"); - - g.setFontAlign(-1,-1); - g.drawString("DT", 184, 10); - g.drawString("STP", 184, 70); - g.drawString("BPM", 184, 140); - g.drawString("BTY", 184, 210); - - g.setFontAlign(1,-1); - g.drawString(month + "/" + date, 236, 10); - g.drawString(stepCounter, 236, 70); - g.drawString(myHeartRate, 236, 140); - g.drawString(E.getBattery(), 236, 210); - -} - -function stop () { - if (interval) { - clearInterval(interval); - } -} - -function start () { - if (interval) { - clearInterval(interval); - } - // first time init - interval = setInterval(drawTime, 10000); - drawTime(); -} - -start(); - -// Bangle.loadWidgets(); -// Bangle.drawWidgets(); - -Bangle.on('lcdPower', function (on) { - if (on) { - start(); - } else { - stop(); - } -}); - -function btn1Func() { - fillDigits = !fillDigits; - g.clear(); - lastHour = 99; - lastMinute = 99; - drawTime(); -} - -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); - -setWatch(btn1Func, BTN1, {repeat:true,edge:"falling"}); - -Bangle.on('step', function(cnt) { - stepCounter = cnt; -}); - From fa287de2fa829494b3686ea5de02a5106eee0036 Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:15:16 -0400 Subject: [PATCH 22/29] Delete apps.json old app --- apps/g26/apps.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 apps/g26/apps.json diff --git a/apps/g26/apps.json b/apps/g26/apps.json deleted file mode 100644 index e037c8f17..000000000 --- a/apps/g26/apps.json +++ /dev/null @@ -1,13 +0,0 @@ -}, -{ "id": "g26", - "name": "G26 Watch", - "shortName":"G26 Watch", - "type": "clock", - "version":"0.01", - "description": "This is a watchface loosely based on a $5 step tracker", - "tags": "", - "storage": [ - {"name":"g26.app.js","url":"g26.js"} - ] -} -] From 921d8703125a6074ff80c69201e9c5748a57922c Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:23:18 -0400 Subject: [PATCH 23/29] Create app-icon.js --- apps/nixie/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/nixie/app-icon.js diff --git a/apps/nixie/app-icon.js b/apps/nixie/app-icon.js new file mode 100644 index 000000000..99de52534 --- /dev/null +++ b/apps/nixie/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkBIf4A/AH4A/AH4AtgtVAANQAwIFCAwYTGBIQDBqsF6AXCqFQroXDBQQXFAxNUBRAQKAAXVAYUEFBY7EBgtVC5UEDotdERwQBC4pGDTgQXJgoRDMoQGCqisFR5pICDQQwDCAxVJZAYXKQo7nEC6AtBCYgXGCYYDCJQYXBF5ThDKwoNCB4UMC4yyBToIGDAYNUDoRiBO5CyBLwi5Ea4RyGAH4A/AH4A/AH4A/ACQ=")) From 642a46e863a9e7b7faed2f8ef24e7e365d19ee3c Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:24:45 -0400 Subject: [PATCH 24/29] Rename nixie.app.js to app.js --- apps/nixie/{nixie.app.js => app.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/nixie/{nixie.app.js => app.js} (100%) diff --git a/apps/nixie/nixie.app.js b/apps/nixie/app.js similarity index 100% rename from apps/nixie/nixie.app.js rename to apps/nixie/app.js From 2f7bdb8805c79d2845c20f381aded9d6eb4445c4 Mon Sep 17 00:00:00 2001 From: JV <61598758+yngv27@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:35:08 -0400 Subject: [PATCH 25/29] Update apps.json added Nixie Clock --- apps.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps.json b/apps.json index 2b28509cf..2320ecd6e 100644 --- a/apps.json +++ b/apps.json @@ -3410,5 +3410,20 @@ {"name":"thermomF.app.js","url":"app.js"}, {"name":"thermomF.img","url":"app-icon.js","evaluate":true} ] +}, +{ "id": "vNixie", + "name": "Nixie Clock", + "shortName":"Nixie", + "icon": "nixie.png", + "version":"1.0", + "description": "A nixie tube clock for both Bangle 1 and 2.", + "tags": "clock", + "type":"clock", + "readme": "README.md", + "storage": [ + {"name":"nixie.app.js","url":"app.js"}, + {"name":"nixie.img","url":"app-icon.js","evaluate":true}, + {"name":"m_vatch.js","url":"m_vatch.js"} + ] } ] From 409444a85ce9c73ffe69f7cb166d63f4b21643cb Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 Aug 2021 08:44:14 +0100 Subject: [PATCH 26/29] tweaks to make Nixie app work --- apps.json | 4 ++-- apps/nixie/ChangeLog | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 apps/nixie/ChangeLog diff --git a/apps.json b/apps.json index 763cc15e4..08677cd59 100644 --- a/apps.json +++ b/apps.json @@ -3411,11 +3411,11 @@ {"name":"thermomF.img","url":"app-icon.js","evaluate":true} ] }, -{ "id": "vNixie", +{ "id": "nixie", "name": "Nixie Clock", "shortName":"Nixie", "icon": "nixie.png", - "version":"1.0", + "version":"0.01", "description": "A nixie tube clock for both Bangle 1 and 2.", "tags": "clock", "type":"clock", diff --git a/apps/nixie/ChangeLog b/apps/nixie/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/nixie/ChangeLog @@ -0,0 +1 @@ +0.01: New App! From 0d7bddddde2452a4a0fd1a43578485908239b572 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 Aug 2021 08:45:09 +0100 Subject: [PATCH 27/29] widbat 0.08: Ensure battery updates every 60s even if LCD was on at boot and stays on --- apps.json | 2 +- apps/widbat/ChangeLog | 1 + apps/widbat/widget.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 08677cd59..96029ec91 100644 --- a/apps.json +++ b/apps.json @@ -616,7 +616,7 @@ { "id": "widbat", "name": "Battery Level Widget", "icon": "widget.png", - "version":"0.07", + "version":"0.08", "description": "Show the current battery level and charging status in the top right of the clock", "tags": "widget,battery,b2", "type":"widget", diff --git a/apps/widbat/ChangeLog b/apps/widbat/ChangeLog index 138ed64e6..a5fdc31cc 100644 --- a/apps/widbat/ChangeLog +++ b/apps/widbat/ChangeLog @@ -4,3 +4,4 @@ 0.05: Fix regression stopping correct widget updates 0.06: Use 'g.theme' (requires bootloader 0.23) 0.07: Move CHARGING variable to more readable string +0.08: Ensure battery updates every 60s even if LCD was on at boot and stays on diff --git a/apps/widbat/widget.js b/apps/widbat/widget.js index 3fb07a099..739326df0 100644 --- a/apps/widbat/widget.js +++ b/apps/widbat/widget.js @@ -23,7 +23,7 @@ Bangle.drawWidgets(); // relayout widgets g.flip(); }); - var batteryInterval; + var batteryInterval = Bangle.isLCDOn() ? setInterval(()=>WIDGETS["bat"].draw(), 60000) : undefined; Bangle.on('lcdPower', function(on) { if (on) { WIDGETS["bat"].draw(); From 0410a0dd8e1eaef230e69e4904c1305876b0977c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 Aug 2021 17:00:44 +0100 Subject: [PATCH 28/29] accellog: 0.02: Use the new multiplatform 'Layout' library Loads of layout lib improvements --- apps.json | 4 +- apps/accellog/ChangeLog | 1 + apps/accellog/app.js | 39 ++++++---- modules/Layout.js | 163 +++++++++++++++++++++++++++++----------- 4 files changed, 144 insertions(+), 63 deletions(-) diff --git a/apps.json b/apps.json index 96029ec91..b7cfffa37 100644 --- a/apps.json +++ b/apps.json @@ -2409,10 +2409,10 @@ "name": "Acceleration Logger", "shortName":"Accel Log", "icon": "app.png", - "version":"0.01", + "version":"0.02", "interface": "interface.html", "description": "Logs XYZ acceleration data to a CSV file that can be downloaded to your PC", - "tags": "outdoor", + "tags": "outdoor,b2", "readme": "README.md", "storage": [ {"name":"accellog.app.js","url":"app.js"}, diff --git a/apps/accellog/ChangeLog b/apps/accellog/ChangeLog index 5560f00bc..084f26aff 100644 --- a/apps/accellog/ChangeLog +++ b/apps/accellog/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Use the new multiplatform 'Layout' library diff --git a/apps/accellog/app.js b/apps/accellog/app.js index 045b9eba0..5408264f1 100644 --- a/apps/accellog/app.js +++ b/apps/accellog/app.js @@ -90,16 +90,26 @@ function startRecord(force) { // display g.clear(1); Bangle.drawWidgets(); - var w = g.getWidth(); - var h = g.getHeight(); - g.setColor("#ff0000").fillRect(0,h-48,w,h); - g.setColor("#ffffff").setFont("6x8",2).setFontAlign(0,0).drawString("RECORDING", w/2,h-24); - g.setFont("6x8").drawString("Samples:",w/2,h/3 - 20); - g.setFont("6x8").drawString("Time:",w/2,h*2/3 - 20); - g.setFont("6x8",2).setFontAlign(0,0,1).drawString("STOP",w-10,h/2); + + var Layout = require("Layout"); + var layout = new Layout({ type: "v", c: [ + {type:"txt", font:"6x8", label:"Samples", pad:2}, + {type:"txt", id:"samples", font:"6x8:2", label:" - ", pad:5}, + {type:"txt", font:"6x8", label:"Time", pad:2}, + {type:"txt", id:"time", font:"6x8:2", label:" - ", pad:5}, + {type:"txt", font:"6x8:2", label:"RECORDING", bgCol:"#f00", pad:5, fillx:true}, + ] + },[ // Buttons... + {label:"STOP", cb:()=>{ + Bangle.removeListener('accel', accelHandler); + showMenu(); + }} + ]); + layout.update(); + layout.render(); // now start writing - f = require("Storage").open(getFileName(fileNumber), "w"); + var f = require("Storage").open(getFileName(fileNumber), "w"); f.write("Time (ms),X,Y,Z\n"); var start = getTime(); var sampleCount = 0; @@ -113,17 +123,14 @@ function startRecord(force) { accel.z*8192].map(n=>Math.round(n)).join(",")+"\n"); sampleCount++; - g.reset().setFont("6x8",2).setFontAlign(0,0); - g.drawString(" "+sampleCount+" ",w/2,h/3,true); - g.drawString(" "+Math.round(t)+"s ",w/2,h*2/3,true); + layout.samples.label = sampleCount; + layout.time.label = Math.round(t)+"s"; + layout.render(layout.samples); + layout.render(layout.time); } - Bangle.setPollInterval(80); // 12.5 Hz + Bangle.setPollInterval(80); // 12.5 Hz - the default Bangle.on('accel', accelHandler); - setWatch(()=>{ - Bangle.removeListener('accel', accelHandler); - showMenu(); - }, BTN2); } diff --git a/modules/Layout.js b/modules/Layout.js index f21fbe45d..f1bf1eb1c 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -1,39 +1,101 @@ -if (!g.theme) { - g.theme = { - fg:-1,bg:0,fgH:-1,bgH:"#008" - }; -} + +/* + +Usage: + +var layout = new Layout( layoutObject, btns ) +layout.render(optionalObject); + +layoutObject has: + +* A `type` field of: + * `undefined` - blank, can be used for padding + * `"txt"` - a text label, with value `label` and `r` for text rotation + * `"btn"` - a button, with value `label` and callback `cb` + * `"img"` - an image where the function `src` is called to return an image to draw + * `"custom"` - a custom block where `render(layoutObj)` is called to render + * `"h"` - Horizontal layout, `c` is an array of more `layoutObject` + * `"v"` - Veritical layout, `c` is an array of more `layoutObject` +* A `id` field. If specified the object is added with this name to the + returned `layout` object, so can be referenced as `layout.foo` +* A `font` field, eg `6x8` or `30%` to use a percentage of screen height +* A `col` field, eg `#f00` for red +* A `bgCol` field for background color (will automatically fill on render) +* A `halign` field to set horizontal alignment. `-1`=left, `1`=right, `0`=center +* A `valign` field to set vertical alignment. `-1`=top, `1`=bottom, `0`=center +* A `pad` integer field to set pixels padding +* A `fillx` boolean to choose if the object should fill available space in x +* A `filly` boolean to choose if the object should fill available space in y +* `width` and `height` fields to optionally specify minimum size + +btns is an array of objects containing: + +* `label` - the text on the button +* `cb` - a callback function +* `cbl` - a callback function for long presses + +Once `layout.update()` is called, the following fields are added +to each object: + +* `x` and `y` for the top left position +* `w` and `h` for the width and height +* `_w` and `_h` for the **minimum** width and height + + +Other functions: + +* `layout.update()` - update positions of everything if contents have changed +* `layout.debug(obj)` - draw outlines for objects on screen +* `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render) + +*/ + function Layout(layout, buttons) { this._l = this.l = layout; this.b = buttons; - // Do we have physical buttons? - this.physBtn = process.env.HWVERSION!=2; + // Do we have >1 physical buttons? + this.physBtns = (process.env.HWVERSION==2) ? 1 : 3; 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 (buttons) { + if (this.physBtns >= buttons.length) { + // enough physical buttons + var btnHeight = Math.floor((g.getHeight()-this.yOffset) / this.physBtns); if (Bangle.btnWatch) Bangle.btnWatch.forEach(clearWatch); Bangle.btnWatch = []; + if (this.physBtns > 2 && buttons.length==1) + buttons.unshift({label:""}); // pad so if we have a button in the middle + while (this.physBtns > buttons.length) + buttons.push({label:""}); 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:"h", filly:1, c: [ this._l, - {type:"v", content: buttons.map(b=>(b.type="txt",b.font="6x8",b.height=btnHeight,b.r=1,b))} + {type:"v", pad:1, filly:1, c: buttons.map(b=>(b.type="txt",b.font="6x8",b.height=btnHeight,b.r=1,b))} ]}; - } else { // no physical buttons, use touchscreen + } else { + var btnHeight = Math.floor((g.getHeight()-this.yOffset) / buttons.length); this._l.width = g.getWidth()-20; // button width - this._l = {type:"h", content: [ + this._l = {type:"h", c: [ this._l, - {type:"v", content: buttons.map(b=>(b.type="btn",b.height=btnHeight,b.width=32,b.r=1,b))} + {type:"v", c: buttons.map(b=>(b.type="btn",b.h=btnHeight,b.w=32,b.r=1,b))} ]}; Bangle.touchHandler = (_,e) => touchHandler(this._l,e); Bangle.on('touch',Bangle.touchHandler); } } + + // add IDs + var ll = this; + function idRecurser(l) { + if (l.id) ll[l.id] = l; + if (l.c) l.c.forEach(idRecurser); + } + idRecurser(layout); + this.update(); } Layout.prototype.remove = function (l) { @@ -59,7 +121,7 @@ function pressHandler(btn,e) { 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)); + if (l.c) l.c.forEach(n => touchHandler(n,e)); } @@ -68,7 +130,13 @@ function updateMin(l) { case "txt": { if (l.font.endsWith("%")) l.font = "Vector"+Math.round(g.getHeight()*l.font.slice(0,-1)/100); - g.setFont(l.font); + // Not needed in new firmwares - 'font' is enough + if (l.font.includes(":")) { + var f = l.font.split(":"); + l.font = f[0]; + l.fsz = f[1]; + } + g.setFont(l.font,l.fsz); l._h = g.getFontHeight(); l._w = g.stringWidth(l.label); break; @@ -84,6 +152,7 @@ function updateMin(l) { l._w = im.charCodeAt(1); break; } + case undefined: case "custom": { // size should already be set up in width/height l._w = 0; @@ -91,17 +160,17 @@ function updateMin(l) { 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); + l.c.forEach(updateMin); + l._h = l.c.reduce((a,b)=>Math.max(a,b._h+(b.pad<<1)),0); + l._w = l.c.reduce((a,b)=>a+b._w+(b.pad<<1),0); + l.fillx |= l.c.some(c=>c.fillx); 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); + l.c.forEach(updateMin); + l._h = l.c.reduce((a,b)=>a+b._h+(b.pad<<1),0); + l._w = l.c.reduce((a,b)=>Math.max(a,b._w+(b.pad<<1)),0); + l.filly |= l.c.some(c=>c.filly); break; } default: throw "Unknown item type "+l.type; @@ -116,9 +185,10 @@ function render(l) { if (!l) l = this.l; g.reset(); if (l.col) g.setColor(l.col); + if (l.bgCol!==undefined) g.setBgColor(l.bgCol).clearRect(l.x,l.y,l.x+l.w,l.y+l.h); 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)); + g.setFont(l.font,l.fsz).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1), true/*solid bg*/); break; case "btn": var poly = [ @@ -141,7 +211,7 @@ function render(l) { l.render(l); break; } - if (l.content) l.content.forEach(render); + if (l.c) l.c.forEach(render); } Layout.prototype.render = function (l) { @@ -152,23 +222,24 @@ Layout.prototype.render = function (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); + var fillx = l.c.reduce((a,l)=>a+(0|l.fillx),0); + var filly = l.c.reduce((a,l)=>a+(0|l.filly),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; + if (fillx) { x = l.x; } + l.c.forEach(c => { + c.w = c._w + (c.fillx?(l.w-l._w)/fillx:0); + c.h = c.filly ? 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; + c.w += c.pad*2; + c.h += c.pad*2; } - if (c.content) { + if (c.c) { this.layout(c); } }); @@ -176,19 +247,19 @@ Layout.prototype.layout = function (l) { } 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); + if (filly) { y = l.y; } + l.c.forEach(c => { + c.w = c.fillx ? l.w : c._w; + c.h = c._h + (c.filly?(l.h-l._h)/filly: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; + c.w += c.pad*2; + c.h += c.pad*2; } - if (c.content) this.layout(c); + if (c.c) this.layout(c); }); break; } @@ -199,7 +270,7 @@ Layout.prototype.debug = function(l,c) { 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)); + if (l.c) l.c.forEach(n => this.debug(n,c)); }; Layout.prototype.update = function() { var l = this._l; @@ -209,7 +280,7 @@ Layout.prototype.update = function() { // update sizes updateMin(l); // center - if (l.fill) { + if (l.fillx || l.filly) { l.w = w; l.h = h; l.x = 0; @@ -226,7 +297,9 @@ Layout.prototype.update = function() { 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); + g.reset(); + if (l.bgCol!==undefined) g.setBgColor(l.bgCol); + g.clearRect(l.x,l.y,l.x+l.w-1,l.y+l.h-1); }; exports = Layout; From 97bdf0b7d090c9a6cb9acff26c12ef20e165dd2d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 Aug 2021 17:06:06 +0100 Subject: [PATCH 29/29] force use of unminified module for now --- modules/Layout.min.js | 305 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 modules/Layout.min.js diff --git a/modules/Layout.min.js b/modules/Layout.min.js new file mode 100644 index 000000000..f1bf1eb1c --- /dev/null +++ b/modules/Layout.min.js @@ -0,0 +1,305 @@ + +/* + +Usage: + +var layout = new Layout( layoutObject, btns ) +layout.render(optionalObject); + +layoutObject has: + +* A `type` field of: + * `undefined` - blank, can be used for padding + * `"txt"` - a text label, with value `label` and `r` for text rotation + * `"btn"` - a button, with value `label` and callback `cb` + * `"img"` - an image where the function `src` is called to return an image to draw + * `"custom"` - a custom block where `render(layoutObj)` is called to render + * `"h"` - Horizontal layout, `c` is an array of more `layoutObject` + * `"v"` - Veritical layout, `c` is an array of more `layoutObject` +* A `id` field. If specified the object is added with this name to the + returned `layout` object, so can be referenced as `layout.foo` +* A `font` field, eg `6x8` or `30%` to use a percentage of screen height +* A `col` field, eg `#f00` for red +* A `bgCol` field for background color (will automatically fill on render) +* A `halign` field to set horizontal alignment. `-1`=left, `1`=right, `0`=center +* A `valign` field to set vertical alignment. `-1`=top, `1`=bottom, `0`=center +* A `pad` integer field to set pixels padding +* A `fillx` boolean to choose if the object should fill available space in x +* A `filly` boolean to choose if the object should fill available space in y +* `width` and `height` fields to optionally specify minimum size + +btns is an array of objects containing: + +* `label` - the text on the button +* `cb` - a callback function +* `cbl` - a callback function for long presses + +Once `layout.update()` is called, the following fields are added +to each object: + +* `x` and `y` for the top left position +* `w` and `h` for the width and height +* `_w` and `_h` for the **minimum** width and height + + +Other functions: + +* `layout.update()` - update positions of everything if contents have changed +* `layout.debug(obj)` - draw outlines for objects on screen +* `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render) + +*/ + + +function Layout(layout, buttons) { + this._l = this.l = layout; + this.b = buttons; + // Do we have >1 physical buttons? + this.physBtns = (process.env.HWVERSION==2) ? 1 : 3; + this.yOffset = Object.keys(global.WIDGETS).length ? 24 : 0; + + if (buttons) { + if (this.physBtns >= buttons.length) { + // enough physical buttons + var btnHeight = Math.floor((g.getHeight()-this.yOffset) / this.physBtns); + if (Bangle.btnWatch) Bangle.btnWatch.forEach(clearWatch); + Bangle.btnWatch = []; + if (this.physBtns > 2 && buttons.length==1) + buttons.unshift({label:""}); // pad so if we have a button in the middle + while (this.physBtns > buttons.length) + buttons.push({label:""}); + 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", filly:1, c: [ + this._l, + {type:"v", pad:1, filly:1, c: buttons.map(b=>(b.type="txt",b.font="6x8",b.height=btnHeight,b.r=1,b))} + ]}; + } else { + var btnHeight = Math.floor((g.getHeight()-this.yOffset) / buttons.length); + this._l.width = g.getWidth()-20; // button width + this._l = {type:"h", c: [ + this._l, + {type:"v", c: buttons.map(b=>(b.type="btn",b.h=btnHeight,b.w=32,b.r=1,b))} + ]}; + Bangle.touchHandler = (_,e) => touchHandler(this._l,e); + Bangle.on('touch',Bangle.touchHandler); + } + } + + // add IDs + var ll = this; + function idRecurser(l) { + if (l.id) ll[l.id] = l; + if (l.c) l.c.forEach(idRecurser); + } + idRecurser(layout); + this.update(); +} + +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.c) l.c.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); + // Not needed in new firmwares - 'font' is enough + if (l.font.includes(":")) { + var f = l.font.split(":"); + l.font = f[0]; + l.fsz = f[1]; + } + g.setFont(l.font,l.fsz); + 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 undefined: + case "custom": { + // size should already be set up in width/height + l._w = 0; + l._h = 0; + break; + } + case "h": { + l.c.forEach(updateMin); + l._h = l.c.reduce((a,b)=>Math.max(a,b._h+(b.pad<<1)),0); + l._w = l.c.reduce((a,b)=>a+b._w+(b.pad<<1),0); + l.fillx |= l.c.some(c=>c.fillx); + break; + } + case "v": { + l.c.forEach(updateMin); + l._h = l.c.reduce((a,b)=>a+b._h+(b.pad<<1),0); + l._w = l.c.reduce((a,b)=>Math.max(a,b._w+(b.pad<<1)),0); + l.filly |= l.c.some(c=>c.filly); + 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); + if (l.bgCol!==undefined) g.setBgColor(l.bgCol).clearRect(l.x,l.y,l.x+l.w,l.y+l.h); + switch (l.type) { + case "txt": + g.setFont(l.font,l.fsz).setFontAlign(0,0,l.r).drawString(l.label, l.x+(l.w>>1), l.y+(l.h>>1), true/*solid bg*/); + 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.c) l.c.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 fillx = l.c.reduce((a,l)=>a+(0|l.fillx),0); + var filly = l.c.reduce((a,l)=>a+(0|l.filly),0); + switch (l.type) { + case "h": { + let x = l.x + (l.w-l._w)/2; + if (fillx) { x = l.x; } + l.c.forEach(c => { + c.w = c._w + (c.fillx?(l.w-l._w)/fillx:0); + c.h = c.filly ? 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.w += c.pad*2; + c.h += c.pad*2; + } + if (c.c) { + this.layout(c); + } + }); + break; + } + case "v": { + let y = l.y + (l.h-l._h)/2; + if (filly) { y = l.y; } + l.c.forEach(c => { + c.w = c.fillx ? l.w : c._w; + c.h = c._h + (c.filly?(l.h-l._h)/filly: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.w += c.pad*2; + c.h += c.pad*2; + } + if (c.c) 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.c) l.c.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.fillx || l.filly) { + 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(); + if (l.bgCol!==undefined) g.setBgColor(l.bgCol); + g.clearRect(l.x,l.y,l.x+l.w-1,l.y+l.h-1); +}; + +exports = Layout;