From b0de874f87980588a8bf54b3b2f6580268ce59ab Mon Sep 17 00:00:00 2001 From: marko Date: Wed, 16 Sep 2020 11:17:37 -0400 Subject: [PATCH 001/110] Reduce flicker, continuous sensor battery updates --- apps/cscsensor/cscsensor.app.js | 100 ++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/apps/cscsensor/cscsensor.app.js b/apps/cscsensor/cscsensor.app.js index 65b50dfe7..7b6546343 100644 --- a/apps/cscsensor/cscsensor.app.js +++ b/apps/cscsensor/cscsensor.app.js @@ -26,8 +26,10 @@ class CSCSensor { this.speedUnit = this.qMetric ? "km/h" : "mph"; this.distUnit = this.qMetric ? "km" : "mi"; this.distFactor = this.qMetric ? 1.609344 : 1; + this.screenInit = true; this.batteryLevel = -1; } + reset() { this.settings.totaldist = this.totaldist; storage.writeJSON(SETTINGS_FILE, this.settings); @@ -35,10 +37,30 @@ class CSCSensor { this.movingTime = 0; this.lastRevsStart = this.lastRevs; this.maxSpeed = 0; + this.screenInit = true; } + setBatteryLevel(level) { - this.batteryLevel = level; + if (level!=this.batteryLevel) { + this.batteryLevel = level; + this.drawBatteryIcon(); + } } + + updateBatteryLevel(event) { + if (event.target.uuid == "0x2a19") this.setBatteryLevel(event.target.value.getUint8(0)); + } + + drawBatteryIcon() { + if (this.batteryLevel!=-1) { + g.setColor(1, 1, 1).drawRect(10, 55, 20, 75).fillRect(14, 53, 16, 55); + if (this.batteryLevel<25) g.setColor(1, 0, 0); + else if (this.batteryLevel<50) g.setColor(1, 0.5, 0); + else g.setColor(0, 1, 0); + g.fillRect(11, 74-18*this.batteryLevel/100, 19, 74); + } + } + updateScreen() { var dist = this.distFactor*(this.lastRevs-this.lastRevsStart)*this.wheelCirc/63360.0; var ddist = Math.round(100*dist)/100; @@ -50,39 +72,41 @@ class CSCSensor { if (dsecs.length<2) dsecs = "0"+dsecs; var avespeed = (this.movingTime>2 ? Math.round(10*dist/(this.movingTime/3600))/10 : 0); var maxspeed = Math.round(10*this.distFactor*this.maxSpeed)/10; - for (var i=0; i<6; ++i) { - if ((i&1)==0) g.setColor(0, 0, 0); - else g.setColor(0.2, 0.1, 0.4); - g.fillRect(0, 48+i*32, 86, 48+(i+1)*32); - if ((i&1)==1) g.setColor(0, 0, 0); - else g.setColor(0.2, 0.1, 0.4); - g.fillRect(87, 48+i*32, 239, 48+(i+1)*32); - g.setColor(0.5, 0.5, 0.5).drawRect(87, 48+i*32, 239, 48+(i+1)*32).drawLine(0, 239, 239, 239).drawRect(0, 48, 87, 239); - } - g.setFontAlign(1, 0, 0).setFontVector(19).setColor(1, 1, 0); - g.drawString("Time:", 87, 66); - g.drawString("Speed:", 87, 98); - g.drawString("Ave spd:", 87, 130); - g.drawString("Max spd:", 87, 162); - g.drawString("Trip:", 87, 194); - g.drawString("Total:", 87, 226); - g.setFontAlign(-1, 0, 0).setFontVector(26).setColor(1, 1, 1);//.clearRect(92, 60, 239, 239); - g.drawString(dmins+":"+dsecs, 92, 66); - g.drawString(dspeed+" "+this.speedUnit, 92, 98); - g.drawString(avespeed + " " + this.speedUnit, 92, 130); - g.drawString(maxspeed + " " + this.speedUnit, 92, 162); - g.drawString(ddist + " " + this.distUnit, 92, 194); - g.drawString(tdist + " " + this.distUnit, 92, 226); - if (this.batteryLevel!=-1) { - g.setColor(1, 1, 1).drawRect(10, 55, 20, 75).fillRect(14, 53, 16, 55); - if (this.batteryLevel<25) g.setColor(1, 0, 0); - else if (this.batteryLevel<50) g.setColor(1, 0.5, 0); - else g.setColor(0, 1, 0); - g.fillRect(11, 74-18*this.batteryLevel/100, 19, 74); - console.log(this.batteryLevel); - this.batteryLevel = -1; + if (this.screenInit) { + for (var i=0; i<6; ++i) { + if ((i&1)==0) g.setColor(0, 0, 0); + else g.setColor(0x30cd); + g.fillRect(0, 48+i*32, 86, 48+(i+1)*32); + if ((i&1)==1) g.setColor(0); + else g.setColor(0x30cd); + g.fillRect(87, 48+i*32, 239, 48+(i+1)*32); + g.setColor(0.5, 0.5, 0.5).drawRect(87, 48+i*32, 239, 48+(i+1)*32).drawLine(0, 239, 239, 239).drawRect(0, 48, 87, 239); + } + g.setFontAlign(1, 0, 0).setFontVector(19).setColor(1, 1, 0); + g.drawString("Time:", 87, 66); + g.drawString("Speed:", 87, 98); + g.drawString("Ave spd:", 87, 130); + g.drawString("Max spd:", 87, 162); + g.drawString("Trip:", 87, 194); + g.drawString("Total:", 87, 226); + this.drawBatteryIcon(); + this.screenInit = false; } + g.setFontAlign(-1, 0, 0).setFontVector(26); + g.setColor(0x30cd).fillRect(88, 49, 238, 79); + g.setColor(0xffff).drawString(dmins+":"+dsecs, 92, 66); + g.setColor(0).fillRect(88, 81, 238, 111); + g.setColor(0xffff).drawString(dspeed+" "+this.speedUnit, 92, 98); + g.setColor(0x30cd).fillRect(88, 113, 238, 143); + g.setColor(0xffff).drawString(avespeed + " " + this.speedUnit, 92, 130); + g.setColor(0).fillRect(88, 145, 238, 175); + g.setColor(0xffff).drawString(maxspeed + " " + this.speedUnit, 92, 162); + g.setColor(0x30cd).fillRect(88, 177, 238, 207); + g.setColor(0xffff).drawString(ddist + " " + this.distUnit, 92, 194); + g.setColor(0).fillRect(88, 209, 238, 238); + g.setColor(0xffff).drawString(tdist + " " + this.distUnit, 92, 226); } + updateSensor(event) { var qChanged = false; if (event.target.uuid == "0x2a5b") { @@ -103,7 +127,7 @@ class CSCSensor { var dBT = (Date.now()-this.lastBangleTime)/1000; this.lastBangleTime = Date.now(); if (dT<0) dT+=64; - if (Math.abs(dT-dBT)>2) dT = dBT; + if (Math.abs(dT-dBT)>3) dT = dBT; this.lastTime = wheelTime; this.speed = this.lastSpeed; if (dRevs>0 && dT>0) { @@ -132,9 +156,8 @@ function getSensorBatteryLevel(gatt) { gatt.getPrimaryService("180f").then(function(s) { return s.getCharacteristic("2a19"); }).then(function(c) { - return c.readValue(); - }).then(function(d) { - mySensor.setBatteryLevel(d.buffer[0]); + c.on('characteristicvaluechanged', (event)=>mySensor.updateBatteryLevel(event)); + return c.startNotifications(); }); } @@ -159,17 +182,18 @@ function parseDevice(d) { mySensor.updateScreen(); }).catch(function(e) { g.clearRect(0, 60, 239, 239).setColor(1, 0, 0).setFontAlign(0, 0, 0).drawString("ERROR"+e, 120, 120).flip(); - console.log(e); + console.log(e); })} function connection_setup() { + NRF.setScan(); NRF.setScan(parseDevice, { filters: [{services:["1816"]}], timeout: 2000}); g.clearRect(0, 60, 239, 239).setFontVector(18).setFontAlign(0, 0, 0).setColor(0, 1, 0); g.drawString("Scanning for CSC sensor...", 120, 120); } connection_setup(); -setWatch(function() { mySensor.reset(); g.clearRect(0, 60, 239, 239); mySensor.updateScreen(); }, BTN1, {repeat:true, debounce:20}); +setWatch(function() { mySensor.reset(); g.clearRect(0, 48, 239, 239); mySensor.updateScreen(); }, BTN1, {repeat:true, debounce:20}); E.on('kill',()=>{ if (gatt!=undefined) gatt.disconnect(); mySensor.settings.totaldist = mySensor.totaldist; storage.writeJSON(SETTINGS_FILE, mySensor.settings); }); NRF.on('disconnect', connection_setup); From 39fafdac6ab32a9ef1ae37f468b11afdcad2b4ff Mon Sep 17 00:00:00 2001 From: marko Date: Wed, 16 Sep 2020 15:08:31 -0400 Subject: [PATCH 002/110] Better presentation of sensor battery icon --- apps/cscsensor/cscsensor.app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/cscsensor/cscsensor.app.js b/apps/cscsensor/cscsensor.app.js index 7b6546343..d7d0812e0 100644 --- a/apps/cscsensor/cscsensor.app.js +++ b/apps/cscsensor/cscsensor.app.js @@ -52,13 +52,14 @@ class CSCSensor { } drawBatteryIcon() { + g.setColor(1, 1, 1).drawRect(10, 55, 20, 75).fillRect(14, 53, 16, 55).setColor(0).fillRect(11, 56, 19, 74); if (this.batteryLevel!=-1) { - g.setColor(1, 1, 1).drawRect(10, 55, 20, 75).fillRect(14, 53, 16, 55); if (this.batteryLevel<25) g.setColor(1, 0, 0); else if (this.batteryLevel<50) g.setColor(1, 0.5, 0); else g.setColor(0, 1, 0); g.fillRect(11, 74-18*this.batteryLevel/100, 19, 74); } + else g.setFontVector(14).setFontAlign(0, 0, 0).setColor(0xffff).drawString("?", 16, 66); } updateScreen() { @@ -80,7 +81,8 @@ class CSCSensor { if ((i&1)==1) g.setColor(0); else g.setColor(0x30cd); g.fillRect(87, 48+i*32, 239, 48+(i+1)*32); - g.setColor(0.5, 0.5, 0.5).drawRect(87, 48+i*32, 239, 48+(i+1)*32).drawLine(0, 239, 239, 239).drawRect(0, 48, 87, 239); + g.setColor(0.5, 0.5, 0.5).drawRect(87, 48+i*32, 239, 48+(i+1)*32).drawLine(0, 239, 239, 239);//.drawRect(0, 48, 87, 239); + g.moveTo(0, 80).lineTo(30, 80).lineTo(30, 48).lineTo(87, 48).lineTo(87, 239).lineTo(0, 239).lineTo(0, 80); } g.setFontAlign(1, 0, 0).setFontVector(19).setColor(1, 1, 0); g.drawString("Time:", 87, 66); From a0b2aa30d217ecbcda4ef4012ca9d9ad5a3f9395 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 22 Sep 2020 09:07:27 +0100 Subject: [PATCH 003/110] Adjust position of notification src text and notifications without title --- apps.json | 4 ++-- apps/notify/ChangeLog | 3 ++- apps/notify/notify.js | 4 ++-- apps/notifyfs/ChangeLog | 1 + apps/notifyfs/notify.js | 8 ++++---- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/apps.json b/apps.json index 726b9d14b..6a9a73d30 100644 --- a/apps.json +++ b/apps.json @@ -80,7 +80,7 @@ "name": "Notifications (default)", "shortName":"Notifications", "icon": "notify.png", - "version":"0.03", + "version":"0.05", "description": "A handler for displaying notifications that displays them in a bar at the top of the screen", "tags": "widget", "type": "notify", @@ -93,7 +93,7 @@ "name": "Fullscreen Notifications", "shortName":"Notifications", "icon": "notify.png", - "version":"0.05", + "version":"0.06", "description": "A handler for displaying notifications that displays them fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notifications library.", "tags": "widget", "type": "notify", diff --git a/apps/notify/ChangeLog b/apps/notify/ChangeLog index cb974e12d..558d62b31 100644 --- a/apps/notify/ChangeLog +++ b/apps/notify/ChangeLog @@ -1,3 +1,4 @@ 0.01: New Library! 0.02: Add notification ID option -0.03: Pass `area{x,y,w,h}` to render callback instead of just `y` \ No newline at end of file +0.03: Pass `area{x,y,w,h}` to render callback instead of just `y` +0.04: Adjust position of notification src text diff --git a/apps/notify/notify.js b/apps/notify/notify.js index d8168e048..6f5261de1 100644 --- a/apps/notify/notify.js +++ b/apps/notify/notify.js @@ -94,8 +94,8 @@ exports.show = function(options) { g.setColor(-1).setFontAlign(-1, -1, 0).setFont("6x8", 2); g.drawString(title.trim().substring(0, 13), x+25,y+3); if (options.title && options.src) { - g.setFont("6x8", 1); - g.drawString(options.src.substring(0, 10), x+215,y+5); + g.setFont("6x8", 1).setFontAlign(1, 1, 0); + g.drawString(options.src.substring(0, 10), g.getWidth()-23,y+18); } y += 20;h -= 20; } diff --git a/apps/notifyfs/ChangeLog b/apps/notifyfs/ChangeLog index b359d314b..16bc0ebb3 100644 --- a/apps/notifyfs/ChangeLog +++ b/apps/notifyfs/ChangeLog @@ -3,3 +3,4 @@ 0.03: Fix custom render callback 0.04: Pass `area{x,y,w,h}` to render callback instead of just `y` 0.05: Fix `g` corruption issue if .hide gets called twice +0.06: Adjust position of notification src text and notifications without title diff --git a/apps/notifyfs/notify.js b/apps/notifyfs/notify.js index 74a8d4912..2c622f624 100644 --- a/apps/notifyfs/notify.js +++ b/apps/notifyfs/notify.js @@ -49,14 +49,13 @@ exports.show = function(options) { if (size>120) {size=120} Bangle.setLCDMode("direct"); let x = 0, - y = 0, + y = 40, w = 240, - h = 240; + h = size; // clear screen g.clear(1); // top bar if (options.title||options.src) { - y=40;h=size; const title = options.title || options.src g.setColor(0x39C7).fillRect(x, y, x+w-1, y+30); g.setColor(-1).setFontAlign(-1, -1, 0).setFont("6x8", 3); @@ -64,7 +63,8 @@ exports.show = function(options) { if (options.title && options.src) { g.setColor(-1).setFontAlign(1, 1, 0).setFont("6x8", 2); // above drawing area, but we are fullscreen - g.drawString(options.src.substring(0, 10), x+235, y-32); + print(options.src.substring(0, 10), w-23, y-4); + g.drawString(options.src.substring(0, 10), w-16, y-4); } y += 30;h -= 30; } From 8623bc7f968fdd671cd94e16ccffdfcc9c0e355b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 22 Sep 2020 09:07:53 +0100 Subject: [PATCH 004/110] more GPS config --- testing/GPS-comms.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/testing/GPS-comms.js b/testing/GPS-comms.js index b9c2c645c..38d4c9dde 100644 --- a/testing/GPS-comms.js +++ b/testing/GPS-comms.js @@ -1,13 +1,13 @@ Bangle.setGPSPower(1) //Bangle.on('GPS',print); -/*Bangle.on('GPS-raw',function (d) { +Bangle.on('GPS-raw',function (d) { if (d[0]=="$") return; if (d.startsWith("\xB5\x62\x05\x01")) print("GPS ACK"); else if (d.startsWith("\xB5\x62\x05\x00")) print("GPS NACK"); // 181,98 sync chars else print("GPS",E.toUint8Array(d).join(",")); -});*/ +}); function writeGPScmd(cmd) { var d = [0xB5,0x62]; // sync chars d = d.concat(cmd); @@ -91,9 +91,9 @@ function getUBX_CFG_GNSS() { for (var i=4;i Date: Tue, 22 Sep 2020 15:33:55 +0100 Subject: [PATCH 005/110] tweak for making firmware --- bin/firmwaremaker.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bin/firmwaremaker.js b/bin/firmwaremaker.js index ce885c394..4e22dd168 100755 --- a/bin/firmwaremaker.js +++ b/bin/firmwaremaker.js @@ -19,6 +19,13 @@ var APPS = [ // IDs of apps to install var MINIFY = true; var fs = require("fs"); +global.Const = { + /* Are we only putting a single app on a device? If so + apps should all be saved as .bootcde and we write info + about the current app into app.info */ + SINGLE_APP_ONLY : false, +}; + var AppInfo = require(ROOTDIR+"/core/js/appinfo.js"); var appjson = JSON.parse(fs.readFileSync(APPJSON).toString()); var appfiles = []; From cdf5748fa641d88738ec110d50c8d60dc7fb7c1f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Sep 2020 08:44:42 +0100 Subject: [PATCH 006/110] tweak based on sanity check --- apps/notify/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notify/ChangeLog b/apps/notify/ChangeLog index 558d62b31..a1e8e4418 100644 --- a/apps/notify/ChangeLog +++ b/apps/notify/ChangeLog @@ -1,4 +1,4 @@ 0.01: New Library! 0.02: Add notification ID option 0.03: Pass `area{x,y,w,h}` to render callback instead of just `y` -0.04: Adjust position of notification src text +0.05: Adjust position of notification src text From 23cb4ea18ed9deab5c502fe7fdbe9b1a02646fbc Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Sep 2020 08:44:58 +0100 Subject: [PATCH 007/110] Added vibrate clock --- apps.json | 13 ++++ apps/vibrclock/ChangeLog | 1 + apps/vibrclock/app-icon.js | 1 + apps/vibrclock/app.js | 125 +++++++++++++++++++++++++++++++++++++ apps/vibrclock/app.png | Bin 0 -> 2850 bytes 5 files changed, 140 insertions(+) create mode 100644 apps/vibrclock/ChangeLog create mode 100644 apps/vibrclock/app-icon.js create mode 100644 apps/vibrclock/app.js create mode 100644 apps/vibrclock/app.png diff --git a/apps.json b/apps.json index 104609ae6..7f97b6f84 100644 --- a/apps.json +++ b/apps.json @@ -692,6 +692,19 @@ {"name":"sclock.img","url":"clock-simple-icon.js","evaluate":true} ] }, + { "id": "vibrclock", + "name": "Vibrate Clock", + "icon": "app.png", + "version":"0.01", + "description": "When BTN1 is pressed, vibrate out the time as a series of buzzes, one digit at a time. Hours, then Minutes. Zero is signified by one long buzz. Otherwise a simple digital clock.", + "tags": "clock", + "type":"clock", + "allow_emulator":true, + "storage": [ + {"name":"vibrclock.app.js","url":"app.js"}, + {"name":"vibrclock.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "svclock", "name": "Simple V-Clock", "icon": "vclock-simple.png", diff --git a/apps/vibrclock/ChangeLog b/apps/vibrclock/ChangeLog new file mode 100644 index 000000000..b4d1ae593 --- /dev/null +++ b/apps/vibrclock/ChangeLog @@ -0,0 +1 @@ +0.01: First commit diff --git a/apps/vibrclock/app-icon.js b/apps/vibrclock/app-icon.js new file mode 100644 index 000000000..c41aa0f9c --- /dev/null +++ b/apps/vibrclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATlgAGFlgylEQUyq1WwOB1msAYIHBmQxeDwQrB1nXABA0BqwxaP4eBFhIAFwIwYLgYtPAAZiWCgMrLhS7BMRUrGCQuN1gvBYxQwCF6S6LF5rEDFyC7MF5zDDF50rD5gvP1iRORpovRSJ6NNF6SRCLzQvSMBksmQdOF6OsmQvLRxwvSSBZqBF5+BmUyUJwvCGBC+QwMrCQMrCZ4vZxErLoJhBGAOsAAgvTwR6OH4QfBmTEBAAYwGwQv7R5uCR8DbOrrvSOoIuHF4VWDZ2CQwOICR3XFxAwCF54ATF5cyUo4vmYB4AM63P53O5/Q6wvKSDfW52j44AC0YFBMEnPFgYAGGBcrYKvWFAnP64wPMAKRV5wuE63W6HIMB6RU6y7E5HO6BfF0aRMGCS9D54EBF4I3BTIhgMGCSOCXYIwBSAICC6ySCF5QwCYYL0PF4fW53OAYjzDF5ZiTR4g0BR4OiR4LxDF5piEwJjLW4QACLgLvBFobvMGJEyqwzBwOCwQ3E6wvFXYLtEF6QxEAAtWBoYmEeYReERx4yNBYowFAAouWABouuAATDE0a7TAH4ASA")) diff --git a/apps/vibrclock/app.js b/apps/vibrclock/app.js new file mode 100644 index 000000000..817a69815 --- /dev/null +++ b/apps/vibrclock/app.js @@ -0,0 +1,125 @@ +/* jshint esversion: 6 */ +const timeFontSize = 6; +const dateFontSize = 3; +const gmtFontSize = 2; +const font = "6x8"; + +const xyCenter = g.getWidth() / 2; +const yposTime = 75; +const yposDate = 130; +const yposYear = 175; + +// Check settings for what type our clock should be +var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; +var d, da, time, hours, minutes, meridian = ""; + +function drawSimpleClock() { + // get date + var d = new Date(); + var da = d.toString().split(" "); + + g.reset(); // default draw styles + // drawSting centered + g.setFontAlign(0, 0); + + // draw time + var time = da[4].substr(0, 5).split(":"); + var hours = time[0], + minutes = time[1]; + var meridian = ""; + if (is12Hour) { + hours = parseInt(hours,10); + meridian = "AM"; + if (hours == 0) { + hours = 12; + meridian = "AM"; + } else if (hours >= 12) { + meridian = "PM"; + if (hours>12) hours -= 12; + } + hours = (" "+hours).substr(-2); + } + + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, true); + g.setFont(font, gmtFontSize); + g.drawString(meridian, xyCenter + 102, yposTime + 10, true); + + // draw Day, name of month, Date + var date = [da[0], da[1], da[2]].join(" "); + g.setFont(font, dateFontSize); + + g.drawString(date, xyCenter, yposDate, true); + + // draw year + g.setFont(font, dateFontSize); + g.drawString(d.getFullYear(), xyCenter, yposYear, true); + + // draw gmt + var gmt = da[5]; + g.setFont(font, gmtFontSize); + g.drawString(gmt, xyCenter, yposGMT, true); +} + +// handle switch display on by pressing BTN1 +Bangle.on('lcdPower', function(on) { + if (on) drawSimpleClock(); +}); + +// clean app screen +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// refesh every 15 sec +setInterval(drawSimpleClock, 15E3); + +// draw now +drawSimpleClock(); + +// vibrate 0..9 +function vibrateDigit(num) { + if (num==0) return Bangle.buzz(500); + return new Promise(function f(resolve){ + if (num--<=0) return resolve(); + Bangle.buzz(100).then(()=>{ + setTimeout(()=>f(resolve), 200); + }); + }); +} +// vibrate multiple digits (num must be a string) +function vibrateNumber(num) { + return new Promise(function f(resolve){ + if (!num.length) return resolve(); + var digit = num[0]; + num = num.substr(1); + vibrateDigit(digit).then(()=>{ + setTimeout(()=>f(resolve),500); + }); + }); +} + +var vibrateBusy; +function vibrateTime() { + if (vibrateBusy) return; + vibrateBusy = true; + + var d = new Date(); + var hours = d.getHours(), minutes = d.getMinutes(); + if (is12Hour) { + if (hours == 0) hours = 12; + else if (hours>12) hours -= 12; + } + + vibrateNumber(hours.toString()). + then(() => new Promise(resolve=>setTimeout(resolve,500))). + then(() => vibrateNumber(minutes.toString())). + then(() => vibrateBusy=false); +} + + + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +// when BTN1 pressed, vibrate +setWatch(vibrateTime, BTN1, {repeat:true,edge:"rising"}); diff --git a/apps/vibrclock/app.png b/apps/vibrclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..79ff0b9922dd1c5310ea7d737df3079bb231f27d GIT binary patch literal 2850 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 Date: Wed, 23 Sep 2020 08:51:24 +0100 Subject: [PATCH 008/110] fix regression where apps weren't scanned for modules --- apps/vibrclock/app.js | 114 ++++++++++++++++-------------------------- core | 2 +- 2 files changed, 44 insertions(+), 72 deletions(-) diff --git a/apps/vibrclock/app.js b/apps/vibrclock/app.js index 817a69815..188470cdc 100644 --- a/apps/vibrclock/app.js +++ b/apps/vibrclock/app.js @@ -1,82 +1,58 @@ -/* jshint esversion: 6 */ -const timeFontSize = 6; -const dateFontSize = 3; -const gmtFontSize = 2; -const font = "6x8"; - -const xyCenter = g.getWidth() / 2; -const yposTime = 75; -const yposDate = 130; -const yposYear = 175; - +// Simple clock from https://www.espruino.com/Bangle.js+Clock +// Load fonts +require("Font7x11Numeric7Seg").add(Graphics); // Check settings for what type our clock should be var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]; -var d, da, time, hours, minutes, meridian = ""; +// position on screen +const X = 160, Y = 140; -function drawSimpleClock() { - // get date +function draw() { + // work out how to display the current time var d = new Date(); - var da = d.toString().split(" "); - - g.reset(); // default draw styles - // drawSting centered - g.setFontAlign(0, 0); - - // draw time - var time = da[4].substr(0, 5).split(":"); - var hours = time[0], - minutes = time[1]; - var meridian = ""; + var h = d.getHours(), m = d.getMinutes(); if (is12Hour) { - hours = parseInt(hours,10); - meridian = "AM"; - if (hours == 0) { - hours = 12; - meridian = "AM"; - } else if (hours >= 12) { - meridian = "PM"; - if (hours>12) hours -= 12; - } - hours = (" "+hours).substr(-2); + if (h == 0) h = 12; + else if (h>12) h -= 12; } - - g.setFont(font, timeFontSize); - g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, true); - g.setFont(font, gmtFontSize); - g.drawString(meridian, xyCenter + 102, yposTime + 10, true); - - // draw Day, name of month, Date - var date = [da[0], da[1], da[2]].join(" "); - g.setFont(font, dateFontSize); - - g.drawString(date, xyCenter, yposDate, true); - - // draw year - g.setFont(font, dateFontSize); - g.drawString(d.getFullYear(), xyCenter, yposYear, true); - - // draw gmt - var gmt = da[5]; - g.setFont(font, gmtFontSize); - g.drawString(gmt, xyCenter, yposGMT, true); + var time = (" "+h).substr(-2) + ":" + ("0"+m).substr(-2); + // Reset the state of the graphics library + g.reset(); + // draw the current time (4x size 7 segment) + g.setFont("7x11Numeric7Seg",4); + g.setFontAlign(1,1); // align right bottom + g.drawString(time, X, Y, true /*clear background*/); + // draw the seconds (2x size 7 segment) + g.setFont("7x11Numeric7Seg",2); + g.drawString(("0"+d.getSeconds()).substr(-2), X+30, Y, true /*clear background*/); + // draw the date, in a normal font + g.setFont("6x8"); + g.setFontAlign(0,1); // align center bottom + // pad the date - this clears the background if the date were to change length + var dateStr = " "+require("locale").date(d)+" "; + g.drawString(dateStr, g.getWidth()/2, Y+15, true /*clear background*/); } -// handle switch display on by pressing BTN1 -Bangle.on('lcdPower', function(on) { - if (on) drawSimpleClock(); -}); - -// clean app screen +// Clear the screen once, at startup g.clear(); +// draw immediately at first +draw(); +var secondInterval = setInterval(draw, 1000); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw, 1000); + draw(); // draw immediately + } +}); +// Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); -// refesh every 15 sec -setInterval(drawSimpleClock, 15E3); - -// draw now -drawSimpleClock(); - +// ====================================== Vibration // vibrate 0..9 function vibrateDigit(num) { if (num==0) return Bangle.buzz(500); @@ -117,9 +93,5 @@ function vibrateTime() { then(() => vibrateBusy=false); } - - -// Show launcher when middle button pressed -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); // when BTN1 pressed, vibrate setWatch(vibrateTime, BTN1, {repeat:true,edge:"rising"}); diff --git a/core b/core index 9708e1a15..c99967381 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 9708e1a15ee20734a24f6f2913078aa8bba625dc +Subproject commit c99967381280f483877c3f11ae7b0d4dc8c53e0e From 063929f75094dc77ca12810cefe43b757f9d68c7 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Sep 2020 11:18:20 +0100 Subject: [PATCH 009/110] Handle 'RAM' as filename to allow direct uploads Add ability to upload assisted GPS data --- README.md | 3 +- apps.json | 11 ++++ apps/assistedgps/ChangeLog | 1 + apps/assistedgps/app.png | Bin 0 -> 1549 bytes apps/assistedgps/custom.html | 113 +++++++++++++++++++++++++++++++++++ core | 2 +- testing/GPS-comms.js | 4 +- 7 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 apps/assistedgps/ChangeLog create mode 100644 apps/assistedgps/app.png create mode 100644 apps/assistedgps/custom.html diff --git a/README.md b/README.md index 22a12bd5b..326599d14 100644 --- a/README.md +++ b/README.md @@ -241,7 +241,8 @@ and which gives information about the app for the Launcher. // add an icon to allow your app to be tested "storage": [ // list of files to add to storage - {"name":"appid.js", // filename to use in storage + {"name":"appid.js", // filename to use in storage. + // If name=='RAM', the code is sent directly to Bangle.js and is not saved to a file "url":"", // URL of file to load (currently relative to apps/) "content":"..." // if supplied, this content is loaded directly "evaluate":true // if supplied, data isn't quoted into a String before upload diff --git a/apps.json b/apps.json index 7f97b6f84..284116c5e 100644 --- a/apps.json +++ b/apps.json @@ -895,6 +895,17 @@ {"name":"gpsinfo.img","url": "gps-info-icon.js","evaluate": true} ] }, + { "id": "assistedgps", + "name": "Assisted GPS Update", + "icon": "app.png", + "version":"0.01", + "description": "Downloads assisted GPS data to Bangle.js for faster GPS startup and more accurate fixes", + "custom": "custom.html", + "tags": "tool,outdoors", + "readme": "README.md", + "storage": [ + ] + }, { "id": "pomodo", "name":"Pomodoro", diff --git a/apps/assistedgps/ChangeLog b/apps/assistedgps/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/assistedgps/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/assistedgps/app.png b/apps/assistedgps/app.png new file mode 100644 index 0000000000000000000000000000000000000000..970e851397d87a1e47af18285c6fbc7cc256d634 GIT binary patch literal 1549 zcmV+o2J-odP)CE&t({iyuEG@K=f~Lq#3qgS_q|Fdp|SnnX{J< zy;wT8a|S3p^n04wd#$zqHEZp2_H1B?A%+;@L9t->l9c?ti`Ry;5rZYhDhqZmNwF!$ zA!ge2Vp-wpP z3T6MuwUCsev`73Y8`HdS;(o}y%(xC)GHX5j>oZ^hqq0;>*bGkjj`Bp?ysMlc-&lr5!;V$NGu-9uqn zp}PzG69L%(YJ`w0t;R6bLWiq)*l#yFcU^9k&kdMjCX_RYbz2uYs;w+sSXSuPfl30V zqFel2tL+1r+{AvnvC*MYT#zXuMuCv>%!&$a<6DQ>VRm61c)dq_wJyb+Xv70168NQ- zQ^EYk2p4(7nAsUvXVbKkD=ONv%`99|w0AR@-qod;d+?<_*GwxOK*ScRs?*moW20a4 zrQOy3aVBDRf@xLhBIj2CfH~V7aWS-kK(7E`5bbR98SmrQ<-TY|_a|Znm@yjwR6*lL z#f!g9#Eb!PY4LvVmnA3I)+2rmfX4u&fO&0vjQHptb@vf@4=~btKTb~(y4k=ijgqcQ z|5gczSA)zhGaDxoVIQN+OjULMvAy486v|HbC?{*1j41%Xx)0LZ1nF&tp*2BjO<->` z46PaLYXP&IZMS90PJLjfk})U=5D{0_>bCx46XQEZojI^W8XdO;`#VEB3kAaI!RX;q z)HWys0%LphlJCaMi>w8}u--4O*!YypjEuT-C$6TE%>m)`Ksen{TpkFQ2jp}^ak)W` zL=Xu)?Kgn(eYo1FbC)h|FyuFF)cV2wN+9A>sIpeC0g%yujG1w~!FQsrRh?>Pk@i2o zhQFyE&aAw%zNDE`zF$gRQR)pK@+Kzy6);4EX``JJlALtW%p%g;3;<9QModbK)3#U@ z84fc~p<}^@35d;2RUI)3!XJ610omEs?c+!SnBFY@QCky*)}WZE03QiCMHrJePQ9iG zbcC{zz7~KbNVP-6xOyD%@!RFvvr*^`AYuZ!V{Lx`xDaaIuF#}{@wOU8P|!DPZ~F+R zyZ^8%1ioFipA)Rf4J2X$M8sfh4QFFlFnM9Raz+pWo~u&pO~5m7D$OB%pIFcu6jP^B zB6S;p_HZ__HkzKFp`No5+WL?8RlwyA@FC)NN-DG&rqu?)R06r_be(|>k?b4_P0r7> zU2&>(vv=(O77C~U00@I|PgOAer`|^DCV*-q+6iRkXQ=uxSNFj$LINPdtb5terW2T( zMm{O!QUF>cTLMPSOI6Y)B#R@4)&u}hg0xVdz2FkFItF6tT4lj_`^mG7#^+#D=B}qk zD6=MI&!~rDXL2TnG$f+=R&?CuYt}V_6!W>5Xlju$wo;^~TS(K@semq_|4g}Qj zax~%rixnuY(2liwjb~2Px5KAPIBWt-v*VGIYKKjj4`ncF8r%6wL%Xya%-$QV{Nd(2 z*YB3q!$JbZ2RiZ~sR97H{EUCDX=rTjK2#>T6ugiXi|Jz=UGa9<&BkP)QiZYl`E+Yn zGW{{1K!tW3-Pa&}+-}!#vC)SXufH!?PMWJ``Lwt#f-#eco+NNG10Dc=fUgp$o(V@8 z{N4OC`>AM!N0UIv9&OV6xN^G_H(Pb6f^gxzlz_PFnZ + + + + + +

Assisted GPS

+

GPS can take a long time (~5 minutes) to get an accurate position the first time it is used. + AGPS uploads a few hints to the GPS receiver about satellite positions that allow it + to get a faster, more accurate fix - however they are only valid for a short period of time.

+

You can upload data that covers a longer period of time, but the upload will take longer.

+
+ + + + + +
+

Click

+ + + + + + diff --git a/core b/core index c99967381..1b66c4ce1 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit c99967381280f483877c3f11ae7b0d4dc8c53e0e +Subproject commit 1b66c4ce1ba71036bcb612a2f16bbd7fbc2c66de diff --git a/testing/GPS-comms.js b/testing/GPS-comms.js index 38d4c9dde..ca0db16b6 100644 --- a/testing/GPS-comms.js +++ b/testing/GPS-comms.js @@ -16,7 +16,7 @@ function writeGPScmd(cmd) { a += d[i]; b += a; } - d.push(a,b); + d.push(a&255,b&255); Serial1.write(d); } function readGPScmd(cmd, callback) { @@ -131,7 +131,7 @@ function setUBX_MGA_INI_TIME_UTC() { dv.setUint8(9, d.getMinutes()); dv.setUint8(10, d.getSeconds()); dv.setUint16(16, 10*60); // seconds part of accuracy - 10 minutes - writeGPScmd(a.slice()); + writeGPScmd([].slice.call(a)); } setUBX_MGA_INI_TIME_UTC(); From 2e45174d4a87d9cb47e6c47d7e28f96394c01b05 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 23 Sep 2020 11:38:02 +0100 Subject: [PATCH 010/110] Fix sanity check - handle 'to RAM' uploads better, allowing the app loader to upload stuff that doesn't actually ever stay in storage --- README.md | 7 ++++++- apps.json | 5 ++--- core | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 326599d14..240163f6c 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,12 @@ and which gives information about the app for the Launcher. "shortName": "Short name", // short name for launcher "icon": "icon.png", // icon in apps/ "description": "...", // long description (can contain markdown) - "type":"...", // optional(if app) - 'app'/'widget'/'launch'/'bootloader' + "type":"...", // optional(if app) - + // 'app' - an application + // 'widget' - a widget + // 'launch' - replacement launcher app + // 'bootloader' - code that runs at startup only + // 'RAM' - code that runs and doesn't upload anything to storage "tags": "", // comma separated tag list for searching "dependencies" : { "notify":"type" } // optional, app 'types' we depend on // for instance this will use notify/notifyfs is they exist, or will pull in 'notify' diff --git a/apps.json b/apps.json index 284116c5e..50f76f875 100644 --- a/apps.json +++ b/apps.json @@ -902,9 +902,8 @@ "description": "Downloads assisted GPS data to Bangle.js for faster GPS startup and more accurate fixes", "custom": "custom.html", "tags": "tool,outdoors", - "readme": "README.md", - "storage": [ - ] + "type": "RAM", + "storage": [ ] }, { "id": "pomodo", diff --git a/core b/core index 1b66c4ce1..62615f6ea 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 1b66c4ce1ba71036bcb612a2f16bbd7fbc2c66de +Subproject commit 62615f6ea4855381e0b4b4b74f8ca69aa594181e From d2dd0db6c3e71ebf47f0e96d64ab827426e648a9 Mon Sep 17 00:00:00 2001 From: marko Date: Wed, 23 Sep 2020 11:31:31 -0400 Subject: [PATCH 011/110] Reduce screen flicker, more robust average&max speed --- apps/cscsensor/cscsensor.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/cscsensor/cscsensor.app.js b/apps/cscsensor/cscsensor.app.js index d7d0812e0..5be9e1591 100644 --- a/apps/cscsensor/cscsensor.app.js +++ b/apps/cscsensor/cscsensor.app.js @@ -71,7 +71,7 @@ class CSCSensor { if (dmins.length<2) dmins = "0"+dmins; var dsecs = (Math.floor(this.movingTime) % 60).toString(); if (dsecs.length<2) dsecs = "0"+dsecs; - var avespeed = (this.movingTime>2 ? Math.round(10*dist/(this.movingTime/3600))/10 : 0); + var avespeed = (this.movingTime>3 ? Math.round(10*dist/(this.movingTime/3600))/10 : 0); var maxspeed = Math.round(10*this.distFactor*this.maxSpeed)/10; if (this.screenInit) { for (var i=0; i<6; ++i) { @@ -146,7 +146,7 @@ class CSCSensor { } } this.lastSpeed = this.speed; - if (this.speed > this.maxSpeed) this.maxSpeed = this.speed; + if (this.speed>this.maxSpeed && (this.movingTime>3 || this.speed<20)) this.maxSpeed = this.speed; } if (qChanged && this.qUpdateScreen) this.updateScreen(); } From bced6ac420d9c6777bc631fc07cc0e298d85afa9 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 12:51:49 -0400 Subject: [PATCH 012/110] Create myclockapp.js --- apps/myclockapp/myclockapp.js | 154 ++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 apps/myclockapp/myclockapp.js diff --git a/apps/myclockapp/myclockapp.js b/apps/myclockapp/myclockapp.js new file mode 100644 index 000000000..7f74f2242 --- /dev/null +++ b/apps/myclockapp/myclockapp.js @@ -0,0 +1,154 @@ +//load fonts +require("Font7x11Numeric7Seg").add(Graphics); +require("FontHaxorNarrow7x17").add(Graphics); +//screen position +const X = 170; +const Y = 140; + +function draw() { + // Date Variables + var date = new Date(); + var h = date.getHours(); + var m = date.getMinutes(); + var day = date.getDay(); + var month = date.getMonth(); + var dateNum = date.getDate(); + var year = date.getFullYear(); + var half = "AM"; + var time = (" " + h).substr(-2) + ":" + ("0" + m).substr(-2); + + //convert day into string + switch (day) { + case 0: + day = "Sunday"; + break; + + case 1: + day = "Monday"; + break; + + case 2: + day = "Tuesday"; + break; + + case 3: + day = "Wednesday"; + break; + + case 4: + day = "Thursday"; + break; + + case 5: + day = "Friday"; + break; + + case 6: + day = "Saturday"; + break; + + default: + day = "ERROR"; + break; + } + + //convert month into String + switch(month) { + case 0: + month = "Jan"; + break; + + case 1: + month = "Feb"; + break; + + case 2: + month = "Mar"; + break; + + case 3: + month = "Apr"; + break; + + case 4: + month = "May"; + break; + + case 5: + month = "Jun"; + break; + + case 6: + month = "Jul"; + break; + + case 7: + month = "Aug"; + break; + + case 8: + month = "Sep"; + break; + + case 9: + month = "Oct"; + break; + + case 10: + month = "Nov"; + break; + + case 11: + month = "Dec"; + break; + + default: + month = "ERROR"; + break; + + } + + if (h > 12) { + half = "PM"; + h = h - 12; + } + //reset graphics + g.reset(); + //draw the time + g.setFont("7x11Numeric7Seg", 5); + g.setFontAlign(1,1); + g.drawString(time, X, Y, true /*clear background*/); + g.setFont("7x11Numeric7Seg", 3); + g.drawString(("0"+date.getSeconds()).substr(-2), X+50, Y, true /*clear background*/); + g.setFontAlign(0,1); + g.setFont("HaxorNarrow7x17", 2); + g.drawString(half, X+30, Y-35, true); + g.setFont("HaxorNarrow7x17", 3); + g.drawString(day, X-60, Y+53, true); + g.drawString(month, X-100, Y+95, true); + g.drawString(dateNum, X-40, Y+95, true); + g.drawString(year, X-90, Y-55, true); + + +} + +//clear screen at startup +g.clear(); +//draw immediatly +draw(); + +var secondInterval = setInterval(draw, 1000); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw, 1000); + draw(); // draw immediately + } +}); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +setWatch(Bangle.showLauncher, BTN2, {repeat : false, edge: "falling"}); From da96d3d5127a7cbac6942d4733347809e35bfde8 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:06:06 -0400 Subject: [PATCH 013/110] Added icon JS file --- apps/myclockapp/app.js | Bin 0 -> 1265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/myclockapp/app.js diff --git a/apps/myclockapp/app.js b/apps/myclockapp/app.js new file mode 100644 index 0000000000000000000000000000000000000000..e70978c3704b6805da64058335ca2f8fb2dc7546 GIT binary patch literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ literal 0 HcmV?d00001 From 5e503ac9f3a870cc8d052adff31a6cc81a49b556 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:09:10 -0400 Subject: [PATCH 014/110] Create app-icon.js --- apps/myclockapp/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/myclockapp/app-icon.js diff --git a/apps/myclockapp/app-icon.js b/apps/myclockapp/app-icon.js new file mode 100644 index 000000000..737561863 --- /dev/null +++ b/apps/myclockapp/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("/wA/AH4A/AH4A/ACmsAEQuMlcAAD0rGBQKBFr4ADGBOsqwvjqwvJRsCRFF/8Gg4ADEZYQEgwvWg8+AAgwKCJgvQDgoABF5IRMF5xEBJpBhGCJwvNDQM4AYMNAAQaBnCAFCJ4vNIwQeBAAkxQAwGCmIRFFwIRDF64dDgwGBgwRNF/4v/F/4v/F/4v/F/4dJmIdECIkxF7MHFwUHhoACg4eCAYIACCJ4vNDQIgCAAgICKwoROF5yAEAAgtFCKAvQJpAAICJgvQgEGg4ADFxIwCAAcGBYovRADov6qwvjqwvJ1gvjEoIvHGASRgRoIuJGAYAhFxQA/AH4A/AH4A/ABQ")) From 636e0ff2f451ce56f27ecad320a998b409ff983e Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:12:22 -0400 Subject: [PATCH 015/110] Add files via upload --- apps/myclockapp/app.png | Bin 0 -> 1265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/myclockapp/app.png diff --git a/apps/myclockapp/app.png b/apps/myclockapp/app.png new file mode 100644 index 0000000000000000000000000000000000000000..e70978c3704b6805da64058335ca2f8fb2dc7546 GIT binary patch literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ literal 0 HcmV?d00001 From 44eb212d3e5a6948b3f19572356021b88652bcd8 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:13:11 -0400 Subject: [PATCH 016/110] Delete app.js --- apps/myclockapp/app.js | Bin 1265 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/myclockapp/app.js diff --git a/apps/myclockapp/app.js b/apps/myclockapp/app.js deleted file mode 100644 index e70978c3704b6805da64058335ca2f8fb2dc7546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ From 0397846c9af8f8f35dce972d3a803a35cecc5d78 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:16:59 -0400 Subject: [PATCH 017/110] Rename myclockapp.js to digiclock.js --- apps/myclockapp/{myclockapp.js => digiclock.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/myclockapp/{myclockapp.js => digiclock.js} (100%) diff --git a/apps/myclockapp/myclockapp.js b/apps/myclockapp/digiclock.js similarity index 100% rename from apps/myclockapp/myclockapp.js rename to apps/myclockapp/digiclock.js From 6dabbe115aa258a9619de6fa42a816efa24670f4 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:17:51 -0400 Subject: [PATCH 018/110] Rename app-icon.js to digi-icon.js --- apps/myclockapp/{app-icon.js => digi-icon.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/myclockapp/{app-icon.js => digi-icon.js} (100%) diff --git a/apps/myclockapp/app-icon.js b/apps/myclockapp/digi-icon.js similarity index 100% rename from apps/myclockapp/app-icon.js rename to apps/myclockapp/digi-icon.js From a5e454e3ee6b269cc7900f14b36afcd75e3118d4 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:18:28 -0400 Subject: [PATCH 019/110] Delete app.png --- apps/myclockapp/app.png | Bin 1265 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/myclockapp/app.png diff --git a/apps/myclockapp/app.png b/apps/myclockapp/app.png deleted file mode 100644 index e70978c3704b6805da64058335ca2f8fb2dc7546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ From ee9b08bcfa0b9f278117bf263c69a762cc3859fd Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:18:47 -0400 Subject: [PATCH 020/110] Add files via upload --- apps/myclockapp/app.png | Bin 0 -> 1265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/myclockapp/app.png diff --git a/apps/myclockapp/app.png b/apps/myclockapp/app.png new file mode 100644 index 0000000000000000000000000000000000000000..e70978c3704b6805da64058335ca2f8fb2dc7546 GIT binary patch literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ literal 0 HcmV?d00001 From 2b1eb421da35865b17785a8a7af6150f5849f9e3 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:19:24 -0400 Subject: [PATCH 021/110] Added digiclock.png --- digiclock.png | Bin 0 -> 1265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 digiclock.png diff --git a/digiclock.png b/digiclock.png new file mode 100644 index 0000000000000000000000000000000000000000..e70978c3704b6805da64058335ca2f8fb2dc7546 GIT binary patch literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ literal 0 HcmV?d00001 From b570e8dfd7befacf435f86bc8faa2367be345cc1 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:23:32 -0400 Subject: [PATCH 022/110] Rename apps/myclockapp/digi-icon.js to apps/digiclock/digi-icon.js --- apps/{myclockapp => digiclock}/digi-icon.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/{myclockapp => digiclock}/digi-icon.js (100%) diff --git a/apps/myclockapp/digi-icon.js b/apps/digiclock/digi-icon.js similarity index 100% rename from apps/myclockapp/digi-icon.js rename to apps/digiclock/digi-icon.js From 222ea7ee2527c2623b0b7e04f6557dbfd7e02866 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:24:12 -0400 Subject: [PATCH 023/110] Rename apps/myclockapp/digiclock.js to apps/digiclock/digiclock.js --- apps/{myclockapp => digiclock}/digiclock.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/{myclockapp => digiclock}/digiclock.js (100%) diff --git a/apps/myclockapp/digiclock.js b/apps/digiclock/digiclock.js similarity index 100% rename from apps/myclockapp/digiclock.js rename to apps/digiclock/digiclock.js From 9fc5ee2ab588fa8644c2131f74992e016e3467cb Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:24:34 -0400 Subject: [PATCH 024/110] Delete app.png --- apps/myclockapp/app.png | Bin 1265 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/myclockapp/app.png diff --git a/apps/myclockapp/app.png b/apps/myclockapp/app.png deleted file mode 100644 index e70978c3704b6805da64058335ca2f8fb2dc7546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ From fd6245c5301a0874d9c5de886cd96dafb2d5379b Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:25:11 -0400 Subject: [PATCH 025/110] Added digiclock.png --- apps/digiclock/digiclock.png | Bin 0 -> 1265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/digiclock/digiclock.png diff --git a/apps/digiclock/digiclock.png b/apps/digiclock/digiclock.png new file mode 100644 index 0000000000000000000000000000000000000000..e70978c3704b6805da64058335ca2f8fb2dc7546 GIT binary patch literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ literal 0 HcmV?d00001 From 736ef026d90717ab315709ea2b549cf898a80c01 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 13:38:08 -0400 Subject: [PATCH 026/110] Update apps.json --- apps.json | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 50f76f875..c47097564 100644 --- a/apps.json +++ b/apps.json @@ -1,11 +1,11 @@ [ { "id": "boot", "name": "Bootloader", + "tags": "tool,system", + "type":"bootloader", "icon": "bootloader.png", "version":"0.21", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", - "tags": "tool,system", - "type":"bootloader", "storage": [ {"name":".boot0","url":"boot0.js"}, {"name":".bootcde","url":"bootloader.js"} @@ -2226,3 +2226,18 @@ ] } ] + +}, +{ "id": "digiclock", + "name": "Digital Clock", + "shortName":"Digi Clock", + "icon": "digiclock.png", + "version":"0.01", + "description": "A simple digital clock with the time, day, month, and year", + "tags": "", + "storage": [ + {"name":"digiclock.app.js","url":"digiclock.js"}, + {"name":"digiclock.img","url":"digi-icon.js","evaluate":true} + ] +} +] From 6cd5af484ee1b78b213165c2620b80c5a565a26c Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 15:55:03 -0400 Subject: [PATCH 027/110] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index c47097564..cf4b5794b 100644 --- a/apps.json +++ b/apps.json @@ -2234,10 +2234,10 @@ "icon": "digiclock.png", "version":"0.01", "description": "A simple digital clock with the time, day, month, and year", - "tags": "", + "tags": "clock", "storage": [ {"name":"digiclock.app.js","url":"digiclock.js"}, {"name":"digiclock.img","url":"digi-icon.js","evaluate":true} ] -} + } ] From 4e47e445e33459631f776a3aab59c8a89f300e82 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 16:11:40 -0400 Subject: [PATCH 028/110] Update apps.json --- apps.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index cf4b5794b..3bc058b16 100644 --- a/apps.json +++ b/apps.json @@ -2226,9 +2226,9 @@ ] } ] - }, -{ "id": "digiclock", + +{ "id": "digiclock" "name": "Digital Clock", "shortName":"Digi Clock", "icon": "digiclock.png", @@ -2238,6 +2238,5 @@ "storage": [ {"name":"digiclock.app.js","url":"digiclock.js"}, {"name":"digiclock.img","url":"digi-icon.js","evaluate":true} - ] - } -] + ], +}, From 1857bdc33d6875184efed561ee29b2f67acc11d0 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 16:12:59 -0400 Subject: [PATCH 029/110] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3bc058b16..d113242a7 100644 --- a/apps.json +++ b/apps.json @@ -2228,7 +2228,7 @@ ] }, -{ "id": "digiclock" +{ "id": "digiclock", "name": "Digital Clock", "shortName":"Digi Clock", "icon": "digiclock.png", From 89e7438e66d1c7ed207c50f96cbbabfe7ff8f721 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 16:14:29 -0400 Subject: [PATCH 030/110] Update apps.json --- apps.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps.json b/apps.json index d113242a7..6ee7dad98 100644 --- a/apps.json +++ b/apps.json @@ -2224,9 +2224,7 @@ {"name":"worldclock.settings.json"}, {"name":"worldclock.img","url":"worldclock-icon.js","evaluate":true} ] - } -] -}, + }, { "id": "digiclock", "name": "Digital Clock", From 00afedf8ad5794e5da8c9a89ad07e77cfb8ccb9e Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 16:19:53 -0400 Subject: [PATCH 031/110] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 6ee7dad98..4ca50583a 100644 --- a/apps.json +++ b/apps.json @@ -2236,5 +2236,5 @@ "storage": [ {"name":"digiclock.app.js","url":"digiclock.js"}, {"name":"digiclock.img","url":"digi-icon.js","evaluate":true} - ], + ] }, From 175d1b8d6bf64c564cefa129123177bbb81426c2 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 16:33:26 -0400 Subject: [PATCH 032/110] Delete digiclock.png --- digiclock.png | Bin 1265 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 digiclock.png diff --git a/digiclock.png b/digiclock.png deleted file mode 100644 index e70978c3704b6805da64058335ca2f8fb2dc7546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1265 zcmVWW4y%kWJZ(igv29c@#=ChfW!TbO0((j=F= z`}tyR%=L2lGcnnV`@p@(@Au@n@Ar7_c%D1J#Kgp;k}&x;=jZ27avayjFpQ&Ig0i8M z#(AFqt-ZZ{(&iyi;IhSjaGtvO;s$*p2%L;7?5RI1b}op zT|Q++B1sYeKv5KH_PV9iL{?7?L{E)2`Q`&8LR%%}u{~D{!CkFcONH+v8NOdqo{|jM z+v?DKtsk62(5%z6g7u3(AU3yJRGzArn$UE$4~(Eay_!fPGBktuFNTkO9c z*6mY8#m2}@s3{qa4!2<*M~53~O2)>>O;APE?W;){8^g0;?L2HPwM7{yX!W3M($N^g zgVR`jZwj_&k85I5YkwoLvW@1+v#>w^G}bTp5xX7H#2kIO8I5Co*jxGwk)auc2d5!6 zxim3}m2IS>F?g=O3BK+qBIj;k?@sjb4KOT|sd?_yF`T^gD%Q?_hs3h}hIN1ZO6KY} zj`bmQ=1a&siAN`K+R!-G2S(uF=y0QMs1uu?{gkuTo5tUO_0%x{K=ZYJEcbi?s!~IZ z`AdjlG&Rp15e-AL_ZWc#lU2uzXaOT|CFkKB0>I>N#frX(pHxf(mButsX-or^#xziA z@*AKON?gkPR34@bL$mj&q=2UWZTe_R29=bO^C)o%pvG+kP@os0Dn;bnjZ8Cl@A56! zT55APbJ58;SUokFX6~R50swg@f%OaiOfwgqoP*;9cg|++-sM~HT(8bFbNTw9f(8I! z?@koq!D*zUF<3n{Xqr3=)~fv*RaD&lWEPR38Q7jVj`)JUNsHZ%ApHI}Nc_Hysu!Ek zaHSUvr!4?ADPwKFQ|0T9=4=`dQ`9|>Sl)uVmqz_)uTDGwFdU2ek<(yBOHT0z#1}Tf ziWbz5oYsj40M=?j{b(=Ly>wCHi#7lNYD&i1hu=bpC3Sl=t>EtPkD9VELf%PW{o?na zl728!;u6+B@ From 9f2906c81424f59717ce45ff50fd4b4589605a54 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 16:40:08 -0400 Subject: [PATCH 033/110] Rename digi-icon.js to digiclock-icon.js --- apps/digiclock/{digi-icon.js => digiclock-icon.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/digiclock/{digi-icon.js => digiclock-icon.js} (100%) diff --git a/apps/digiclock/digi-icon.js b/apps/digiclock/digiclock-icon.js similarity index 100% rename from apps/digiclock/digi-icon.js rename to apps/digiclock/digiclock-icon.js From 876368eefa63c0a8cff1644928f4b6ad48d853b7 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Thu, 24 Sep 2020 16:41:19 -0400 Subject: [PATCH 034/110] Update apps.json --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4ca50583a..4d814d99d 100644 --- a/apps.json +++ b/apps.json @@ -2227,14 +2227,15 @@ }, { "id": "digiclock", - "name": "Digital Clock", + "name": "Digital Clock Face", "shortName":"Digi Clock", "icon": "digiclock.png", "version":"0.01", "description": "A simple digital clock with the time, day, month, and year", "tags": "clock", + "type" : "clock", "storage": [ {"name":"digiclock.app.js","url":"digiclock.js"}, - {"name":"digiclock.img","url":"digi-icon.js","evaluate":true} + {"name":"digiclock.img","url":"digiclock-icon.js","evaluate":true} ] }, From 9f7461f4348b52d31b6d575f8ab6acfda375a528 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 25 Sep 2020 11:50:26 +0100 Subject: [PATCH 035/110] findphone Remove HID requirement, update screen (fix #565) --- apps.json | 4 +-- apps/findphone/ChangeLog | 3 ++- apps/findphone/README.md | 9 +++---- apps/findphone/app.js | 57 ++++++++++++++++++++-------------------- 4 files changed, 37 insertions(+), 36 deletions(-) diff --git a/apps.json b/apps.json index 50f76f875..c8f0a58c7 100644 --- a/apps.json +++ b/apps.json @@ -1768,8 +1768,8 @@ "name": "Find Phone", "shortName":"Find Phone", "icon": "app.png", - "version":"0.01", - "description": "Find your phone via Gadgetbridge. Click any button to let your phone ring. 📳", + "version":"0.02", + "description": "Find your phone via Gadgetbridge. Click any button to let your phone ring. 📳 Note: The functionality is available even without this app, just go to Settings, App Settings, Gadgetbridge, Find Phone.", "tags": "tool,android", "readme": "README.md", "allow_emulator": true, diff --git a/apps/findphone/ChangeLog b/apps/findphone/ChangeLog index 9297fc6c7..86558abf5 100644 --- a/apps/findphone/ChangeLog +++ b/apps/findphone/ChangeLog @@ -1 +1,2 @@ -0.01: First Version \ No newline at end of file +0.01: First Version +0.02: Remove HID requirement, update screen diff --git a/apps/findphone/README.md b/apps/findphone/README.md index 870847222..c655457a2 100644 --- a/apps/findphone/README.md +++ b/apps/findphone/README.md @@ -2,8 +2,7 @@ Ring your phone via GadgetBridge if you lost it somewhere. -1. Enable HID in settings -2. Connect GadgetBridge -3. Lose phone -4. Open app -5. Click any button or screen +1. Connect GadgetBridge +2. Lose phone +3. Open app +4. Click any button or screen diff --git a/apps/findphone/app.js b/apps/findphone/app.js index a532e3b50..4b9ea02f5 100644 --- a/apps/findphone/app.js +++ b/apps/findphone/app.js @@ -1,33 +1,34 @@ -var storage = require('Storage'); - //notify your phone -function find(){ - Bluetooth.println(JSON.stringify({t:"findPhone", n:true})); + +var finding = false; + +function draw() { + // show message + g.clear(); + require("Font8x12").add(Graphics); + g.setFont("8x12",3); + g.setFontAlign(0,0); + g.setColor(0x03E0); + if (finding) { + g.drawString("Finding...", g.getWidth()/2, (g.getHeight()/2)-20); + g.drawString("Click to stop", g.getWidth()/2, (g.getHeight()/2)+20); + } else { + g.drawString("Click to find", g.getWidth()/2, g.getHeight()/2); + } + g.flip(); } -//init graphics -g.clear(); -require("Font8x12").add(Graphics); -g.setFont("8x12",3); -g.setFontAlign(0,0); -g.flip(); +function find(){ + finding = !finding; + draw(); + Bluetooth.println("\n"+JSON.stringify({t:"findPhone", n:finding})); +} -//init settings -const settings = storage.readJSON('setting.json',1) || { HID: false }; +draw(); -//check if HID enabled and show message -if (settings.HID=="kb" || settings.HID=="kbmedia") { - g.setColor(0x03E0); - g.drawString("click to find", g.getWidth()/2, g.getHeight()/2); - - //register all buttons and screen to find phone - setWatch(find, BTN1); - setWatch(find, BTN2); - setWatch(find, BTN3); - setWatch(find, BTN4); - setWatch(find, BTN5); - -}else{ - g.setColor(0xf800); - g.drawString("enable HID!", g.getWidth()/2, g.getHeight()/2); -} \ No newline at end of file +//register all buttons and screen to find phone +setWatch(find, BTN1, {repeat:true}); +setWatch(find, BTN2, {repeat:true}); +setWatch(find, BTN3, {repeat:true}); +setWatch(find, BTN4, {repeat:true}); +setWatch(find, BTN5, {repeat:true}); From f9d97a734aac3b24b0b5add26dc05c28a5bc4274 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 25 Sep 2020 11:52:59 +0100 Subject: [PATCH 036/110] tweak --- apps/findphone/app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/findphone/app.js b/apps/findphone/app.js index 4b9ea02f5..34f729bc7 100644 --- a/apps/findphone/app.js +++ b/apps/findphone/app.js @@ -4,11 +4,10 @@ var finding = false; function draw() { // show message - g.clear(); + g.clear(1); require("Font8x12").add(Graphics); g.setFont("8x12",3); g.setFontAlign(0,0); - g.setColor(0x03E0); if (finding) { g.drawString("Finding...", g.getWidth()/2, (g.getHeight()/2)-20); g.drawString("Click to stop", g.getWidth()/2, (g.getHeight()/2)+20); From f3522814825c065062bcb636446c85d3676412fb Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 28 Sep 2020 09:05:28 +0100 Subject: [PATCH 037/110] settings: Move HID to BLE menu --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apps.json b/apps.json index c8f0a58c7..408bae4eb 100644 --- a/apps.json +++ b/apps.json @@ -152,7 +152,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.21", + "version":"0.22", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "readme": "README.md", diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 6a5b1dd76..229337dc9 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -24,3 +24,4 @@ 0.20: Fix set time menu, allow dates to roll over 0.21: Add passkey pairing option (BETA) Add whitelist option (fix #78) +0.22: Move HID to BLE menu diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 8fa919535..6e766afd4 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -61,8 +61,6 @@ const boolFormat = v => v ? "On" : "Off"; function showMainMenu() { var beepV = [false, true, "vib"]; var beepN = ["Off", "Piezo", "Vibrate"]; - var hidV = [false, "kbmedia", "kb", "joy"]; - var hidN = ["Off", "Kbrd & Media", "Kbrd","Joystick"]; const mainmenu = { '': { 'title': 'Settings' }, 'Make Connectable': ()=>makeConnectable(), @@ -101,15 +99,6 @@ function showMainMenu() { }, 'Locale': ()=>showLocaleMenu(), 'Select Clock': ()=>showClockMenu(), - 'HID': { - value: 0 | hidV.indexOf(settings.HID), - min: 0, max: 3, - format: v => hidN[v], - onchange: v => { - settings.HID = hidV[v]; - updateSettings(); - } - }, 'Set Time': ()=>showSetTimeMenu(), 'LCD': ()=>showLCDMenu(), 'Reset Settings': ()=>showResetMenu(), @@ -120,6 +109,8 @@ function showMainMenu() { } function showBLEMenu() { + var hidV = [false, "kbmedia", "kb", "joy"]; + var hidN = ["Off", "Kbrd & Media", "Kbrd","Joystick"]; E.showMenu({ 'BLE': { value: settings.ble, @@ -137,6 +128,15 @@ function showBLEMenu() { updateSettings(); } }, + 'HID': { + value: 0 | hidV.indexOf(settings.HID), + min: 0, max: 3, + format: v => hidN[v], + onchange: v => { + settings.HID = hidV[v]; + updateSettings(); + } + }, 'Passkey BETA': { value: settings.passkey?settings.passkey:"none", onchange: () => setTimeout(showPasskeyMenu) // graphical_menu redraws after the call From 9c5b4142a534b85a3b40c514cc35925b531961d2 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 28 Sep 2020 09:05:48 +0100 Subject: [PATCH 038/110] verticalface: Tweak sizing to allow widgets at top, and add widgets (fix #567) --- apps.json | 2 +- apps/verticalface/ChangeLog | 1 + apps/verticalface/app.js | 11 +++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 408bae4eb..5b0a5c854 100644 --- a/apps.json +++ b/apps.json @@ -1940,7 +1940,7 @@ "name": "Vertical watch face", "shortName":"Vertical Face", "icon": "app.png", - "version":"0.05", + "version":"0.06", "description": "A simple vertical watch face with the date.", "tags": "clock", "type":"clock", diff --git a/apps/verticalface/ChangeLog b/apps/verticalface/ChangeLog index c30b02411..4ba4f7ec4 100644 --- a/apps/verticalface/ChangeLog +++ b/apps/verticalface/ChangeLog @@ -1,2 +1,3 @@ 0.04: Fixed day being displayed 0.05: Stop hours being displayed wrong if moving from 2 digits to 1 (fix #516) +0.06: Tweak sizing to allow widgets at top, and add widgets (fix #567) diff --git a/apps/verticalface/app.js b/apps/verticalface/app.js index 52c8e47a7..8503265ca 100644 --- a/apps/verticalface/app.js +++ b/apps/verticalface/app.js @@ -12,16 +12,15 @@ function drawTimeDate() { var mins= ("0"+m).substr(-2); var date = `${daysOfWeek[weekDay]}|${day}|${("0"+(month+1)).substr(-2)}`; - // Reset the state of the graphics library g.reset(); // Set color g.setColor('#2ecc71'); // draw the current time (4x size 7 segment) - g.setFont("8x12",9); + g.setFont("8x12",8); g.setFontAlign(-1,0); // align right bottom - g.drawString(hours, 25, 65, true /*clear background*/); - g.drawString(mins, 25, 155, true /*clear background*/); + g.drawString(hours, 25, 75, true /*clear background*/); + g.drawString(mins, 25, 165, true /*clear background*/); // draw the date (2x size 7 segment) g.setFont("6x8",2); @@ -84,6 +83,10 @@ function drawBattery() { // Clear the screen once, at startup g.clear(); +// Load and draw widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); + // draw immediately at first drawTimeDate(); drawSteps(); From e908552a0e7b8c82d6b7a8f68261641f05ece5f9 Mon Sep 17 00:00:00 2001 From: marko Date: Mon, 28 Sep 2020 13:46:53 -0400 Subject: [PATCH 039/110] Manually reconnect with button 3 push --- apps/cscsensor/README.md | 2 ++ apps/cscsensor/cscsensor.app.js | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/cscsensor/README.md b/apps/cscsensor/README.md index 8ba862241..a31a4dc28 100644 --- a/apps/cscsensor/README.md +++ b/apps/cscsensor/README.md @@ -9,8 +9,10 @@ Currently the app displays the following data: - maximum speed - trip distance traveled - total distance traveled +- an icon with the battery status of the remote sensor Button 1 resets all measurements except total distance traveled. The latter gets preserved by being written to storage every 0.1 miles and upon exiting the app. +If the watch app has not received an update from the sensor for at least 10 seconds, pushing button 3 will attempt to reconnect to the sensor. I do not have access to a cadence sensor at the moment, so only the speed part is currently implemented. Values displayed are imperial or metric (depending on locale), the wheel circumference can be adjusted in the global settings app. diff --git a/apps/cscsensor/cscsensor.app.js b/apps/cscsensor/cscsensor.app.js index 5be9e1591..c402c06da 100644 --- a/apps/cscsensor/cscsensor.app.js +++ b/apps/cscsensor/cscsensor.app.js @@ -146,7 +146,7 @@ class CSCSensor { } } this.lastSpeed = this.speed; - if (this.speed>this.maxSpeed && (this.movingTime>3 || this.speed<20)) this.maxSpeed = this.speed; + if (this.speed>this.maxSpeed && (this.movingTime>3 || this.speed<20) && this.speed<50) this.maxSpeed = this.speed; } if (qChanged && this.qUpdateScreen) this.updateScreen(); } @@ -189,14 +189,16 @@ function parseDevice(d) { function connection_setup() { NRF.setScan(); + mySensor.screenInit = true; NRF.setScan(parseDevice, { filters: [{services:["1816"]}], timeout: 2000}); - g.clearRect(0, 60, 239, 239).setFontVector(18).setFontAlign(0, 0, 0).setColor(0, 1, 0); + g.clearRect(0, 48, 239, 239).setFontVector(18).setFontAlign(0, 0, 0).setColor(0, 1, 0); g.drawString("Scanning for CSC sensor...", 120, 120); } connection_setup(); setWatch(function() { mySensor.reset(); g.clearRect(0, 48, 239, 239); mySensor.updateScreen(); }, BTN1, {repeat:true, debounce:20}); E.on('kill',()=>{ if (gatt!=undefined) gatt.disconnect(); mySensor.settings.totaldist = mySensor.totaldist; storage.writeJSON(SETTINGS_FILE, mySensor.settings); }); +setWatch(function() { if (Date.now()-mySensor.lastBangleTime>10000) connection_setup(); }, BTN3, {repeat:true, debounce:20}); NRF.on('disconnect', connection_setup); Bangle.loadWidgets(); From 14b18a68e74496e1ba6ef035a7d8dc52e32f3803 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Tue, 29 Sep 2020 13:43:51 -0400 Subject: [PATCH 040/110] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 4d814d99d..27414714e 100644 --- a/apps.json +++ b/apps.json @@ -2238,4 +2238,4 @@ {"name":"digiclock.app.js","url":"digiclock.js"}, {"name":"digiclock.img","url":"digiclock-icon.js","evaluate":true} ] -}, +} From 40d0e305ed8a5ce91d867a64ca431822af968cf3 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Tue, 29 Sep 2020 13:46:04 -0400 Subject: [PATCH 041/110] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 27414714e..c24ce0669 100644 --- a/apps.json +++ b/apps.json @@ -2239,3 +2239,4 @@ {"name":"digiclock.img","url":"digiclock-icon.js","evaluate":true} ] } +] From 431b70a0f83e9d8c24069c29baec32e38e9b8fb4 Mon Sep 17 00:00:00 2001 From: marko Date: Tue, 29 Sep 2020 17:41:56 -0400 Subject: [PATCH 042/110] New file manager app --- apps.json | 13 +++ apps/fileman/ChangeLog | 1 + apps/fileman/README.md | 11 +++ apps/fileman/fileman-icon.js | 1 + apps/fileman/fileman.app.js | 101 ++++++++++++++++++++++ apps/fileman/icons8-filing-cabinet-48.png | Bin 0 -> 467 bytes 6 files changed, 127 insertions(+) create mode 100644 apps/fileman/ChangeLog create mode 100644 apps/fileman/README.md create mode 100644 apps/fileman/fileman-icon.js create mode 100644 apps/fileman/fileman.app.js create mode 100644 apps/fileman/icons8-filing-cabinet-48.png diff --git a/apps.json b/apps.json index 5b0a5c854..4f1aa4e24 100644 --- a/apps.json +++ b/apps.json @@ -2209,6 +2209,19 @@ {"name":"cscsensor.img","url":"cscsensor-icon.js","evaluate":true} ] }, + { "id": "fileman", + "name": "Simple file manager", + "shortName":"FileManager", + "icon": "icons8-filing-cabinet-48.png", + "version":"0.01", + "description": "Simple file manager, allows to examine storage, display or delete files", + "tags": "tools", + "readme": "README.md", + "storage": [ + {"name":"fileman.app.js","url":"fileman.app.js"}, + {"name":"fileman.img","url":"fileman-icon.js","evaluate":true} + ] + }, { "id": "worldclock", "name": "World Clock - 4 time zones", "shortName":"World Clock", diff --git a/apps/fileman/ChangeLog b/apps/fileman/ChangeLog new file mode 100644 index 000000000..1a3bc1757 --- /dev/null +++ b/apps/fileman/ChangeLog @@ -0,0 +1 @@ +0.01: New app! diff --git a/apps/fileman/README.md b/apps/fileman/README.md new file mode 100644 index 000000000..df589d589 --- /dev/null +++ b/apps/fileman/README.md @@ -0,0 +1,11 @@ +# FileManager + +A small file manager, mostly written for debugging issues on the watch. +Upon opening, the app will display a list of all the files in storage (it will contract the sub-components of a StorageFile into one entry). +When selecting a file the following option occurs (depending on file type detected by extension): + +- Length: file size in bytes +- Display file: print out file contents on screen (will attempt to add back newlines for minimized JS code) +- Load file [*.js files only, no widgets]: load and execute javascript file +- Display image [*.img files only]: attempt to render file contents as image on screen +- Delete file: delete file (asks for confirmation first, will delete all components of a StorageFile) diff --git a/apps/fileman/fileman-icon.js b/apps/fileman/fileman-icon.js new file mode 100644 index 000000000..b96649fff --- /dev/null +++ b/apps/fileman/fileman-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/ABuIABgWIhAXNwAuVGBIXZmYAKC/4XXkQACC9Z3/C7YANC8J3/C8ciAAQXrO/4XbABoXhO/4XjkQACC9Z3/C7YANC78ICxuAC44wOCxAABiMRBKIAtA==")) diff --git a/apps/fileman/fileman.app.js b/apps/fileman/fileman.app.js new file mode 100644 index 000000000..a8acb22f6 --- /dev/null +++ b/apps/fileman/fileman.app.js @@ -0,0 +1,101 @@ +const STOR = require("Storage"); + +const n = 9; +var nstart = 0; +var nend; +var m; +var files; + +function delete_file(fn) { + E.showPrompt("Delete\n"+fn+"?", {buttons: {"No":false, "Yes":true}}).then(function(v) { + if (v) { + if (fn.charCodeAt(fn.length-1)==1) { + var fh = STOR.open(fn.substr(0, fn.length-1), "w"); + fh.erase(); + } + else STOR.erase(fn); + } + }).then(function() { files=get_pruned_file_list(); }).then(drawMenu); +} + +function get_length(fn) { + var len; + if (fn.charCodeAt(fn.length-1)==1) { + var fh = STOR.open(fn.substr(0, fn.length-1), "r"); + len = fh.getLength(); + } + else len = STOR.read(fn).length; + return len; +} + +function display_file(fn, qJS) { + g.clear().setColor(1, 1, 1); + var qStorageFile = (fn.charCodeAt(fn.length-1)==1); + var np = 0; + Terminal.println(""); + var file_len = get_length(fn); + var fb = (qStorageFile ? STOR.open(fn.substr(0, fn.length-1), "r") : STOR.read(fn)); + for (var i=0; i 38) { + Terminal.println(""); + np = 0; + } + var c = (qStorageFile ? fb.read(1) : fb[i]); + if (c=="\n") np = 0; + if (qJS && !qStorageFile && c==";" && fb[i+1]!="\n") { + Terminal.println(";"); + np = 0; + } + else Terminal.print(c); + } + Terminal.println(""); +} + +function visit_file(fn) { + var menu = { + '' : {'title' : fn + (fn.charCodeAt(fn.length-1)==1 ? "(S)" : "")} + }; + var qJS = fn.endsWith(".js"); + menu['Length: '+get_length(fn)+' bytes'] = function() {}; + menu['Display file'] = function () { display_file(fn, qJS); }; + if (qJS && !fn.endsWith(".wid.js")) menu['Load file'] = function() { load(fn); } + if (fn.endsWith(".img")) menu['Display image'] = function() { g.clear().drawImage(STOR.read(fn),0,20); } + menu['Delete file'] = function () { delete_file(fn); } + menu['< Back'] = drawMenu; + E.showMenu(menu); +} + +function drawMenu() { + nend = (nstart+n0 ? files.length-n : 0; + menu = {}; + drawMenu(); + } + for (var i=nstart; i next"] = function() { + if (nstart+n (f.charCodeAt(f.length-1)>31 || f.charCodeAt(f.length-1)<2)); + return fl; +} + +files = get_pruned_file_list(); +drawMenu(); diff --git a/apps/fileman/icons8-filing-cabinet-48.png b/apps/fileman/icons8-filing-cabinet-48.png new file mode 100644 index 0000000000000000000000000000000000000000..75774c9ea10b314dbb232dfc3cd74341a2a6c86b GIT binary patch literal 467 zcmV;^0WAKBP)jMbdSc!#=RqXv!1Z*!>!K4t37z=}PcNU4^VsW#3?%sN2e%;>9&VJv{E(|QdFn>bG z1Qm~~v%Zfb0ILAT%u2#LAj(4!dw1LUDiur`=!$;;kkcYho~9cHi#Iz9^|&C1%F^BW zw8aBJ?o&92R1j$ZonvDKA+h$bM4rAgzd84c>5;F*qT;BxU7Xe?qn{?IIWiUK!<2Xc zm>E^it!&`Gk$D3$cR-1=%d6P`8|!OY*W(KOM)wX=WWEAyz&6Tv;J}+Qp(8PaSAqS) zvk4tNR4bhM3a|m&a4%#V?uBf_25iHm%UK|5)}~FI+P@&Oa+hz97mJ@yl9c5Ml0S z;2fRfWSSO$i@+Df%I^Fl6)g2qAEmIo5=O^f Date: Tue, 29 Sep 2020 17:45:02 -0400 Subject: [PATCH 043/110] Adjust wording --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4f1aa4e24..80fccce3d 100644 --- a/apps.json +++ b/apps.json @@ -2210,11 +2210,11 @@ ] }, { "id": "fileman", - "name": "Simple file manager", + "name": "File manager", "shortName":"FileManager", "icon": "icons8-filing-cabinet-48.png", "version":"0.01", - "description": "Simple file manager, allows to examine storage, display or delete files", + "description": "Simple file manager, allows user to examine watch storage and display, load or delete individual files", "tags": "tools", "readme": "README.md", "storage": [ From 2fdd551aecf467fe41abf2ab1139d5c1d683d19d Mon Sep 17 00:00:00 2001 From: marko Date: Tue, 29 Sep 2020 17:48:16 -0400 Subject: [PATCH 044/110] Fix typo --- apps/fileman/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/fileman/README.md b/apps/fileman/README.md index df589d589..49fa9e31d 100644 --- a/apps/fileman/README.md +++ b/apps/fileman/README.md @@ -2,7 +2,7 @@ A small file manager, mostly written for debugging issues on the watch. Upon opening, the app will display a list of all the files in storage (it will contract the sub-components of a StorageFile into one entry). -When selecting a file the following option occurs (depending on file type detected by extension): +When selecting a file the following options appear (depending on file type detected by extension): - Length: file size in bytes - Display file: print out file contents on screen (will attempt to add back newlines for minimized JS code) From 9cdb41f6529ba000d1c107a720a42dff936f7329 Mon Sep 17 00:00:00 2001 From: SpyGuy Date: Wed, 30 Sep 2020 11:07:52 -0400 Subject: [PATCH 045/110] Create ChangeLog --- apps/digiclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/digiclock/ChangeLog diff --git a/apps/digiclock/ChangeLog b/apps/digiclock/ChangeLog new file mode 100644 index 000000000..0bb55854e --- /dev/null +++ b/apps/digiclock/ChangeLog @@ -0,0 +1 @@ +0.01: App Made! From 7a8418110299e4c651f43375f8f15255a27825e9 Mon Sep 17 00:00:00 2001 From: "Marko.Kl.Berkenbusch@gmail.com" Date: Wed, 14 Oct 2020 21:23:37 -0400 Subject: [PATCH 046/110] First commit DSDRelay --- apps.json | 15 +++- apps/dsdrelay/ChangeLog | 1 + apps/dsdrelay/README.md | 14 ++++ apps/dsdrelay/dsdrelay-icon.js | 1 + apps/dsdrelay/dsdrelay-pic.jpg | Bin 0 -> 56538 bytes apps/dsdrelay/dsdrelay.app.js | 116 ++++++++++++++++++++++++++++++ apps/dsdrelay/dsdrelay.info | 1 + apps/dsdrelay/icons8-relay-48.png | Bin 0 -> 409 bytes 8 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 apps/dsdrelay/ChangeLog create mode 100644 apps/dsdrelay/README.md create mode 100644 apps/dsdrelay/dsdrelay-icon.js create mode 100644 apps/dsdrelay/dsdrelay-pic.jpg create mode 100644 apps/dsdrelay/dsdrelay.app.js create mode 100644 apps/dsdrelay/dsdrelay.info create mode 100644 apps/dsdrelay/icons8-relay-48.png diff --git a/apps.json b/apps.json index 622216ecf..688518bb0 100644 --- a/apps.json +++ b/apps.json @@ -2251,5 +2251,18 @@ {"name":"digiclock.app.js","url":"digiclock.js"}, {"name":"digiclock.img","url":"digiclock-icon.js","evaluate":true} ] -} +}, + { "id": "dsdrelay", + "name": "DSD BLE Relay controller", + "shortName":"DSDRelay", + "icon": "icons8-relay-48.png", + "version":"0.01", + "description": "Control BLE relay board from the watch", + "tags": "ble,bluetooth", + "readme": "README.md", + "storage": [ + {"name":"dsdrelay.app.js","url":"dsdrelay.app.js"}, + {"name":"dsdrelay.img","url":"dsdrelay-icon.js","evaluate":true} + ] + } ] diff --git a/apps/dsdrelay/ChangeLog b/apps/dsdrelay/ChangeLog new file mode 100644 index 000000000..1a3bc1757 --- /dev/null +++ b/apps/dsdrelay/ChangeLog @@ -0,0 +1 @@ +0.01: New app! diff --git a/apps/dsdrelay/README.md b/apps/dsdrelay/README.md new file mode 100644 index 000000000..395aba636 --- /dev/null +++ b/apps/dsdrelay/README.md @@ -0,0 +1,14 @@ +# DSDRelay + +Small app to control DSD Tech BLE relay boards from the watch. I have seen them being sold as 1-, 2- and 4-relay boards. The app shows controls for +4 relays, regardless of the actual configuration of the board connected. + +![](dsdrelay-pic.jpg) + +## Controls +- buttons 1 and 3 cycle the selection of the currently active channel +- swipe right turns the selected channel's relay *on* +- swipe left turns the selected channel's relay *off* + +I only own a 1-relay board, so only the "Ch 1" functionality was tested; the other channels were implemented per the manufacturer's documentation. +In particular, the method for determining the relay states on app startup for channels 2-4 was mostly an educated guess. diff --git a/apps/dsdrelay/dsdrelay-icon.js b/apps/dsdrelay/dsdrelay-icon.js new file mode 100644 index 000000000..ac98e6eea --- /dev/null +++ b/apps/dsdrelay/dsdrelay-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4A/AAcK1QAO0AXFCx4ABFyowGC/4X/C/4X/C48AC6IWEGCIuFAAUN6AED7vdAwgEDC/4X/C/4X86AGGC85fpAH4A/AH4ASA")) diff --git a/apps/dsdrelay/dsdrelay-pic.jpg b/apps/dsdrelay/dsdrelay-pic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5bffebe1839181186a03a5be7ecd7fc010b29b07 GIT binary patch literal 56538 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 D!dgUm literal 0 HcmV?d00001 diff --git a/apps/dsdrelay/dsdrelay.app.js b/apps/dsdrelay/dsdrelay.app.js new file mode 100644 index 000000000..18e7293aa --- /dev/null +++ b/apps/dsdrelay/dsdrelay.app.js @@ -0,0 +1,116 @@ +var device; +var gatt; +var service; +var characteristic; + +// on/off commands +// Channel 1 ON: A00101A2 +// Channel 1 OFF: A00100A1 +// Channel 2 ON: A00201A3 +// Channel 2 OFF: A00200A2 +// Channel 3 ON: A00301A4 +// Channel 3 OFF: A00300A3 +// Channel 4 ON: A00401A5 +// Channel 4 OFF: A00400A4 + +var cmds = [{ on: new Uint8Array([0xa0, 0x01, 0x01, 0xa2]), + off: new Uint8Array([0xa0, 0x01, 0x00, 0xa1]) }, + { on: new Uint8Array([0xa0, 0x02, 0x01, 0xa3]), + off: new Uint8Array([0xa0, 0x02, 0x00, 0xa2]) }, + { on: new Uint8Array([0xa0, 0x03, 0x01, 0xa4]), + off: new Uint8Array([0xa0, 0x03, 0x00, 0xa3]) }, + { on: new Uint8Array([0xa0, 0x04, 0x01, 0xa5]), + off: new Uint8Array([0xa0, 0x04, 0x00, 0xa4]) }]; + +const button_w = 100; +const button_h = 36; +const button_r = button_h/2-4; +const button_sp = 46; + +var n_channels = 4; +var channel = 0; +var channel_state = []; + +function drawButton(x, y, state) { + if (state) g.setColor(0.2, 0.2, 0.95); + else g.setColor(0.5, 0.5, 0.5); + g.fillCircle(x+button_h/2, y+button_h/2, button_h/2). + fillRect(x+button_h/2, y, x+button_w-button_h/2, y+button_h). + fillCircle(x+button_w-button_h/2, y+button_h/2, button_h/2); + g.setColor(0.85, 0.85, 0.85); + if (state) + g.fillCircle(x+button_w-button_h/2, y+button_h/2, button_r); + else + g.fillCircle(x+button_h/2, y+button_h/2, button_r); + g.flip(); +} + +function setup_screen() { + g.clearRect(0, 60, g.getWidth()-1, g.getHeight()-1); + for (var i=0; i<4; ++i) { + g.setFontVector(22).setFontAlign(-1, 0, 0).setColor(0xffff).drawString("Ch"+String(i+1), 16, 60+i*button_sp+button_h/2); + drawButton((g.getWidth()-button_w)/2, 60+i*button_sp, channel_state[i]); + } + moveChannelFrame(channel, channel); +} + +function parseDevice(d) { + device = d; + g.clearRect(0, 60, 239, 239).setFontAlign(0, 0, 0).setColor(0, 1, 0).drawString("Found device", 120, 120).flip(); + device.gatt.connect().then(function(ga) { + gatt = ga; + g.clearRect(0, 60, 239, 239).setFontAlign(0, 0, 0).setColor(0, 1, 0).drawString("Connected", 120, 120).flip(); + return gatt.getPrimaryService("FFE0"); +}).then(function(s) { + service = s; + return service.getCharacteristic("FFE1"); +}).then(function(c) { + characteristic = c; + console.log(c); + return; +}).then(function() { + console.log("Done!"); + g.clearRect(0, 60, 239, 239).setColor(1, 1, 1).flip(); + setup_app(); +}).catch(function(e) { + g.clearRect(0, 60, 239, 239).setColor(1, 0, 0).setFontAlign(0, 0, 0).drawString("ERROR"+e, 120, 120).flip(); + console.log(e); +})} + +function connection_setup() { + NRF.setScan(); + NRF.setScan(parseDevice, { filters: [{services:["FFE0"]}], timeout: 2000}); + g.clearRect(0, 60, 239, 239).setFontVector(18).setFontAlign(0, 0, 0).setColor(0, 1, 0); + g.drawString("Scanning for relay...", 120, 120); +} + +function moveChannelFrame(oldc, newc) { + g.setColor(0).drawRect(8, 60+oldc*button_sp-4, g.getWidth()-8, 60+oldc*button_sp+button_h+4); + g.setColor(0.9, 0.9, 0.9).drawRect(8, 60+newc*button_sp-4, g.getWidth()-8, 60+newc*button_sp+button_h+4); +} + +function setup_app() { + characteristic.readValue().then(function(r) { + for (var i=0; i#8|>elHXf`3Gr+KUy#wkYyQ`p=q=V(FPUGq8M$M`oe)Ch)JU~5vs~uPy zW`K{enKoumB>|$%{3wgoVp)Kh;Q?av0I_+1*vbO*C)&k$UaZBk0G9z9`6caIt7d>4 znjp_%8>*xydD^r#%mBA%oA*hYuK>ry9j89%iR8)Z_4&r5RZ#jqV9^!|AiJZl`>gwR z*qGP-R97^&zd|#^1H|S5V)Fp8d4LfVr41Z`{m=Xt(oi1^v}KPS0Br$~g*YVK9niw_ zj8uE(sv_JS5Hf8c2!gU5>X?utBtRB!`kiymxjFC-9BxQxvM Date: Wed, 14 Oct 2020 21:29:39 -0400 Subject: [PATCH 047/110] Rescale screenshot --- apps/dsdrelay/dsdrelay-pic.jpg | Bin 56538 -> 29710 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/dsdrelay/dsdrelay-pic.jpg b/apps/dsdrelay/dsdrelay-pic.jpg index 5bffebe1839181186a03a5be7ecd7fc010b29b07..879f995cb489f9e1edb3dfbe91e4872ac9485300 100644 GIT binary patch delta 22322 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

ve5=~SrT=LyXk~iM2HjW3_N`Trb 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 From ba4eab2a3ea90b44d9729c4e210683f5dc9bd7ea Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 15 Oct 2020 13:53:42 +0100 Subject: [PATCH 048/110] add docs re #454 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 688518bb0..c9322b12a 100644 --- a/apps.json +++ b/apps.json @@ -1941,7 +1941,7 @@ "shortName":"Vertical Face", "icon": "app.png", "version":"0.06", - "description": "A simple vertical watch face with the date.", + "description": "A simple vertical watch face with the date. Heart rate monitor is toggled with BTN1", "tags": "clock", "type":"clock", "allow_emulator":true, From 315e7c6bc133f1a2c2ab362e16f7c5dc38e0b7b8 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 15 Oct 2020 14:09:45 +0100 Subject: [PATCH 049/110] simpletimer: Fix buzz error, remove '+' when timer running and add 'back' text (fix #577) --- apps.json | 2 +- apps/simpletimer/ChangeLog | 1 + apps/simpletimer/app.js | 21 ++++++++++++++------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index c9322b12a..3cafdae78 100644 --- a/apps.json +++ b/apps.json @@ -1718,7 +1718,7 @@ "id": "simpletimer", "name": "Timer", "icon": "app.png", - "version": "0.05", + "version": "0.06", "description": "Simple timer, useful when playing board games or cooking", "tags": "timer", "readme": "README.md", diff --git a/apps/simpletimer/ChangeLog b/apps/simpletimer/ChangeLog index e548d90fa..0a0d47126 100644 --- a/apps/simpletimer/ChangeLog +++ b/apps/simpletimer/ChangeLog @@ -3,3 +3,4 @@ 0.03: BTN2 to open launcher 0.04: Remember last set time 0.05: Fix buzz that doesn't stop (fix #521) +0.06: Fix buzz error, remove '+' when timer running and add 'back' text (fix #577) diff --git a/apps/simpletimer/app.js b/apps/simpletimer/app.js index 75c118980..f6332a8b7 100644 --- a/apps/simpletimer/app.js +++ b/apps/simpletimer/app.js @@ -1,6 +1,6 @@ let counter = 0; let setValue = 0; -let counterInterval; +let counterInterval, alarmInterval; let state; let saved = require("Storage").readJSON("simpletimer.json",true) || {}; @@ -19,7 +19,8 @@ function outOfTime() { g.drawString("Time UP!", 120, 50); counter = setValue; buzzAndBeep(); - setInterval(() => { + if (alarmInterval) clearInterval(alarmInterval); + alarmInterval = setInterval(() => { g.clearRect(0, 70, 220, 160); setTimeout(draw, 200); }, 400); @@ -55,7 +56,9 @@ function countDown() { } function clearIntervals() { - clearInterval(); + if (alarmInterval) clearInterval(alarmInterval); + if (counterInterval) clearInterval(counterInterval); + alarmInterval = undefined; counterInterval = undefined; } @@ -93,16 +96,21 @@ const stateMap = { function changeState() { if (stateMap[state]) stateMap[state](); + drawLabels(); + draw(); } function drawLabels() { g.clear(); g.setFontAlign(-1, 0); g.setFont("6x8", 7); - g.drawString(`+ +`, 35, 180); + if (state != "started") // only when not runnung + g.drawString(`+ +`, 35, 180); g.setFontAlign(0, 0, 3); g.setFont("6x8", 1); - g.drawString(`reset (re)start`, 230, 120); + g.drawString("Reset (re)start", 230, 120); + if (state != "started") // only when not runnung + g.drawString("Back", 230, 120); } function resetTimer(value) { @@ -130,8 +138,7 @@ function addWatch() { { repeat: false, edge: "falling", - }, - ); + }); setWatch( () => { resetTimer(0); From 326db60aada6df7c402e34516a232671f5340c64 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 15 Oct 2020 17:22:43 +0100 Subject: [PATCH 050/110] Added customised welcome screen - christmas only for now --- apps.json | 18 +++ apps/mywelcome/ChangeLog | 13 ++ apps/mywelcome/app-icon.js | 1 + apps/mywelcome/app.js | 298 +++++++++++++++++++++++++++++++++++++ apps/mywelcome/app.png | Bin 0 -> 1939 bytes apps/mywelcome/boot.js | 9 ++ apps/mywelcome/custom.html | 78 ++++++++++ apps/mywelcome/settings.js | 18 +++ 8 files changed, 435 insertions(+) create mode 100644 apps/mywelcome/ChangeLog create mode 100644 apps/mywelcome/app-icon.js create mode 100644 apps/mywelcome/app.js create mode 100644 apps/mywelcome/app.png create mode 100644 apps/mywelcome/boot.js create mode 100644 apps/mywelcome/custom.html create mode 100644 apps/mywelcome/settings.js diff --git a/apps.json b/apps.json index 3cafdae78..5939740ef 100644 --- a/apps.json +++ b/apps.json @@ -118,6 +118,24 @@ {"name":"welcome.json"} ] }, + { "id": "mywelcome", + "name": "Customised Welcome", + "shortname": "My Welcome", + "icon": "app.png", + "version":"0.09", + "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting", + "tags": "start,welcome", + "custom":"custom.html", + "storage": [ + {"name":"mywelcome.boot.js","url":"boot.js"}, + {"name":"mywelcome.app.js","url":"app.js"}, + {"name":"mywelcome.settings.js","url":"settings.js"}, + {"name":"mywelcome.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"mywelcome.json"} + ] + }, { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", diff --git a/apps/mywelcome/ChangeLog b/apps/mywelcome/ChangeLog new file mode 100644 index 000000000..9545dbbfa --- /dev/null +++ b/apps/mywelcome/ChangeLog @@ -0,0 +1,13 @@ +0.01: New App! +0.02: Animate balloon intro +0.03: BTN3 now won't restart when at the end +0.04: Fix regression after tweaks to Storage.readJSON +0.05: Move configuration into App/widget settings +0.06: Move loader into welcome.boot.js +0.07: Run again when updated + Don't run again when settings app is updated (or absent) + Add "Run Now" option to settings +0.08: Don't overwrite existing settings on app update +0.09: Allow welcome to run after a fresh install + More useful app menu + BTN2 now goes to menu on release diff --git a/apps/mywelcome/app-icon.js b/apps/mywelcome/app-icon.js new file mode 100644 index 000000000..5c1373e17 --- /dev/null +++ b/apps/mywelcome/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AU5gAEFtoxnEwXN53WAAXO5oJB42Wy26AAIueFoPXFggAD4AwEGTQiB6otBFgwAD3QvFGC5dCFxiRGGClhrdbv67BXAIuLMBIwPsIABF4OpLwXOFxjBCF6gtBw2r1mHXoXWFxqQWFwOH62rL4IeB6xeOAAIvHGBYuC6+rR4QvCXpovXw3X1i/DR4QuPR5AvKFQOs6+GF4eod4IvPd5AvLwvWLwQvCv4fBR54vURwOHF4iQCX0yOCF4aQBX0QvHSAoAN3SOSd4WyF4yQPLyhgD1YvDMCJeIFxhgCF47BN4BeHFxpgDSAiRORpAuPMIYAFGBYuaF5aSHFwQvEFqQwOeggSBLa4xNF4X+4wAC/xeCFjIADrYwGBIIvlMQiPDBAOk0gDBz2XF8BlEF4eIxADFF8lcF9n+wIrFF05bHF9AsGF9wupGAYv/F8QupGAov/F/4wOF1gA/AH4Ap")) diff --git a/apps/mywelcome/app.js b/apps/mywelcome/app.js new file mode 100644 index 000000000..fcd193ce2 --- /dev/null +++ b/apps/mywelcome/app.js @@ -0,0 +1,298 @@ +// exec each function from seq one after the other +function animate(seq,period) { + var i = setInterval(function() { + if (seq.length) { + var f = seq.shift(); + if (f) f(); + } else clearInterval(i); + },period); +} + +// Fade in to FG color with angled lines +function fade(callback) { + var n = 0; + function f() { + for (var i=n;i<240;i+=10) { + g.drawLine(i,0,0,i); + g.drawLine(i,240,240,i); + } + g.flip(); + n++; + if (n<10) setTimeout(f,0); + else callback(); + } + f(); +} + + +var scenes = [ + function() { + g.clear(1); + eval(require("Storage").read("mywelcome.custom.js")); + },function() { + g.clear(1); + g.setFont("4x6",2); + var n=0; + var i = setInterval(function() { + n+=0.04; + g.setColor(n,n,n); + g.drawImage(Bangle.getLogo(),(240-222)/2,(240-100)/2); + if (n>=1) { + clearInterval(i); + setTimeout(()=>g.drawString("Open",34,144), 500); + setTimeout(()=>g.drawString("Hackable",34,156), 1000); + setTimeout(()=>g.drawString("Smart Watch",34,168), 1500); + } + },50); + },function() { + var img = require("heatshrink").decompress(atob("ptRxH+qYAfvl70mj5gAC0ekvd8FkAAdz3HJAYAH4+eJXWkJJYAF0hK2vfNJaIAB5t7S3fN5/V6wAD6vOTg9SumXy2W3QAB3eXul2JdnO63XAApPEVYvAJQIACJoRQDzBLoJQ3W5/NIwr4GJohMFAAROgJYvVJQiPGABZNN3bsdvYyESwnWJSIAC3RNM3V1JjZAES4nVJSYAB4xMNJrbkE56WD5xLVdB5NbFofNJbgABJh26qREPrFXrlbAAWjFgfWJgRLaTQhMLy5KNJINhsJLDrYrD5xLC6pLa5nGTR7oLq9bJQJMKTAXWJbbnR3RLJSoRMHv4pC5rkec6SaIrBLGw2r2XW1epcoqYeJiOXJYziEsOH2RBBw7lF56Yg5nGc6FScZOGJQPX2TmDFIfVTEBMSc4hLEw5KB6+rsJMH63X6pMf5hMQzBLCq5LD1ZLEJhTlfJiWXTA2GJYpMIcwPNc2O6TAuGRIPX1igDJg/PJmyYDcgXWwxMH1ApC53XcsHAJiVYcg2HJYZME0YpC5vWJkhLNJgLlDTAeFJhF/FQfVJkG6JiGXcomyJgOrJYhMErYqD53NJj7lRzBMDcoeGJhzoBJb3GJiN1qZBCJgWyJYpNF1LigAAXAJiNSJgzlGJgt/JkZLRy9TJgeHJhznFcuSZGw5MHJomjcuhLBqdcJiSaiTChMV1CYxy5LCqdXIAWy6+rJhCalTCN2JgdYH4WHJiGpTF7kDc43W2RMJTUZLQzBLFc4mr6+GJh2jTFmXJYyaEwuyc5Sag4xLZTQmG2WFJhxNaJYZMLJZSaEJoOHTR9/Ja+6JbdTqRNETRRNF1JLV4BLcAANYI5ToK1BLYJhWYJZwABq5NoJZ91JaAABdAZNS0ZLey9SJaRNYv5KM426JZmXuxKUJrKcL0lTzBLKzBKYJrVXvfGSol7EYWXJI27zF1JLQADq5NUrgYB4wAEEIV0comXI7wAFrCcPJgYWBTIIAETIN2JYmWuhMkdSdYCgOeJgueqRLFyzhfTi9bq4TC45MF49TuuXJlpONcogAC0hKB0gHDvZMEqRMpAANSq9crlbJAYADqwRDxGk0mIA4eCTQOeveXJdYAHqxNFdAeIAAQGCrOI0oHEAGVXTRJMGvgGCwRM7TAZMHwQGCvhM1rBMERIhMGAwdZJmtSqVTwNcwJEDJg19cvIADa4d9JhANDJnSLHJgrl6AAhFFAwpZDegjn7vhMGcvwABrJAFJgjl/TQpBBI4jl/AAN8TQhHDcv4ADcJBMDvpM+IYaeDAAhL+qd9SgycEJn7iEAA18Jf7nEcv4AIrJLIcv6aMcv4ADvhMHrJJ/AAbl/c6ZM/AAt9cv7nSIv7nLcv4AHrLl/TRpJBvgnjA==")); + g.reset(); + g.setColor("#6633ff"); + g.setBgColor("#6633ff"); + var y = 240, speed = 5; + function balloon(callback) { + y-=speed; + var x = (240-77)/2; + g.drawImage(img,x,y); + g.clearRect(x,y+81,x+77,y+81+speed); + if (y>60) setTimeout(balloon,0,callback); + else callback(); + } + fade(function() { + balloon(function() { + g.setColor(-1); + g.setFont("6x8",3); + g.setFontAlign(0,0); + g.drawString("Welcome.",120,160); + }); + }); + setTimeout(function() { + var n=0; + var i = setInterval(function() { + n+=5; + g.scroll(0,-5); + if (n>170) + clearInterval(i); + },20); + },3500); + + },function() { + g.reset(); + g.setBgColor("#ffa800");g.clear(); + g.setFont("6x8",2); + g.setFontAlign(0,0); + var x = 80, y = 35, h=35; + animate([ + ()=>g.drawString("Your",x,y+=h), + ()=>g.drawString("Bangle.js",x,y+=h), + ()=>g.drawString("has",x,y+=h), + ()=>g.drawString("3 buttons",x,y+=h), + ()=>{g.setFont("Vector",36);g.drawString("1",200,40);}, + ()=>g.drawString("2",200,120), + ()=>g.drawString("3",200,200) + ],200); + }, + function() { + g.reset(); + g.setBgColor("#00a8ff");g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",48); + g.drawString("1",200,40); + g.setFontAlign(-1,-1); + g.setFont("6x8",2); + g.drawString("Move up\nin menus\n\nTurn Bangle.js on\nif it was off", 20,40); + }, + function() { + g.reset(); + g.setBgColor("#00a8ff");g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",48); + g.drawString("2",200,120); + g.setFontAlign(-1,-1); + g.setFont("6x8",2); + g.drawString("Select menu\nitem\n\nLaunch app\nwhen watch\nis showing", 20,70); + }, + function() { + g.reset(); + g.setBgColor("#00a8ff");g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",48); + g.drawString("3",200,200); + g.setFontAlign(-1,-1); + g.setFont("6x8",2); + g.drawString("Move down\nin menus\n\nLong press\nto exit app\nand go back\nto clock", 20,100); + }, + function() { + g.reset(); + g.setBgColor("#ff3300");g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",48); + g.drawString("1",200,40); + g.drawString("2",200,120); + g.setFontAlign(-1,-1); + g.setFont("6x8",2); + g.drawString("If Bangle.js\never stops,\nhold buttons\n1 and 2 for\naround six\nseconds.\n\n\n\nBangle.js will\nthen reboot.", 20,20); + }, + function() { + g.reset(); + g.setBgColor("#00a8ff");g.clear(); + g.setFont("6x8",2); + g.setFontAlign(0,0); + var x = 120, y = 10, h=21; + animate([ + ()=>{g.drawString("Bangle.js has a",x,y+=h); + g.drawString("simple touchscreen",x,y+=h);}, + 0,0, + ()=>{g.drawString("It'll detect touch",x,y+=h*2); + g.drawString("on left and right",x,y+=h);}, + 0,0, + ()=>{g.drawString("Horizontal swipes",x,y+=h*2); + g.drawString("work too. Try now",x,y+=h); + g.drawString("to change page.",x,y+=h);} + ],300); + }, + function() { + g.reset(); + g.setBgColor("#339900");g.clear(); + g.setFont("6x8",2); + g.setFontAlign(0,0); + var x = 120, y = 10, h=21; + animate([ + ()=>{g.drawString("Bangle.js",x,y+=h); + g.drawString("comes with",x,y+=h); + g.drawString("a few simple",x,y+=h); + g.drawString("apps installed",x,y+=h);}, + 0,0, + ()=>{g.drawString("To add more, visit",x,y+=h*2); + g.drawString("banglejs.com/apps",x,y+=h); + g.drawString("with a Bluetooth",x,y+=h); + g.drawString("capable device",x,y+=h);}, + ],400); + }, + function() { + g.reset(); + g.setBgColor("#990066");g.clear(); + g.setFont("6x8",2); + g.setFontAlign(0,0); + var x = 120, y = 10, h=21; + g.drawString("You can also make",x,y+=h); + g.drawString("your own apps!",x,y+=h); + y=160; + g.drawString("Check out",x,y+=h); + g.drawString("banglejs.com",x,y+=h); + + var rx = 0, ry = 0; + var h = Graphics.createArrayBuffer(96,96,1,{msb:true}); + // draw a cube + function draw() { + // rotate + rx += 0.1; + ry += 0.11; + var rcx=Math.cos(rx), + rsx=Math.sin(rx), + rcy=Math.cos(ry), + rsy=Math.sin(ry); + // Project 3D coordinates into 2D + function p(x,y,z) { + var t; + t = x*rcy + z*rsy; + z = z*rcy - x*rsy; + x=t; + t = y*rcx + z*rsx; + z = z*rcx - y*rsx; + y=t; + z += 4; + return [96*(0.5+x/z), 96*(0.5+y/z)]; + } + + var a; + // draw a series of lines to make up our cube + h.clear(); + a = p(-1,-1,-1); h.moveTo(a[0],a[1]); + a = p(1,-1,-1); h.lineTo(a[0],a[1]); + a = p(1,1,-1); h.lineTo(a[0],a[1]); + a = p(-1,1,-1); h.lineTo(a[0],a[1]); + a = p(-1,-1,-1); h.lineTo(a[0],a[1]); + a = p(-1,-1,1); h.moveTo(a[0],a[1]); + a = p(1,-1,1); h.lineTo(a[0],a[1]); + a = p(1,1,1); h.lineTo(a[0],a[1]); + a = p(-1,1,1); h.lineTo(a[0],a[1]); + a = p(-1,-1,1); h.lineTo(a[0],a[1]); + a = p(-1,-1,-1); h.moveTo(a[0],a[1]); + a = p(-1,-1,1); h.lineTo(a[0],a[1]); + a = p(1,-1,-1); h.moveTo(a[0],a[1]); + a = p(1,-1,1); h.lineTo(a[0],a[1]); + a = p(1,1,-1); h.moveTo(a[0],a[1]); + a = p(1,1,1); h.lineTo(a[0],a[1]); + a = p(-1,1,-1); h.moveTo(a[0],a[1]); + a = p(-1,1,1); h.lineTo(a[0],a[1]); + g.drawImage({width:96,height:96,buffer:h.buffer},(240-96)/2,68); + } + + setInterval(draw,50); + }, + function() { + g.reset(); + g.setBgColor("#660099");g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",36); + g.drawString("2",200,120); + g.setFont("6x8",2); + + var x = 90, y = 30, h=21; + animate([ + ()=>g.drawString("That's it!",x,y+=h), + ()=>{g.drawString("Press",x,y+=h*3); + g.drawString("Button 2",x,y+=h); + g.drawString("to start",x,y+=h); + g.drawString("Bangle.js",x,y+=h);} + ],400); + } +]; + +var sceneNumber = 0; + +function move(dir) { + if (dir>0 && sceneNumber+1 == scenes.length) return; // at the end + sceneNumber = (sceneNumber+dir)%scenes.length; + if (sceneNumber<0) sceneNumber=0; + clearInterval(); + Bangle.setLCDMode(); + g.clear(); + scenes[sceneNumber](); + if (sceneNumber>1) { + var l = scenes.length; + for (var i=0;imove(1), BTN3, {repeat:true}); +setWatch(()=>{ + // If we're on the last page + if (sceneNumber == scenes.length-1) { + load(); + } +}, BTN2, {repeat:true,edge:"falling"}); +setWatch(()=>move(-1), BTN1, {repeat:true}); + +Bangle.setLCDTimeout(0); +Bangle.setLCDPower(1); +move(0); diff --git a/apps/mywelcome/app.png b/apps/mywelcome/app.png new file mode 100644 index 0000000000000000000000000000000000000000..ebbf254bd7c3546e8337c97648a7eb56747c81ac GIT binary patch literal 1939 zcmV;E2WP)^Vse?M*ABwfS z8MZ{CGrE{9Te8V!(51`XGM!;roJ%xW2E^g2NO{qXsim}(VOBaof>d5Dolx3xFQxb1 z-nZxMkEd_+KDRC9c8eL`e{OQldCvKM@9+H1@Ao`#6F2ey4asCOZNf#^U4iltNGVVP zD9{Fa2%!dFY=)EdIoSdkU1+ff<1#70}x@Hu6Kz{*xG?E@iS0CV6Z_UXTXX+c`#EfepLM z7bkj*!-~A7=*pg+Sbi*K%7RHf4giWO!Qq3`KOGl&fb97ejd1$m`W-Ff7CVP?6!NP@ z*#dZSJOwP6bwBxEm_^gcdS*L+X9eY#LFhPi?iv?)0Qct&s7(@2rVYtLc?9_Na7Wq| z*s!a7VL$mhO77$FB^z-&y=>gMfp-sY$1lBBpl3RC?8G{+#s}vNi$-#!6vBPB&)OMR zSFd&$bZt`bEWGtWzIxkQ4xXu@;q+gK#Us}SYaD|6$H%;%Ti;I9kp;}PGuy7fJm2Nj z3iFC{=TP>!hdI^J%>L8W066-F^;LCQ!M&eAbbP(vkK`q5{1_wcNTtxuZ2ySr8h}N& zRszc2md$8ii@03Y-n|s>8yCR?kc`--87pEZEdlP41PEPrX4^*;%A5{2vnS8zR7W$x z$ly8R&9b`gL{GM5xU>zNlg7h)0KF}J0vsa*DW~nsDFU8oDs=&cd09m`4HsuS|8}Go}cbc4m$MYKWCB5WaYg-fnm1w~?N@s{QIvQxc8y;|@aI_lzb}w~BisS# zemenx-!nLkY_L)4u$>fXwvAaIiTBWc+v}7`&~p6!uCs3uaov50-F-3g3k#a`wiTU zvP%9=C|wR)0Y87>{T;xe;}`am?ajxK)a*r5vJpf0+j$=?(bQEM4dHi_T)m(OP>_0! z1_+^4NFyyH<*{D@K^5csiY97XHdE-Io)Y4AJ18jdq6!;N6w__G$4oxaYSOXO>ixVd z+ws{6d|mcaH(IW=leb~(nby14&Nh=~ygVGcVjJW0xrjs(bVp2%hH_X~(1Taf-^c)x z7fdd^7$=di#^z*S%ALL$;a+Lr=xF3e6aY{@cU@z0T5E~G9qD5HeiuEVI9(y3DL9Gw z1yOPg`+ITpuxVa+DK3e)^{?OJ2V;=^WrSx4^Q0WKKXvUe>I+R(Rh1DhZFp7C$I`_l zlS*4#H@%Sr4uO?(LjPWs*V=<2)&jK*IPU`jS>z$Ju_P`2WvTIvXn zmH3zi^y9hR%brk`mjK)IQWZKoBLssHEiBBw=l9z94dC&#M}GJIl*eYU7cZ~QEIAx*jx#4V*6tXFt75D0`S3i z9}Y}9+K^{NLmzuXR~F6skih>$z;LX3{!6Pxw0a<^>ZsE89`|RJp-`2xV9n22`K4{uPal12c#LV76{gFJ8nP!- zaw36avkT_Uy!ZAWT)neo#k6g;jWdVG2vqd_X5^b_KQbcVPgUo7pa0hDpH9h{^Jkwc z-!McT8S3Bl{(_CIEp)Rdry0B}FR$L8xE8Y*}X}Yi3ly zimxsC2XF#(_RiV^WkXzj?IRg&AIPu(06{kcC_FmEycEFvEC@)5a|@6}ST)4#1`by) zyX#!0>t$TP%4Lh%RHy~~L+v8eWV#kifB-A0ZW?Y&s`=Rw5cL>u!8JF_b1TZrj!Z7V#$X$n89sf7V!{MeE?v?nqF**mb8fyw8z-vHP29u{ Z;y>o9o!*JS4-fzV002ovPDHLkV1gG+pke?3 literal 0 HcmV?d00001 diff --git a/apps/mywelcome/boot.js b/apps/mywelcome/boot.js new file mode 100644 index 000000000..84d235bc5 --- /dev/null +++ b/apps/mywelcome/boot.js @@ -0,0 +1,9 @@ +(function() { + let s = require('Storage').readJSON('mywelcome.json', 1) || {}; + if (!s.welcomed) { + setTimeout(() => { + require('Storage').write('mywelcome.json', {welcomed: true}) + load('mywelcome.app.js') + }) + } +})() diff --git a/apps/mywelcome/custom.html b/apps/mywelcome/custom.html new file mode 100644 index 000000000..87713e7a2 --- /dev/null +++ b/apps/mywelcome/custom.html @@ -0,0 +1,78 @@ + + + + + + +

Line 1:

+

Line 2:

+

Line 3 (smaller):

+

Line 4 (smaller):

+

+

+

This is currently Christmas-themed, but more themes will be added in the future.

+ + + + + + diff --git a/apps/mywelcome/settings.js b/apps/mywelcome/settings.js new file mode 100644 index 000000000..cf7208d65 --- /dev/null +++ b/apps/mywelcome/settings.js @@ -0,0 +1,18 @@ +(function(back) { + let settings = require('Storage').readJSON('mywelcome.json', 1) + || require('Storage').readJSON('setting.json', 1) || {} + E.showMenu({ + '': { 'title': 'Welcome App' }, + 'Run next boot': { + value: !settings.welcomed, + format: v => v ? 'Yes' : 'No', + onchange: v => require('Storage').write('mywelcome.json', {welcomed: !v}), + }, + 'Run Now': () => load('mywelcome.app.js'), + 'Turn off & run next': () => { + require('Storage').write('mywelcome.json', {welcomed: false}); + Bangle.off(); + }, + '< Back': back, + }) +}) From 624bc9d6044e054503ef73ee74ae5008cff714a3 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 15 Oct 2020 17:36:22 +0100 Subject: [PATCH 051/110] minor tweaks --- apps/mywelcome/app.js | 14 +++++++------- apps/mywelcome/custom.html | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/mywelcome/app.js b/apps/mywelcome/app.js index fcd193ce2..23cdd0d49 100644 --- a/apps/mywelcome/app.js +++ b/apps/mywelcome/app.js @@ -9,12 +9,12 @@ function animate(seq,period) { } // Fade in to FG color with angled lines -function fade(callback) { +function fade(col, callback) { var n = 0; function f() { + g.setColor(col); for (var i=n;i<240;i+=10) { - g.drawLine(i,0,0,i); - g.drawLine(i,240,240,i); + g.drawLine(i,0,0,i).drawLine(i,240,240,i); } g.flip(); n++; @@ -27,6 +27,7 @@ function fade(callback) { var scenes = [ function() { + console.log("Start app"); g.clear(1); eval(require("Storage").read("mywelcome.custom.js")); },function() { @@ -47,7 +48,6 @@ var scenes = [ },function() { var img = require("heatshrink").decompress(atob("ptRxH+qYAfvl70mj5gAC0ekvd8FkAAdz3HJAYAH4+eJXWkJJYAF0hK2vfNJaIAB5t7S3fN5/V6wAD6vOTg9SumXy2W3QAB3eXul2JdnO63XAApPEVYvAJQIACJoRQDzBLoJQ3W5/NIwr4GJohMFAAROgJYvVJQiPGABZNN3bsdvYyESwnWJSIAC3RNM3V1JjZAES4nVJSYAB4xMNJrbkE56WD5xLVdB5NbFofNJbgABJh26qREPrFXrlbAAWjFgfWJgRLaTQhMLy5KNJINhsJLDrYrD5xLC6pLa5nGTR7oLq9bJQJMKTAXWJbbnR3RLJSoRMHv4pC5rkec6SaIrBLGw2r2XW1epcoqYeJiOXJYziEsOH2RBBw7lF56Yg5nGc6FScZOGJQPX2TmDFIfVTEBMSc4hLEw5KB6+rsJMH63X6pMf5hMQzBLCq5LD1ZLEJhTlfJiWXTA2GJYpMIcwPNc2O6TAuGRIPX1igDJg/PJmyYDcgXWwxMH1ApC53XcsHAJiVYcg2HJYZME0YpC5vWJkhLNJgLlDTAeFJhF/FQfVJkG6JiGXcomyJgOrJYhMErYqD53NJj7lRzBMDcoeGJhzoBJb3GJiN1qZBCJgWyJYpNF1LigAAXAJiNSJgzlGJgt/JkZLRy9TJgeHJhznFcuSZGw5MHJomjcuhLBqdcJiSaiTChMV1CYxy5LCqdXIAWy6+rJhCalTCN2JgdYH4WHJiGpTF7kDc43W2RMJTUZLQzBLFc4mr6+GJh2jTFmXJYyaEwuyc5Sag4xLZTQmG2WFJhxNaJYZMLJZSaEJoOHTR9/Ja+6JbdTqRNETRRNF1JLV4BLcAANYI5ToK1BLYJhWYJZwABq5NoJZ91JaAABdAZNS0ZLey9SJaRNYv5KM426JZmXuxKUJrKcL0lTzBLKzBKYJrVXvfGSol7EYWXJI27zF1JLQADq5NUrgYB4wAEEIV0comXI7wAFrCcPJgYWBTIIAETIN2JYmWuhMkdSdYCgOeJgueqRLFyzhfTi9bq4TC45MF49TuuXJlpONcogAC0hKB0gHDvZMEqRMpAANSq9crlbJAYADqwRDxGk0mIA4eCTQOeveXJdYAHqxNFdAeIAAQGCrOI0oHEAGVXTRJMGvgGCwRM7TAZMHwQGCvhM1rBMERIhMGAwdZJmtSqVTwNcwJEDJg19cvIADa4d9JhANDJnSLHJgrl6AAhFFAwpZDegjn7vhMGcvwABrJAFJgjl/TQpBBI4jl/AAN8TQhHDcv4ADcJBMDvpM+IYaeDAAhL+qd9SgycEJn7iEAA18Jf7nEcv4AIrJLIcv6aMcv4ADvhMHrJJ/AAbl/c6ZM/AAt9cv7nSIv7nLcv4AHrLl/TRpJBvgnjA==")); g.reset(); - g.setColor("#6633ff"); g.setBgColor("#6633ff"); var y = 240, speed = 5; function balloon(callback) { @@ -58,7 +58,7 @@ var scenes = [ if (y>60) setTimeout(balloon,0,callback); else callback(); } - fade(function() { + fade("#6633ff", function() { balloon(function() { g.setColor(-1); g.setFont("6x8",3); @@ -260,7 +260,7 @@ function move(dir) { Bangle.setLCDMode(); g.clear(); scenes[sceneNumber](); - if (sceneNumber>1) { + if (sceneNumber>2) { var l = scenes.length; for (var i=0;i Date: Thu, 15 Oct 2020 17:38:53 +0100 Subject: [PATCH 052/110] fix sanitycheck error --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 5939740ef..d60d81dd1 100644 --- a/apps.json +++ b/apps.json @@ -120,7 +120,7 @@ }, { "id": "mywelcome", "name": "Customised Welcome", - "shortname": "My Welcome", + "shortName": "My Welcome", "icon": "app.png", "version":"0.09", "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting", From 2eb134a8f0afefe8b8b9845c3fcc17f9c7ef3d91 Mon Sep 17 00:00:00 2001 From: Malte Kiefer <59220985+MalteKiefer@users.noreply.github.com> Date: Fri, 16 Oct 2020 07:33:29 +0200 Subject: [PATCH 053/110] added leading zero to hours and minutes --- apps/verticalface/app.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/verticalface/app.js b/apps/verticalface/app.js index 8503265ca..f9138335f 100644 --- a/apps/verticalface/app.js +++ b/apps/verticalface/app.js @@ -6,6 +6,14 @@ let currentHRM = "CALC"; function drawTimeDate() { var d = new Date(); var h = d.getHours(), m = d.getMinutes(), day = d.getDate(), month = d.getMonth(), weekDay = d.getDay(); + + if (h < 10) { + h = "0" + h; + } + + if (m < 10) { + m = "0" + h; + } var daysOfWeek = ["SUN", "MON", "TUE","WED","THU","FRI","SAT"]; var hours = (" "+h).substr(-2); From 7ab729ec7f7927cf1f3cca7d551ef48e7083a533 Mon Sep 17 00:00:00 2001 From: Malte Kiefer <59220985+MalteKiefer@users.noreply.github.com> Date: Fri, 16 Oct 2020 07:34:53 +0200 Subject: [PATCH 054/110] Update ChangeLog --- apps/verticalface/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/verticalface/ChangeLog b/apps/verticalface/ChangeLog index 4ba4f7ec4..e26120599 100644 --- a/apps/verticalface/ChangeLog +++ b/apps/verticalface/ChangeLog @@ -1,3 +1,4 @@ 0.04: Fixed day being displayed 0.05: Stop hours being displayed wrong if moving from 2 digits to 1 (fix #516) 0.06: Tweak sizing to allow widgets at top, and add widgets (fix #567) +0.07: Added leading zero to hours and minutes From f49ac99d00a821aebfdb7b2905a2fb3326ab1e2f Mon Sep 17 00:00:00 2001 From: Malte Kiefer <59220985+MalteKiefer@users.noreply.github.com> Date: Fri, 16 Oct 2020 07:36:04 +0200 Subject: [PATCH 055/110] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index d60d81dd1..0e0320bd7 100644 --- a/apps.json +++ b/apps.json @@ -1958,7 +1958,7 @@ "name": "Vertical watch face", "shortName":"Vertical Face", "icon": "app.png", - "version":"0.06", + "version":"0.07", "description": "A simple vertical watch face with the date. Heart rate monitor is toggled with BTN1", "tags": "clock", "type":"clock", From 991cd17f0082b68ff38b2ab467d251f0f6fd0f5d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 16 Oct 2020 09:34:48 +0100 Subject: [PATCH 056/110] simpletimer: Fix buzz regression from 0.06 --- apps.json | 2 +- apps/simpletimer/ChangeLog | 1 + apps/simpletimer/app.js | 10 ++++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index d60d81dd1..1d2c2ccd7 100644 --- a/apps.json +++ b/apps.json @@ -1736,7 +1736,7 @@ "id": "simpletimer", "name": "Timer", "icon": "app.png", - "version": "0.06", + "version": "0.07", "description": "Simple timer, useful when playing board games or cooking", "tags": "timer", "readme": "README.md", diff --git a/apps/simpletimer/ChangeLog b/apps/simpletimer/ChangeLog index 0a0d47126..f1f3a1ec0 100644 --- a/apps/simpletimer/ChangeLog +++ b/apps/simpletimer/ChangeLog @@ -4,3 +4,4 @@ 0.04: Remember last set time 0.05: Fix buzz that doesn't stop (fix #521) 0.06: Fix buzz error, remove '+' when timer running and add 'back' text (fix #577) +0.07: Fix buzz regression from 0.06 diff --git a/apps/simpletimer/app.js b/apps/simpletimer/app.js index f6332a8b7..e99761810 100644 --- a/apps/simpletimer/app.js +++ b/apps/simpletimer/app.js @@ -1,15 +1,19 @@ let counter = 0; let setValue = 0; -let counterInterval, alarmInterval; +let counterInterval, alarmInterval, buzzInterval; let state; let saved = require("Storage").readJSON("simpletimer.json",true) || {}; const DEBOUNCE = 50; function buzzAndBeep() { + buzzInterval = -1; return Bangle.buzz(1000, 1) .then(() => Bangle.beep(200, 3000)) - .then(() => setTimeout(buzzAndBeep, 5000)); + .then(() => { + if (buzzInterval==-1) + buzzInterval = setTimeout(buzzAndBeep, 5000); + }); } function outOfTime() { @@ -58,8 +62,10 @@ function countDown() { function clearIntervals() { if (alarmInterval) clearInterval(alarmInterval); if (counterInterval) clearInterval(counterInterval); + if (buzzInterval>0) clearTimeout(buzzInterval); alarmInterval = undefined; counterInterval = undefined; + buzzInterval = undefined; } function set(delta) { From c95069a5b6749a076c9896d75099a8e170380851 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 16 Oct 2020 11:42:33 +0100 Subject: [PATCH 057/110] mywelcome: Add birthday style --- apps.json | 2 +- apps/mywelcome/ChangeLog | 1 + apps/mywelcome/custom.html | 65 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 0c34f382d..9ecda0aa5 100644 --- a/apps.json +++ b/apps.json @@ -122,7 +122,7 @@ "name": "Customised Welcome", "shortName": "My Welcome", "icon": "app.png", - "version":"0.09", + "version":"0.10", "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting", "tags": "start,welcome", "custom":"custom.html", diff --git a/apps/mywelcome/ChangeLog b/apps/mywelcome/ChangeLog index 9545dbbfa..15a286604 100644 --- a/apps/mywelcome/ChangeLog +++ b/apps/mywelcome/ChangeLog @@ -11,3 +11,4 @@ 0.09: Allow welcome to run after a fresh install More useful app menu BTN2 now goes to menu on release +0.10: Add birthday style diff --git a/apps/mywelcome/custom.html b/apps/mywelcome/custom.html index 933a82e25..d0bb13538 100644 --- a/apps/mywelcome/custom.html +++ b/apps/mywelcome/custom.html @@ -3,11 +3,17 @@ - +
+

Style: +

Line 1:

Line 2:

Line 3 (smaller):

Line 4 (smaller):

+

This is currently Christmas-themed, but more themes will be added in the future.

@@ -21,9 +27,62 @@ function getApp() { var line2 = document.getElementById("line2").value; var line3 = document.getElementById("line3").value; var line4 = document.getElementById("line4").value; + var style = document.getElementById("style").value; // build the app's text using a templated String - return ` - (function() { + if (style=="Birthday") return `(function() { + var ib = require("heatshrink").decompress(atob("jEtwgHEhOZzOQCQwJBAAYVHAAYZEAwOTn/znIYECwOT/84DAwEBBQoYCCwOf+YKFDAILBn4rCBY4WHBYI5B/ALHKAQiHAAWfxILKBRIjBBawAKUoxrGBarVGbIoLLEhDLCBZYkIfYYYGCwYLMEgwKEBgoKGEoYhFBggKJEgQLVgUgBZMzmALKBRILYgYvKgYwjBZQ7LgALLAAoA=")); +var ir = require("heatshrink").decompress(atob("jEtwgHEhvd7vQCQwJBAAYVHAAYZEAwPT///noYECwIKBmYYGAgP//oxGCwPf+YKFDAILBn4rCBY//BQwLBHIItGAAffEQ4LPBRILM6YLKABSlGNYwLVaozZFBZYkIZYQLLEhD7DDAwWDBZgkGBQgMFBQwlDEIoADhnABREA5nMBasCoALJmcwBZQKJBbEDF5UDGEYLKHZcABZYAF")); +var ig = require("heatshrink").decompress(atob("jEtwgHEg93u9wCQwJBAAYVHAAYZEAwNz///m4YECwIKBmYYGAgP/+QxGCwN/+YKFDAILBn4rCBY//BQwLBHIItGAAd/EQ4LPBRILMuYLKABSlGNYwLVaozZFBZYkIZYQLLEhD7DDAwWDBZgkGBQgMFBQwlDEIoMEBRIkCBasCkALJmcwBZQKJBbEDF5UDGEYLKHZcABZYAFA")); + var igift = require("heatshrink").decompress(atob("q1QxH+ADOi0QbZ5nMHDQAbKgIACKa4ACKnJWVKghW0KgxWTKgxWyKhBWRKhBWwKhRWPKhRWuKhhWNKhhWtKpxWKKhys8KxBU8Ky5U+KypU/KyhU/KyhU/KynGKn5WTKn5WUKmHCADpJJE7uYABZUfKuuYKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/AAv+Kv5VT/wADyIAaKpIlbABZSEKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/ADNtKv6rdKzZVwKhAABy5V/Khw")); + + var W=240,H=160; + var blns = []; + function updateFlake(f) { + f.im = [ir,ig,ib][Math.round(Math.random()*100)%3]; + f.s = 0.4+Math.random(); + } + + for (var i=0;i<6;i++) { + var f = { + y:Math.random()*H,x:(0.5+(i<3?i:i+3))*W/9, + v:1+Math.random(),r:0, + t:(0.5+Math.random())*0.2, + }; + updateFlake(f); + blns.push(f); + } + + function draw() { + blns.forEach(f=>{ + var s = f.s*18; + g.clearRect(f.x-s,f.y-s*2,f.x+s,f.y+s*2); + }); + blns.forEach(f=>{ + f.y-=f.v;f.r+=f.t; + if (f.y<-22) { + f.y=H+22; + updateFlake(f); + } + g.drawImage(f.im,f.x,f.y,{rotate:Math.sin(f.r)/2,scale:f.s}); + }); + var x = W/2, y = H/2; + g.drawImage(igift,x-43,y-80); + g.setFont("6x8",2).setFontAlign(0,0); + g.drawString(${JSON.stringify(line1)},x,y+=20); + g.drawString(${JSON.stringify(line2)},x,y+=20); + g.setFont("6x8"); + g.drawString(${JSON.stringify(line3)},x,y+=20); + g.drawString(${JSON.stringify(line4)},x,y+=10); + g.flip(); + } + + Bangle.setLCDMode("doublebuffered") + g.clear().flip(); + g.clear().flip(); + setInterval(draw,50); +})()`; + // if (style=="Christmas") + return `(function() { var isnow = require("heatshrink").decompress(atob("iUUxH+AA/X64KICA4SPCKI1KBAIKFCIwOCFw4FHA4QEIBZoALFYwGKM5YRdHhxPGBJB9Ua5IYGYpzpRNxISOCKI1KA==")) var itree = require("heatshrink").decompress(atob("mtWxH+ADHHDTI0aGuXH5vNGmhqvTYIzBGtoxF6fTG4g4oGgQyBAAZssGoI0Ga1g1FGdo01ZgIAEGmHHNoLSuAAN/rdb0YFBGlgCBGYIABA4YArGYY1CGn4znAAM6GeVd5PQ5Iyurc/vQ0oGZFAn+d4XC3d5GddiGYIEBy+7zoEBGlFhoEcsQ9GT08+oFk1mkGdaVBMgNArnJ6/KzswGs/J6GlrlbqtbvPC5PCy8wGohniMIPJvIpCqmX3e7vI0BqhqlMIY0DqhtBqoEBa0xgBMIIoEqoABGQwzfsIhBv4qHABM50vQGjg1CGaN66DoBGt1ioGd5LoBGjo1PGYNhvLoCa7wnBqgvGA4YzCAgN5GUAsCqoDBmAHCAYU/wPQ0oSDGcBiDqkwAYcxoFd5PX6GdGjrIIqtUAAc3jk5vPC4fCy5pef5I2BTQMcnAHBy+7y95T0oADnFk1ekBpI2aGRUin7NGAA9hsIzVsIgHTAKZBZoPJ5LNDGhBpXGolcwOsrtcA4TNB3bNDGb/+sVin9AoGe6HX5InEvN/TkP+5XQwM/sRsBzqWB4QuKGjvC6HQ4QdDvKWBZYMwmAuHmFUCYNbqibX3fD5O7qolEZQQ0FBwgKDqgJBGiphEDwNUEgJbBFIQqCAgYOCB4IzCnE6GyhYFGoQnDABYzGAAQ1UAAo2NBoQSBnOB0t/Gjo2EABIPCoGe6HX4QzTGRIAEqtVF4QEBBQc4oE4y/J5PCvIxeABk/oADBvO73eXTyAyZMwM/Awd5vIOFGslAr2Av4PLNcU/jmA6HX5I1KasFcn8dTIOd5PJ4SZGGiNhAAIyNn0ckU+ZYe7AAJpJEYJnNGZk+n9kw9cBAcwGoN5aZg1JJJQABm8/oEjoDKC5ALCrUwqh/NrvQ6HDGp04n9doEdoE/sQJBZQZhCqgABGZk6zw0K/1dnVAoNAFwOlCYL1FubJBy4GCGh1AnOX4XC3YzHFYOeCgdV5PQ5OdD4rKBqqYNGYlbv+X3edGY3CGgKMDAAO7JAJgDAClcr2BEYgADaIZ0DL4uXGbDuB6HX5I1GsP+sNhOgWXIhBmWd4Od5PK4TwFGIJoBAYI2BAD0/jlcQoO7AAJaEGQQADGr0/sjNEvOdAoZmDGgw2ZsVAkeAZpQACGZI2VsU/kVGn1bZoPJZogpGGhA4GfRYwBoGC1mlBQbNFFoo0JNxAGCEod/wM6oFAn9iv/J6/Kzo1Ey9/MZQAKCg4GCFgTDEvPCSwI0BC5I0RN4ocEYYPQ5OdHgeXSwTFKGaJyKFYPC3f+MIdbpzFLAD4zB/1OqtbqtOGgYArGAIADGl9UAAI0wGQN5GoQ0vvIABGoI0uGYQABqo0zNOg0uaQY0/GllOGn40//w=")); From bbb3bca5a2713631efdf7b2cf3284bd86ce8f4a7 Mon Sep 17 00:00:00 2001 From: marko Date: Fri, 16 Oct 2020 14:37:32 -0400 Subject: [PATCH 058/110] First commit, app Mandel --- apps.json | 14 ++- apps/mandel/README.md | 7 ++ apps/mandel/mandel-icon.js | 1 + apps/mandel/mandel.app.js | 192 +++++++++++++++++++++++++++++++++++++ apps/mandel/mandel.info | 1 + apps/mandel/mandel.min.js | 163 +++++++++++++++++++++++++++++++ 6 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 apps/mandel/README.md create mode 100644 apps/mandel/mandel-icon.js create mode 100644 apps/mandel/mandel.app.js create mode 100644 apps/mandel/mandel.info create mode 100644 apps/mandel/mandel.min.js diff --git a/apps.json b/apps.json index 688518bb0..b1963974b 100644 --- a/apps.json +++ b/apps.json @@ -2238,7 +2238,6 @@ {"name":"worldclock.img","url":"worldclock-icon.js","evaluate":true} ] }, - { "id": "digiclock", "name": "Digital Clock Face", "shortName":"Digi Clock", @@ -2264,5 +2263,18 @@ {"name":"dsdrelay.app.js","url":"dsdrelay.app.js"}, {"name":"dsdrelay.img","url":"dsdrelay-icon.js","evaluate":true} ] + }, + { "id": "mandel", + "name": "Mandelbrot", + "shortName":"Mandel", + "icon": "mandel.png", + "version":"0.01", + "description": "Draw a zoomable Mandelbrot set", + "tags": "game", + "readme": "README.md", + "storage": [ + {"name":"mandel.app.js","url":"mandel.min.js"}, + {"name":"mandel.img","url":"mandel-icon.js","evaluate":true} + ] } ] diff --git a/apps/mandel/README.md b/apps/mandel/README.md new file mode 100644 index 000000000..de8148b53 --- /dev/null +++ b/apps/mandel/README.md @@ -0,0 +1,7 @@ +# Mandel + +Draw a colored rendition of the famous Mandelbrot set. Pushing button 2 activates zoom mode: the top and left edge of the zoom region can be moved up/down +with buttons 1 and 3 and left/right by touching the screen left right. Pushing button 2 again allows movement of the bottom and right edge in the same manner. +Pushing button 2 a third time renders the selected region full screen. + +The code uses inlined C code for perfomance reasons. Full source is provided on github. diff --git a/apps/mandel/mandel-icon.js b/apps/mandel/mandel-icon.js new file mode 100644 index 000000000..2c09ad91b --- /dev/null +++ b/apps/mandel/mandel-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkA/4A/AEGIACQX/C/4X3x4XX/AXV/4XsBoYYFC6IPFC5gWFGAgXSDAgXIXAYXGF5mPA4ICCF6QUGC5wWKI5YVKR5ovWL7CPZX6zvXC5KPMDBYXVFwgXOB4QWFC9GPC65pKC5aBLC/4X/C54A/ADo")) diff --git a/apps/mandel/mandel.app.js b/apps/mandel/mandel.app.js new file mode 100644 index 000000000..e6d8c766e --- /dev/null +++ b/apps/mandel/mandel.app.js @@ -0,0 +1,192 @@ + +var aux = new Float32Array(8); +var p_aux = E.getAddressOf(aux, true); +aux[0] = -2; +aux[1] = -1.5; +aux[2] = 1; +aux[3] = 1.5; + +var buf_height = 40; + +var frameX1=0, frameX2=239, frameY1=0, frameY2=239; +var frameCorner = 0; + +var imbuf = Graphics.createArrayBuffer(240, buf_height, 16); +var imbufaddr = E.getAddressOf(imbuf.buffer, true); +var mimg = { + width :imbuf.getWidth(), + height:imbuf.getHeight(), + bpp :16, + buffer:imbuf.buffer +}; + +var c = E.compiledC(` +// void mandel(int, int) +union shortbytes { + short s; + char b[2]; +}; +void mandel(float *p, short *ib) { + float mincx = p[0]; + float mincy = p[1]; + float maxcx = p[2]; + float maxcy = p[3]; + int minx = (int)p[4]; + int miny = (int)p[5]; + int maxx = (int)p[6]; + int maxy = (int)p[7]; + int pib = 0; + for (int y=miny; y-2 && zr<1 && zi>-1.5 && zi<1.5) { + float nr = zr*zr-zi*zi + cr; + zi = 2*zr*zi + ci; + zr = nr; + } + union shortbytes c, d; + c.s = niter | (niter << 7)&0x7ff | (niter<<13)&0xffff; + d.b[0] = c.b[1]; + d.b[1] = c.b[0]; + ib[pib++] = d.s; + } +} +`); + +function drawRectangle(x1, y1, x2, y2) { + if (frameCorner==1) g.setColor(1, 0, 0); + else g.setColor(1, 1, 1); + g.drawLine(x1, y1, x2, y1).drawLine(x1, y1, x1, y2); + if (frameCorner==2) g.setColor(1, 0, 0); + else g.setColor(1, 1, 1); + g.drawLine(x1, y2, x2, y2).drawLine(x2, y1, x2, y2); +} + +function restoreRow(y) { + mimg.width = 240; + mimg.height = 1; + aux[4] = 0; + aux[5] = y; + aux[6] = 240; + aux[7] = y+1; + c.mandel(p_aux, imbufaddr); + g.drawImage(mimg, 0, y); +} + +function restoreCol(x) { + mimg.width = 1; + mimg.height = 240; + aux[4] = x; + aux[5] = 0; + aux[6] = x+1; + aux[7] = 240; + c.mandel(p_aux, imbufaddr); + g.drawImage(mimg, x, 0); +} + +function moveUp() { + restoreCol(frameX1); + restoreCol(frameX2); + if (frameCorner==1 && frameY1>3) { + restoreRow(frameY1); + frameY1 -= 4; + } + if (frameCorner==2 && frameY2>3) { + restoreRow(frameY2); + frameY2 -= 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + +function moveDown() { + restoreCol(frameX1); + restoreCol(frameX2); + if (frameCorner==1 && frameY1<235) { + restoreRow(frameY1); + frameY1 += 4; + } + if (frameCorner==2 && frameY2<235) { + restoreRow(frameY2); + frameY2 += 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + +function moveRight() { + restoreRow(frameY1); + restoreRow(frameY2); + if (frameCorner==1 && frameX1<235) { + restoreCol(frameX1); + frameX1 += 4; + } + if (frameCorner==2 && frameX2<235) { + restoreCol(frameX2); + frameX2 += 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + +function moveLeft() { + restoreRow(frameY1); + restoreRow(frameY2); + if (frameCorner==1 && frameX1>3) { + restoreCol(frameX1); + frameX1 -= 4; + } + if (frameCorner==2 && frameX2>3) { + restoreCol(frameX2); + frameX2 -= 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + + +function toggleFrame() { + if (frameCorner<2) { + frameCorner++; + drawRectangle(frameX1, frameY1, frameX2, frameY2); + } + else { + frameCorner = 0; + var mincx = aux[0] + (aux[2]-aux[0])*frameX1/240.0; + var maxcx = aux[0] + (aux[2]-aux[0])*frameX2/240.0; + var mincy = aux[1] + (aux[3]-aux[1])*frameY1/240.0; + var maxcy = aux[1] + (aux[3]-aux[1])*frameY2/240.0; + aux[0] = mincx; + aux[1] = mincy; + aux[2] = maxcx; + aux[3] = maxcy; + drawIt(); + } +} + +setWatch(toggleFrame, BTN2, {repeat: true}); +setWatch(moveUp, BTN1, {repeat: true}); +setWatch(moveDown, BTN3, {repeat: true}); +Bangle.on('touch', function(button) { + switch(button) { + case 1: moveLeft(); break; + case 2: moveRight(); break; + } +}); + + +function drawIt() { + aux[4] = 0; + aux[5] = 0; + aux[6] = 240; + aux[7] = buf_height; + mimg.width = 240; + mimg.height = buf_height; + for (var y=0; y<240/buf_height; ++y) { + c.mandel(p_aux, imbufaddr); + aux[5] += buf_height; + aux[7] += buf_height; + g.drawImage(mimg, 0, y*buf_height); + } +} + +setTimeout(drawIt, 50); diff --git a/apps/mandel/mandel.info b/apps/mandel/mandel.info new file mode 100644 index 000000000..d4cddbc56 --- /dev/null +++ b/apps/mandel/mandel.info @@ -0,0 +1 @@ +{"id":"mandel","name":"Mandel","src":"mandel.app.js","icon":"mandel.img"} \ No newline at end of file diff --git a/apps/mandel/mandel.min.js b/apps/mandel/mandel.min.js new file mode 100644 index 000000000..0a1bd5fcd --- /dev/null +++ b/apps/mandel/mandel.min.js @@ -0,0 +1,163 @@ + +var aux = new Float32Array(8); +var p_aux = E.getAddressOf(aux, true); +aux[0] = -2; +aux[1] = -1.5; +aux[2] = 1; +aux[3] = 1.5; + +var buf_height = 40; + +var frameX1=0, frameX2=239, frameY1=0, frameY2=239; +var frameCorner = 0; + +var imbuf = Graphics.createArrayBuffer(240, buf_height, 16); +var imbufaddr = E.getAddressOf(imbuf.buffer, true); +var mimg = { + width :imbuf.getWidth(), + height:imbuf.getHeight(), + bpp :16, + buffer:imbuf.buffer +}; + +var c = (function(){ + var bin=atob("0O0EepDtAFrQ7QFK0O0COpDtAzqf7URK/e7nei3p8EMX7pBa0O0Fev3u53rF68V8F+6QStDtBnr97ud6ACMX7pCK0O0Hev3u53q47gAqF+6QmvfuABq/7ggaTEVi2gzrAwaeRgHrRgYqRvfuCCqu6wUDQkUTRETaB+4QKnPuxXq47sd6HyNn7od6B+4QSsfuhGq47sd6c+5kenbuhWpn7od6n+0iesfuhFrw7kd6de6kWgE7E/D/AxPQ9O7CevHuEPoO3fTu4Xrx7hD6CdW07sF68e4Q+gTdtO7ievHuEPoR1NgBwPMKAEPqQzMDQ8PzByBg8wcHY/MPJyb4EnABMrXnATSp5yfuR2rw7mUKp+6nanfup3rn7icKdu4merDuYHrG573o8IMAAHBDAAAAAA=="); + return { + mandel:E.nativeCall(1, "void(int, int)", bin), + }; +})(); + +function drawRectangle(x1, y1, x2, y2) { + if (frameCorner==1) g.setColor(1, 0, 0); + else g.setColor(1, 1, 1); + g.drawLine(x1, y1, x2, y1).drawLine(x1, y1, x1, y2); + if (frameCorner==2) g.setColor(1, 0, 0); + else g.setColor(1, 1, 1); + g.drawLine(x1, y2, x2, y2).drawLine(x2, y1, x2, y2); +} + +function restoreRow(y) { + mimg.width = 240; + mimg.height = 1; + aux[4] = 0; + aux[5] = y; + aux[6] = 240; + aux[7] = y+1; + c.mandel(p_aux, imbufaddr); + g.drawImage(mimg, 0, y); +} + +function restoreCol(x) { + mimg.width = 1; + mimg.height = 240; + aux[4] = x; + aux[5] = 0; + aux[6] = x+1; + aux[7] = 240; + c.mandel(p_aux, imbufaddr); + g.drawImage(mimg, x, 0); +} + +function moveUp() { + restoreCol(frameX1); + restoreCol(frameX2); + if (frameCorner==1 && frameY1>3) { + restoreRow(frameY1); + frameY1 -= 4; + } + if (frameCorner==2 && frameY2>3) { + restoreRow(frameY2); + frameY2 -= 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + +function moveDown() { + restoreCol(frameX1); + restoreCol(frameX2); + if (frameCorner==1 && frameY1<235) { + restoreRow(frameY1); + frameY1 += 4; + } + if (frameCorner==2 && frameY2<235) { + restoreRow(frameY2); + frameY2 += 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + +function moveRight() { + restoreRow(frameY1); + restoreRow(frameY2); + if (frameCorner==1 && frameX1<235) { + restoreCol(frameX1); + frameX1 += 4; + } + if (frameCorner==2 && frameX2<235) { + restoreCol(frameX2); + frameX2 += 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + +function moveLeft() { + restoreRow(frameY1); + restoreRow(frameY2); + if (frameCorner==1 && frameX1>3) { + restoreCol(frameX1); + frameX1 -= 4; + } + if (frameCorner==2 && frameX2>3) { + restoreCol(frameX2); + frameX2 -= 4; + } + drawRectangle(frameX1, frameY1, frameX2, frameY2); +} + + +function toggleFrame() { + if (frameCorner<2) { + frameCorner++; + drawRectangle(frameX1, frameY1, frameX2, frameY2); + } + else { + frameCorner = 0; + var mincx = aux[0] + (aux[2]-aux[0])*frameX1/240.0; + var maxcx = aux[0] + (aux[2]-aux[0])*frameX2/240.0; + var mincy = aux[1] + (aux[3]-aux[1])*frameY1/240.0; + var maxcy = aux[1] + (aux[3]-aux[1])*frameY2/240.0; + aux[0] = mincx; + aux[1] = mincy; + aux[2] = maxcx; + aux[3] = maxcy; + drawIt(); + } +} + +setWatch(toggleFrame, BTN2, {repeat: true}); +setWatch(moveUp, BTN1, {repeat: true}); +setWatch(moveDown, BTN3, {repeat: true}); +Bangle.on('touch', function(button) { + switch(button) { + case 1: moveLeft(); break; + case 2: moveRight(); break; + } +}); + + +function drawIt() { + aux[4] = 0; + aux[5] = 0; + aux[6] = 240; + aux[7] = buf_height; + mimg.width = 240; + mimg.height = buf_height; + for (var y=0; y<240/buf_height; ++y) { + c.mandel(p_aux, imbufaddr); + aux[5] += buf_height; + aux[7] += buf_height; + g.drawImage(mimg, 0, y*buf_height); + } +} + +setTimeout(drawIt, 50); From 951490ea54fea71c7d2889b6bcc03eb6f65c6ab1 Mon Sep 17 00:00:00 2001 From: marko Date: Fri, 16 Oct 2020 14:45:35 -0400 Subject: [PATCH 059/110] Add icon --- apps/mandel/mandel.png | Bin 0 -> 353 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/mandel/mandel.png diff --git a/apps/mandel/mandel.png b/apps/mandel/mandel.png new file mode 100644 index 0000000000000000000000000000000000000000..64dcb8b1b75f2d827903d787ff9bdef4fe2bc034 GIT binary patch literal 353 zcmV-n0iOPeP)sq%cu8u z!H)q4P!{M0lmmvRcLOjYO&jCQ` zn?4IYjXea9Aj}L<08rDT5w8A1(Tw64 zCMI3)2BZ_Ep6`AG)I?U--}g`b>O`s6Ki Date: Wed, 21 Oct 2020 09:09:51 +0100 Subject: [PATCH 060/110] accelrec: Increase record time to 5 second Calculate the time moving in graph display Trigger on 1.04g now, and record 10 samples before trigger --- apps.json | 2 +- apps/accelrec/ChangeLog | 3 +++ apps/accelrec/app.js | 23 ++++++++++++++++------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index 7fa521098..a0be4d7e8 100644 --- a/apps.json +++ b/apps.json @@ -2109,7 +2109,7 @@ "name": "Acceleration Recorder", "shortName":"Accel Rec", "icon": "app.png", - "version":"0.01", + "version":"0.02", "interface": "interface.html", "description": "This app puts the Bangle's accelerometer into 100Hz mode and reads 2 seconds worth of data after movement starts. The data can then be exported back to the PC.", "tags": "", diff --git a/apps/accelrec/ChangeLog b/apps/accelrec/ChangeLog index 5560f00bc..7327ae25f 100644 --- a/apps/accelrec/ChangeLog +++ b/apps/accelrec/ChangeLog @@ -1 +1,4 @@ 0.01: New App! +0.02: Increase record time to 5 second + Calculate the time moving in graph display + Trigger on 1.04g now, and record 10 samples before trigger diff --git a/apps/accelrec/app.js b/apps/accelrec/app.js index 5fb91e2e4..23b265e9e 100644 --- a/apps/accelrec/app.js +++ b/apps/accelrec/app.js @@ -1,23 +1,24 @@ var acc; var HZ = 100; -var SAMPLES = 2*HZ; // 2 seconds +var SAMPLES = 5*HZ; // 5 seconds var SCALE = 5000; -var THRESH = 1.01; +var THRESH = 1.04; var accelx = new Int16Array(SAMPLES); var accely = new Int16Array(SAMPLES); // North var accelz = new Int16Array(SAMPLES); // Into clock face var accelIdx = 0; -var lastAccel = undefined; +var lastAccel; function accelHandlerTrigger(a) {"ram" if (a.mag*2>THRESH) { // *2 because 8g mode tStart = getTime(); g.drawString("Recording",g.getWidth()/2,g.getHeight()/2,1); Bangle.removeListener('accel',accelHandlerTrigger); Bangle.on('accel',accelHandlerRecord); - if (lastAccel) accelHandlerRecord(lastAccel); + lastAccel.forEach(accelHandlerRecord); accelHandlerRecord(a); } - lastAccel = a; + if (lastAccel.length>10) lastAccel.shift(); + lastAccel.push(a); } function accelHandlerRecord(a) {"ram" var i = accelIdx++; @@ -29,7 +30,8 @@ function accelHandlerRecord(a) {"ram" function recordStart() {"ram" Bangle.setLCDTimeout(0); // force LCD on accelIdx = 0; - lastAccel = undefined; + lastAccel = []; + Bangle.accelWr(0x18,0b01110100); // off, +-8g Bangle.accelWr(0x1B,0x03 | 0x40); // 100hz output, ODR/2 filter Bangle.accelWr(0x18,0b11110100); // +-8g Bangle.setPollInterval(10); // 100hz input @@ -42,8 +44,9 @@ function recordStart() {"ram" function recordStop() {"ram" - console.log("Length:",getTime()-tStart); + //console.log("Length:",getTime()-tStart); Bangle.setPollInterval(80); // default poll interval + Bangle.accelWr(0x18,0b01101100); // off, +-4g Bangle.accelWr(0x1B,0x0); // default 12.5hz output Bangle.accelWr(0x18,0b11101100); // +-4g Bangle.removeListener('accel',accelHandlerRecord); @@ -76,9 +79,14 @@ function showData() { // work out stats var maxAccel = 0; + var tStart = SAMPLES, tEnd = 0; var vel = 0, maxVel = 0; for (var i=0;i0.1) { + if (itEnd) tEnd=i; + } if (a>maxAccel) maxAccel=a; vel += a/HZ; if (vel>maxVel) maxVel=vel; @@ -87,6 +95,7 @@ function showData() { g.setFont("6x8").setFontAlign(1,0); g.drawString("Max Y Accel: "+maxAccel.toFixed(2)+" g",g.getWidth()-14,g.getHeight()-50); g.drawString("Max Y Vel: "+maxVel.toFixed(2)+" m/s",g.getWidth()-14,g.getHeight()-40); + g.drawString("Time moving: "+(tEnd-tStart)/HZ,g.getWidth()-14,g.getHeight()-30); //console.log("End Velocity "+vel); g.setFont("6x8").setFontAlign(0,0,1); g.drawString("FINISH",g.getWidth()-4,g.getHeight()/2); From 192e45e5aabb5cd5157be2fdafe01a188a3e58bc Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 21 Oct 2020 09:13:24 +0100 Subject: [PATCH 061/110] minor tweak --- apps/accelrec/app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/accelrec/app.js b/apps/accelrec/app.js index 23b265e9e..b60f38049 100644 --- a/apps/accelrec/app.js +++ b/apps/accelrec/app.js @@ -16,9 +16,10 @@ function accelHandlerTrigger(a) {"ram" Bangle.on('accel',accelHandlerRecord); lastAccel.forEach(accelHandlerRecord); accelHandlerRecord(a); + } else { + if (lastAccel.length>10) lastAccel.shift(); + lastAccel.push(a); } - if (lastAccel.length>10) lastAccel.shift(); - lastAccel.push(a); } function accelHandlerRecord(a) {"ram" var i = accelIdx++; From 02640f2aa1fbd83c72d90e18948a0ace38e4835c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 21 Oct 2020 09:19:10 +0100 Subject: [PATCH 062/110] tweak --- apps/accelrec/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/accelrec/app.js b/apps/accelrec/app.js index b60f38049..65f2a63ca 100644 --- a/apps/accelrec/app.js +++ b/apps/accelrec/app.js @@ -96,7 +96,7 @@ function showData() { g.setFont("6x8").setFontAlign(1,0); g.drawString("Max Y Accel: "+maxAccel.toFixed(2)+" g",g.getWidth()-14,g.getHeight()-50); g.drawString("Max Y Vel: "+maxVel.toFixed(2)+" m/s",g.getWidth()-14,g.getHeight()-40); - g.drawString("Time moving: "+(tEnd-tStart)/HZ,g.getWidth()-14,g.getHeight()-30); + g.drawString("Time moving: "+(tEnd-tStart)/HZ+" s",g.getWidth()-14,g.getHeight()-30); //console.log("End Velocity "+vel); g.setFont("6x8").setFontAlign(0,0,1); g.drawString("FINISH",g.getWidth()-4,g.getHeight()/2); From 0ec2bad835b28252ab1d0f01e2f4ce02eac30b96 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 21 Oct 2020 14:05:21 +0100 Subject: [PATCH 063/110] bledetect: Ensure manufacturer:undefined doesn't overflow screen --- apps.json | 2 +- apps/bledetect/ChangeLog | 3 ++- apps/bledetect/bledetect.js | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index a0be4d7e8..49d1422d9 100644 --- a/apps.json +++ b/apps.json @@ -1423,7 +1423,7 @@ "name": "BLE Detector", "shortName":"BLE Detector", "icon": "bledetect.png", - "version":"0.02", + "version":"0.03", "description": "Detect BLE devices and show some informations.", "tags": "app,bluetooth,tool", "readme": "README.md", diff --git a/apps/bledetect/ChangeLog b/apps/bledetect/ChangeLog index 520ccfa2f..e52015f04 100644 --- a/apps/bledetect/ChangeLog +++ b/apps/bledetect/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! -0.02: Fixed issue with wrong device informations \ No newline at end of file +0.02: Fixed issue with wrong device informations +0.03: Ensure manufacturer:undefined doesn't overflow screen diff --git a/apps/bledetect/bledetect.js b/apps/bledetect/bledetect.js index 2831b5b62..ca8699f9a 100644 --- a/apps/bledetect/bledetect.js +++ b/apps/bledetect/bledetect.js @@ -18,7 +18,7 @@ function showDeviceInfo(device){ value: device.rssi }, "manufacturer": { - value: device.manufacturer + value: device.manufacturer===undefined ? "-" : device.manufacturer } }; @@ -56,4 +56,4 @@ function waitMessage() { } scan(); -waitMessage(); \ No newline at end of file +waitMessage(); From 785b48f47a3a460a991ab2160573bb45899c71ac Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 21 Oct 2020 14:48:30 +0100 Subject: [PATCH 064/110] * Added progress bar on Bangle.js for uploads * Provide a proper error message in case JSON decode fails * Check you're connecting with a Bangle.js of the correct version --- CHANGELOG.md | 3 +++ core | 2 +- loader.js | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b57c91bb..c243093c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,3 +26,6 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * Added ability to specify dependencies (used for `notify` at the moment) * Fixed Promise-based bug in removeApp * Fixed bin/firmwaremaker and bin/apploader CLI to handle binary file uploads correctly +* Added progress bar on Bangle.js for uploads +* Provide a proper error message in case JSON decode fails +* Check you're connecting with a Bangle.js of the correct version diff --git a/core b/core index 62615f6ea..06204c852 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 62615f6ea4855381e0b4b4b74f8ca69aa594181e +Subproject commit 06204c852d5cd8101fc8e23ef8d43903c25a4edc diff --git a/loader.js b/loader.js index 248d1c2a9..77174a24c 100644 --- a/loader.js +++ b/loader.js @@ -11,10 +11,20 @@ if (window.location.host=="banglejs.com") { 'This is not the official Bangle.js App Loader - you can try the
Official Version here.'; } -var APP_SOURCECODE_URL; +var RECOMMENDED_VERSION = "2v08"; +// could check http://www.espruino.com/json/BANGLEJS.json for this + (function() { let username = "espruino"; let githubMatch = window.location.href.match(/\/(\w+)\.github\.io/); if (githubMatch) username = githubMatch[1]; - APP_SOURCECODE_URL = `https://github.com/${username}/BangleApps/tree/master/apps`; + Const.APP_SOURCECODE_URL = `https://github.com/${username}/BangleApps/tree/master/apps`; })(); + +function onFoundDeviceInfo(deviceId, deviceVersion) { + if (deviceId != "BANGLEJS") { + showToast(`You're using ${deviceId}, not a Bangle.js. Did you want espruino.com/apps instead?` ,"warning", 20000); + } else if (versionLess(deviceVersion, RECOMMENDED_VERSION)) { + showToast(`You're using an old Bangle.js firmware (${deviceVersion}). You can update with the instructions here` ,"warning", 20000); + } +} From 2ce854323d62f7b63d97e0cc817336898225cd57 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 21 Oct 2020 16:44:21 +0100 Subject: [PATCH 065/110] pull latest --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 06204c852..f3092088e 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 06204c852d5cd8101fc8e23ef8d43903c25a4edc +Subproject commit f3092088eea15b2014a668a99ed9815d97dddb6d From 51d699d6dd1f9d7faf94d394fcc6f491408723bd Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 22 Oct 2020 17:02:35 +0100 Subject: [PATCH 066/110] Added automatic charge animation --- apps.json | 12 ++++++++++++ apps/chargeanim/ChangeLog | 1 + apps/chargeanim/app-icon.js | 1 + apps/chargeanim/app.js | 28 ++++++++++++++++++++++++++++ apps/chargeanim/boot.js | 1 + apps/chargeanim/icon.png | Bin 0 -> 1178 bytes 6 files changed, 43 insertions(+) create mode 100644 apps/chargeanim/ChangeLog create mode 100644 apps/chargeanim/app-icon.js create mode 100644 apps/chargeanim/app.js create mode 100644 apps/chargeanim/boot.js create mode 100644 apps/chargeanim/icon.png diff --git a/apps.json b/apps.json index 49d1422d9..bfae0931a 100644 --- a/apps.json +++ b/apps.json @@ -447,6 +447,18 @@ {"name": "weather.json"} ] }, + { "id": "chargeanim", + "name": "Charge Animation", + "icon": "icon.png", + "version":"0.01", + "description": "When charging, show a sideways charging animation and keep the screen on. When removed from the charger load the clock again.", + "tags": "battery", + "storage": [ + {"name":"chargeanim.app.js","url":"app.js"}, + {"name":"chargeanim.boot.js","url":"boot.js"}, + {"name":"chargeanim.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "widbat", "name": "Battery Level Widget", "icon": "widget.png", diff --git a/apps/chargeanim/ChangeLog b/apps/chargeanim/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/chargeanim/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/chargeanim/app-icon.js b/apps/chargeanim/app-icon.js new file mode 100644 index 000000000..0252d9ac2 --- /dev/null +++ b/apps/chargeanim/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ASwoAIF/4pZABYuuGDIv/F/4v/F/4vt1Ivt6Zft1Ivu6fNF9nT6a+JF8SNBF9ouBXxQvhFwQvrRoTuLF8BeDXxQvfFwYAFGgwvdRoYAGd840GX84AC5rCLF8ReLF8wMJF8K+CRpAvmNhQvhdwIuKF8SNLF8guLF8JdML8Yv/F/4v/F/4v/GDguYAH4A/AGYA==")) diff --git a/apps/chargeanim/app.js b/apps/chargeanim/app.js new file mode 100644 index 000000000..c2702337a --- /dev/null +++ b/apps/chargeanim/app.js @@ -0,0 +1,28 @@ +g.clear().flip(); +var imgbat = require("heatshrink").decompress(atob("nlWhH+AH4A/AH4AHwoAQHXQ8pHf47rF6YAXHXQ8OHVo8NHf47/Hf47/Hf47/Hf47/Hf47/Hf47r1I766Y756Z351I766ayTHco6BHfCxBHfI6CdyY7jHQQ73WIayUHcQ6DHew6EHeqxEdyo7gOwo70HQqyVHbyxFHeo6GHeY6Hdyo7cWI47zHQ6yWHbY6IHeKxIABa9MHbI6TQJo7YHUI7YWMKzbQKQYOHdYYPHcK9IWJw7sDKA7hHTA7pWKA7qDKQ7gdwwaTHcyxSHcR2ZHcwZUHcqxUHcLuEHSo7kHSw7gWLI7kHS47iHTA7fdwKxYHcQ6ZHb46bO8A76ADg7/Hf47/Hf47/Hf47/Hf47/Hf47/HbY8uHRg8tHRwA/AH4AsA==")); +var imgbubble = require("heatshrink").decompress(atob("ikQhH+AAc0AAgKEAAwRFCpgMDnVerwULCIuCCYoUGCQQQBnQ9MA4Q3GChI5DEpATIJYISKCY46LCYwANCa4UObJ7INeCoSOCpAOI")); + + var W=240,H=240; +var bubbles = []; +for (var i=0;i<10;i++) { + bubbles.push({y:Math.random()*H,ly:0,x:(0.5+(i<5?i:i+8))*W/18,v:0.6+Math.random(),s:0.5+Math.random()}); +} + +function anim() { + /* we don't use any kind of buffering here. Just draw one image + at a time (image contains a background) too, and there is minimal + flicker. */ + var mx = 120, my = 120; + bubbles.forEach(f=>{ + f.y-=f.v;if (f.y<-24) f.y=H+8; + g.drawImage(imgbubble,f.y,f.x,{scale:f.s}); + }); + g.drawImage(imgbat, mx,my,{rotate:Math.sin(getTime()*2)*0.5-Math.PI/2}); + g.flip(); +} + +setInterval(anim,20); + +Bangle.on("charging", isCharging => { + if (!isCharging) load(); +}); diff --git a/apps/chargeanim/boot.js b/apps/chargeanim/boot.js new file mode 100644 index 000000000..cbc78681b --- /dev/null +++ b/apps/chargeanim/boot.js @@ -0,0 +1 @@ +Bangle.on("charging", isCharging => { if (isCharging) load("chargeanim.app.js"); }); diff --git a/apps/chargeanim/icon.png b/apps/chargeanim/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9860c323dd336b65a32e11d571957d677cc16701 GIT binary patch literal 1178 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGoY)RhkE)4%caKYZ?lNlIT{5@S9 zLn`LHog0{cIZWjE|8J#}mX$`Wbn=~`)_Be9wuE%Qhlhb^)UJ<=-y|P2ikta9R`&7m zxqaMW&(>QZQ5qgKjh(y_3*N0%(qx*rEH@_U_q&D0UX!g#!{YB(ANsjhb!$!k-_L*N zU)~bR*p?^(Ms_ATcUg}VK7P0~U-2V%!zo4o(5*}M{QA4|e*W^n@LM-_ad)WBoz2f6 zni;u&S%IAD3~hzEv*im-jutQNI>}_mVf2#Ger?U?iEnS%GZ*nWXm*?OJ2D@b#Pe3Z z{zulsov)5g;l8o==QVkTW1;J(8s)ca*uSSNEz$R>(kbPP?6cdz?AIIb+_33p_7k z#O8Vl7vvl{{!vgqdf!I-SMQP%Sf1o|?(`CVZS7R9S!-y(wCuER&oieG+o`uaEsK(|h#`eZ*QHP z{QlnlWn%UWiHxj@hSA@??Qvhr$lSs@XMV<_Dcs-p9Jf|bR*RLN|KI%U7H6Og3#&-W z5ucqmzuFyT;}H-kNIdkqORgd955o}_pIvr-TYPQb2IL%IPz0OyvTq*8J;tt?n&uC! z?p_pj+{no60#v43V|L5-t4l!c0R~1!SHVX~{Vy0Bq%Qtp=it~8aPMG;a3_z< ztRSUUyZ&Ff>^GHliGQHS8QHIVb^;~R1`HC>KYf;VCJNer-BO&IrF^ll-n?i=ytJK9 z?Gue)DYH)RSPffXancw@W(l+MLZlRA^z6jfT zR_>a3e6yS0)#7EXg|-QGxe}i_`-*nSqvF>fBgI+ zSMI+6&|yhTf9|e)E_xT}<|HO3oqak<=?sh1n|c_ob8g)AlE(*VieP| Date: Thu, 22 Oct 2020 17:09:33 +0100 Subject: [PATCH 067/110] remove grey background for icons --- css/main.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css/main.css b/css/main.css index 4acddf0dc..8e91aec3d 100644 --- a/css/main.css +++ b/css/main.css @@ -5,7 +5,7 @@ } .avatar img { border-radius: 5px 5px 5px 5px; - background: #ddd; + background: #fff; } #toastcontainer { position:fixed; From a1d7a5480dde63c0aaa0f632a5390dc3c4ab3364 Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Thu, 22 Oct 2020 14:19:19 -0700 Subject: [PATCH 068/110] Spelling Corrected lose message grammar. Should be "Loser", not "Looser". --- apps/blackjack/blackjack.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/blackjack/blackjack.app.js b/apps/blackjack/blackjack.app.js index ccc437e58..bbee8137b 100644 --- a/apps/blackjack/blackjack.app.js +++ b/apps/blackjack/blackjack.app.js @@ -59,7 +59,7 @@ function hitMe() { if(playerWeight == 21) EndGameMessdage('WINNER'); else if(playerWeight > 21) - EndGameMessdage('LOOSER'); + EndGameMessdage('LOSER'); } function calcWeight(hand, hideCard) { @@ -188,4 +188,4 @@ setWatch(hitMe, BTN4, {repeat:true, edge:"falling"}); setWatch(stand, BTN5, {repeat:true, edge:"falling"}); setWatch(startGame, BTN1, {repeat:true, edge:"falling"}); -startGame(); \ No newline at end of file +startGame(); From 117bfd52b3ef29583e15e82d314163baa6ba46e0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 23 Oct 2020 15:49:16 +0100 Subject: [PATCH 069/110] Skip double buffering, use 240x240 size --- apps.json | 2 +- apps/mywelcome/ChangeLog | 1 + apps/mywelcome/custom.html | 46 ++++++++++++++++++-------------------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/apps.json b/apps.json index bfae0931a..b1e18f3c1 100644 --- a/apps.json +++ b/apps.json @@ -122,7 +122,7 @@ "name": "Customised Welcome", "shortName": "My Welcome", "icon": "app.png", - "version":"0.10", + "version":"0.11", "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting", "tags": "start,welcome", "custom":"custom.html", diff --git a/apps/mywelcome/ChangeLog b/apps/mywelcome/ChangeLog index 15a286604..bca4ff2dd 100644 --- a/apps/mywelcome/ChangeLog +++ b/apps/mywelcome/ChangeLog @@ -12,3 +12,4 @@ More useful app menu BTN2 now goes to menu on release 0.10: Add birthday style +0.11: Skip double buffering, use 240x240 size diff --git a/apps/mywelcome/custom.html b/apps/mywelcome/custom.html index d0bb13538..b021b7b1a 100644 --- a/apps/mywelcome/custom.html +++ b/apps/mywelcome/custom.html @@ -30,33 +30,29 @@ function getApp() { var style = document.getElementById("style").value; // build the app's text using a templated String if (style=="Birthday") return `(function() { - var ib = require("heatshrink").decompress(atob("jEtwgHEhOZzOQCQwJBAAYVHAAYZEAwOTn/znIYECwOT/84DAwEBBQoYCCwOf+YKFDAILBn4rCBY4WHBYI5B/ALHKAQiHAAWfxILKBRIjBBawAKUoxrGBarVGbIoLLEhDLCBZYkIfYYYGCwYLMEgwKEBgoKGEoYhFBggKJEgQLVgUgBZMzmALKBRILYgYvKgYwjBZQ7LgALLAAoA=")); -var ir = require("heatshrink").decompress(atob("jEtwgHEhvd7vQCQwJBAAYVHAAYZEAwPT///noYECwIKBmYYGAgP//oxGCwPf+YKFDAILBn4rCBY//BQwLBHIItGAAffEQ4LPBRILM6YLKABSlGNYwLVaozZFBZYkIZYQLLEhD7DDAwWDBZgkGBQgMFBQwlDEIoADhnABREA5nMBasCoALJmcwBZQKJBbEDF5UDGEYLKHZcABZYAF")); -var ig = require("heatshrink").decompress(atob("jEtwgHEg93u9wCQwJBAAYVHAAYZEAwNz///m4YECwIKBmYYGAgP/+QxGCwN/+YKFDAILBn4rCBY//BQwLBHIItGAAd/EQ4LPBRILMuYLKABSlGNYwLVaozZFBZYkIZYQLLEhD7DDAwWDBZgkGBQgMFBQwlDEIoMEBRIkCBasCkALJmcwBZQKJBbEDF5UDGEYLKHZcABZYAFA")); + var ib = require("heatshrink").decompress(atob("jk0ggGDhOZAAWQCYwMEBxAMFAAIaHyc/+c5DgwMC/84Dg4aCBgwcDBoOf+Y4GBoQEBn4zCI44DBDQ4NEyf4BpgoIBoefxINMBhApEBrQAKBrrrGWpANZHBT7FBpYqIFAYcJBggNOFQwoFDgwMHBwoMIBwYMKBrkykANLmcwBu0zBrMDBv4AFN5gA/ADY")); +var ir = require("heatshrink").decompress(atob("jk0ggGDhvdAAXQCYwMEBxAMFAAIaH6c/+c9DgwMC/8zDg4aC/4YCHIwNB7/zHAwNCAgM/DQwqDAYIaHBonT/oNMFBAND74NNBhApEBrQAKBrrrGWpANZHBT7FBpYqIFAYcJBgkA5oMF7gNFFQwoFDgwMHHIoMIAAPM5gMKBrk0oANLmcwBu0zBrMDBv4AFN5gA/ADYA=")); +var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/+c3DgwMC/8yDg4aC/4YCHIwNBv/zHAwNCAgM/DQwqDAYIaHBolz+4NMFBANDv8nBpgMIFIgNaABQNddYy1IBrI4KfYoNLFRAoDDhIMEgHnBgt+BooqGFAoqGBg4OFBhAODBhQNcmUgBpczmAN2mYNZgYN/AApvMAH4Ab")); var igift = require("heatshrink").decompress(atob("q1QxH+ADOi0QbZ5nMHDQAbKgIACKa4ACKnJWVKghW0KgxWTKgxWyKhBWRKhBWwKhRWPKhRWuKhhWNKhhWtKpxWKKhys8KxBU8Ky5U+KypU/KyhU/KyhU/KynGKn5WTKn5WUKmHCADpJJE7uYABZUfKuuYKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/AAv+Kv5VT/wADyIAaKpIlbABZSEKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/ADNtKv6rdKzZVwKhAABy5V/Khw")); - var W=240,H=160; + var W=240,H=240; var blns = []; function updateFlake(f) { f.im = [ir,ig,ib][Math.round(Math.random()*100)%3]; - f.s = 0.4+Math.random(); + f.s = 0.4+Math.random()*0.5; } for (var i=0;i<6;i++) { var f = { - y:Math.random()*H,x:(0.5+(i<3?i:i+3))*W/9, - v:1+Math.random(),r:0, - t:(0.5+Math.random())*0.2, + y:Math.random()*H,x:(0.5+(i<3?i:i+5))*W/11, + v:0.5+Math.random(),r:0, + t:(0.5+Math.random())*0.15, }; updateFlake(f); blns.push(f); } function draw() { - blns.forEach(f=>{ - var s = f.s*18; - g.clearRect(f.x-s,f.y-s*2,f.x+s,f.y+s*2); - }); blns.forEach(f=>{ f.y-=f.v;f.r+=f.t; if (f.y<-22) { @@ -76,26 +72,30 @@ var ig = require("heatshrink").decompress(atob("jEtwgHEg93u9wCQwJBAAYVHAAYZEAwNz g.flip(); } - Bangle.setLCDMode("doublebuffered") - g.clear().flip(); - g.clear().flip(); + g.clear(); setInterval(draw,50); })()`; // if (style=="Christmas") return `(function() { - var isnow = require("heatshrink").decompress(atob("iUUxH+AA/X64KICA4SPCKI1KBAIKFCIwOCFw4FHA4QEIBZoALFYwGKM5YRdHhxPGBJB9Ua5IYGYpzpRNxISOCKI1KA==")) + var isnow = require("heatshrink").decompress(atob("jEagQWTgfAAocf+gFDh4FDiARBggVB3AFBl3Agf8jfkn/AgX/v/9/+Agfv/2//YrBgfwh4wCgfghYFJCIYdFFIw1EIIpNFL44FFOIoAP")); var itree = require("heatshrink").decompress(atob("mtWxH+ADHHDTI0aGuXH5vNGmhqvTYIzBGtoxF6fTG4g4oGgQyBAAZssGoI0Ga1g1FGdo01ZgIAEGmHHNoLSuAAN/rdb0YFBGlgCBGYIABA4YArGYY1CGn4znAAM6GeVd5PQ5Iyurc/vQ0oGZFAn+d4XC3d5GddiGYIEBy+7zoEBGlFhoEcsQ9GT08+oFk1mkGdaVBMgNArnJ6/KzswGs/J6GlrlbqtbvPC5PCy8wGohniMIPJvIpCqmX3e7vI0BqhqlMIY0DqhtBqoEBa0xgBMIIoEqoABGQwzfsIhBv4qHABM50vQGjg1CGaN66DoBGt1ioGd5LoBGjo1PGYNhvLoCa7wnBqgvGA4YzCAgN5GUAsCqoDBmAHCAYU/wPQ0oSDGcBiDqkwAYcxoFd5PX6GdGjrIIqtUAAc3jk5vPC4fCy5pef5I2BTQMcnAHBy+7y95T0oADnFk1ekBpI2aGRUin7NGAA9hsIzVsIgHTAKZBZoPJ5LNDGhBpXGolcwOsrtcA4TNB3bNDGb/+sVin9AoGe6HX5InEvN/TkP+5XQwM/sRsBzqWB4QuKGjvC6HQ4QdDvKWBZYMwmAuHmFUCYNbqibX3fD5O7qolEZQQ0FBwgKDqgJBGiphEDwNUEgJbBFIQqCAgYOCB4IzCnE6GyhYFGoQnDABYzGAAQ1UAAo2NBoQSBnOB0t/Gjo2EABIPCoGe6HX4QzTGRIAEqtVF4QEBBQc4oE4y/J5PCvIxeABk/oADBvO73eXTyAyZMwM/Awd5vIOFGslAr2Av4PLNcU/jmA6HX5I1KasFcn8dTIOd5PJ4SZGGiNhAAIyNn0ckU+ZYe7AAJpJEYJnNGZk+n9kw9cBAcwGoN5aZg1JJJQABm8/oEjoDKC5ALCrUwqh/NrvQ6HDGp04n9doEdoE/sQJBZQZhCqgABGZk6zw0K/1dnVAoNAFwOlCYL1FubJBy4GCGh1AnOX4XC3YzHFYOeCgdV5PQ5OdD4rKBqqYNGYlbv+X3edGY3CGgKMDAAO7JAJgDAClcr2BEYgADaIZ0DL4uXGbDuB6HX5I1GsP+sNhOgWXIhBmWd4Od5PK4TwFGIJoBAYI2BAD0/jlcQoO7AAJaEGQQADGr0/sjNEvOdAoZmDGgw2ZsVAkeAZpQACGZI2VsU/kVGn1bZoPJZogpGGhA4GfRYwBoGC1mlBQbNFFoo0JNxAGCEod/wM6oFAn9iv/J6/Kzo1Ey9/MZQAKCg4GCFgTDEvPCSwI0BC5I0RN4ocEYYPQ5OdHgeXSwTFKGaJyKFYPC3f+MIdbpzFLAD4zB/1OqtbqtOGgYArGAIADGl9UAAI0wGQN5GoQ0vvIABGoI0uGYQABqo0zNOg0uaQY0/GllOGn40//w=")); - var W=240,H=160; + var W=g.getWidth(),H=g.getHeight(); var flakes = []; for (var i=0;i<10;i++) { - flakes.push({y:Math.random()*H,x:(0.5+(i<5?i:i+5))*W/15,v:1+Math.random(),s:0.4+Math.random(),r:0,t:0.1*(Math.random()-0.5)}); + var f = { + y:Math.random()*H, + x:(0.5+(i<5?i:i+5))*W/15, + v:0.7+Math.random(), + s:0.6+Math.random(), + r:0, + t:0.1*(Math.random()-0.5) + }; + f.v = f.s * (1+Math.random()); + flakes.push(f); } function draw() { - flakes.forEach(f=>{ - g.clearRect(f.x-16,f.y-16,f.x+16,f.y+16); - }); flakes.forEach(f=>{ f.y+=f.v;f.r+=f.t; if (f.y>H+16) f.y=-8; @@ -112,9 +112,7 @@ var ig = require("heatshrink").decompress(atob("jEtwgHEg93u9wCQwJBAAYVHAAYZEAwNz g.flip(); } - Bangle.setLCDMode("doublebuffered") - g.clear().flip(); - g.clear().flip(); + g.clear(); setInterval(draw,50); })(); `; From 47a5253383b96892a377809a9be278859da39640 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 26 Oct 2020 16:35:33 +0000 Subject: [PATCH 070/110] emu --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index b1e18f3c1..9680742ea 100644 --- a/apps.json +++ b/apps.json @@ -453,6 +453,7 @@ "version":"0.01", "description": "When charging, show a sideways charging animation and keep the screen on. When removed from the charger load the clock again.", "tags": "battery", + "allow_emulator":true, "storage": [ {"name":"chargeanim.app.js","url":"app.js"}, {"name":"chargeanim.boot.js","url":"boot.js"}, From 021a96cb4d84542f19b575d815a34344396c5200 Mon Sep 17 00:00:00 2001 From: singintime Date: Tue, 27 Oct 2020 00:46:16 +0100 Subject: [PATCH 071/110] petrock v0.01 --- apps.json | 13 ++++++++ apps/petrock/ChangeLog | 1 + apps/petrock/app-icon.js | 1 + apps/petrock/app.js | 70 +++++++++++++++++++++++++++++++++++++++ apps/petrock/petrock.png | Bin 0 -> 4213 bytes 5 files changed, 85 insertions(+) create mode 100644 apps/petrock/ChangeLog create mode 100644 apps/petrock/app-icon.js create mode 100644 apps/petrock/app.js create mode 100644 apps/petrock/petrock.png diff --git a/apps.json b/apps.json index 9680742ea..768551284 100644 --- a/apps.json +++ b/apps.json @@ -2307,5 +2307,18 @@ {"name":"mandel.app.js","url":"mandel.min.js"}, {"name":"mandel.img","url":"mandel-icon.js","evaluate":true} ] + }, + { + "id": "petrock", + "name": "Pet rock", + "icon": "petrock.png", + "version": "0.01", + "description": "A virtual pet rock with wobbly eyes", + "tags": "game", + "type": "app", + "storage": [ + {"name": "petrock.app.js", "url": "app.js"}, + {"name": "petrock.img", "url": "app-icon.js", "evaluate": true} + ] } ] diff --git a/apps/petrock/ChangeLog b/apps/petrock/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/petrock/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/petrock/app-icon.js b/apps/petrock/app-icon.js new file mode 100644 index 000000000..e05d47f85 --- /dev/null +++ b/apps/petrock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("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")) diff --git a/apps/petrock/app.js b/apps/petrock/app.js new file mode 100644 index 000000000..c2804efd9 --- /dev/null +++ b/apps/petrock/app.js @@ -0,0 +1,70 @@ +const buffer = Graphics.createArrayBuffer(61, 61, 2, { msb: true }); +const eye = { + width: buffer.getWidth(), + height: buffer.getWidth(), + bpp: 2, + transparent: 2, + buffer: buffer.buffer, +}; +const rock = { + width: 240, + height: 160, + bpp: 2, + buffer: require("heatshrink").decompress(atob("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")) +}; + +let px = 0; +let py = 0; +let vx = 0; +let vy = 0; +let ax = 0; +let ay = 0; +let gx = 0; +let gy = 0; + +function draw() { + vx += ax; + vy += ay; + px += vx; + py += vy; + + const pp = Math.sqrt(px * px + py * py); + + if (pp > 14) { + const vv = Math.sqrt(vx * vx + vy * vy); + const alpha = Math.atan2(px, py); + const ratio = 14 / pp; + + px *= ratio; + py *= ratio; + vx = -0.9 * vv * Math.sin(alpha); + vy = -0.9 * vv * Math.cos(alpha); + } + + buffer.setColor(2); + buffer.fillRect(0, 0, 60, 60); + buffer.setColor(3); + buffer.fillCircle(30, 30, 30); + buffer.setColor(0); + buffer.fillCircle(30 + px, 30 + py, 16); + + g.drawImage(eye, 55, 90); + g.drawImage(eye, 125, 90); +} + +Bangle.setLCDPower(1); +Bangle.setLCDTimeout(0); + +g.clear(); +g.drawImage(rock, 0, 40); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +Bangle.on('accel', (accel) => { + gx += 0.1 * (accel.x - gx); + gy += 0.1 * (accel.y - gy); + ax = 90 * gx - 100 * accel.x; + ay = 90 * gy - 100 * accel.y; + draw(); +}); diff --git a/apps/petrock/petrock.png b/apps/petrock/petrock.png new file mode 100644 index 0000000000000000000000000000000000000000..d17283e1cfc25aa72b05e23676dc9f485d9bd4f7 GIT binary patch literal 4213 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 Date: Wed, 28 Oct 2020 08:25:41 +0000 Subject: [PATCH 072/110] Fix newline in 'BTN3 to reload' --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index f3092088e..b08532283 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit f3092088eea15b2014a668a99ed9815d97dddb6d +Subproject commit b08532283ca10f55f249097df847b2e52c740d31 From 1f2ccce17b72923385b99a648f36849b4c0fc0d4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Oct 2020 08:51:41 +0000 Subject: [PATCH 073/110] petrock: Ensure eyes are white even if a widget (eg Bluetooth) changes the draw color --- apps.json | 2 +- apps/petrock/ChangeLog | 1 + apps/petrock/app.js | 9 ++++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 768551284..660de544a 100644 --- a/apps.json +++ b/apps.json @@ -2312,7 +2312,7 @@ "id": "petrock", "name": "Pet rock", "icon": "petrock.png", - "version": "0.01", + "version": "0.02", "description": "A virtual pet rock with wobbly eyes", "tags": "game", "type": "app", diff --git a/apps/petrock/ChangeLog b/apps/petrock/ChangeLog index 5560f00bc..fef39743a 100644 --- a/apps/petrock/ChangeLog +++ b/apps/petrock/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Ensure eyes are white even if a widget (eg Bluetooth) changes the draw color diff --git a/apps/petrock/app.js b/apps/petrock/app.js index c2804efd9..dc394a2ef 100644 --- a/apps/petrock/app.js +++ b/apps/petrock/app.js @@ -6,12 +6,14 @@ const eye = { transparent: 2, buffer: buffer.buffer, }; -const rock = { +function getRock() { + return { width: 240, height: 160, bpp: 2, buffer: require("heatshrink").decompress(atob("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")) }; +} let px = 0; let py = 0; @@ -48,6 +50,7 @@ function draw() { buffer.setColor(0); buffer.fillCircle(30 + px, 30 + py, 16); + g.reset(); // ensure we're drawing in white g.drawImage(eye, 55, 90); g.drawImage(eye, 125, 90); } @@ -55,8 +58,8 @@ function draw() { Bangle.setLCDPower(1); Bangle.setLCDTimeout(0); -g.clear(); -g.drawImage(rock, 0, 40); +g.clear(1); // ensure we're drawing in white +g.drawImage(getRock(), 0, 40); Bangle.loadWidgets(); Bangle.drawWidgets(); From aedd35e7d47693493a6fb7d75e17b3bf1b7c2243 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Oct 2020 08:51:52 +0000 Subject: [PATCH 074/110] Decrease chunk size - makes progress indicator update more often on Bangle, which looks better --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index b08532283..e2775902a 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit b08532283ca10f55f249097df847b2e52c740d31 +Subproject commit e2775902a3e3d88a1f6378fc33290ac6c3d9a1a5 From d0082775c5aaa97b7b8a97de678a10e0dace1e49 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Oct 2020 13:26:01 +0000 Subject: [PATCH 075/110] bootloader: Stop LCD timeout being disabled on first run (when there is no settings.json) --- apps.json | 2 +- apps/boot/ChangeLog | 1 + apps/boot/boot0.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 660de544a..bf6a1b637 100644 --- a/apps.json +++ b/apps.json @@ -4,7 +4,7 @@ "tags": "tool,system", "type":"bootloader", "icon": "bootloader.png", - "version":"0.21", + "version":"0.22", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "storage": [ {"name":".boot0","url":"boot0.js"}, diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index d2f68fd0e..7e9fd4a81 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -20,3 +20,4 @@ 0.19: Tweaks to simplify code and lower memory usage 0.20: Allow Gadgetbridge to work even with programmable:off 0.21: Handle echo off char from Gadgetbridge app when programmable:off (fix #558) +0.22: Stop LCD timeout being disabled on first run (when there is no settings.json) diff --git a/apps/boot/boot0.js b/apps/boot/boot0.js index 630252dea..550513b11 100644 --- a/apps/boot/boot0.js +++ b/apps/boot/boot0.js @@ -50,7 +50,7 @@ if (!Bangle.F_BEEPSET) { }); }; } -Bangle.setLCDTimeout(s.timeout); +if (s.timeout!==undefined) Bangle.setLCDTimeout(s.timeout); if (!s.timeout) Bangle.setLCDPower(1); E.setTimeZone(s.timezone); delete s; From 5feb3c611375312944134924bd8bf8f547a671da Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 28 Oct 2020 15:17:56 +0000 Subject: [PATCH 076/110] miplant: Adjust alignment for >1 device found --- apps.json | 2 +- apps/miplant/ChangeLog | 1 + apps/miplant/app.js | 14 +++++++------- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index bf6a1b637..0bf59c041 100644 --- a/apps.json +++ b/apps.json @@ -1737,7 +1737,7 @@ "name": "Xiaomi Plant Sensor", "shortName":"Mi Plant", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Reads and displays data from Xiaomi bluetooth plant moisture sensors", "tags": "xiaomi,mi,plant,ble,bluetooth", "storage": [ diff --git a/apps/miplant/ChangeLog b/apps/miplant/ChangeLog index 5560f00bc..71da064cb 100644 --- a/apps/miplant/ChangeLog +++ b/apps/miplant/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Adjust alignment for >1 device found diff --git a/apps/miplant/app.js b/apps/miplant/app.js index f26bfc5b8..b6c4ab89a 100644 --- a/apps/miplant/app.js +++ b/apps/miplant/app.js @@ -49,19 +49,19 @@ eg. { */ function show(event) { g.reset().setFont("6x8"); - var y = 45 + 50*Object.keys(deviceInfo).indexOf(event.id); + var y = 45 + 55*Object.keys(deviceInfo).indexOf(event.id); g.drawString(event.id.substr(0,17),0,y); - g.drawImage(getImgHum(),0,y+15); + g.drawImage(getImgHum(),0,y+10); g.setFont("6x8",2); var t = (event.moisture===undefined) ? "?" : event.moisture; - g.drawString((t+" ").substr(0,3),35,y+25,true); - g.drawImage(getImgFert(),80,y+15); + g.drawString((t+" ").substr(0,3),35,y+20,true); + g.drawImage(getImgFert(),80,y+10); t = Math.round(event.fertility) || "?"; - g.drawString((t+" ").substr(0,3), 120, y+25, true); - g.drawImage(getImgTemp(),160,y+15); + g.drawString((t+" ").substr(0,3), 120, y+20, true); + g.drawImage(getImgTemp(),160,y+10); t = Math.round(event.temperature) || "?"; - g.drawString((t+" ").substr(0,3), 180, y+25, true); + g.drawString((t+" ").substr(0,3), 180, y+20, true); g.flip(); } From 59afadc55a0506b6015e387770048050cacd3cf5 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 6 Nov 2020 12:02:49 +0000 Subject: [PATCH 077/110] Added smartibot controller to allow controlling the Smartibot robot from Bangle.js --- apps.json | 12 + apps/smartibot/ChangeLog | 1 + apps/smartibot/app-icon.js | 1 + apps/smartibot/app.js | 150 ++++++++++++ apps/smartibot/app.png | Bin 0 -> 2221 bytes apps/smartibot/watchface.svg | 433 ++++++++++++++++++++++++++++++++++ apps/smartibot/watchface2.svg | 100 ++++++++ 7 files changed, 697 insertions(+) create mode 100644 apps/smartibot/ChangeLog create mode 100644 apps/smartibot/app-icon.js create mode 100644 apps/smartibot/app.js create mode 100644 apps/smartibot/app.png create mode 100644 apps/smartibot/watchface.svg create mode 100644 apps/smartibot/watchface2.svg diff --git a/apps.json b/apps.json index 0bf59c041..e089a6b13 100644 --- a/apps.json +++ b/apps.json @@ -2320,5 +2320,17 @@ {"name": "petrock.app.js", "url": "app.js"}, {"name": "petrock.img", "url": "app-icon.js", "evaluate": true} ] + }, + { "id": "smartibot", + "name": "Smartibot controller", + "shortName":"Smartibot", + "icon": "app.png", + "version":"0.01", + "description": "Control a [Smartibot Robot](https://thecraftyrobot.net/) straight from your Bangle.js", + "tags": "", + "storage": [ + {"name":"smartibot.app.js","url":"app.js"}, + {"name":"smartibot.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/smartibot/ChangeLog b/apps/smartibot/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/smartibot/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/smartibot/app-icon.js b/apps/smartibot/app-icon.js new file mode 100644 index 000000000..b118983c1 --- /dev/null +++ b/apps/smartibot/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkA7oA/AH4At6c9AZIAL7//CAP/+YWB//9F50zC4MzmYGEABYSBABIXL/4AKC/4XV+YUFn4XPYIQACXoIXQFIQXTI4Pzn5LCI6AACmfTU/4XV6YhLABfzDYUznvdmczAwixBC4/fDAICBCAKnBC4LBCn4aCLw/96YMCAYokCABHf/4jIGIIuJKQQNHCwIuKBwaeFA45JKE4g3BO4IANCIIYCAgjuMEwIDCCwY4BJJKaBK4JaDCQaABn5KIBwXfR4PT/oEEfwgAFBAQPCIIQXBDQRlBC44jCC4K5CYoXfQQYvKMQP/maPDn4vCPBAgCeAzGD6ZfIBoIWGeAY4BBQwACmfzBZHTn5PCAH4A/AFQ")) diff --git a/apps/smartibot/app.js b/apps/smartibot/app.js new file mode 100644 index 000000000..5d26be471 --- /dev/null +++ b/apps/smartibot/app.js @@ -0,0 +1,150 @@ +/*digitalWrite([D4,D6],1) +digitalWrite([D10,D11],1)*/ + +function drawBGBtn() { + var c1 = g.setColor("#ff8100").getColor(); + var c2 = g.setColor("#6beaff").getColor(); + g.drawImage({ + width : 240, height : 240, bpp : 2, + palette : new Uint16Array([0,c1,c2,0xFFFF]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4AngNVADFAHf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hdn/6oDBv/1AYNf/o76/472OYQ70HgNXAYNVAYY7/HdgARHf47jr6qBABPVHfX1Hf47/Hf47/Hf47/Hf47/Hf47/HY/9q44Fqo7yGAI6E/tVv47/Hf7vqHYrvBHeX/745DHAP3AgI7xGYV//o7BA4Y7yWwK3FHef/6tXHfIAGHf47/Hf47/Hf47/Hf47Pq/VFgoAJq53p/o7Pvo7pv4DCVQPVq4DBOIIDCAgK1EHctfFYQ7LB4Y7nGAI7CF4V/XgVfBYfVHdI4DF4d/H4Q7Cr7/FHcxwCHZSCDHdIwBUogAFYIIMFHcwuBUwqEFeIQ7qF4R4II5A7nWgLjFIwgKGHc5sBVAwABBIKCGHc4xCNoyBBfQ47oGRBEIHdK0CVQgHHHdZvCPAl/WRA7qWgJwDOwSyHHdQ1FOwP/CA47oOYQ2EXIZFBHdjlDWgX1XAi2HHcwuBGYn9A4S8DPAo7lFwPXNYR0COQYGBAIJIBHdFfWITnD/q7Be4Q+Bv47rFYNXHYI1CIIS6BB4TwEHcpnDGQhECBAZIDHdADFq/1IgY3CHeTtB/6sBG4g7qUwQ7DHQIABHe1f//9PIP1XAI7zOgY+BO97vEOwJxCPAPVHeTrDAAJ4BPIIFCHdfVHYboDegRCCr4KEHcorCGYj7EWoJLBHdSpBdAY7FIgKwBBYo7ldgbiEYAj5FHdAvCHQ6ECI4w7mF4LhEWo6+FHcwAUHf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/HcgA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AEEC1WqwAd2hQcBAAOgDuhXCAAZbWDow8WDgoABDuSTELTAddDg5aVDrhYIeKjtGPC0qDpOoDtxYKSyYdLSyCyKDqRZMWiCUKDqRZMWiAcLWiIdcShg7faRyUMDqBZOaRzuMDqBZOeBwcNDp5ZOaRwcODtbQOeBwddaBw7f0A7cDtUqHduoHbgdqCQuv/47f//6A4o7R3//9QlIDqIAC1f//wdQgRVGHcKZGwA7PDISSGDqbUFLowdKhQZHHcIhF0A7PdwI7ieAo7QDALvKDqDVGeAodKlQYMHbJeI1A7OSBA7aaw47PdxgdQeBodPdxg7Wa44dOdxo7WMA4dKdyI7XbA47NCoQAIHaIcKMIg7NDpSWDHZrQDLJY7NDpiWCHZrQCLJg7/HazSCHZu/O/47/HamqHdItDHZrSLLIQ7NSpf+HaJaDA4YAGHZoAISgo7PLQY7kdwY7KDogWHHbZgHDp7wCRwg7bbATuEDp4XHHbZfHDp7wN0AdJhTuRLKDwMHaheIDqCQCHcLWFDqDwCZggAEwAdJgQUIEJA7QKoQ7hTIo7KDoyzLHa4dXeAI7JDhIABd5TuFHZYdGKwIlIHaqZBagwdR1ZVGAAWoDpcqCxG/TAwdVHbodk0AdLhQ7cDqA7dDruADpcCHbgdQDhYABLLgdQHbodNlQcN1Ad6aBgABhQ7cDpzQNgECLLgdODhrwPLJwdNShzSPDriUOaRxZQDpiUPaRpZQWhgcQDry0KLCKWLWSCWMWSAdfSxJYSSxYdTSxBYTPBLQSPBJ2UPBIdVLQwcVDo6UUDw4cXDryYCZqoAGhTOWAH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AjA=")) +}); +} + +function drawBGAccel() { + var c1 = g.setColor("#ff8100").getColor(); + var c2 = g.setColor("#6beaff").getColor(); + g.drawImage({ + width : 240, height : 240, bpp : 2, + palette : new Uint16Array([0,c1,c2,0xFFFF]), + buffer : require("heatshrink").decompress(atob("AH4A/AH4A/AH4A/AH4A/AH4AngNVADFAHf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hdn/6oDBv/1AYNf/o72G4Vf/47yOYQ74PANXAYNVAYY7/HdgARHf47jr6qBABP1Hf47/Hf47/Hf47/Hf47/Hf47/Hf47D/tXHAtVHeY0CAAQGBv47xGAI7/HeqzGd4I7y//fHIY4B+4EBHeIzCv/9HYIHDHeS2BW4o7z//Vq475AAw7/Hf47/Hf47/Hf47/HZ9X6osFABNXO9P9HZ99HdN/PASqB6tXAYJxBAYQEBWog7lr4rCHZYPDHc4wBHYQvCv68Cr4LDQ4Q7nHAYvDHY1ff4o7mGgQ7EPYQ7CQQY7pGAKlEAArBBBgo7mFwKmFQgrxCHdQvCPBBHIHc60BcYpGEBQw7nNgKoGAAIJBQQw7nGIRtGQIL6HHdAyIIhA7pWgSqEA447rN4R4Ev6yIHdS0BOAZ2CWQ47qGop2B/4QHHdBzCGwi5DIoI7scoa0C+q4EWw47mFwIzE/oHCXgZ4FHcouB+5rCWgRyDPYIBBJAI7or6xCc4f9HwL3CIoQ7rFwNXHYI1CIIS6BB4g7oM4YyEGgYICJAY7oAYtX+pEDG4Q7rNQQ7DdoP/Xgo/DHdw6BAAI72r///p5B+o71OgPVq4+BHd6vCAYJ2BdgLyC6o7v6rsEBIR4BPIIFCHdo0COwQABPoJCCr4KEHcorCGYj7EWoJLBHdR0BdAY7FIgP9BwILEHcrsDcQjAEfIo7oF4R2GQgZHGHcwvBcIi1HI4o7mACg7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47kAH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ACECwA75hWgHfMq1A751Wqd3I7BeHEKHYLw4lQ7BeHA6BeHDuCeHDuCeHDuCeHA6DeGzuEeGzuEeHB5COujxGHXA7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/AAMgHZsIHdegHZsKHVUCHZ+AHdMKHZ4PGAEcqHZ+oHdOqHZ4HGd0Y7ReFAqBHaDwolQ7ReFAyBHaDwndwIASeExlCACLwmdwIASeEw6TeEzuUeEw77WfcAlQ6T1A7lhQ7T0A7leAQpGVI5NCd0oyDHaI6meAQ7Qd0wqDHaDumeAY7Qd04zCHaA6oeAI7Pd1ArCHZ7uoeAQ7Pd1IABHZ46qAA47HAGY7/Hf47/Hf47/Hf47/Hf47/Hf47/Hf47/Hf8AlQ5BAAeoHecKHYugHecCHYuAduwADeHTu0eAzu0eAzu1eAo62eAbu2eAju2eAju3eAY64eALu4eATu4eATu5AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AXA==")) +}); +} + +function findDevices() { + E.showMenu(); + E.showMessage("Searching..."); + NRF.findDevices(function(devices) { + if (!devices.length) { + E.showPrompt("No Smartibot found.\nTry again?").then(function(x) { + if (x) findDevices(); else load(); + }); + } else { + var m = { "": {title:"Smartibots"} }; + devices.forEach(dev=>{ + m[dev.id.substr(0,17)] = () => startConnectChoose(dev); + }); + m["Search again"] = () => findDevices(); + m["Back"] = () => load(); + E.showMenu(m); + } + }, {timeout : 2000, filters : [{ name : "Espruino SMARTIBOT" }] }); +} + +function startConnectChoose(device) { + E.showMenu({ + "": {title:"Control Method"}, + "Accelerometer" : () => startConnectAccel(device), + "Button" : () => startConnectBtn(device), + "Back": () => load(), + }); +} + +function startConnectBtn(device) { + E.showMenu(); + startConnect(device, + "\x03\x10var w=digitalWrite.bind(null,[D4,D6,D10,D11])\n", + function(gatt, write) { + function setMotors(val) { write(`\x10w(${val})\n`); } + drawBGBtn(); + g.reset().setFont("6x8",2).setFontAlign(0,0,1).drawString("BACK", 230,200); + var state = 0; + var watches = [ + setWatch(e=>setMotors(state = (state&0b1100) | e.state), BTN4, {repeat:true, edge:0}), + setWatch(e=>setMotors(state = (state&0b0011) | (e.state<<2)), BTN5, {repeat:true, edge:0}), + setWatch(() => { + g.clear(); + watches.forEach(clearWatch); + write(`\x10w(0)\n`); + setTimeout(()=>{ + gatt.disconnect() + findDevices(); + },500); + }, BTN3, {repeat:true}) + ]; + }); +} + +function startConnectAccel(device) { + E.showMenu(); + startConnect(device, + "\x03\x10function w(x,y,z,v){var a=analogWrite;a(D4,x);a(D6,y);a(D10,z);a(D11,v);}\n", + function(gatt, write) { + drawBGAccel(); + g.reset().setFont("6x8",2).setFontAlign(0,0,1).drawString("BACK", 230,200); + Bangle.on("accel", function(a) { + var v = [0,0,0,0]; + if (a.z<-0.5) { + var vel = 0, rot = 0; + if (a.y<-0.2) vel = -(a.y+0.2); + if (a.y>0.2) vel = a.y-0.2; + if (a.x<-0.2) rot = -(a.x+0.2); + if (a.x>0.2) rot = a.x-0.2; + var rl = Math.round((vel+rot)*200)/100; + var rr = Math.round((vel-rot)*200)/100; + v[0] = rl>0 ? rl:0; + v[1] = rl<0 ? -rl:0; + v[2] = rr>0 ? rr:0; + v[3] = rr<0 ? -rr:0; + write(`\x10w(${v.join(",")})\n`); + } + }); + setWatch(() => { + g.clear(); + Bangle.removeAllListeners("accel"); + write(`\x10w(0,0,0,0)\n`); + setTimeout(()=>{ + gatt.disconnect() + findDevices(); + },500); + }, BTN3, {repeat:0}) + }); +} + +function startConnect(device, text, callback) { + var gatt, tx; + var busy; + function write(data) { + var cmd = function() { + return tx.writeValue(data); + }; + if (!busy) busy=Promise.resolve().then(cmd).then(()=>busy=false); + else busy = busy.then(cmd).then(()=>busy=false); + } + + E.showMessage("Connecting..."); + return device.gatt.connect().then(function(d) { + gatt = d; + return d.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); + }).then(function(s) { + return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); + }).then(function(c) { + E.showMessage("Uploading..."); + tx = c; + function sender(resolve, reject) { + if (text.length) { + tx.writeValue(text.substr(0,20)).then(function() { + sender(resolve, reject); + }).catch(reject); + text = text.substr(20); + } else { + resolve(); + } + } + return new Promise(sender); + }).then(function() { + callback(gatt, write); + }); +} + +findDevices(); diff --git a/apps/smartibot/app.png b/apps/smartibot/app.png new file mode 100644 index 0000000000000000000000000000000000000000..2b39faf58877625d704e39291391746c88432882 GIT binary patch literal 2221 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 literal 0 HcmV?d00001 diff --git a/apps/smartibot/watchface.svg b/apps/smartibot/watchface.svg new file mode 100644 index 000000000..e37276379 --- /dev/null +++ b/apps/smartibot/watchface.svg @@ -0,0 +1,433 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/apps/smartibot/watchface2.svg b/apps/smartibot/watchface2.svg new file mode 100644 index 000000000..448e5e6c8 --- /dev/null +++ b/apps/smartibot/watchface2.svg @@ -0,0 +1,100 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + From baf2ae0ada0059296b614c75aabe732e1c50cd31 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 6 Nov 2020 12:20:02 +0000 Subject: [PATCH 078/110] quick tweak --- apps/smartibot/app.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/smartibot/app.js b/apps/smartibot/app.js index 5d26be471..88ea5e276 100644 --- a/apps/smartibot/app.js +++ b/apps/smartibot/app.js @@ -53,15 +53,15 @@ function startConnectChoose(device) { function startConnectBtn(device) { E.showMenu(); startConnect(device, - "\x03\x10var w=digitalWrite.bind(null,[D4,D6,D10,D11])\n", + "\x03\x10var w=digitalWrite.bind(null,[D4,D6,D11,D10])\n", function(gatt, write) { function setMotors(val) { write(`\x10w(${val})\n`); } drawBGBtn(); g.reset().setFont("6x8",2).setFontAlign(0,0,1).drawString("BACK", 230,200); var state = 0; var watches = [ - setWatch(e=>setMotors(state = (state&0b1100) | e.state), BTN4, {repeat:true, edge:0}), - setWatch(e=>setMotors(state = (state&0b0011) | (e.state<<2)), BTN5, {repeat:true, edge:0}), + setWatch(e=>setMotors(state = (state&0b0011) | (e.state<<2)), BTN4, {repeat:true, edge:0}), + setWatch(e=>setMotors(state = (state&0b1100) | e.state), BTN5, {repeat:true, edge:0}), setWatch(() => { g.clear(); watches.forEach(clearWatch); @@ -86,18 +86,18 @@ function startConnectAccel(device) { var v = [0,0,0,0]; if (a.z<-0.5) { var vel = 0, rot = 0; - if (a.y<-0.2) vel = -(a.y+0.2); + if (a.y<-0.2) vel = a.y+0.2; if (a.y>0.2) vel = a.y-0.2; - if (a.x<-0.2) rot = -(a.x+0.2); + if (a.x<-0.2) rot = a.x+0.2; if (a.x>0.2) rot = a.x-0.2; - var rl = Math.round((vel+rot)*200)/100; + var rl = Math.round(-(vel+rot)*200)/100; var rr = Math.round((vel-rot)*200)/100; - v[0] = rl>0 ? rl:0; - v[1] = rl<0 ? -rl:0; - v[2] = rr>0 ? rr:0; - v[3] = rr<0 ? -rr:0; - write(`\x10w(${v.join(",")})\n`); + v[0] = (rl>0) ? rl:0; + v[1] = (rl<0) ? -rl:0; + v[2] = (rr>0) ? rr:0; + v[3] = (rr<0) ? -rr:0; } + write(`\x10w(${v.join(",")})\n`); }); setWatch(() => { g.clear(); From feaf011beef6abe5223ea249e6bc9563c5b1540c Mon Sep 17 00:00:00 2001 From: Nico Kaiser Date: Mon, 2 Nov 2020 19:57:24 +0100 Subject: [PATCH 079/110] Add a watch face and a widget for NodeConf Remote --- apps.json | 24 ++++++++ apps/ncrclk/ChangeLog | 1 + apps/ncrclk/app-icon.js | 1 + apps/ncrclk/app.js | 129 ++++++++++++++++++++++++++++++++++++++++ apps/ncrclk/app.png | Bin 0 -> 5893 bytes apps/widncr/ChangeLog | 1 + apps/widncr/widget.js | 5 ++ apps/widncr/widget.png | Bin 0 -> 3915 bytes 8 files changed, 161 insertions(+) create mode 100644 apps/ncrclk/ChangeLog create mode 100644 apps/ncrclk/app-icon.js create mode 100644 apps/ncrclk/app.js create mode 100644 apps/ncrclk/app.png create mode 100644 apps/widncr/ChangeLog create mode 100644 apps/widncr/widget.js create mode 100644 apps/widncr/widget.png diff --git a/apps.json b/apps.json index e089a6b13..3c04f292a 100644 --- a/apps.json +++ b/apps.json @@ -2332,5 +2332,29 @@ {"name":"smartibot.app.js","url":"app.js"}, {"name":"smartibot.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "widncr", + "name": "NCR Logo Widget", + "icon": "widget.png", + "version":"0.01", + "description": "Show the NodeConf Remote logo in the top left", + "tags": "widget", + "type":"widget", + "storage": [ + {"name":"widncr.wid.js","url":"widget.js"} + ] + }, + { "id": "ncrclk", + "name": "NCR Clock", + "shortName":"NCR Clock", + "icon": "app.png", + "version":"0.01", + "description": "NodeConf Remote clock", + "tags": "clock", + "type": "clock", + "storage": [ + {"name":"ncrclk.app.js","url":"app.js"}, + {"name":"ncrclk.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/ncrclk/ChangeLog b/apps/ncrclk/ChangeLog new file mode 100644 index 000000000..68209352b --- /dev/null +++ b/apps/ncrclk/ChangeLog @@ -0,0 +1 @@ +0.01: A copy of the analogimgclk to work for NodeConf Remote diff --git a/apps/ncrclk/app-icon.js b/apps/ncrclk/app-icon.js new file mode 100644 index 000000000..e9c28da6b --- /dev/null +++ b/apps/ncrclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkGswA/AFEiAAMoCqcykWEDQQWW0YYNsQXCn8//8zDgMiwwWNmf/CwICCDAUmIpYWD+YYFkIuKkYTBCogGCmUhGBAuBn4QBF4wJBiR6IFwYRCFoYBCVZBGBRQIYFFwaUBkUWFw4XKBIUhGAwXBEwYXFmcTBIMxC4pGBUgQXCLYc/kMvAgKqBSIheGGInyiQGCn8SC43zCwouDHQfzF4x2DFAgFCCwbaBSAi9CAAPxiMTRIcvEQIYCeQIXI+chiMSn8zGgJeDn8yiQXHBoMzDAMRiEzCwgXBF5IPCCwMQCoZUDYAhHFCQUBgIHFF5YRDkMDCwpfKAAn074UDC5QOHC48xL4jvDF5kznFGC4ovOmciwwXFWwIACB4M0C48hC4x4EC44kB+UYI4h4DGIhHEBIUyjAWEC4JIEF4VPF4shlAXFJAYQD+gXBEAcziReEGAg/F74ECBIIuHC4UhCAIZC+UzOokhkIXHJAMTDAQCGmOEkwXHGASSDAQk4oUSCxAwCiUjC4sooUhFxIYCkMilEzCwMymIgBRg5JGiUiwoDBlUijFCCxgYDIQIXCRZAAJJQIWBCqIA/AC4=")) diff --git a/apps/ncrclk/app.js b/apps/ncrclk/app.js new file mode 100644 index 000000000..05c62530e --- /dev/null +++ b/apps/ncrclk/app.js @@ -0,0 +1,129 @@ +var locale = require("locale"); + +var bgimg = { + width : 100, height : 100, bpp : 4, + buffer : require("heatshrink").decompress(atob("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")) +} + +function getImg(g, col) { + return { + width:g.getWidth(), + height:g.getHeight(), + bpp:1,transparent:0, + buffer:g.buffer, + palette:new Uint16Array([0,col])}; +} + +var handSizeMin = 40; +var handSizeHr = 25; +var handSizeSec = 55; +var gmin = Graphics.createArrayBuffer(6,handSizeMin*2,1,{msb:true}); +var gminimg = getImg(gmin, 0xFFFF); +var ghr = Graphics.createArrayBuffer(8,handSizeHr*2,1,{msb:true}); +var ghrimg = getImg(ghr, g.setColor("#E0E0E0").getColor()); +var gsec = Graphics.createArrayBuffer(2,handSizeSec*2,1,{msb:true}); +var gsecimg = getImg(gsec, g.setColor("#FF0000").getColor()); +var lastDate; + +// create hand images +var c = gmin.getHeight()/2; +var o = 8; // overhang +gmin.fillCircle(2,2,2); +gmin.fillCircle(2,c+o,2); +gmin.fillRect(0,2,4,c+o); +c = ghr.getHeight()/2; +ghr.fillCircle(4,4,4); +ghr.fillCircle(4,c+o,4); +ghr.fillRect(0,4,7,c+o); +c = gsec.getHeight()/2; +gsec.fillRect(0,1,2,c+o); + +// last positions of hands (in radians) +var lastrmin=0, lastrhr=0, lastrsec=0; + +// draw hands - just the bit of the image that changed +function drawHands(full) { + var d = new Date(); + var rsec = d.getSeconds()*Math.PI/30; + var rmin = d.getMinutes()*Math.PI/30; + // hack so hour hand only moves every 10 minutes + var rhr = (d.getHours() + Math.round(d.getMinutes()/10)/6)*Math.PI/6; + var bounds = {}; + if (!full) { // work out the bounds of the hands + var x1 = (g.getWidth()/2)-10; + var y1 = (g.getHeight()/2)-10 - 36; + var x2 = (g.getWidth()/2)+10; + var y2 = (g.getHeight()/2)+10 - 36; + function addPt(ang, r, ry) { + var x = (g.getWidth()/2) + Math.sin(ang)*r + Math.cos(ang)*ry; + var y = (g.getHeight()/2) - Math.cos(ang)*r + Math.sin(ang)*ry - 36; + //g.setColor("#ff0000").fillRect(x-2,y-2,x+2,y+2); + if (xx2)x2=x; + if (y>y2)y2=y; + } + function addSec(r) { + addPt(r,handSizeSec,5);addPt(r,handSizeSec,-5); + addPt(r,-(o+8),5);addPt(r,-(o+8),-5); + } + function addMin(r) { + addPt(r,handSizeMin,5);addPt(r,handSizeMin,-5); + addPt(r,-(o+8),5);addPt(r,-(o+8),-5); + } + function addHr(r) { + addPt(r,handSizeHr,8);addPt(r,handSizeHr,-8); + addPt(r,-(o+8),8);addPt(r,-(o+8),-8); + } + if (rsec!=lastrsec) { + addSec(rsec);addSec(lastrsec); + } + if (rmin!=lastrmin) { + addMin(rmin);addMin(lastrmin); + } + if (rhr!=lastrhr) { + addHr(rhr);addHr(lastrhr); + } + bounds = {x:x1,y:y1,width:1+x2-x1,height:1+y2-y1}; + } + + g.drawImages([ + {image:bgimg,x:20,y:25,scale:2}, + {image:ghrimg,x:120,y:120-31,center:true,rotate:rhr}, + {image:gminimg,x:120,y:120-31,center:true,rotate:rmin}, + {image:gsecimg,x:120,y:120-31,center:true,rotate:rsec} + ],bounds); + lastrsec = rsec; + lastrmin = rmin; + lastrhr = rhr; + + // Date + var date = locale.date(new Date(),false); + if (date === lastDate) return; + lastDate = date; + g.reset(); + g.setFont("6x8"); + g.setFontAlign(0,-1); + g.drawString(date, g.getWidth()/2, 232, true); +} + +var secondInterval = setInterval(drawHands,1000); +// handle display switch on/off +Bangle.on('lcdPower', (on) => { + if (secondInterval) { + clearInterval(secondInterval); + secondInterval = undefined; + } + if (on) { + drawHands(); + secondInterval = setInterval(drawHands,1000); + } +}); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawHands(true); + +// Show launcher when middle button pressed +setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); diff --git a/apps/ncrclk/app.png b/apps/ncrclk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..a0139e4ca3364bfd02931c5321609d8b58a8b054 GIT binary patch literal 5893 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 literal 0 HcmV?d00001 diff --git a/apps/widncr/ChangeLog b/apps/widncr/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/widncr/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/widncr/widget.js b/apps/widncr/widget.js new file mode 100644 index 000000000..7efa59273 --- /dev/null +++ b/apps/widncr/widget.js @@ -0,0 +1,5 @@ +WIDGETS["ncr"]={area:"tl",width:75,draw:function(){ + g.reset().setColor(1,0.2,0.5); + g.drawImage(atob("SxgCAAAAAAAAAAAAAAAAAAAAAAAAApAKAGpAGqgBqqQG+AAApAKBqq/APA//gP/9C//g//wAA/QPD///wPD//4P//S9VS9GRpA/wPD5V/4PH//9P//y4AD0AH/g/4PD4A99PL//+P//y//HwAL/w99PD+p8vPL//+P//2//LgAP/w9fPD/+9P/L//+P//y4AHwAL/w9P/D4A9D/H//9P//y4AD4AD/Q9D/D4A9B/D//4P//S//h+rQUA9B/D4A9AvA//gP/9C//gf/gAA9AvC0AAAAAGpAFVQAAAABpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaoCqkgAUC+BqpKqQAuAuQaQLggGDAA4A4NBwDAIAACRiQxw0kcgCTAA5DokAYDAIAAAAyAYAqQJgDDFQzGowAMDAIVAABqAMA3AGv5Dqgx8owAMDAOqAAHJAMCTAGgcDAAwUowAYDAIAAAcGAMJCAKgFDAAwAocAwDAIAABgDAk0BgMgDTqkwAoHrQDAOqQHqh7S60e0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), this.x,this.y); + g.setColor(1,1,1); +}}; diff --git a/apps/widncr/widget.png b/apps/widncr/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..85543d860b73918b7429028831b87a5765be3bd0 GIT binary patch literal 3915 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 literal 0 HcmV?d00001 From 51c5eaa2018bbcf507bd55fbf0e79e6923b5387b Mon Sep 17 00:00:00 2001 From: Nico Kaiser Date: Sun, 8 Nov 2020 13:50:33 +0100 Subject: [PATCH 080/110] ncrclk: fix seconds display --- apps/ncrclk/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/ncrclk/app.js b/apps/ncrclk/app.js index 05c62530e..acf611b1d 100644 --- a/apps/ncrclk/app.js +++ b/apps/ncrclk/app.js @@ -16,7 +16,7 @@ function getImg(g, col) { var handSizeMin = 40; var handSizeHr = 25; -var handSizeSec = 55; +var handSizeSec = 50; var gmin = Graphics.createArrayBuffer(6,handSizeMin*2,1,{msb:true}); var gminimg = getImg(gmin, 0xFFFF); var ghr = Graphics.createArrayBuffer(8,handSizeHr*2,1,{msb:true}); @@ -64,8 +64,8 @@ function drawHands(full) { if (y>y2)y2=y; } function addSec(r) { - addPt(r,handSizeSec,5);addPt(r,handSizeSec,-5); - addPt(r,-(o+8),5);addPt(r,-(o+8),-5); + addPt(r,handSizeSec+5,5);addPt(r,handSizeSec+5,-5); + addPt(r,-(o+10),5);addPt(r,-(o+10),-5); } function addMin(r) { addPt(r,handSizeMin,5);addPt(r,handSizeMin,-5); From 326eb7b764caa47a9591101eee341c10c4d373f7 Mon Sep 17 00:00:00 2001 From: jonathan Date: Thu, 12 Nov 2020 18:53:41 +0000 Subject: [PATCH 081/110] Don't clear all intervals during initialisation of Large Clock --- apps.json | 2 +- apps/largeclock/ChangeLog | 1 + apps/largeclock/largeclock.js | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 3c04f292a..73e2101eb 100644 --- a/apps.json +++ b/apps.json @@ -1690,7 +1690,7 @@ "id": "largeclock", "name": "Large Clock", "icon": "largeclock.png", - "version": "0.06", + "version": "0.07", "description": "A readable and informational digital watch, with date, seconds and moon phase", "readme": "README.md", "tags": "clock", diff --git a/apps/largeclock/ChangeLog b/apps/largeclock/ChangeLog index 091f7d65b..d06cc9edf 100644 --- a/apps/largeclock/ChangeLog +++ b/apps/largeclock/ChangeLog @@ -4,3 +4,4 @@ 0.04: Adjust layout to account for new vector font 0.05: Add support for 12 hour time 0.06: Allow to disable BTN1 and BTN3 buttons +0.07: Don't clear all intervals during initialisation diff --git a/apps/largeclock/largeclock.js b/apps/largeclock/largeclock.js index 6f3d638fa..24127ac15 100644 --- a/apps/largeclock/largeclock.js +++ b/apps/largeclock/largeclock.js @@ -198,7 +198,6 @@ if (BTN3app) setWatch( ); g.clear(); -clearInterval(); drawClockFace(); interval = setInterval(drawClockFace, REFRESH_RATE); From fe1c5962cc97349210b5c2d55a2bc6b34ce51cd9 Mon Sep 17 00:00:00 2001 From: MISUMI Masaru Date: Sat, 14 Nov 2020 09:08:52 +0900 Subject: [PATCH 082/110] Fix datePattern of locale.en_JP --- apps/locale/locales.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index fc7a545d7..01b482e10 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -146,7 +146,7 @@ var locales = { temperature: "°F", ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%y/%M/%d", 1: "%y/%m;/%d" }, + datePattern: { 0: "%Y/%m/%d", 1: "%y/%m/%d" }, abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", From 70850db7ad99ab9dd98c2d7e44910ed6c27f101d Mon Sep 17 00:00:00 2001 From: MISUMI Masaru Date: Sat, 14 Nov 2020 09:13:12 +0900 Subject: [PATCH 083/110] Fix temperature of locale.en_JP --- apps/locale/locales.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index 01b482e10..c29a49937 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -143,7 +143,7 @@ var locales = { int_curr_symbol: "JPY", speed: "kmh", distance: { 0: "m", 1: "km" }, - temperature: "°F", + temperature: "°C", ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%Y/%m/%d", 1: "%y/%m/%d" }, From 3bceda7f2763785e67612f3a5e6adabbf9cb44ef Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Sat, 14 Nov 2020 09:48:37 -0800 Subject: [PATCH 084/110] Create ChangeLog --- apps/isoclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/isoclock/ChangeLog diff --git a/apps/isoclock/ChangeLog b/apps/isoclock/ChangeLog new file mode 100644 index 000000000..cd3ceea5c --- /dev/null +++ b/apps/isoclock/ChangeLog @@ -0,0 +1 @@ +0.01: Created app based on digiclock with some small tweaks. From 04ca435ec79d83c1556ad7534312f9622081d272 Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Sat, 14 Nov 2020 09:49:31 -0800 Subject: [PATCH 085/110] Created ISOClock --- apps/isoclock/isoclock-icon.js | 1 + apps/isoclock/isoclock.js | 95 +++++++++++++++++++++++++++++++++ apps/isoclock/isoclock.png | Bin 0 -> 9913 bytes 3 files changed, 96 insertions(+) create mode 100644 apps/isoclock/isoclock-icon.js create mode 100644 apps/isoclock/isoclock.js create mode 100644 apps/isoclock/isoclock.png diff --git a/apps/isoclock/isoclock-icon.js b/apps/isoclock/isoclock-icon.js new file mode 100644 index 000000000..261a54c35 --- /dev/null +++ b/apps/isoclock/isoclock-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwUC1QA/ACev/4AG/QLB3ptHvwLB+ALHh4LB6ALHg4LDnkD/8An4eBBYsPgcA+E8BY8AgfAAYILG+ALJF4ILJJwPDBZMDBZMMEQJHJL5J3LBfX/M4PAgaRB/gLC6ZnCmEPNQM8BYpnBWwQLG/4ZBBYvQn7UCC5ILXmAKBI4pfDLoIBB//HR8p0BAA0PBYO9BY9+BYOv/4AG/QLBAH4ASA=")) diff --git a/apps/isoclock/isoclock.js b/apps/isoclock/isoclock.js new file mode 100644 index 000000000..5f63a1248 --- /dev/null +++ b/apps/isoclock/isoclock.js @@ -0,0 +1,95 @@ +//load fonts +require("Font7x11Numeric7Seg").add(Graphics); +require("FontHaxorNarrow7x17").add(Graphics); +//screen position +const X = 170; +const Y = 140; + +function draw() { + // Date Variables + var date = new Date(); + var h = date.getHours(); + var m = date.getMinutes(); + var day = date.getDay(); + var month = date.getMonth()+1; + var dateNum = date.getDate(); + var year = date.getFullYear(); + var half = "AM"; + var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2); + + //convert day into string + switch (day) { + case 0: + day = "Sunday"; + break; + + case 1: + day = "Monday"; + break; + + case 2: + day = "Tuesday"; + break; + + case 3: + day = "Wednesday"; + break; + + case 4: + day = "Thursday"; + break; + + case 5: + day = "Friday"; + break; + + case 6: + day = "Saturday"; + break; + + default: + day = "ERROR"; + break; + } + + + if (h > 12) { + half = "PM"; + h = h - 12; + } + //reset graphics + g.reset(); + //draw the time + g.setFont("7x11Numeric7Seg", 5); + g.setFontAlign(1,1); + g.drawString(time, X+10, Y, true /*clear background*/); + g.setFont("7x11Numeric7Seg", 3); + g.drawString(("0"+date.getSeconds()).substr(-2), X+55, Y, true /*clear background*/); + g.setFontAlign(0,1); + g.setFont("HaxorNarrow7x17", 3); + g.drawString(day, X-60, Y+53, true); + g.drawString(year+"-"+month+"-"+dateNum, X-55, Y-55, true); + + +} + +//clear screen at startup +g.clear(); +//draw immediatly +draw(); + +var secondInterval = setInterval(draw, 1000); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw, 1000); + draw(); // draw immediately + } +}); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +setWatch(Bangle.showLauncher, BTN2, {repeat : false, edge: "falling"}); diff --git a/apps/isoclock/isoclock.png b/apps/isoclock/isoclock.png new file mode 100644 index 0000000000000000000000000000000000000000..09cf9661d410e43ce8686215641c6264991ed116 GIT binary patch literal 9913 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 literal 0 HcmV?d00001 From a135a17f0dfd1dc8f6aab9997e6cd1a2eca67b88 Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Sat, 14 Nov 2020 09:57:29 -0800 Subject: [PATCH 086/110] Update apps.json --- apps.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 73e2101eb..e03d93ddc 100644 --- a/apps.json +++ b/apps.json @@ -2356,5 +2356,18 @@ {"name":"ncrclk.app.js","url":"app.js"}, {"name":"ncrclk.img","url":"app-icon.js","evaluate":true} ] - } + }, +{ "id": "isoclock", + "name": "ISO Compliant Clock Face", + "shortName":"ISO Clock", + "icon": "isoclock.png", + "version":"0.01", + "description": "Tweaked fork of digiclock for ISO date and time", + "tags": "clock", + "type" : "clock", + "storage": [ + {"name":"isoclock.app.js","url":"isoclock.js"}, + {"name":"isoclock.img","url":"isoclock-icon.js","evaluate":true} + ] +} ] From 6ece6931d8bad8bc944349a88f369a4cb34c9c61 Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Sat, 14 Nov 2020 14:39:34 -0800 Subject: [PATCH 087/110] Negative numbers and touch functionality Added the ability to count down (including going negative), and touchscreen input. --- apps/counter/counter.js | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/counter/counter.js b/apps/counter/counter.js index 9f77e34d8..86db23ba9 100644 --- a/apps/counter/counter.js +++ b/apps/counter/counter.js @@ -6,22 +6,41 @@ function updateScreen() { g.clearRect(0, 50, 250, 150); g.setFont("Vector",40).setFontAlign(0,0); g.drawString(Math.floor(counter), g.getWidth()/2, 100); + g.drawString('-', 45, 100); + g.drawString('+', 185, 100); } -// add a count by using BTN1 +// add a count by using BTN1 or BTN5 setWatch(() => { counter += 1; updateScreen(); }, BTN1, {repeat:true}); setWatch(() => { - counter = 0; + counter += 1; + updateScreen(); +}, BTN5, {repeat:true}); + +// subtract a count by using BTN3 or BTN4 +setWatch(() => { + counter -= 1; + updateScreen(); +}, BTN4, {repeat:true}); + +setWatch(() => { + counter -= 1; updateScreen(); }, BTN3, {repeat:true}); +// reset by using BTN2 +setWatch(() => { + counter = 0; + updateScreen(); +}, BTN2, {repeat:true}); + g.clear(1).setFont("6x8"); -g.drawString('Use BTN1 to increase\nthe counter by one.\nUse BTN3 to reset counter.', 25, 200); +g.drawString('Tap right or BTN1 to increase\nTap left or BTN3 to decrease\nPress BTN2 to reset.', 25, 200); Bangle.loadWidgets(); Bangle.drawWidgets(); From 1adc23377a790a592687a773c2c1ed6fe7a905b9 Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Sun, 15 Nov 2020 12:27:12 -0800 Subject: [PATCH 088/110] Added maidenhead readout I wrote a new function specifically to calculate maidenhead squares on Bangle.js. --- apps/gpsinfo/gps-info.js | 41 ++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 836e3a71b..7992cc8ca 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -21,7 +21,35 @@ function formatTime(now) { var date = [fd[0], fd[1], fd[2]].join(" "); return time + " - " + date; } +function getMaidenHead(param1,param2){ + var lat=-100.0; + var lon=0.0; + var U = 'ABCDEFGHIJKLMNOPQRSTUVWX'; + var L = U.toLowerCase(); + lat = param1; + lon = param2; + + lon = lon + 180; + t = lon/20; + fLon = Math.floor(t); + t = (t % fLon)*10; + sqLon = Math.floor(t); + t=(t-sqLon)*24; + subLon = Math.floor(t); + extLon = Math.floor((t-subLon)*10); + + lat = lat + 90; + t = lat/10; + fLat = Math.floor(t); + t = (t % fLat)*10; + sqLat = Math.floor(t); + t=(t-sqLat)*24; + subLat = Math.floor(t); + extLat = Math.floor((t-subLat)*10); + + return U[fLon]+U[fLat]+sqLon+sqLat+L[subLon]+L[subLat]+extLon+extLat; +} function onGPS(fix) { lastFix = fix; g.clear(); @@ -41,12 +69,13 @@ function onGPS(fix) { var s = 15; g.setFontVector(s); - g.drawString("Altitude: "+alt+" m",10,44); - g.drawString("Lat: "+lat,10,44+20); - g.drawString("Lon: "+lon,10,44+40); - g.drawString("Speed: "+speed.toFixed(1)+" km/h",10,44+60); - g.drawString("Time: "+time,10,44+80); - g.drawString("Satellites: "+satellites,10,44+100); + g.drawString("Altitude: "+alt+" m",10,36); + g.drawString("Lat: "+lat,10,54); + g.drawString("Lon: "+lon,10,72); + g.drawString("Speed: "+speed.toFixed(1)+" km/h",10,90); + g.drawString("Time: "+time,10,108); + g.drawString("Satellites: "+satellites,10,126); + g.drawString("Maidenhead: "+maidenhead,10,144); } else { g.setFontAlign(0, 1); g.setFont("6x8", 2); From 756839f5343c5e94e96e9aa48aa14379742c6a4a Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Sun, 15 Nov 2020 12:39:04 -0800 Subject: [PATCH 089/110] Update gps-info.js --- apps/gpsinfo/gps-info.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 7992cc8ca..1a8cb2fd1 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -66,7 +66,7 @@ function onGPS(fix) { var speed = fix.speed; var time = formatTime(fix.time); var satellites = fix.satellites; - + var maidenhead = getMaidenHead(lat,lon); var s = 15; g.setFontVector(s); g.drawString("Altitude: "+alt+" m",10,36); From 63c2e62d980150ce46403f95f53979d0d8809020 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 16 Nov 2020 09:05:32 +0000 Subject: [PATCH 090/110] Fix https://github.com/espruino/BangleApps/issues/593 --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index e2775902a..0389671ba 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit e2775902a3e3d88a1f6378fc33290ac6c3d9a1a5 +Subproject commit 0389671ba6678a12c9f35644ffb96c190bbe0278 From 82379b6edc69d9938c9029549a19da16c0f7d43b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 16 Nov 2020 09:12:22 +0000 Subject: [PATCH 091/110] bump version based on 715040862384cb92259490bf0c698b2c41ffd279 --- apps.json | 2 +- apps/counter/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e03d93ddc..5a9483495 100644 --- a/apps.json +++ b/apps.json @@ -2188,7 +2188,7 @@ {"id": "counter", "name": "Counter", "icon": "counter_icon.png", - "version": "0.01", + "version": "0.02", "description": "Simple counter", "tags": "tool", "allow_emulator": true, diff --git a/apps/counter/ChangeLog b/apps/counter/ChangeLog index 5560f00bc..8d0f821fd 100644 --- a/apps/counter/ChangeLog +++ b/apps/counter/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Added decrement and touch functions From ae5b7ba7b97492e295ce42dddea2411face1a984 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 16 Nov 2020 09:17:33 +0000 Subject: [PATCH 092/110] Bump for b65b73ed4b16eb7effa382e7b51acde3f9ab0eac --- apps.json | 2 +- apps/gpsinfo/ChangeLog | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 5a9483495..681c77c9b 100644 --- a/apps.json +++ b/apps.json @@ -917,7 +917,7 @@ "id": "gpsinfo", "name": "GPS Info", "icon": "gps-info.png", - "version":"0.03", + "version":"0.04", "description": "An application that displays information about altitude, lat/lon, satellites and time", "tags": "gps", "type": "app", diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 90ace259c..ceff7011e 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -1,2 +1,3 @@ 0.02: Ensure screen doesn't display garbage at startup -0.03: Show number of satellites while waiting for fix \ No newline at end of file +0.03: Show number of satellites while waiting for fix +0.04: Add Maidenhead readout of GPS location From 24c84f9ba6a42d0d5aeda4743243d80f3fd7cb48 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 16 Nov 2020 09:18:49 +0000 Subject: [PATCH 093/110] add GPS Time Server --- apps.json | 12 +++++++ apps/gpstimeserver/ChangeLog | 1 + apps/gpstimeserver/README.md | 59 ++++++++++++++++++++++++++++++++++ apps/gpstimeserver/widget.js | 53 ++++++++++++++++++++++++++++++ apps/gpstimeserver/widget.png | Bin 0 -> 2011 bytes 5 files changed, 125 insertions(+) create mode 100644 apps/gpstimeserver/ChangeLog create mode 100644 apps/gpstimeserver/README.md create mode 100644 apps/gpstimeserver/widget.js create mode 100644 apps/gpstimeserver/widget.png diff --git a/apps.json b/apps.json index 681c77c9b..ad5200593 100644 --- a/apps.json +++ b/apps.json @@ -2369,5 +2369,17 @@ {"name":"isoclock.app.js","url":"isoclock.js"}, {"name":"isoclock.img","url":"isoclock-icon.js","evaluate":true} ] +}, +{ "id": "gpstimeserver", + "name": "GPS Time Server", + "icon": "widget.png", + "version":"0.01", + "description": "A widget which automatically starts the GPS and turns Bangle.js into a Bluetooth time server.", + "tags": "widget", + "type": "widget", + "readme": "README.md", + "storage": [ + {"name":"gpstimeserver.wid.js","url":"widget.js"} + ] } ] diff --git a/apps/gpstimeserver/ChangeLog b/apps/gpstimeserver/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/gpstimeserver/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/gpstimeserver/README.md b/apps/gpstimeserver/README.md new file mode 100644 index 000000000..c6d89d56f --- /dev/null +++ b/apps/gpstimeserver/README.md @@ -0,0 +1,59 @@ +# GPS Time Server + +A widget which automatically starts the GPS and turns Bangle.js into a Bluetooth time server, UUID 0x1805. + +Other Espruino Bluetooth devices can then find it and use it to synchronise time. + +**Note:** Because GPS is kept on, you'll need to keep your Bangle.js on charge for this to be useful. + +## Usage + +Just install this widget, and from then on any app which loads widgets will +display the icon ![](widget.png) in the top left, and Bangle.js will be +broadcasting the current time to any device that connects. + +## Technical + +This implements the [Bluetooth Time Service](https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=292957) listed [here](https://www.bluetooth.com/specifications/gatt/). + +The Bluetooth docs are verbose and hard to read, so here's a rundown of how it works. + +* The Bangle advertises service `0x1805` +* You connect to it, and request service `0x1805` and characteristic `0x2A2B` +* A 10 byte array is returned: + +``` +[ + year_lowbyte, + year_highbyte, + month, + day_of_month, + hours, + minutes, + seconds, + day_of_week, // 1=monday...7=sunday + subseconds, // 0..255 + update_reason // 0=unknown currently +] +``` + +``` +//NRF.requestDevice({ filters: [{ services: ['1805'] }] }).then(print) + +var gatt; +NRF.connect("c7:4b:2e:c6:f5:45 random").then(function(g) { + gatt = g; + return gatt.getPrimaryService("1805"); +}).then(function(service) { + return service.getCharacteristic("2A2B"); +}).then(function(c) { + return c.readValue(); +}).then(function(d) { + console.log("Got:", JSON.stringify(d.buffer)); + var year = d.getUint16(0,1); + // ... + gatt.disconnect(); +}).catch(function(e) { + console.log("Something's broken.",e); +}); +``` diff --git a/apps/gpstimeserver/widget.js b/apps/gpstimeserver/widget.js new file mode 100644 index 000000000..5d1dd4c34 --- /dev/null +++ b/apps/gpstimeserver/widget.js @@ -0,0 +1,53 @@ +(() => { + +function getBLECurrentTimeData(d) { + var updateReason = 0; // unknown update reason + return [ + d.getFullYear()&0xFF, + d.getFullYear()>>8, + d.getMonth()+1, + d.getDate(), + d.getHours(), + d.getMinutes(), + d.getSeconds(), + d.getDay() ? d.getDay() : 7/*sunday*/, + Math.floor(d.getMilliseconds()*255/1000), + updateReason + ]; +} + +NRF.setServices({ + 0x1805 : { + 0x2A2B : { + value : getBLECurrentTimeData(new Date()), + readable : true, + notify : true + } + } +}, { advertise: [ '1805' ] }); + +Bangle.on('GPS', function(fix) { + if (fix.time !== undefined) { + NRF.updateServices({ + 0x1805 : { + 0x2A2B : { + value : getBLECurrentTimeData(fix.time), + notify : true + } + } + }); + } +}); +Bangle.setGPSPower(1); + + + function draw() { + g.reset(); + g.drawImage(require("heatshrink").decompress(atob("i0XxH+CR0HhEHEyEOi1AAAMWhAUNisW6/XwICBi0PHpgUC69WAYUWIpcVxAVGsgsLi2sCAOsg4EDiwVPlZYCCoUzss6IwxBE68rDYJBBldlAAVeNpIADNoNdxIWDssrCYMJgKZDF4SZCxGtCollmcJAALFDnTFE1utxNdrtXq9WqwVDeJAVB1tdrwABFgM6maOKwQWCIQgbBmQVJmQVCCwlXF4LoKCoaHDCoSgFAAldCwYtCqxbCLRQVECwNWr4VBr4VJmYWFrpcDCpM6neJC4pdCChEsss7C4+IFRI4DC4LBKCpBQLAAgA=")), this.x, this.y); + } + WIDGETS["gpstimeserver"]={ + area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right) + width: 24, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout + draw:draw // called to draw the widget + }; +})() diff --git a/apps/gpstimeserver/widget.png b/apps/gpstimeserver/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..793b025510045a65d9bce13c9a79654f6999f224 GIT binary patch literal 2011 zcmV<12PF83P)1yxzB@n9HU?uGW73%5fZTPS zp{OcVQ&pr@RaB8SQ3@qZP;#g=Zls1nN^wjK7^I{{q@p|mH8D2E3Fj9+-+OoZ;e3Z* zhmX{D+N$$ucV>3>H~;y+_P_97*2JX0v956qPy;LiatC_5fF=+g+*JquGl1(FzY6RJ z94G~*0;L8h1V|aD=|`}ZRj#)_JK(y;-vAp?idl{{HkVFeS$-B}HY)&EgCYLn?c3=@EpCr<*fWXTc$GBn9ctzI^tZ;eSDcH?$^ zYw&V%B3U=Qdm|8sJ-(ovwbPslSb(OcCYqX>68ApCWPMRC4GYS_Gy$HXuJO@H1AeXZ ziVdZBp`wI&88%c3&zK4-v+V4uD2eO1XL5k+8rMXW$*lA=HWlZk1UneIwj`foyA>dV zx_8%1hJhBV@iLd9248;Qexinv81#5Ncp8oaQ04KkdiCnWn67EO^Zo~< z>ss7f8KQo>!BW^VC)pJSTUGDNxnH8nK|AvkvI7~8jRXX(qJ`bAoCI$Z4=|IipF7+Ic1*!ujj)1mj@5;0bcL{t7DOVox z_OX6??ufx~IE>rvX5G4V6c!dzRaHepLj&{Y&ri%b+SwOZiBqGh#E~niBoGlV1Eqiy z#2f@$5XL{AIPCx9hPQ*W?;@{y9Ra_(<|RW*u6e;=kR3aAP+MC|eSJNerX`}@^DQ?A zVzKay8k&zbN9sUzCe^2WPD7I!Y-F z!$1mn^?DauF0_FVKHRR%5fW}_4$cO??zG+6L=-$@@%#VwGrY#C|drvkACPzdq6zM%1azBB6=KrNAE{TlZ}wWEh-#X^8QyCC15l8Z@0sJ$Bx2X=4ztFjEhZULqNg($T(Gfh5++x2Z= zH&U?e;&tvhah`qcUEByoNY^#eb&d8=gnjK@l%Kr7)(dTMLwjjB>`)0eM=k;705^Ol z$6Jk*OiL*fqyOgdH-CF#wn9xEHu`bjk#9}|;17*oL9rjmKoN^zazI}3>llp>#2VaH zhm!hXrIe_@8ZC`?7G_AMXDH&vry@bjKsRQf2gBcu>F-7bdNBMws9-NjnN?OxxfzNK zKN)d**Q;CyflS_Ld?3h>}|{eH~AA%svznKp|cM}y2 zC0{{mNV}7wDW+_0*M^_p{t@$6yAA*cK5aA_95{M`g7{5drh|LR=W^-2KO-zQq}_?M z=b$;9NQV<)&p~tKAZ*zPA*qZSaPTdzcSKY;B0o`>ulI>tKbWwu=A+G#3&4Ft^;2=O zHAH*AmeOLr_g*8~-GaSh#kpYa;xE4O4G|u1U^xix?1BUu>hcTu@^D#y|PDOc<~U$CFKRSOiN; zH1s<#o55aCCPKF&(;RVy`}u~0{)H0)yu8eMR=@|zCg#}%OJ?XK6Lef1q&;VdQA>%Z z=CH~dcVGZhs8{YZd8$LOs7M=;69Ab0IIwg0P?^mP?wk-{3zmHYb*`jsdZxrxqGORs zB<#o;>57DUV$&i2f^i3~E)zWp^~13qDo7VRRH|beq|~=n!a3@D48_iI2L`aTSat({ zAM*>-CRjdGBiANU0Y(UxjE4b^0IseUQK1=M1H5BBY_|v=F4dWtEiwGvv9w?ml}JEK zwQ1ae0Ujx}HJ@k+zo69E1shGmg6SHwE2|Ki6=Ba#4lKm-2`gw`sXJheq7(nhn=bA#`(EU9xT#$ zc&1Kah8!skLF>N*o3t)bkZpPT0c$2_TYPx?BJ4cY#TSZgJa&INx%RQ8oo^RZm1y*Z zG_Lzhx`PUo3R*Sw%($z>#<%-dV2VQk;i%%`4L=<{v82nQ2`Z-9c;sHYzoJ05rC2$N zDwM|}EZ?gx6CL9Ze8~Sk@TI|hoxTWHI)d~DZhxGX<=f6}ug?C75G({$iNc8>XJE~b zlu|8Ha$1X8-mJb?w2gZ{JP0_cj&=K^w04HLc`Jf01(&xKPWoS{yQ-}@9Xd{jj;R#A teuK-OLGAEURWGFwIMa3h-~JcdzW|Ck!|Z)wy}JMa002ovPDHLkV1lHfqQ?LL literal 0 HcmV?d00001 From 5fc5b8310217d26dcf5f15939c4d7bff2a34ecbf Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 17 Nov 2020 12:31:56 +0000 Subject: [PATCH 094/110] add new bluetoothdock app --- apps.json | 14 +++ apps/bluetoothdock/ChangeLog | 1 + apps/bluetoothdock/README.md | 35 ++++++ apps/bluetoothdock/add_to_apps.json | 15 +++ apps/bluetoothdock/app-icon.js | 1 + apps/bluetoothdock/app.js | 182 ++++++++++++++++++++++++++++ apps/bluetoothdock/app.png | Bin 0 -> 2604 bytes apps/bluetoothdock/boot.js | 1 + 8 files changed, 249 insertions(+) create mode 100644 apps/bluetoothdock/ChangeLog create mode 100644 apps/bluetoothdock/README.md create mode 100644 apps/bluetoothdock/add_to_apps.json create mode 100644 apps/bluetoothdock/app-icon.js create mode 100644 apps/bluetoothdock/app.js create mode 100644 apps/bluetoothdock/app.png create mode 100644 apps/bluetoothdock/boot.js diff --git a/apps.json b/apps.json index ad5200593..116f1488d 100644 --- a/apps.json +++ b/apps.json @@ -460,6 +460,20 @@ {"name":"chargeanim.img","url":"app-icon.js","evaluate":true} ] }, + { "id": "bluetoothdock", + "name": "Bluetooth Dock", + "shortName":"Dock", + "icon": "app.png", + "version":"0.01", + "description": "When charging shows the time, scans Bluetooth for known devices (eg temperature) and shows them on the screen", + "tags": "bluetooth", + "readme": "README.md", + "storage": [ + {"name":"bluetoothdock.app.js","url":"app.js"}, + {"name":"bluetoothdock.boot.js","url":"boot.js"}, + {"name":"bluetoothdock.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "widbat", "name": "Battery Level Widget", "icon": "widget.png", diff --git a/apps/bluetoothdock/ChangeLog b/apps/bluetoothdock/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/bluetoothdock/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/bluetoothdock/README.md b/apps/bluetoothdock/README.md new file mode 100644 index 000000000..37d6dd463 --- /dev/null +++ b/apps/bluetoothdock/README.md @@ -0,0 +1,35 @@ +# Charging Dock + +When charging shows the time, scans Bluetooth for known devices (eg temperature) and shows them on the screen. + +Rotates by 90 degrees if it detects it is sideways, allowing for use +in a Charging Dock. + +When devices are out of range (eg low water level in a plant) they are +highlighted red. + +Currently supported devices: + +* Mi Flora/other Xiaomi +* Bluetooth 0x1809 (eg. [Espruino Apps](https://espruino.github.io/EspruinoApps/#bletemp)) +* Espruino Manufacturer Data (0x0590) + +In the future it'd be nice to support more types of device in the future! + +## Espruino Devices + +To use your own Espruino device, use code like the following: + +``` +var data = {a:1,t:E.getTemperature()}; +NRF.setAdvertising({},{ + showName:false, + manufacturer:0x0590, + manufacturerData:JSON.stringify(data) +}); +``` + +Currently: + +* `t` is the temperature (if defined) +* `t` is the alert status (1 or 0) diff --git a/apps/bluetoothdock/add_to_apps.json b/apps/bluetoothdock/add_to_apps.json new file mode 100644 index 000000000..cb59dcdbe --- /dev/null +++ b/apps/bluetoothdock/add_to_apps.json @@ -0,0 +1,15 @@ +// Create an entry in apps.json as follows: +{ "id": "bluetoothdock", + "name": "Bluetooth Dock", + "shortName":"Dock", + "icon": "app.png", + "version":"0.01", + "description": "When charging shows the time, scans Bluetooth for known devices (eg temperature) and shows them on the screen", + "tags": "bluetooth", + "readme": "README.md", + "storage": [ + {"name":"bluetoothdock.app.js","url":"app.js"}, + {"name":"bluetoothdock.boot.js","url":"boot.js"}, + {"name":"bluetoothdock.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/bluetoothdock/app-icon.js b/apps/bluetoothdock/app-icon.js new file mode 100644 index 000000000..06e21d106 --- /dev/null +++ b/apps/bluetoothdock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwggNK93gEikO93uC6gWBF6ECkQuVkUikAuVAAIuVAAIuGGZgXDlwuDhWkpWqAARHLkQpChWql3kC4YYHmQXDSQWq0Xu8QXE0AWEgYWESQIuC90qlQwJFwoABFwnyGBBdEC4guC1X/GBAXIVYJdC/4wFUw4XFFYX/GApIDC5BJBC4YwEC6QwEC5pHD+YwE0IXMGAX//U/GAgXNU4X60YwEU5YABnQXC0RhEFxkv+YXCl5iBF4gXKLQM6IgIuBGoIXCIxOqlRaBRoIABFwYXBUheqGAIACFwYXKBoYwBFwwXGVoQuDGAguEC4MzCwUQC4UKBwmvFw2qgczmUikAWCC4OikUzAAQvH+YXCCwcAmQVDC4YwFBIIVEgA3BAALADR48zmAWEh4VBPAS/DAIQXKJwIlDd4f6AgQXIIoSPCFwWqC4IFDL4YAFmAXCFIYXB0RhBKQRvDAAa/Dl4oCC4Mv//ya4gWFC4eiLAQUBFwgXBAA8Bc4qnCFwehC5EAC5AuD0AXRFwYXTFweqwAXJPAQXDFwh2JC5AuE0QXKJAouFLxQwGFwhGLPJAuPMI4uQDBAKD")) diff --git a/apps/bluetoothdock/app.js b/apps/bluetoothdock/app.js new file mode 100644 index 000000000..bb0ef4682 --- /dev/null +++ b/apps/bluetoothdock/app.js @@ -0,0 +1,182 @@ +var deviceInfo = {}; +if (Bangle.getAccel().x < -0.7) + g.setRotation(3); // assume watch in charge cradle +// Tile sizes +var TILESIZE = 60; +// Tiles along width of screen +var TILEX = 4; + +// Map devices to nice names... +var deviceNames = { + "eb:44:c1:71:2e:89 random" : "Office", + "c4:7c:8d:6a:ac:79 public" : "Peacelily" +}; + +var scanHandlers = [ + { filter : {serviceData:{"fe95":{}}}, // Xiaomi + handler : function(device) { + if (!device.serviceData["fe95"]) return; + var d = new DataView(device.serviceData["fe95"]); + var frame = d.getUint16(0,true); + var offset = 5; + if (frame&16) offset+=6; // mac address + if (frame&32) offset+=1; // capabilitities + if (frame&64) { // event + var l = d.getUint8(offset+2); + var code = d.getUint16(offset,true); + if (!deviceInfo[device.id]) deviceInfo[device.id]={id:device.id}; + event = deviceInfo[device.id]; + switch (code) { + case 0x1004: event.temperature = d.getInt16(offset+3,true)/10; break; + case 0x1006: event.humidity = d.getInt16(offset+3)/10; break; + case 0x100D: + event.temperature = d.getInt16(offset+3,true)/10; + event.humidity = d.getInt16(offset+5)/10; break; + case 0x1008: event.moisture = d.getUint8(offset+3); break; + case 0x1009: event.fertility = d.getUint16(offset+3,true)/10; break; + // case 0x1007: break; // 3 bytes? got 84,0,0 or 68,0,0 + default: event.code = code; + event.raw = new Uint8Array(d.buffer, offset+3, l); + break; + } + }}}, { + filter : {serviceData:{"1809":{}}}, // Standard Bluetooth + handler : function(device) { + if (!device.serviceData["1809"]) return; + var d = new DataView(device.serviceData["1809"]); + if (!deviceInfo[device.id]) deviceInfo[device.id]={id:device.id,name:device.name}; + event = deviceInfo[device.id]; + event.temperature = d.getInt16(0,1)/100; + }}, { + filter : { manufacturerData:{0x0590:{}} }, // Espruino + handler : function(device) { + if (!device.manufacturerData) return; + var j; + try { j = JSON.parse(E.toString(device.manufacturerData)); } + catch (e) { return; } // not JSON + if (!deviceInfo[device.id]) deviceInfo[device.id]={id:device.id,name:device.name}; + event = deviceInfo[device.id]; + if (j.t) event.temperature = j.t; + if (j.a) event.alert = j.a; + }} +]; + +function getImgHum() { + return require("heatshrink").decompress(atob("jUoxH+AEtlsoYYDS4ZYDAYaVDLAYFDSQYHDSIZYDBIaPDLAYLDRoZYDBoaLDLAYPDRIZYDCIaHDLAYTDQoZYDCoaDDOQYXAA+JxIYX1utDSwYBAAIzYGiwZUTgpODQpzPGGgY3OdI4aRDIIaMDJIYCDIztDGRwaJP5oaWDAwaRDBAbOC5YcKB5I=")); +} +function getImgTemp() { + return require("heatshrink").decompress(atob("iUqxH+AA2sAAQLHCBASMCAoSLCPOBAAQRfI/5Hn3YACy4ACCL4ADCL5H/I/AQHCRAQJCQwQLCQgQNCQYRQCB4A/ADaPjYqTpSCRYQGCZALFA")); +} + +function drawAlert(tile,x,y) { + g.setFont("Vector",56).setFontAlign(0,0); + g.drawString("!",x+TILESIZE/2,y+10+TILESIZE/2); +} + +function drawMoisture(tile,x,y) { + g.drawImage(getImgHum(),x+2,y+18); + g.setFont("Vector",28); + g.drawString(tile.device.moisture,x+26,y+12); +} + +function drawTemperature(tile,x,y) { + g.drawImage(getImgTemp(),x+3,y+16); + g.setFont("Vector",30); + var t = Math.round(tile.device.temperature); + g.drawString(t,x+25,y+13); +} + +function getTiles() { + var tiles = []; + Object.keys(deviceInfo).forEach(id=>{ + var dev = deviceInfo[id]; + if (dev.alert) { + tiles.push({ + alert: true, device: dev, + draw: drawAlert + }); + } + if (dev.moisture && dev.moisture<40) { + tiles.push({ + alert: true, device: dev, + draw: drawMoisture + }); + } + if (dev.temperature) { + tiles.push({ + device: dev, + draw: drawTemperature + }); + } + }); + tiles.sort((a,b)=>(b.alert|0)-(a.alert|0)) + return tiles; +} + + +g.clear(); +require("Font7x11Numeric7Seg").add(Graphics); +function drawClock() { + var d = new Date(); + var size = 3; + var x = (g.getWidth()/2) - size*6, + y = size; + g.reset(); + g.setFont("7x11Numeric7Seg",size).setFontAlign(1,-1); + g.drawString(d.getHours(), x, y, true); + g.setFontAlign(-1,-1); + if (d.getSeconds()&1) g.drawString(":", x,y); + g.drawString(("0"+d.getMinutes()).substr(-2),x+size*4,y, true); + // draw seconds + g.setFont("7x11Numeric7Seg",size/2); + g.drawString(("0"+d.getSeconds()).substr(-2),x+size*18,y + size*7, true); + // date + var s = d.toString().split(" ").slice(0,4).join(" "); + g.reset().setFontAlign(0,-1); + g.drawString(s,g.getWidth()/2, y + size*12, true); + // keep screen on + g.flip(); +} +function drawTiles() { + // draw tiles + var tiles = getTiles(); + for (var i=0;i<6;i++) { + var x = (i%TILEX)*TILESIZE; + var y = TILESIZE + TILESIZE*((i/TILEX)|0); + g.reset(); + var tile = tiles[i]; + if (tile && tile.alert) { + g.setBgColor(0.5,0,0); + } + g.clearRect(x,y,x+TILESIZE-1,y+TILESIZE-1); + if (tile) { + g.reset().setFont("6x8"); + var t = deviceNames[tile.device.id]; + if (!t) t = tile.device.name || tile.device.id.substr(0,17); + g.drawString(t,x+2,y+2); + tile.draw(tile, x, y); + if (tile.alert) { + g.setColor(1,1,0); + g.drawRect(x,y,x+TILESIZE-1,y+TILESIZE-1); + } + } + } + g.flip(); // keep forcing display on +} + +setInterval(drawClock, 1000); +setInterval(drawTiles, 10000); +drawClock(); +drawTiles(); + +function parseDevice(dev) { + if (!dev.serviceData) dev.serviceData={}; + scanHandlers.forEach(s=>s.handler(dev)); +} +NRF.setScan(parseDevice, { filters: scanHandlers.map(s=>s.filter), timeout: 2000 }); + +if (Bangle.isCharging()) { + Bangle.on("charging", isCharging => { + if (!isCharging) load(); + }); +} diff --git a/apps/bluetoothdock/app.png b/apps/bluetoothdock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..db489f8c1d4737ff0b223f12880ee8900834c486 GIT binary patch literal 2604 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 O0000 { if (isCharging) load("bluetoothdock.app.js"); }); From d74c9d86fff43d5a9cfab14fdc3cbac2d398e1f0 Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Tue, 17 Nov 2020 20:38:58 -0800 Subject: [PATCH 095/110] Change colours based on final roll result Changed text colour to grey while bouncing, changing to white on final bounce except for critical rolls. Critical hit is red text on black, critical miss is black text on red. --- apps/rpgdice/app.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/rpgdice/app.js b/apps/rpgdice/app.js index 2007d6ab0..be7b934e2 100755 --- a/apps/rpgdice/app.js +++ b/apps/rpgdice/app.js @@ -14,12 +14,18 @@ function getDie() { } function setColors(lastBounce) { - if (lastBounce) { - bgColor = 0xFFFF; + if (lastBounce && face == getDie()) { + bgColor = 0x0000; // Critical Hit + fgColor = 0xF800; + } else if (lastBounce && face == 1){ + bgColor = 0xF800; // Critical Miss fgColor = 0x0000; - } else { - bgColor = 0x0000 + } else if (lastBounce){ + bgColor = 0x0000; // Other Result fgColor = 0xFFFF; + } else { + bgColor = 0x0000; // Still Rolling + fgColor = 0x7BEF; } } From e50e6896ad0fa6461cd831f3e8a1febbe3b2e3bb Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Tue, 17 Nov 2020 20:39:37 -0800 Subject: [PATCH 096/110] Update ChangeLog --- apps/rpgdice/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/rpgdice/ChangeLog b/apps/rpgdice/ChangeLog index 7b83706bf..62806fb71 100755 --- a/apps/rpgdice/ChangeLog +++ b/apps/rpgdice/ChangeLog @@ -1 +1,2 @@ 0.01: First release +0.02: Colour changes dependent on roll result From afb6ab36693e5dbf1dc4fd4174c5ea080b6fb2b8 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 18 Nov 2020 10:11:24 +0000 Subject: [PATCH 097/110] Add Tilt Hydrometer app --- apps.json | 12 +++++ apps/tilthydro/ChangeLog | 1 + apps/tilthydro/app-icon.js | 1 + apps/tilthydro/app.js | 87 +++++++++++++++++++++++++++++++++++++ apps/tilthydro/app.png | Bin 0 -> 14919 bytes 5 files changed, 101 insertions(+) create mode 100644 apps/tilthydro/ChangeLog create mode 100644 apps/tilthydro/app-icon.js create mode 100644 apps/tilthydro/app.js create mode 100644 apps/tilthydro/app.png diff --git a/apps.json b/apps.json index 116f1488d..3207f8ab0 100644 --- a/apps.json +++ b/apps.json @@ -2395,5 +2395,17 @@ "storage": [ {"name":"gpstimeserver.wid.js","url":"widget.js"} ] +}, +{ "id": "tilthydro", + "name": "Tilt Hydrometer Display", + "shortName":"Tilt Hydro", + "icon": "app.png", + "version":"0.01", + "description": "A display for the [Tilt Hydrometer](https://tilthydrometer.com/) - [more info here](http://www.espruino.com/Tilt+Hydrometer+Display)", + "tags": "tools,bluetooth", + "storage": [ + {"name":"tilthydro.app.js","url":"app.js"}, + {"name":"tilthydro.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/tilthydro/ChangeLog b/apps/tilthydro/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/tilthydro/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/tilthydro/app-icon.js b/apps/tilthydro/app-icon.js new file mode 100644 index 000000000..86fd7d388 --- /dev/null +++ b/apps/tilthydro/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwggNKgtQESUF5gAEDR8M5nFAwdVAwoWJBxFcDBZEBBZNc4ALJCxQMCMZAiLHgRJHBBBsHGAwHHABAnGFxwoHhhdMLAgRErj8RT4hGQJApGTJAaNQrnMIIJDCLx0F5gACCgZeNhgWDCQMMBIJeNC4ZcEVYpCFrgLBC4wVBRxQTBBYMFqAFBLIQXCRw/MCIp4DAoQXBFhIRFEAIFD4oXECIIfBIgQXHIQQXEZIIXDIgIREBoRyCC4TJE4pEDCIgXIZIpEDJYafBAoYXDIoQ/DAgRLCFgQXGBoNVHIgREHQhkDa4ghEVArtEC4bZBCQZfCSAvFcwoVCC4QnBfQaQDFgokCDwL7DaAjVFC4xvCcQ7UEAAwUCeApAHAAxvDSA4AKRgYbEIRR2GMAoAOCQhIDABpGEJAhGSGoRdOFA8FGBxYIGBsFe5AJJEp0MJJVcKpYMJrg7MBwQ9EKIK0PCIIAEZaAZCqtVS5QA==")) diff --git a/apps/tilthydro/app.js b/apps/tilthydro/app.js new file mode 100644 index 000000000..b64fa4573 --- /dev/null +++ b/apps/tilthydro/app.js @@ -0,0 +1,87 @@ + +function displayInfo(reading) { + g.reset(1).setColor(1,0,0); + g.clearRect(0,24,g.getWidth(),g.getHeight()-48); + g.drawImage(require("heatshrink").decompress(atob("o1GgQIFgOr///0oZLg4PBAAP+oAQJjf/yolBtf/yAQIj/5AocGCJMf+hKF3+AGQ4QFCIRHGg/4DI0B/wHFgRDEBIn9A4u+QJI9Fl6DJhfQApIAFDgkCMwwAE3oEILA4dDj7IKIAPAAYMDIhQABnwDC3AQLgI0CPBQ0FGZsAlwzOGgZnMgO8heAgXgCBUG//QnsAAIIAJr///wgBg+AGJO////+EfgDPJgIPBEQIPBCQIAIn4QB/tAheBKxFAgQQCAwN8loPGgr7Bj4RBDwMD4atGD4PggP+t//BAMtngQFqEvKIMFLAJkBgPnPIu/BgPwAoMP/4NBj94CAgOBBgLIC3/8AYP7aAcUBwW//AHBg//4AmB2gQCt/QDYIMDRoJ6CEQS3B/wOB6AMDNoQiDBoJDBBwIMDRoQiDQAIABBwQMDPQYiBl4QCBwYMCgh6D/dCCARJBBwIMCjfQv56BEQLHEBwW//uv/0DNoX3wAiCSwZdCLwMvyAbBvELyI/CPQYRCoKHC+6gCJgU//xrBAAIZBAAMenrHEcIRNCGIKgC6XQGAaWCoH//1Qdoc9jzHC/z1C/EL/L+Eg/B+DHCAYMLOYNkCAkAvEPLYIwCgCWCAAoPB3AwCMAMD/oUBAAkB+EHPQIwBPQMZEI0AlwBCGBIACgfQEgIEBPQQAIIYMLGAMvOgoAEj5NBvpKB8gQJgXgAQI0BABYfBPgI0BABSaCCgYzMAYL7DABG9AYULTwJnMAAN+CBUHSon4CBMBBYkHPZQuFj6+Jl6GFAwwbK35dDAAcLZI0B/wRGg5hHgQRGhf9Hg8G/+QAwcbCBAjB//lHQVv/KUK3//1Wv/4QKAANr/4ABygKFA==")),24,24); + g.setColor(-1).setFont("6x8",2); + + if (reading=="startup") { + g.setFontAlign(0,0); + g.drawString("Scanning...", g.getWidth()/2, g.getHeight()*2/3); + } else if (!reading) { + g.setFontAlign(0,0); + g.drawString("No Tilt found", g.getWidth()/2, g.getHeight()*2/3); + } else { + g.drawString("Temperature",0,100); + g.drawString("Gravity",0,160); + g.setFontAlign(0,0); + g.drawString(reading.color, g.getWidth()*3/4, 24+40); + g.setFontVector(34); + g.setFontAlign(0,-1); + g.drawString(reading.F.toFixed(1),g.getWidth()/2,120); + g.drawString(reading.gravity,g.getWidth()/2,180); + } + g.flip(); +} + +function arrayBufferToHex (arrayBuffer){ + return (new Uint8Array(arrayBuffer)).slice().map(x=>(256+x).toString(16).substr(-2)).join(""); +} + +var TILT_DEVICES = { + 'a495bb30c5b14b44b5121370f02d74de': 'Black', + 'a495bb60c5b14b44b5121370f02d74de': 'Blue', + 'a495bb20c5b14b44b5121370f02d74de': 'Green', + 'a495bb50c5b14b44b5121370f02d74de': 'Orange', + 'a495bb80c5b14b44b5121370f02d74de': 'Pink', + 'a495bb40c5b14b44b5121370f02d74de': 'Purple', + 'a495bb10c5b14b44b5121370f02d74de': 'Red', + 'a495bb70c5b14b44b5121370f02d74de': 'Yellow', +}; + +var failures = 0; + +function takeReading() { + // scan for 5 seconds max + NRF.setScan(function(device) { + d = new DataView(device.manufacturerData); + if (d.getUint8(4) == 0xbb) { + var hexData = arrayBufferToHex(device.manufacturerData); + var tempF = d.getUint16(18); + var tempC = ( tempF - 32) * 5 / 9; + var gravity = d.getUint16(20) / 1000.0; + var color = TILT_DEVICES[hexData.substr(4,32)]; + readings= { + C:tempC, + F:tempF, + gravity:gravity, + d:device.manufacturerData, + color: color, + }; + failures=0; + NRF.setScan(); + if (notFoundTimeout) clearTimeout(notFoundTimeout); + notFoundTimeout = undefined; + displayInfo(readings); + } + }, { filters: [{ manufacturerData: { 0x004C: {} } }]}); + // stop scanning after 5 seconds + var notFoundTimeout = setTimeout(function() { + NRF.setScan(); + notFoundTimeout = undefined; + failures++; + if (failures>5) displayInfo(); + }, 5000); +} + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + + +// Scan every minute +setInterval(function() { + takeReading(); +}, 60*1000); +// Scan once at boot/upload +displayInfo("startup"); +takeReading(); diff --git a/apps/tilthydro/app.png b/apps/tilthydro/app.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a4e3243dd42bd17451f4893c4a4bb8fdac90b7 GIT binary patch literal 14919 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 AB>(^b literal 0 HcmV?d00001 From 3110d6df4f58c98753e8d8785ae112191b7a8a6b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 18 Nov 2020 10:27:11 +0000 Subject: [PATCH 098/110] use locale for temp --- apps/tilthydro/app.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/tilthydro/app.js b/apps/tilthydro/app.js index b64fa4573..011a19eb6 100644 --- a/apps/tilthydro/app.js +++ b/apps/tilthydro/app.js @@ -1,3 +1,5 @@ +var readings; +var failures = 0; function displayInfo(reading) { g.reset(1).setColor(1,0,0); @@ -18,7 +20,11 @@ function displayInfo(reading) { g.drawString(reading.color, g.getWidth()*3/4, 24+40); g.setFontVector(34); g.setFontAlign(0,-1); - g.drawString(reading.F.toFixed(1),g.getWidth()/2,120); + // we can't use locale directly as it currently is just to the nearest degree + var temp = reading.C.toFixed(1)+"°C"; + if (require("locale").temp(0).endsWith("F")) // check locale + temp = reading.F.toFixed(1)+"°F"; + g.drawString(temp,g.getWidth()/2,120); g.drawString(reading.gravity,g.getWidth()/2,180); } g.flip(); @@ -39,8 +45,6 @@ var TILT_DEVICES = { 'a495bb70c5b14b44b5121370f02d74de': 'Yellow', }; -var failures = 0; - function takeReading() { // scan for 5 seconds max NRF.setScan(function(device) { From 571d733dcaed600e51844775e16f6fb766649e9b Mon Sep 17 00:00:00 2001 From: Fscked-In-The-Head Date: Wed, 18 Nov 2020 19:39:10 -0800 Subject: [PATCH 099/110] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 116f1488d..388791c52 100644 --- a/apps.json +++ b/apps.json @@ -1287,7 +1287,7 @@ "id": "rpgdice", "name": "RPG dice", "icon": "rpgdice.png", - "version": "0.01", + "version": "0.02", "description": "Simple RPG dice rolling app.", "tags": "game,fun", "type": "app", From 6eca09e9178c445f1dd4e6adff4bc65bbb926d09 Mon Sep 17 00:00:00 2001 From: abhinavgolwalkar Date: Thu, 19 Nov 2020 20:02:27 +0000 Subject: [PATCH 100/110] app added --- apps.json | 27 +++++++- apps/supmariodark/ChangeLog | 1 + apps/supmariodark/README.md | 39 +++++++++++ apps/supmariodark/banner-down.js | 1 + apps/supmariodark/banner-up.js | 1 + apps/supmariodark/brick2.js | 1 + apps/supmariodark/enemy.js | 1 + apps/supmariodark/flower.js | 1 + apps/supmariodark/flower_b.js | 1 + apps/supmariodark/mario_wh.js | 1 + apps/supmariodark/pipe.js | 1 + apps/supmariodark/supmario30x24.bin.js | 1 + apps/supmariodark/supmario30x24.wdt.js | 1 + apps/supmariodark/supmariodark-icon.js | 1 + apps/supmariodark/supmariodark.js | 90 +++++++++++++++++++++++++ apps/supmariodark/supmariodark.png | Bin 0 -> 6833 bytes 16 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 apps/supmariodark/ChangeLog create mode 100644 apps/supmariodark/README.md create mode 100644 apps/supmariodark/banner-down.js create mode 100644 apps/supmariodark/banner-up.js create mode 100644 apps/supmariodark/brick2.js create mode 100644 apps/supmariodark/enemy.js create mode 100644 apps/supmariodark/flower.js create mode 100644 apps/supmariodark/flower_b.js create mode 100644 apps/supmariodark/mario_wh.js create mode 100644 apps/supmariodark/pipe.js create mode 100644 apps/supmariodark/supmario30x24.bin.js create mode 100644 apps/supmariodark/supmario30x24.wdt.js create mode 100644 apps/supmariodark/supmariodark-icon.js create mode 100644 apps/supmariodark/supmariodark.js create mode 100644 apps/supmariodark/supmariodark.png diff --git a/apps.json b/apps.json index 4846ca199..2d8701cc8 100644 --- a/apps.json +++ b/apps.json @@ -2407,5 +2407,28 @@ {"name":"tilthydro.app.js","url":"app.js"}, {"name":"tilthydro.img","url":"app-icon.js","evaluate":true} ] -} -] +}, +{ "id": "supmariodark", + "name": "Super mario clock night mode", + "shortName":"supmariodark", + "icon": "supmariodark.png", + "version":"0.01", + "description": "Super mario clock in night mode", + "tags": "clock", + "type" : "clock", + "storage": [ + {"name":"supmariodark.app.js","url":"supmariodark.js"}, + {"name":"supmariodark.img","url":"supmariodark-icon.js","evaluate":true}, + {"name":"supmario30x24.bin","url":"supmario30x24.bin.js"}, + {"name":"supmario30x24.wdt","url":"supmario30x24.wdt.js"}, + {"name":"banner-up.img","url":"banner-up.js","evaluate":true}, + {"name":"banner-down.img","url":"banner-down.js","evaluate":true}, + {"name":"brick2.img","url":"brick2.js","evaluate":true}, + {"name":"enemy.img","url":"enemy.js","evaluate":true}, + {"name":"flower.img","url":"flower.js","evaluate":true}, + {"name":"flower_b.img","url":"flower_b.js","evaluate":true}, + {"name":"mario_wh.img","url":"mario_wh.js","evaluate":true}, + {"name":"pipe.img","url":"pipe.js","evaluate":true} + ] + } +] \ No newline at end of file diff --git a/apps/supmariodark/ChangeLog b/apps/supmariodark/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/supmariodark/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/supmariodark/README.md b/apps/supmariodark/README.md new file mode 100644 index 000000000..cef9f2124 --- /dev/null +++ b/apps/supmariodark/README.md @@ -0,0 +1,39 @@ +# Notifications (default) + +A handler for displaying notifications that displays them in a bar at the top of the screen + +This is not an app, but instead it is a library that can be used by +other applications or widgets to display messages. + +## Usage + +```JS +options = { + on : bool, // turn screen on, default true + size : int, // height of notification, default 80 (max) + title : string, // optional title + id // optional notification ID, used with hide() + src : string, // optional source name + body : string, // optional body text + icon : string, // optional icon (image string) + render function(area) {} // function callback to render in area{x,y,w,h} +}; +// eg... show notification +require("notify").show({title:"Test", body:"Hello"}); +// or display lots of text, with a phone icon +require("notify").show({ + title:"Hello", + src:"Test", + body:"This is a really really really long bit of text that has to be wrapped", + icon:require("heatshrink").decompress(atob("jEYxH+ACcejwUUAAYWVjESCqoABCqoYNCpQXLCxgXJQowtTA4ZbSZiwW/C4gWWjAXVZwIuVWhxFIC6z6OLpIXSCywXYDAIWVAAYXTA==")) +}); +// remove it (can also be removed by tapping) +require("notify").hide(); + +// Use ID to only hide a specific notification if it is still visible +require("notify").show({id:1, title:"Test", body:"Some Alert"}); +require("notify").show({id:"msg", title:"Message", body:"Incoming Message"}); // replaces Test Alert +require("notify").hide({id:1}); // does nothing, because the Test Alert was already replaced +require("notify").hide({id:"msg"}); // hides Message +require("notify").hide(); // hides current notification, whatever it was +``` diff --git a/apps/supmariodark/banner-down.js b/apps/supmariodark/banner-down.js new file mode 100644 index 000000000..9073e6b78 --- /dev/null +++ b/apps/supmariodark/banner-down.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("5EYxH+rVa/2KxX+6/X/wA/AH4A2XIS/CYoLH/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/5P/AH7H/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y87I/AH7G4Y5jWDAH4A/Y+wDBY5IIBa4TJ/AH7F0WoS+DY4jQDCQgA/ACZyLAH5fVXobGDAILRDNP7H/LvC8DYgbJCBYbJDAH4A/AGS5FYYbLDBwgA/ACpwLAH5hXYQgFGJv7H/L/TAFA4gIFAH4A/AGi7CXo4KDAH4AXNxIA/MC5jJMv7H/MP4AD")); \ No newline at end of file diff --git a/apps/supmariodark/banner-up.js b/apps/supmariodark/banner-up.js new file mode 100644 index 000000000..2442ceff5 --- /dev/null +++ b/apps/supmariodark/banner-up.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("5EYxH+AAsvAH4AYMAxh/MMRj/Y/4A/MZDUNAH4A/AF69IA4tkAH4AWNw5H/L7TAFAohN/Y/5h9YQjGHOA4A/AH4AtZA7LEYovXAH4AUOA5H/LrC8DYgTGCBQRn/Y/5f7XobHEaIZyLAH4A/AFK1EXwbHGCIZT/AH7J3AYLHKa4YA/AH7H2XALHMKH4A/ZHLH/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/7H/AH7H/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y8oA=")); \ No newline at end of file diff --git a/apps/supmariodark/brick2.js b/apps/supmariodark/brick2.js new file mode 100644 index 000000000..66b66ce88 --- /dev/null +++ b/apps/supmariodark/brick2.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("hsLxH+y3XAAkAA4YDBywAEgAHDAggMRFAIMJAIIABGZJFDIDIpCCZArCBoYMHIQIdCFgsAA=")); \ No newline at end of file diff --git a/apps/supmariodark/enemy.js b/apps/supmariodark/enemy.js new file mode 100644 index 000000000..6384afeb9 --- /dev/null +++ b/apps/supmariodark/enemy.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("iEQxH+AAucAAQKGBw4QKBwoQIBw4QGAoMrBosrBQQdE6AQElfQEIgPEAAgPEDIYPBBQQEEAAvQAAIEGACIwFAAhxIBwoABRwpYCB5ZqFAAYGBB5AQDAoQgJAwgND")); \ No newline at end of file diff --git a/apps/supmariodark/flower.js b/apps/supmariodark/flower.js new file mode 100644 index 000000000..75c5b834a --- /dev/null +++ b/apps/supmariodark/flower.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("iEQxH+AAfXAAwMEBpARGAoXHAAwQDBom6AAgRFB5wvPJ6BvQAAkSiQIIBIgFHAwIQFAgwFCAgQFEBI4GFFAo0HB5gIEAApuKBg4=")); \ No newline at end of file diff --git a/apps/supmariodark/flower_b.js b/apps/supmariodark/flower_b.js new file mode 100644 index 000000000..d79f04e33 --- /dev/null +++ b/apps/supmariodark/flower_b.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("iEQxH+AAfHAAwMEBpARGAoV4AAwQDBom6AAgRFB5wvPJ6BvQAAkSiQKJB5IEDBIIFFBQ4ECAogJHAwoCEGgwPOFYxjNDY/+A")); \ No newline at end of file diff --git a/apps/supmariodark/mario_wh.js b/apps/supmariodark/mario_wh.js new file mode 100644 index 000000000..c8a52eafa --- /dev/null +++ b/apps/supmariodark/mario_wh.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("iEgxH+AAvPAAYLGBo3P44OOB5wyJ3QABDgICCEAwMFCYYRFBhAQFFggPDEAwbGIgQACJo4QHL4w9JQAogFV5G654rDAgIOHB44+HB5BfGB5IQCBIYPFEAgJIAowJFAAoPI44NDAgILDRIYfHUw4PL/wPNN4IOJCAbNDABQOIA5z1EB6qxEc4wHSWIoPHAA4PJA==")); \ No newline at end of file diff --git a/apps/supmariodark/pipe.js b/apps/supmariodark/pipe.js new file mode 100644 index 000000000..da1f1a1f3 --- /dev/null +++ b/apps/supmariodark/pipe.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("iUgxH+xQAG64AGBAOKmANBmAACCwwOECKAALCIn+EAYAL/xaBGxIiFCP4R/CP4R/CP4R/CP4RTA=")); \ No newline at end of file diff --git a/apps/supmariodark/supmario30x24.bin.js b/apps/supmariodark/supmario30x24.bin.js new file mode 100644 index 000000000..218041c14 --- /dev/null +++ b/apps/supmariodark/supmario30x24.bin.js @@ -0,0 +1 @@ +atob("A/4AA/4AA/4AH//AH//AH//A4AH44AH44AH44AA44AA44AA4/AA4/AA4/AA4H//AH//AH//AA/4AA/4AA/4AAAAAAAA4AAA4AAA4HAA4HAA4HAA4///4///4///4///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4AAAAHAH4HAH4HAH4/A/4/A/4/A/44H/44H/44H/44H444H444H444/444/444/44//A4//A4//A4H4A4H4A4H4A4AAAAAAHAAAHAAAHA4AH44AH44AH44HA44HA44HA44/A44/A44/A4//A4//A4//A4/H/4/H/4/H/44A/A4A/A4A/AAAAAAH4AAH4AAH4AA/4AA/4AA/4AH44AH44AH44A/A4A/A4A/A4A///4///4///4///4///4///4AA4AAA4AAA4AAAAA/4HA/4HA/4HA/4H4/4H4/4H444A444A444A444A444A444A444A444A444A44//44//44//4AH/AAH/AAH/AAAAAA//AA//AA//AH//4H//4H//4/HA4/HA4/HA44HA44HA44HA44HA44HA44HA44H/44H/44H/4AA/AAA/AAA/AAAAA/AAA/AAA/AAA/AAA/AAA/AAA4A/44A/44A/44H/44H/44H/44/AA4/AA4/AA/4AA/4AA/4AA/AAA/AAA/AAAAAAAH4/AH4/AH4/A//A4//A4//A44/A44/A44/A44HA44HA44HA44HA44HA44HA4H4/4H4/4H4/4AA/AAA/AAA/AAAAAH4AAH4AAH4AA//A4//A4//A44HA44HA44HA44HA44HA44HA44HH44HH44HH4///A///A///AH/4AH/4AH/4AAAAAPw/APw/APw/APw/APw/APw/APw/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AA/4AA/4A//4A//4A//4//4A//4A//4A//4A//4A//4AA//4A//4A//4AA/4AA/4AA/4AAAA///4///4///4///4///4///44HA44HA44HA44HA44HA44HA4///4///4///4H4/AH4/AH4/AAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA44AA44AA44AA4AAAA///4///4///4///4///4///44AA44AA44AA4/AH4/AH4/AH4H//AH//AH//AA/4AA/4AA/4AAAAA///4///4///4///4///4///44HA44HA44HA44HA44HA44HA44AA44AA44AA4AAAA///4///4///4///4///4///44HAA4HAA4HAA4HAA4HAA4HAA4AAA4AAA4AAAAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44HA44HA44HA44HA44HA44HA44H/44H/44H/44H/44H/44H/4AAAA///4///4///4///4///4///4AHAAAHAAAHAAAHAAAHAAAHAA///4///4///4///4///4///4AAAA///4///4///4///4///4///4AAAAAAA4AAA4AAA4AAA4AAA4AAA4AAA4AAA4AAA4///4///4///4///A///A///AAAAA///4///4///4///4///4///4A/4AA/4AA/4AH4/AH4/AH4/A/AH4/AH4/AH44AA44AA44AA4AAAA///4///4///4///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4AAAA///4///4///4///4///4///4//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A///4///4///4///4///4///4AAAA///4///4///4///4///4///4//AA//AA//AAA//AA//AA//A///4///4///4///4///4///4AAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA4/AH4/AH4/AH4H//AH//AH//AA/4AA/4AA/4AAAAA///4///4///4///4///4///44HAA4HAA4HAA4HAA4HAA4HAA//AA//AA//AAH4AAH4AAH4AAAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA4/AH//AH//AH/H//HH//HH//HA/4HA/4HA/4HAAAA///4///4///4///4///4///44HAA4HAA4HAA4H4A4H4A4H4A///4///4///4H4H4H4H4H4H4AAAAH4A4H4A4H4A4//A4//A4//A44HA44HA44HA44HA44HA44HA44H/44H/44H/44A/A4A/A4A/AAAAA4AAA4AAA4AAA4AAA4AAA4AAA///4///4///4///4///4///44AAA4AAA4AAA4AAA4AAA4AAAAAAA///A///A///A///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4///4///4///4///A///A///AAAAA/4AA/4AA/4AA//4A//4A//4AAH/4AH/4AH/4AH/4AH/4AH/4//4A//4A//4A/4AA/4AA/4AAAAAA/AAA/AAA/AAA//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A/AAA/AAA/AAA/AH4/AH4/AH4/4/4/4/4/4/4A/4AA/4AA/4AA/4AA/4AA/4A/4/4/4/4/4/4/AH4/AH4/AH4AAAA/AAA/AAA/AAA/4AA/4AA/4AAA//4A//4A//4A//4A//4A//4/4AA/4AA/4AA/AAA/AAA/AAAAAAA4A/44A/44A/44H/44H/44H/44/A44/A44/A4/4A4/4A4/4A4/AA4/AA4/AA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); \ No newline at end of file diff --git a/apps/supmariodark/supmario30x24.wdt.js b/apps/supmariodark/supmario30x24.wdt.js new file mode 100644 index 000000000..81aa0682b --- /dev/null +++ b/apps/supmariodark/supmario30x24.wdt.js @@ -0,0 +1 @@ +atob("FhMWFhYWFhYWFggQEBAQEBATExMTEBAWEwcQEw0ZExkTGRMTExMTHhMTEBAQEBAQ"); \ No newline at end of file diff --git a/apps/supmariodark/supmariodark-icon.js b/apps/supmariodark/supmariodark-icon.js new file mode 100644 index 000000000..3d52111e5 --- /dev/null +++ b/apps/supmariodark/supmariodark-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwgGDgeAmALCCQ0IgYeIn/4wYbBxETEIc4xAABBgIAFgf///4gE43eYBIUIxOZAAOYHQ2YC4u7wAEBCwYABGAsDx/5C4MwhO5xO4FomP/GJC4s4CoIBBxGJ3OY3eICwWIHgP5KIQAC3AWB/+P/+JL4OLIYY8BzIXFIwIUBAAWIC4W4OYX/z+Zz+YmYYDCwn/3AXG/OfGAOYzIXI/G4zeYzZ2BzC+CAAOZ3IXD34XD/eILoO5OgJ/CPYYXJTgKQBxKLBF4jAGC4gMBKgIDCKYIWBDwLxFC4m4BwIrBPIJHBEQQwCC4amFIQQICxgECJA7vBLwQOBMIIDB/P+C4IHB/AXBwDYEFwTmB/JIBz/4C4Q3BYwQXFKoLjB3OfUIIgB/3Ix+I5YIBxBfDgEwWgW/3OPF4O//f/9A6B95gBmEzDIk4UAQXBRwJlBAAI7BxB0BhDgBC4pCBI4IVBDoP5TYeYgZ9CC4cBLQQRDdoQXD/c4ToQXBgYABC4OYFAgXGUAQXCMwQXCboYXG3YDC5AuBNARgCDAe4BQIFC/ZSDYAM4xGb3AXCXgX/z4XBGAO734iDxeDhGL3e4mZIBMIeJUgWJLQI0DAoTdBxB4CJAYTBGAQABQgn4YYIjBBQIABxwVBxK2BPQScFOYIIB3YXCzHMLQOJCoOPzO4C4KVCmcQF4OLzHICIOO5nI/4dBCIRGCGwODdgKnBIwIrBxHIC4OP/eZVQQWBwczgYWBgEwnGYxgXCDgPIxGfYIYWBCgQADGAIXBxisBLYKYCBQOIiYWGC4IvDzY+BSgZ9BFo4ABhZHEAAaJCxAXL5hzBCoQEEC5U7CIIABCwQdDze5wAXI3ImDCoQXCxO5zEwOxCGDAAZlBJARGJnCJCABIWIgCEBC5QuJC4RIHCxgXBGAc5GgmDOhBfDc4WDhA0DmYVKC4eJxEwhA0CIhYADmcziCsBGgIcBC5w1GCx4=")) \ No newline at end of file diff --git a/apps/supmariodark/supmariodark.js b/apps/supmariodark/supmariodark.js new file mode 100644 index 000000000..ae3b976b2 --- /dev/null +++ b/apps/supmariodark/supmariodark.js @@ -0,0 +1,90 @@ +// place your const, vars, functions or classes here +var s=require("Storage"); +let stid; +let hour = -1; +let minute = -1; +const resetFace = ()=>{ + Bangle.setLCDMode(); + g.setClipRect(0,24,239,239) + g.clear(); +}; +const readImage =(img) =>{ + return (s.read(img)); +}; +const drawFace = ()=>{ + resetFace(); + g.drawImages([ + {image:readImage("pipe.img"),x:180,y:160,scale:2}, + {image:readImage("flower_b.img"),x:180,y:128,scale:2}, + {image:readImage("mario_wh.img"),x:100,y:132,scale:2}, + {image:readImage("enemy.img"),x:20,y:165,scale:2}, + ]).drawImages([ + {image:readImage("brick2.img"),x:0,y:196,repeat:true,scale:2} + ]); + drawBanner(); +}; + +const resetTimer =()=>{ + if (stid) { + clearInterval(stid); + stid = undefined; + } +} +const startTimer =() =>{ + hour = -1; + minute = -1; + stid = setInterval(onHalfSecond,500); +} +const drawBanner = (h) =>{ + if(h == undefined) h=24; + g.drawImages([ + {image:readImage("banner-up.img"),x:g.getWidth()/2-100,y:50}, + {image:readImage("banner-down.img"),x:g.getWidth()/2-100,y:(50+24+h)} + ]) +}; + +const updateTimeBanner = (h,m)=>{ + m = (m<10?'0':'')+m; + h = (h<10?'0':'')+h; + bx1=g.getWidth()/2-90; + by1=50+10; + bx2=g.getWidth()/2+90; + by2=50+62; + + g.setFontCustom(eval(s.read("supmario30x24.bin")), 48, eval(s.read("supmario30x24.wdt")), 24); + g.setClipRect(bx1,by1,bx2,by2).clearRect(bx1,by1,bx2,by2); + g.drawString(h,bx1+35,75).drawString(":",g.getWidth()/2,75).drawString(m,bx1+110,75).flip(); +}; +let om = 0; +const onHalfSecond =()=>{ + var d = new Date(); + var sec = d.getSeconds(); + hour = d.getHours(); + minute = d.getMinutes(); + if(minute>om)updateTimeBanner(hour,minute); + let im, pos; + if(sec%2 == 0){im = "flower_b.img";pos = 20;} + else{im = "flower.img";pos = 25;} + g.setClipRect(180,128,180+32,128+32).clearRect(180,128,180+32,128+32).drawImage(readImage(im),180,128,{scale:2}); + g.setClipRect(20,165,25+32,165+32).clearRect(20,165,25+32,165+32).drawImage(readImage("enemy.img"),pos,165,{scale:2}); + om = minute; +}; + + +Bangle.on('lcdPower', (on) => { + resetTimer(); + if (on) { + om=-1; + startTimer(); + drawFace(); + } + else { + resetTimer(); + } +}); +resetTimer(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawFace(); +startTimer(); +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); \ No newline at end of file diff --git a/apps/supmariodark/supmariodark.png b/apps/supmariodark/supmariodark.png new file mode 100644 index 0000000000000000000000000000000000000000..272ae3f289d6c719bf3ae54d5a442b102dec10b7 GIT binary patch literal 6833 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 literal 0 HcmV?d00001 From 1551d9e7a969ad073ef0d2bd7439ff43c1e8d20d Mon Sep 17 00:00:00 2001 From: abhinavgolwalkar Date: Thu, 19 Nov 2020 20:11:27 +0000 Subject: [PATCH 101/110] update read me --- apps/supmariodark/README.md | 40 ++----------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/apps/supmariodark/README.md b/apps/supmariodark/README.md index cef9f2124..3f6b52b9a 100644 --- a/apps/supmariodark/README.md +++ b/apps/supmariodark/README.md @@ -1,39 +1,3 @@ -# Notifications (default) +# Super mario watch face night mode -A handler for displaying notifications that displays them in a bar at the top of the screen - -This is not an app, but instead it is a library that can be used by -other applications or widgets to display messages. - -## Usage - -```JS -options = { - on : bool, // turn screen on, default true - size : int, // height of notification, default 80 (max) - title : string, // optional title - id // optional notification ID, used with hide() - src : string, // optional source name - body : string, // optional body text - icon : string, // optional icon (image string) - render function(area) {} // function callback to render in area{x,y,w,h} -}; -// eg... show notification -require("notify").show({title:"Test", body:"Hello"}); -// or display lots of text, with a phone icon -require("notify").show({ - title:"Hello", - src:"Test", - body:"This is a really really really long bit of text that has to be wrapped", - icon:require("heatshrink").decompress(atob("jEYxH+ACcejwUUAAYWVjESCqoABCqoYNCpQXLCxgXJQowtTA4ZbSZiwW/C4gWWjAXVZwIuVWhxFIC6z6OLpIXSCywXYDAIWVAAYXTA==")) -}); -// remove it (can also be removed by tapping) -require("notify").hide(); - -// Use ID to only hide a specific notification if it is still visible -require("notify").show({id:1, title:"Test", body:"Some Alert"}); -require("notify").show({id:"msg", title:"Message", body:"Incoming Message"}); // replaces Test Alert -require("notify").hide({id:1}); // does nothing, because the Test Alert was already replaced -require("notify").hide({id:"msg"}); // hides Message -require("notify").hide(); // hides current notification, whatever it was -``` +Super mario 2 watch face night mode From dc4274037e41909e8bb1d4191d08514f8093b070 Mon Sep 17 00:00:00 2001 From: abhigkar Date: Thu, 19 Nov 2020 20:23:06 +0000 Subject: [PATCH 102/110] Demo image added --- apps/supmariodark/Watch-demo.png | Bin 0 -> 47943 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/supmariodark/Watch-demo.png diff --git a/apps/supmariodark/Watch-demo.png b/apps/supmariodark/Watch-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..98f28d7ac18f46c9859b706fee6c27dd0d576c0e GIT binary patch literal 47943 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%0A$%mu@Nl^uYz{IB$#m2|Pvmz8? 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 z Date: Mon, 23 Nov 2020 16:10:51 +0000 Subject: [PATCH 103/110] fix build/upload errors caused by non-evaluatable js files --- apps/supmariodark/banner-down.js | 2 +- apps/supmariodark/banner-up.js | 2 +- apps/supmariodark/brick2.js | 2 +- apps/supmariodark/enemy.js | 2 +- apps/supmariodark/flower.js | 2 +- apps/supmariodark/flower_b.js | 2 +- apps/supmariodark/mario_wh.js | 2 +- apps/supmariodark/pipe.js | 2 +- apps/supmariodark/supmario30x24.bin.js | 2 +- apps/supmariodark/supmario30x24.wdt.js | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/supmariodark/banner-down.js b/apps/supmariodark/banner-down.js index 9073e6b78..f3e5d2be2 100644 --- a/apps/supmariodark/banner-down.js +++ b/apps/supmariodark/banner-down.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("5EYxH+rVa/2KxX+6/X/wA/AH4A2XIS/CYoLH/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/5P/AH7H/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y87I/AH7G4Y5jWDAH4A/Y+wDBY5IIBa4TJ/AH7F0WoS+DY4jQDCQgA/ACZyLAH5fVXobGDAILRDNP7H/LvC8DYgbJCBYbJDAH4A/AGS5FYYbLDBwgA/ACpwLAH5hXYQgFGJv7H/L/TAFA4gIFAH4A/AGi7CXo4KDAH4AXNxIA/MC5jJMv7H/MP4AD")); \ No newline at end of file +require("heatshrink").decompress(atob("5EYxH+rVa/2KxX+6/X/wA/AH4A2XIS/CYoLH/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/5P/AH7H/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y87I/AH7G4Y5jWDAH4A/Y+wDBY5IIBa4TJ/AH7F0WoS+DY4jQDCQgA/ACZyLAH5fVXobGDAILRDNP7H/LvC8DYgbJCBYbJDAH4A/AGS5FYYbLDBwgA/ACpwLAH5hXYQgFGJv7H/L/TAFA4gIFAH4A/AGi7CXo4KDAH4AXNxIA/MC5jJMv7H/MP4AD")) diff --git a/apps/supmariodark/banner-up.js b/apps/supmariodark/banner-up.js index 2442ceff5..a6f95bc02 100644 --- a/apps/supmariodark/banner-up.js +++ b/apps/supmariodark/banner-up.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("5EYxH+AAsvAH4AYMAxh/MMRj/Y/4A/MZDUNAH4A/AF69IA4tkAH4AWNw5H/L7TAFAohN/Y/5h9YQjGHOA4A/AH4AtZA7LEYovXAH4AUOA5H/LrC8DYgTGCBQRn/Y/5f7XobHEaIZyLAH4A/AFK1EXwbHGCIZT/AH7J3AYLHKa4YA/AH7H2XALHMKH4A/ZHLH/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/7H/AH7H/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y8oA=")); \ No newline at end of file +require("heatshrink").decompress(atob("5EYxH+AAsvAH4AYMAxh/MMRj/Y/4A/MZDUNAH4A/AF69IA4tkAH4AWNw5H/L7TAFAohN/Y/5h9YQjGHOA4A/AH4AtZA7LEYovXAH4AUOA5H/LrC8DYgTGCBQRn/Y/5f7XobHEaIZyLAH4A/AFK1EXwbHGCIZT/AH7J3AYLHKa4YA/AH7H2XALHMKH4A/ZHLH/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y/7H/AH7H/Y/4A/AH7H/AH4A/Y/4A/AH7H/AH4A/Y8oA=")) diff --git a/apps/supmariodark/brick2.js b/apps/supmariodark/brick2.js index 66b66ce88..9819e58ad 100644 --- a/apps/supmariodark/brick2.js +++ b/apps/supmariodark/brick2.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("hsLxH+y3XAAkAA4YDBywAEgAHDAggMRFAIMJAIIABGZJFDIDIpCCZArCBoYMHIQIdCFgsAA=")); \ No newline at end of file +require("heatshrink").decompress(atob("hsLxH+y3XAAkAA4YDBywAEgAHDAggMRFAIMJAIIABGZJFDIDIpCCZArCBoYMHIQIdCFgsAA=")) diff --git a/apps/supmariodark/enemy.js b/apps/supmariodark/enemy.js index 6384afeb9..fca1dc370 100644 --- a/apps/supmariodark/enemy.js +++ b/apps/supmariodark/enemy.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("iEQxH+AAucAAQKGBw4QKBwoQIBw4QGAoMrBosrBQQdE6AQElfQEIgPEAAgPEDIYPBBQQEEAAvQAAIEGACIwFAAhxIBwoABRwpYCB5ZqFAAYGBB5AQDAoQgJAwgND")); \ No newline at end of file +require("heatshrink").decompress(atob("iEQxH+AAucAAQKGBw4QKBwoQIBw4QGAoMrBosrBQQdE6AQElfQEIgPEAAgPEDIYPBBQQEEAAvQAAIEGACIwFAAhxIBwoABRwpYCB5ZqFAAYGBB5AQDAoQgJAwgND")) diff --git a/apps/supmariodark/flower.js b/apps/supmariodark/flower.js index 75c5b834a..41f4ee742 100644 --- a/apps/supmariodark/flower.js +++ b/apps/supmariodark/flower.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("iEQxH+AAfXAAwMEBpARGAoXHAAwQDBom6AAgRFB5wvPJ6BvQAAkSiQIIBIgFHAwIQFAgwFCAgQFEBI4GFFAo0HB5gIEAApuKBg4=")); \ No newline at end of file +require("heatshrink").decompress(atob("iEQxH+AAfXAAwMEBpARGAoXHAAwQDBom6AAgRFB5wvPJ6BvQAAkSiQIIBIgFHAwIQFAgwFCAgQFEBI4GFFAo0HB5gIEAApuKBg4=")) diff --git a/apps/supmariodark/flower_b.js b/apps/supmariodark/flower_b.js index d79f04e33..1d81df47a 100644 --- a/apps/supmariodark/flower_b.js +++ b/apps/supmariodark/flower_b.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("iEQxH+AAfHAAwMEBpARGAoV4AAwQDBom6AAgRFB5wvPJ6BvQAAkSiQKJB5IEDBIIFFBQ4ECAogJHAwoCEGgwPOFYxjNDY/+A")); \ No newline at end of file +require("heatshrink").decompress(atob("iEQxH+AAfHAAwMEBpARGAoV4AAwQDBom6AAgRFB5wvPJ6BvQAAkSiQKJB5IEDBIIFFBQ4ECAogJHAwoCEGgwPOFYxjNDY/+A")) diff --git a/apps/supmariodark/mario_wh.js b/apps/supmariodark/mario_wh.js index c8a52eafa..c55f1ff1f 100644 --- a/apps/supmariodark/mario_wh.js +++ b/apps/supmariodark/mario_wh.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("iEgxH+AAvPAAYLGBo3P44OOB5wyJ3QABDgICCEAwMFCYYRFBhAQFFggPDEAwbGIgQACJo4QHL4w9JQAogFV5G654rDAgIOHB44+HB5BfGB5IQCBIYPFEAgJIAowJFAAoPI44NDAgILDRIYfHUw4PL/wPNN4IOJCAbNDABQOIA5z1EB6qxEc4wHSWIoPHAA4PJA==")); \ No newline at end of file +require("heatshrink").decompress(atob("iEgxH+AAvPAAYLGBo3P44OOB5wyJ3QABDgICCEAwMFCYYRFBhAQFFggPDEAwbGIgQACJo4QHL4w9JQAogFV5G654rDAgIOHB44+HB5BfGB5IQCBIYPFEAgJIAowJFAAoPI44NDAgILDRIYfHUw4PL/wPNN4IOJCAbNDABQOIA5z1EB6qxEc4wHSWIoPHAA4PJA==")) diff --git a/apps/supmariodark/pipe.js b/apps/supmariodark/pipe.js index da1f1a1f3..d21aebc79 100644 --- a/apps/supmariodark/pipe.js +++ b/apps/supmariodark/pipe.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("iUgxH+xQAG64AGBAOKmANBmAACCwwOECKAALCIn+EAYAL/xaBGxIiFCP4R/CP4R/CP4R/CP4RTA=")); \ No newline at end of file +require("heatshrink").decompress(atob("iUgxH+xQAG64AGBAOKmANBmAACCwwOECKAALCIn+EAYAL/xaBGxIiFCP4R/CP4R/CP4R/CP4RTA=")) diff --git a/apps/supmariodark/supmario30x24.bin.js b/apps/supmariodark/supmario30x24.bin.js index 218041c14..01974bbb3 100644 --- a/apps/supmariodark/supmario30x24.bin.js +++ b/apps/supmariodark/supmario30x24.bin.js @@ -1 +1 @@ -atob("A/4AA/4AA/4AH//AH//AH//A4AH44AH44AH44AA44AA44AA4/AA4/AA4/AA4H//AH//AH//AA/4AA/4AA/4AAAAAAAA4AAA4AAA4HAA4HAA4HAA4///4///4///4///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4AAAAHAH4HAH4HAH4/A/4/A/4/A/44H/44H/44H/44H444H444H444/444/444/44//A4//A4//A4H4A4H4A4H4A4AAAAAAHAAAHAAAHA4AH44AH44AH44HA44HA44HA44/A44/A44/A4//A4//A4//A4/H/4/H/4/H/44A/A4A/A4A/AAAAAAH4AAH4AAH4AA/4AA/4AA/4AH44AH44AH44A/A4A/A4A/A4A///4///4///4///4///4///4AA4AAA4AAA4AAAAA/4HA/4HA/4HA/4H4/4H4/4H444A444A444A444A444A444A444A444A444A44//44//44//4AH/AAH/AAH/AAAAAA//AA//AA//AH//4H//4H//4/HA4/HA4/HA44HA44HA44HA44HA44HA44HA44H/44H/44H/4AA/AAA/AAA/AAAAA/AAA/AAA/AAA/AAA/AAA/AAA4A/44A/44A/44H/44H/44H/44/AA4/AA4/AA/4AA/4AA/4AA/AAA/AAA/AAAAAAAH4/AH4/AH4/A//A4//A4//A44/A44/A44/A44HA44HA44HA44HA44HA44HA4H4/4H4/4H4/4AA/AAA/AAA/AAAAAH4AAH4AAH4AA//A4//A4//A44HA44HA44HA44HA44HA44HA44HH44HH44HH4///A///A///AH/4AH/4AH/4AAAAAPw/APw/APw/APw/APw/APw/APw/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AA/4AA/4A//4A//4A//4//4A//4A//4A//4A//4A//4AA//4A//4A//4AA/4AA/4AA/4AAAA///4///4///4///4///4///44HA44HA44HA44HA44HA44HA4///4///4///4H4/AH4/AH4/AAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA44AA44AA44AA4AAAA///4///4///4///4///4///44AA44AA44AA4/AH4/AH4/AH4H//AH//AH//AA/4AA/4AA/4AAAAA///4///4///4///4///4///44HA44HA44HA44HA44HA44HA44AA44AA44AA4AAAA///4///4///4///4///4///44HAA4HAA4HAA4HAA4HAA4HAA4AAA4AAA4AAAAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44HA44HA44HA44HA44HA44HA44H/44H/44H/44H/44H/44H/4AAAA///4///4///4///4///4///4AHAAAHAAAHAAAHAAAHAAAHAA///4///4///4///4///4///4AAAA///4///4///4///4///4///4AAAAAAA4AAA4AAA4AAA4AAA4AAA4AAA4AAA4AAA4///4///4///4///A///A///AAAAA///4///4///4///4///4///4A/4AA/4AA/4AH4/AH4/AH4/A/AH4/AH4/AH44AA44AA44AA4AAAA///4///4///4///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4AAAA///4///4///4///4///4///4//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A///4///4///4///4///4///4AAAA///4///4///4///4///4///4//AA//AA//AAA//AA//AA//A///4///4///4///4///4///4AAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA4/AH4/AH4/AH4H//AH//AH//AA/4AA/4AA/4AAAAA///4///4///4///4///4///44HAA4HAA4HAA4HAA4HAA4HAA//AA//AA//AAH4AAH4AAH4AAAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA4/AH//AH//AH/H//HH//HH//HA/4HA/4HA/4HAAAA///4///4///4///4///4///44HAA4HAA4HAA4H4A4H4A4H4A///4///4///4H4H4H4H4H4H4AAAAH4A4H4A4H4A4//A4//A4//A44HA44HA44HA44HA44HA44HA44H/44H/44H/44A/A4A/A4A/AAAAA4AAA4AAA4AAA4AAA4AAA4AAA///4///4///4///4///4///44AAA4AAA4AAA4AAA4AAA4AAAAAAA///A///A///A///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4///4///4///4///A///A///AAAAA/4AA/4AA/4AA//4A//4A//4AAH/4AH/4AH/4AH/4AH/4AH/4//4A//4A//4A/4AA/4AA/4AAAAAA/AAA/AAA/AAA//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A/AAA/AAA/AAA/AH4/AH4/AH4/4/4/4/4/4/4A/4AA/4AA/4AA/4AA/4AA/4A/4/4/4/4/4/4/AH4/AH4/AH4AAAA/AAA/AAA/AAA/4AA/4AA/4AAA//4A//4A//4A//4A//4A//4/4AA/4AA/4AA/AAA/AAA/AAAAAAA4A/44A/44A/44H/44H/44H/44/A44/A44/A4/4A4/4A4/4A4/AA4/AA4/AA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); \ No newline at end of file +atob("A/4AA/4AA/4AH//AH//AH//A4AH44AH44AH44AA44AA44AA4/AA4/AA4/AA4H//AH//AH//AA/4AA/4AA/4AAAAAAAA4AAA4AAA4HAA4HAA4HAA4///4///4///4///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4AAAAHAH4HAH4HAH4/A/4/A/4/A/44H/44H/44H/44H444H444H444/444/444/44//A4//A4//A4H4A4H4A4H4A4AAAAAAHAAAHAAAHA4AH44AH44AH44HA44HA44HA44/A44/A44/A4//A4//A4//A4/H/4/H/4/H/44A/A4A/A4A/AAAAAAH4AAH4AAH4AA/4AA/4AA/4AH44AH44AH44A/A4A/A4A/A4A///4///4///4///4///4///4AA4AAA4AAA4AAAAA/4HA/4HA/4HA/4H4/4H4/4H444A444A444A444A444A444A444A444A444A44//44//44//4AH/AAH/AAH/AAAAAA//AA//AA//AH//4H//4H//4/HA4/HA4/HA44HA44HA44HA44HA44HA44HA44H/44H/44H/4AA/AAA/AAA/AAAAA/AAA/AAA/AAA/AAA/AAA/AAA4A/44A/44A/44H/44H/44H/44/AA4/AA4/AA/4AA/4AA/4AA/AAA/AAA/AAAAAAAH4/AH4/AH4/A//A4//A4//A44/A44/A44/A44HA44HA44HA44HA44HA44HA4H4/4H4/4H4/4AA/AAA/AAA/AAAAAH4AAH4AAH4AA//A4//A4//A44HA44HA44HA44HA44HA44HA44HH44HH44HH4///A///A///AH/4AH/4AH/4AAAAAPw/APw/APw/APw/APw/APw/APw/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AA/4AA/4A//4A//4A//4//4A//4A//4A//4A//4A//4AA//4A//4A//4AA/4AA/4AA/4AAAA///4///4///4///4///4///44HA44HA44HA44HA44HA44HA4///4///4///4H4/AH4/AH4/AAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA44AA44AA44AA4AAAA///4///4///4///4///4///44AA44AA44AA4/AH4/AH4/AH4H//AH//AH//AA/4AA/4AA/4AAAAA///4///4///4///4///4///44HA44HA44HA44HA44HA44HA44AA44AA44AA4AAAA///4///4///4///4///4///44HAA4HAA4HAA4HAA4HAA4HAA4AAA4AAA4AAAAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44HA44HA44HA44HA44HA44HA44H/44H/44H/44H/44H/44H/4AAAA///4///4///4///4///4///4AHAAAHAAAHAAAHAAAHAAAHAA///4///4///4///4///4///4AAAA///4///4///4///4///4///4AAAAAAA4AAA4AAA4AAA4AAA4AAA4AAA4AAA4AAA4///4///4///4///A///A///AAAAA///4///4///4///4///4///4A/4AA/4AA/4AH4/AH4/AH4/A/AH4/AH4/AH44AA44AA44AA4AAAA///4///4///4///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4AAAA///4///4///4///4///4///4//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A///4///4///4///4///4///4AAAA///4///4///4///4///4///4//AA//AA//AAA//AA//AA//A///4///4///4///4///4///4AAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA4/AH4/AH4/AH4H//AH//AH//AA/4AA/4AA/4AAAAA///4///4///4///4///4///44HAA4HAA4HAA4HAA4HAA4HAA//AA//AA//AAH4AAH4AAH4AAAAAAA/4AA/4AA/4AH//AH//AH//A/AH4/AH4/AH44AA44AA44AA44AA44AA44AA4/AH//AH//AH/H//HH//HH//HA/4HA/4HA/4HAAAA///4///4///4///4///4///44HAA4HAA4HAA4H4A4H4A4H4A///4///4///4H4H4H4H4H4H4AAAAH4A4H4A4H4A4//A4//A4//A44HA44HA44HA44HA44HA44HA44H/44H/44H/44A/A4A/A4A/AAAAA4AAA4AAA4AAA4AAA4AAA4AAA///4///4///4///4///4///44AAA4AAA4AAA4AAA4AAA4AAAAAAA///A///A///A///4///4///4AAA4AAA4AAA4AAA4AAA4AAA4///4///4///4///A///A///AAAAA/4AA/4AA/4AA//4A//4A//4AAH/4AH/4AH/4AH/4AH/4AH/4//4A//4A//4A/4AA/4AA/4AAAAAA/AAA/AAA/AAA//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A//4A//4A//4AA//4A//4A//4A//4A//4A//4//4A//4A//4A/AAA/AAA/AAA/AH4/AH4/AH4/4/4/4/4/4/4A/4AA/4AA/4AA/4AA/4AA/4A/4/4/4/4/4/4/AH4/AH4/AH4AAAA/AAA/AAA/AAA/4AA/4AA/4AAA//4A//4A//4A//4A//4A//4/4AA/4AA/4AA/AAA/AAA/AAAAAAA4A/44A/44A/44H/44H/44H/44/A44/A44/A4/4A4/4A4/4A4/AA4/AA4/AA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") diff --git a/apps/supmariodark/supmario30x24.wdt.js b/apps/supmariodark/supmario30x24.wdt.js index 81aa0682b..f97141e83 100644 --- a/apps/supmariodark/supmario30x24.wdt.js +++ b/apps/supmariodark/supmario30x24.wdt.js @@ -1 +1 @@ -atob("FhMWFhYWFhYWFggQEBAQEBATExMTEBAWEwcQEw0ZExkTGRMTExMTHhMTEBAQEBAQ"); \ No newline at end of file +atob("FhMWFhYWFhYWFggQEBAQEBATExMTEBAWEwcQEw0ZExkTGRMTExMTHhMTEBAQEBAQ") From 2824cba526d0b5fb98d3fd18db277eb703edbeba Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 24 Nov 2020 08:16:53 +0000 Subject: [PATCH 104/110] Remove tabs --- apps/supmariodark/supmariodark.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/supmariodark/supmariodark.js b/apps/supmariodark/supmariodark.js index ae3b976b2..00a20e5fb 100644 --- a/apps/supmariodark/supmariodark.js +++ b/apps/supmariodark/supmariodark.js @@ -72,13 +72,12 @@ const onHalfSecond =()=>{ Bangle.on('lcdPower', (on) => { - resetTimer(); - if (on) { - om=-1; - startTimer(); - drawFace(); - } - else { + resetTimer(); + if (on) { + om=-1; + startTimer(); + drawFace(); + } else { resetTimer(); } }); @@ -87,4 +86,4 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); drawFace(); startTimer(); -setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); \ No newline at end of file +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); From 4517f202b16ed98a68d0c28cf1add0c11b61c186 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 24 Nov 2020 08:18:15 +0000 Subject: [PATCH 105/110] Turn indent warnings off - nobody seems to care about this, and it just stops us seeing actual useful warnings --- apps/.eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/.eslintrc.json b/apps/.eslintrc.json index b8c5408e3..a9bb785ab 100644 --- a/apps/.eslintrc.json +++ b/apps/.eslintrc.json @@ -136,7 +136,7 @@ }, "rules": { "indent": [ - "warn", + "off", 2, { "SwitchCase": 1 From b3e35726c5ec8db994bf576fc7af9803fb9fdd2f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 Nov 2020 09:06:40 +0000 Subject: [PATCH 106/110] gpsrec: Increase GPS recording accuracy by one decimal place Ensure default time period is 10 from http://forum.espruino.com/conversations/356940 --- apps.json | 4 ++-- apps/gpsrec/ChangeLog | 2 ++ apps/gpsrec/app.js | 6 +++--- apps/gpsrec/widget.js | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/apps.json b/apps.json index 2d8701cc8..959f1afc8 100644 --- a/apps.json +++ b/apps.json @@ -362,7 +362,7 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.12", + "version":"0.13", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", @@ -2431,4 +2431,4 @@ {"name":"pipe.img","url":"pipe.js","evaluate":true} ] } -] \ No newline at end of file +] diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index b002e9914..01788e08f 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -13,3 +13,5 @@ 0.10: Can now graph altitude & speed 0.11: Ensure we don't turn GPS off if it was previously on (eg from another app/widget) 0.12: Add option to plot on top of OpenStreetMap tiles (when they are installed on the watch) +0.13: Increase GPS recording accuracy by one decimal place + Ensure default time period is 10 diff --git a/apps/gpsrec/app.js b/apps/gpsrec/app.js index 7b01786a5..c7de29d32 100644 --- a/apps/gpsrec/app.js +++ b/apps/gpsrec/app.js @@ -37,9 +37,9 @@ function showMainMenu() { } }, 'Time Period': { - value: settings.period||1, + value: settings.period||10, min: 1, - max: 60, + max: 120, step: 1, onchange: v => { settings.recording = false; @@ -226,7 +226,7 @@ function plotTrack(info) { g.drawString("N",2,40); g.setColor(1,1,1); } - else { + else { var map = s.readJSON("openstmap.json"); map.center = Bangle.project({lat:map.lat,lon:map.lon}); var clat = (info.minLat+info.maxLat)/2; diff --git a/apps/gpsrec/widget.js b/apps/gpsrec/widget.js index 3d110f500..f07c9e43a 100644 --- a/apps/gpsrec/widget.js +++ b/apps/gpsrec/widget.js @@ -31,8 +31,8 @@ periodCtr = settings.period; if (gpsTrack) gpsTrack.write([ fix.time.getTime(), - fix.lat.toFixed(5), - fix.lon.toFixed(5), + fix.lat.toFixed(6), + fix.lon.toFixed(6), fix.alt ].join(",")+"\n"); } From 48beacf01728bfe8e3b14ef167a5bdf5013b9bbf Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 30 Nov 2020 11:51:03 +0000 Subject: [PATCH 107/110] Use HRM data and calculations from Bangle.js (don't access hardware directly) --- apps.json | 4 +- apps/hrm/ChangeLog | 1 + apps/hrm/heartrate.js | 108 ++++++++++++++++++------------------------ 3 files changed, 50 insertions(+), 63 deletions(-) diff --git a/apps.json b/apps.json index 959f1afc8..4b210bade 100644 --- a/apps.json +++ b/apps.json @@ -545,8 +545,8 @@ { "id": "hrm", "name": "Heart Rate Monitor", "icon": "heartrate.png", - "version":"0.01", - "description": "Measure your current heart rate", + "version":"0.02", + "description": "Measure your heart rate and see live sensor data", "tags": "health", "storage": [ {"name":"hrm.app.js","url":"heartrate.js"}, diff --git a/apps/hrm/ChangeLog b/apps/hrm/ChangeLog index 5560f00bc..5715e07c7 100644 --- a/apps/hrm/ChangeLog +++ b/apps/hrm/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Use HRM data and calculations from Bangle.js (don't access hardware directly) diff --git a/apps/hrm/heartrate.js b/apps/hrm/heartrate.js index 84658e85f..6f0a176d3 100644 --- a/apps/hrm/heartrate.js +++ b/apps/hrm/heartrate.js @@ -1,74 +1,60 @@ Bangle.setLCDPower(1); Bangle.setLCDTimeout(0); -Bangle.ioWr(0x80,0) -x=0; +Bangle.setHRMPower(1); +var hrmInfo, hrmOffset = 0; +var hrmInterval; +function onHRM(h) { + // this is the first time we're called + if (counter!==undefined) { + counter = undefined; + g.clear(); + } + hrmInfo = h; + hrmOffset = 0; + if (hrmInterval) clearInterval(hrmInterval); + hrmInterval = setInterval(readHRM,40); + + var px = g.getWidth()/2; + g.setFontAlign(0,0); + g.clearRect(0,24,239,90); + g.setFont("6x8").drawString("Confidence "+hrmInfo.confidence+"%", px, 75); + var str = hrmInfo.bpm; + g.setFontVector(40).drawString(str,px,45); + px += g.stringWidth(str)/2; + g.setFont("6x8"); + g.drawString("BPM",px+15,45); +} +Bangle.on('HRM', onHRM); + +// It takes 5 secs for us to get the first HRM event +var counter = 5; +function countDown() { + E.showMessage("Please wait...\n"+counter--); + if (counter) setTimeout(countDown, 1000); +} +countDown(); + + var min=0,max=0; var wasHigh = 0, wasLow = 0; var lastHigh = getTime(); var hrmList = []; -var hrm; +var hrmInfo; function readHRM() { - var a = analogRead(D29); - var h = getTime(); - min=Math.min(min*0.97+a*0.03,a); - max=Math.max(max*0.97+a*0.03,a); - y = E.clip(170 - (a*960*4),100,230); - if (x==0) { + if (!hrmInfo) return; + + if (hrmOffset==0) { g.clearRect(0,100,239,239); g.moveTo(-100,0); } - /*g.setColor(0,1,0); - var z = 170 - (min*960*4); g.fillRect(x,z,x,z); - var z = 170 - (max*960*4); g.fillRect(x,z,x,z);*/ - g.setColor(1,1,1); - g.lineTo(x,y); - if ((max-min)>0.005) { - if (4*a > (min+3*max)) { // high - g.setColor(1,0,0); - g.fillRect(x,230,x,239); - g.setColor(1,1,1); - if (!wasHigh && wasLow) { - var currentHrm = 60/(h-lastHigh); - lastHigh = h; - if (currentHrm<250) { - while (hrmList.length>12) hrmList.shift(); - hrmList.push(currentHrm); - // median filter - var t = hrmList.slice(); // copy - t.sort(); - // average the middle 3 - var mid = t.length>>1; - if (mid+2239)x=0; } - -setInterval(readHRM,50); From 5f5561e433cd3e1620fa9aa78f4d6d8f02a6797b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 2 Dec 2020 16:02:55 +0000 Subject: [PATCH 108/110] Copy just swlclk from https://github.com/espruino/BangleApps/pull/601 - also fix the sanity test issues --- apps.json | 15 +++ apps/swlclk/ChangeLog | 1 + apps/swlclk/README.md | 13 +++ apps/swlclk/app-icon.js | 1 + apps/swlclk/app.js | 220 ++++++++++++++++++++++++++++++++++++++++ apps/swlclk/swlclk.png | Bin 0 -> 1018 bytes 6 files changed, 250 insertions(+) create mode 100644 apps/swlclk/ChangeLog create mode 100644 apps/swlclk/README.md create mode 100644 apps/swlclk/app-icon.js create mode 100644 apps/swlclk/app.js create mode 100644 apps/swlclk/swlclk.png diff --git a/apps.json b/apps.json index 4b210bade..0123d46c7 100644 --- a/apps.json +++ b/apps.json @@ -1597,6 +1597,21 @@ {"name":"hidcam.img","url":"app-icon.js","evaluate":true} ] }, + { "id": "swlclk", + "name": "SWL Clock / Short Wave Listner Clock", + "shortName": "SWL Clock", + "icon": "swlclk.png", + "version":"0.01", + "description": "Display Local, UTC time and some programs on the shorts waves along the day, with the frequencies", + "tags": "tool,clock", + "type":"clock", + "readme": "README.md", + "allow_emulator":true, + "storage": [ + {"name":"swlclk.app.js","url":"app.js"}, + {"name":"swlclk.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "rclock", "name": "Round clock with seconds, minutes and date", diff --git a/apps/swlclk/ChangeLog b/apps/swlclk/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/swlclk/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/swlclk/README.md b/apps/swlclk/README.md new file mode 100644 index 000000000..4a47c3e24 --- /dev/null +++ b/apps/swlclk/README.md @@ -0,0 +1,13 @@ +# SWL Clock + +Display Local, UTC time and some programs on the shorts waves along the day, with the frequencies. + +## Description + +This application allows to read local time and universal time at the same time as well as programs (in French, but modifiable in the source code) of short waves according to the time. +a satellite time-setting function is integrated by pressing the BTN1. +Finally this app is compatible with the Apple Notification Widget made by Jeffmer. + +## Requests + +If you have any bug or feature request, please contact [Renaudgweb](https://github.com/renaudgweb/) diff --git a/apps/swlclk/app-icon.js b/apps/swlclk/app-icon.js new file mode 100644 index 000000000..950fe5639 --- /dev/null +++ b/apps/swlclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A2tdrF1wwtF4YxsGAtrsqVwY+IyzGNiX/Mn4AXsoxDspk/AAkWAB80ACIubF6YwKF6dBRYgADh4ABAgNBF74uIF4trF/4vtCQIDNF/6P/X/4dBoIvNoIvfACKPdF/6PknWt6/X1s6F9E6FoIADGAyPhLoQAD1ovnFwoABR84vvR97vvGAJhC1ouGF8YAMF/4vpGCIudAH4A/AH4AqA")) diff --git a/apps/swlclk/app.js b/apps/swlclk/app.js new file mode 100644 index 000000000..d1abeda8a --- /dev/null +++ b/apps/swlclk/app.js @@ -0,0 +1,220 @@ +require("Font7x11Numeric7Seg").add(Graphics); +var locale = require("locale"); +const xyCenter = g.getWidth()/2; + +function drawTime(){ + let d = new Date(); + var da = d.toString().split(" "); + let date = locale.dow(d,1)+" "+locale.date(d,1); + var time = da[4].split(":"); + var hours = time[0], + minutes = time[1], + seconds = time[2]; + + function getUTCTime(d) { + return d.toUTCString().split(' ')[4].split(':').map(function(d){return Number(d);}); + } + var utc = getUTCTime(d); + var beats = Math.floor((((utc[0] + 1) % 24) + utc[1] / 60 + utc[2] / 3600) * 1000 / 24); + + function drawStation(){ + g.setFont("Vector",10); + g.setColor("#ffffff"); + switch (utc[0]) { + case 0: + g.clearRect(0,25,240,80); + g.drawString("00h00-00h30 Radio Havane Cuba\n15730\n00h00-01h00 Radio for Peace Int.\n9395\n00h30-01h00 Radio Havane Cuba\n5040",xyCenter,30); + break; + case 1: + g.clearRect(0,25,240,80); + g.drawString("01h00-02h00 Radio Roumanie Int.\n6040 7375\n01h00-01h30 R. Argentine vers le monde\n9395",xyCenter,30); + break; + case 2: + g.clearRect(0,25,240,80); + g.drawString("02h30-03h00 R. Argentine vers le monde\n5800",xyCenter,30); + break; + case 4: + g.clearRect(0,25,240,80); + g.drawString("04h00-05h00 R.F.I.\n9790 11700\n04h00-05h00 Voix de la Corée\n13650 15105\n04h30-05h00 A.W.R.\n6155",xyCenter,30); + break; + case 5: + g.clearRect(0,25,240,80); + g.drawString("05h00-05h30 Radio Roumanie Int.\n6015 15340 17520\n05h00-06h00 Radio Ndarason Int.\n5960\n05h30-06h00 Radio Japon\n11730 13840\n",xyCenter,30); + break; + case 6: + g.clearRect(0,25,240,80); + g.drawString("06h00-06h30 B.B.C.\n5875 9440 11620\n06h00-06h30 Voix de l'Amérique\n4960 6180 9885 13830\n06h30-06h45 Vatican News\n11935",xyCenter,30); + break; + case 7: + g.clearRect(0,25,240,80); + g.drawString("07h00-07h30 B.B.C.\n9440 13810?\n07h00-08h00 Radio Chine Int.\n17865\n07h00-08h00 R.F.I.\n11700 13695 15300 17850 21580?",xyCenter,30); + break; + case 8: + g.clearRect(0,25,240,80); + g.drawString("08h00-08h30 A.W.R.\n15145\n08h00-09h00 W.B.C.Q.\n9330\n08h30-09h00 Voix de l'Amérique\n9410 13830 17530",xyCenter,30); + break; + case 9: + g.clearRect(0,25,240,80); + g.drawString("09h00-10h00 R. Argentine vers le monde\n5950\n09h00-10h00 R.F.I.\n13695 15300 15320",xyCenter,30); + break; + case 10: + g.clearRect(0,25,240,80); + g.drawString("10h00-10h30 Voix du Nigéria\n11770\n10h00-11h00 Radio MiAmigo\n6085",xyCenter,30); + break; + case 11: + g.clearRect(0,25,240,80); + g.drawString("11h00-12h00 Voix de la Corée\n11710 11735 13650 15180\n11h30-12h00 Radio Slovaquie Int.\n6005",xyCenter,30); + break; + case 12: + g.clearRect(0,25,240,80); + g.drawString("12h00-12h30 Voix du Vietnam\n7285\n12h00-13h00 Radio MiAmigo\n6085",xyCenter,30); + break; + case 13: + g.clearRect(0,25,240,80); + g.drawString("13h00-14h00 Radio for Peace Int.\n15770\n13h30-14h00 Radio Slovaquie Int.\n6005",xyCenter,30); + break; + case 14: + g.clearRect(0,25,240,80); + g.drawString("14h00-16h00 Radio saoudienne Int.\n17660\n14h00-16h00 Radio Chine Int.\n11920 13670\n14h55-15h25 T.W.R. Swaziland\n9585",xyCenter,30); + break; + case 15: + g.clearRect(0,25,240,80); + g.drawString("15h00-15h30 Radio Tirana\n3985\n15h00-15h30 Radio Nationale Lao\n6130 567",xyCenter,30); + break; + case 16: + g.clearRect(0,25,240,80); + g.drawString("16h00-16h15 Vatican News\n11950\n16h30-17h15 Voix de l'Afrique\n9505",xyCenter,30); + break; + case 17: + g.clearRect(0,25,240,80); + g.drawString("17h00-18h00 R.F.I.\n13740 13770 17850\n17h30-18h25 Voix de la Turquie\n7360",xyCenter,30); + break; + case 18: + g.clearRect(0,25,240,80); + g.drawString("18h00-18h11 Radio Algérie Int.\n13820\n18h30-19h00 Radio Slovaquie Int.\n3985",xyCenter,30); + break; + case 19: + g.clearRect(0,25,240,80); + g.drawString("19h00-19h30 Radio Taiwan Int.\n6005\n19h23-20h23 Voix de la République\nIslamique d'Iran\n7235",xyCenter,30); + break; + case 20: + g.clearRect(0,25,240,80); + g.drawString("20h00-21h15 Radio Le Caire\n9810\n20h00-21h00 Voix de l'Indonésie\n3325 4750\n20h30-20h50 Radio Belarus\n3985",xyCenter,30); + break; + case 21: + g.clearRect(0,25,240,80); + g.drawString("21h00-21h30 Voix de l'Amérique\n5970 9490 9740 11900\n21h00-22h00 Radio for Peace Int.\n6070",xyCenter,30); + break; + case 22: + g.clearRect(0,25,240,80); + g.drawString("22h00-22h15 T.W.R. Bénin\n1566\n22h30-23h00 Radio Extérieure d'Espagne\n9690 11670 11940",xyCenter,30); + break; + case 23: + g.clearRect(0,25,240,80); + g.drawString("23h23-00h23 Voix de la République\nIslamique d'Iran\n7230\n23h30-00h00 R. Argentine vers le monde\n7780",xyCenter,30); + break; + default: + g.clearRect(0,25,240,80); + g.drawString("17h00-18h00 R.F.I.\n13740 15300 17850\n17h00-18h00 R.F.I.\n7205 9790",xyCenter,30); + break; + } + } + drawStation(); + + // Local time + g.setFont("6x8",1); + g.setColor("#cccccc"); + g.drawString("Loc",10,85); + + g.setFont("7x11Numeric7Seg",4); + g.setColor("#ffffff"); + g.drawString(`${hours}:${minutes}:${seconds}`, xyCenter, 115, true); + + // UTC time + g.setFont("6x8",1); + g.setColor("#cccccc"); + g.drawString("UTC",10,155); + + g.setFont("7x11Numeric7Seg",4); + g.setColor("#ff0000"); + g.drawString(utc[0]+`:${minutes}:${seconds}`, xyCenter, 185,true); + + // footer date + g.setFont("Vector",20); + g.setColor("#ffffff"); + g.clearRect(180,220,240,240); + g.drawString(date+" @"+beats,xyCenter,230); +} + +function setGpsTime(){ + Bangle.setGPSPower(1); + Bangle.on('GPS',function(fix) { + if (fix.fix) { + var curTime = fix.time.getTime()/1000; + setTime(curTime); + Bangle.setGPSPower(0); + Bangle.buzz(100, 1); + start(); + } else { + stop(); + g.setFont("Vector",10); + g.setColor("#cccccc"); + g.clearRect(0,25,240,80); + g.drawString("Mise à l'heure\npar satellites\nen cours...",xyCenter,40); + } + }); +} + +function setButtons(){ + // BTN 1 + setWatch(() => { + setGpsTime(); + Bangle.beep(500, 4000); + }, BTN1, {edge:"rising", repeat:true}); + + // BTN 2 + setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); +} + +var intervalRef = null; +function start(){ + g.reset(); + g.clear(); + Bangle.drawWidgets(); + intervalRef = setInterval(drawTime, 1000); + drawTime(); +} + +function stop(){ + clearInterval(intervalRef); +} + +// ANCS Widget +var SCREENACCESS = { + withApp:true, + request:function(){ + this.withApp=false; + stop(); + clearWatch(); + }, + release:function(){ + this.withApp=true; + start(); + setButtons(); + } +}; + +// handle switch display on by pressing BTN1 +Bangle.on('lcdPower', function(on) { + if (!SCREENACCESS.withApp) return; + if (on) { + start(); + } else { + stop(); + } +}); + +// clean app screen +Bangle.loadWidgets(); +start(); +setButtons(); diff --git a/apps/swlclk/swlclk.png b/apps/swlclk/swlclk.png new file mode 100644 index 0000000000000000000000000000000000000000..47bb9cf3c4c46db234342bf0a0bb3a6bc322deaa GIT binary patch literal 1018 zcmV55HAhn653+ZidBI_Xoz{`=j2`Hl)b&vd^NV{AWb|#6B(NTs z0A2?gi`D-Er?ELc+%8w5m+6kHf&bHYUz_qd4gwzlFFUFxfT48-hE8|L{jdeDhHnE- z_GPp)28UI7A7}+o$O&9fC3!B+&xmNKN?oYRK#BLJv|+x1eX1mY-Hv#_tMZM;`1br3 zxf@ue2Z0PY>As^Kz#$Qi0NaX}3&1ZTBsaA&oD|82^}G_H87T3Ys&zTd8zLlt9$;Ou zDkH+l!V+Jd?~p&jdS2)Tob;u%CI18mMEFRRU5=^=AepuJ?x!|c4DyUf4LIpZ>nlJ4 zI0QUhy!-(8L15@?TrO1;w`K-Pyn9cdktKRXISjn%sJgDoNn7~(LR@D3#xojdJCS-v z&_Rk@iE7#M*Fuoy4&=6oow(fJS+O58ZY9DHA1>OC%Alzx=F%b*@uih4-uFCDwmr4# z{o_aa%jd5h{}g~+I!orv3<@2lHf{z&V%dTp@oqH48(Dc3mH66?KFUPf17Xc^9&x;T zU~Ci}yI6Hu@#=j4c*XHFpvXh+*IKRxoxo;T{2hFD>OmM`%KX~Dqe5@QE3r4KHrPwc z1uKTg+Edcoz}P5?tjsQJEUU+qx_N`mCwt>`ZEpr({N_AgjAodb3(-JS>%is>Ha~v+ z5>1UOkKetcg;!tLNbkT6{$BLo6OraX>vUxfsM>sfFwUM`t;RMNul~c)Q)%OHx^}EG z2O?evwDPd?(dK}QB`@4(d^5G*3t2J7Z@OpdrQhbj@;^C7ngcD< z^TzAjn&JBoUu0wB!$Rj4^Yjkf;9l1JUMG+3taT2UnVEy0f$NN3on;|cU?Epv Date: Thu, 3 Dec 2020 15:12:46 +0000 Subject: [PATCH 109/110] Link troubleshooting --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 5aabed4df..a5ae7bff0 100644 --- a/index.html +++ b/index.html @@ -108,6 +108,7 @@
+

Can't connect? Check out the Bangle.js Troubleshooting page

Check out the Source on GitHub, or find out how to add your own app

From 49f0b8841d390cd0c8949bb83f1ea58c98d82ee1 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 3 Dec 2020 15:19:24 +0000 Subject: [PATCH 110/110] Manually merge gmeter from https://github.com/espruino/BangleApps/pull/602 --- apps.json | 56 ++++++++++++++++++++++++---------------- apps/gmeter/app-icon.js | 1 + apps/gmeter/app.js | 6 +++++ apps/gmeter/app.png | Bin 0 -> 2474 bytes 4 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 apps/gmeter/app-icon.js create mode 100644 apps/gmeter/app.js create mode 100644 apps/gmeter/app.png diff --git a/apps.json b/apps.json index 0123d46c7..3d93825e2 100644 --- a/apps.json +++ b/apps.json @@ -2424,26 +2424,38 @@ ] }, { "id": "supmariodark", - "name": "Super mario clock night mode", - "shortName":"supmariodark", - "icon": "supmariodark.png", - "version":"0.01", - "description": "Super mario clock in night mode", - "tags": "clock", - "type" : "clock", - "storage": [ - {"name":"supmariodark.app.js","url":"supmariodark.js"}, - {"name":"supmariodark.img","url":"supmariodark-icon.js","evaluate":true}, - {"name":"supmario30x24.bin","url":"supmario30x24.bin.js"}, - {"name":"supmario30x24.wdt","url":"supmario30x24.wdt.js"}, - {"name":"banner-up.img","url":"banner-up.js","evaluate":true}, - {"name":"banner-down.img","url":"banner-down.js","evaluate":true}, - {"name":"brick2.img","url":"brick2.js","evaluate":true}, - {"name":"enemy.img","url":"enemy.js","evaluate":true}, - {"name":"flower.img","url":"flower.js","evaluate":true}, - {"name":"flower_b.img","url":"flower_b.js","evaluate":true}, - {"name":"mario_wh.img","url":"mario_wh.js","evaluate":true}, - {"name":"pipe.img","url":"pipe.js","evaluate":true} - ] - } + "name": "Super mario clock night mode", + "shortName":"supmariodark", + "icon": "supmariodark.png", + "version":"0.01", + "description": "Super mario clock in night mode", + "tags": "clock", + "type" : "clock", + "storage": [ + {"name":"supmariodark.app.js","url":"supmariodark.js"}, + {"name":"supmariodark.img","url":"supmariodark-icon.js","evaluate":true}, + {"name":"supmario30x24.bin","url":"supmario30x24.bin.js"}, + {"name":"supmario30x24.wdt","url":"supmario30x24.wdt.js"}, + {"name":"banner-up.img","url":"banner-up.js","evaluate":true}, + {"name":"banner-down.img","url":"banner-down.js","evaluate":true}, + {"name":"brick2.img","url":"brick2.js","evaluate":true}, + {"name":"enemy.img","url":"enemy.js","evaluate":true}, + {"name":"flower.img","url":"flower.js","evaluate":true}, + {"name":"flower_b.img","url":"flower_b.js","evaluate":true}, + {"name":"mario_wh.img","url":"mario_wh.js","evaluate":true}, + {"name":"pipe.img","url":"pipe.js","evaluate":true} + ] +}, +{ "id": "gmeter", + "name": "G-Meter", + "shortName":"G-Meter", + "icon": "app.png", + "version":"0.01", + "description": "Simple G-Meter", + "tags": "", + "storage": [ + {"name":"gmeter.app.js","url":"app.js"}, + {"name":"gmeter.img","url":"app-icon.js","evaluate":true} + ] +} ] diff --git a/apps/gmeter/app-icon.js b/apps/gmeter/app-icon.js new file mode 100644 index 000000000..664ff3813 --- /dev/null +++ b/apps/gmeter/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATlgAGFlgylEYdWq+BwOs1gDBq8yGL4eCmQqB64AIGgIyDFzQtBFhIAFGIZcYqxbKMZFWMSoVCLiBiGGCguM2YACGBgub1uJsoAExOtGDK7CFo4sFAAhjIYYQvOmTqGLYetE4mzM4L0JmQvNRpAuCQpAnDqx2GSJxeBFxDnKFwSmIMBheHXYQuPUwxgNBYIWFRh4uECQusF5iOFLwQuRUQIwFSBQ6Bq69GLw+swNdwKMGIgOJCQlXMBK+HXpAbCAAS7F2Z0GYBQJBwQZLVYeBDwREFIo4vMJIi+IDQIqCAgNdF5jwKF4xfBVIovHL5ovMDQztHR4pEER6ovGdwzvFq4TGd6YbFxNl1phHL4JdGaoSlFIYQvHGAMyJQxgHABReBIgsyFxLwHACZeBRwruKYBeJMJy9CLwq+KSBLBCF5ouCXoqOMMBYCERhQuGLxpgDYI5iBQApdM1heNMAdWEg7CJBQI6HqxeOSJQATrouQGDi8PF4wwXLoQvSGAdWeg4AK1i7CFyYxEmRiQwMyFq5iFGIJjK1gtDFzIxFGQNXwI0BFQOBq4sDFrgxHABItfGRgskAH4A/AFwA=")) diff --git a/apps/gmeter/app.js b/apps/gmeter/app.js new file mode 100644 index 000000000..28e82b458 --- /dev/null +++ b/apps/gmeter/app.js @@ -0,0 +1,6 @@ +g.clear(); +g.setFont("6x8",5);g.setFontAlign(-1,0); +Bangle.on('accel',function(accelData) { + g.drawString(" "+accelData.mag.toFixed(1)+" ",75,105,true); + g.drawString('G\'s',75,180,true); +}); diff --git a/apps/gmeter/app.png b/apps/gmeter/app.png new file mode 100644 index 0000000000000000000000000000000000000000..da298ba430240646eb91841f1269e2137ae3962b GIT binary patch literal 2474 zcmV;b303xqP)K~!jg?U{Q})YlcqKljHj3+`$ZL@)}PSO||8O^7jyC@+nKn#mYx zQq!3v?Mx?08`_$ek2Z1A7^60iHch8Z+sR`lI*G=1l8A{S5Cn}iG$;gl2qF(f5m0c2 zWp{tKfBbe)_xIZcjQ&->GtBPZd(XMwbMLw5+-&x*GF-F9YV}=7!qr@?j~&qaf#wK%WFkCE|Uz-TGm1 z@q7JO%HfI(NKXE_dF;gQr-YQx0g>MJ(2x)k;^UYSGnoky;|UE71)#65k5i{RINsdK zk=i=?`yH36YX>%Tw}-u5UjB~rnj4V0Wa%tLRo<151P~l-CM`9Etc>|gPfEmO3JNIi za=AHN^&JI;B^2-7htoO8xl%zqwrj`M@@r;5=DiQ(2_ZHC!9hVm+?R6?4=uZ&u&{9> zQ8S3nu5Pw`yq(YTccH2(fJ4HHJv+AjWw<(qYkGiTW!yyO?8&Sl-&RYZ&*|9v=LhOn@4 zEXqu$t?dNITUtSoGA%YSw6VUrU?|xk4e+?lO8_~Gvv~G5zrbWN1(fL-fRlD;?uAnq zpw9(C0xSV$Gnq`xpErlju5RiZ8bOe9b6nEt#`@}S0?ifBg))~coh4MI6bN3BI+r!i z{Td;RMb0~+>;zPGLYv)K-((w14~GSlAlQ#FQc8aR>g((+`x?NZD(c+A&$j>9A4k7y zl9rZc3Nl%DAh>aAOf>7(t}0dH*Kg!N#!R~F?WU#*moE>+ zw*kOrmk$Gx!NF!8T6Vv#-z~M3@9fuHacB z`GXH&Hk$z^nykIcjm8)nAO(*Aq@|`9CaFCwn%fBAC-IOJHay}0%`I&_zvd;*o;`=n zX65Ag!0I+3`n~-Hws7r$jX?n6FBdLA}!yL5j}G9&#qoeSNBc6CP<4k<7ll+Ik_C_$e~V$*tnAc2 zXGi(>c_}4d>?-8jLzOrN21vLij&1+?lyg13j2S(eO|QIg*)?RsD4OfsX?k;CYNNC1$dYSkHhKbwCT1{>ZOc`w9okD+b&4eSHwXkUVH^xTgi$ z&O`42j1InB=alHlR2-^8s!F`?dJ)xgFl8N`F`Vq*4N!IxmQI6tH|qO^ z5Ug9fnlE-2@omLnKwJ663)B5x#Vb8)HDQ!K0s%C8UTO$gJEQ@?HvrW&b+}wET`rhx z)6PJ6s3Dg@BeEA|ki96w{~!+>ZaCnn5Z$g1e7IaLYU=7e{Kdhc4G1z9;dV-g!yyh= zRda`r-_DNG{;n2wH*3)+Sb@0)dMgfBdCM@WQ!y9$_Uq1or(#wLP*7Oncj5!>u%TSL z=U*v~bV0G_`j8%N>^=oWd%a&via*<;JDA3|QN;TIUzP5ov#Z;1@|te#z1ysd3&X>a zZtWGPO6_%Kbg$|-(>WNy5PV>y$It+`-TEQWJ}}^9%g5Ud3H&G)9={dtj?!G9{InJh zhk`00zX|^No#y}HA@H+AEt&aZ^GDmgg|9ZV+rD|&26$?f8vs7vxtpU6$8=*tO%OLu z%gWo1!iTjN-60UZZr9$>s)T48XSFc zC3XqOIo{GrXID3O-<5pLj8IjTH{X7T!s1e`LC7Zyc5KTJBs1hQ{8)YU!D+FHqY$Lj zH#E}J+`{Zx$wOA>MvA`veqP!5<{)_?SzoZ@lTAa(4XcjOSYN$oT5Mt{f|TZ#R?7At zATd6U@GGoJ`=YMCfz>arqpG?F(8%x3-?nBrvLo_^teo5@K)wN36h$FtaTd!Te1P%c zBY4?gf{rttZ2o9F`Ck@z4{Sd|<`sPY$=`>oW5mv!v1I8Tid%UX!EFF$vzY~{bI3}c z&y49wL%NpJ>Eux5cN7%urKEKKrT^fl5K=rA=)hhT13;^rnyllW09FBm&peC8LPC5j zG0~HWjEKN$)$Yc2`vp#QbkN+~%8}Z79FEIEdYh1P{aCB=*R5N(8WdKpfdLl{c{Idi z?OiTW9udgY5$IEq>_y>yv)jJeUy>RQu39|I&d!Z+3N;;tJEf|`3n6a=ys51RXhX literal 0 HcmV?d00001