diff --git a/apps.json b/apps.json index 497cc828e..3fc312097 100644 --- a/apps.json +++ b/apps.json @@ -98,7 +98,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.04", + "version": "0.05", "description": "Display notifications/music/etc from Gadgetbridge on Android. This replaces the old Gadgetbridge widget.", "icon": "app.png", "tags": "tool,system,messages,notifications", @@ -3294,7 +3294,7 @@ { "id": "dtlaunch", "name": "Desktop Launcher", - "version": "0.05", + "version": "0.07", "description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.", "screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}], "icon": "icon.png", @@ -3305,8 +3305,11 @@ "storage": [ {"name":"dtlaunch.app.js","url":"app-b1.js", "supports": ["BANGLEJS"]}, {"name":"dtlaunch.app.js","url":"app-b2.js", "supports": ["BANGLEJS2"]}, + {"name":"dtlaunch.settings.js","url":"settings-b1.js", "supports": ["BANGLEJS"]}, + {"name":"dtlaunch.settings.js","url":"settings-b2.js", "supports": ["BANGLEJS2"]}, {"name":"dtlaunch.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"dtlaunch.json"}] }, { "id": "HRV", @@ -4734,7 +4737,7 @@ { "id": "pooqroman", "name": "pooq Roman watch face", "shortName":"pooq Roman", - "version":"0.02", + "version":"0.03", "description": "A classic watch face with a certain dynamicity. Most amusing in 24h mode. Slide up to show more hands, down for less(!). By design does not support standard widgets, sorry!", "icon": "app.png", "type": "clock", @@ -4950,5 +4953,21 @@ "data": [ {"name":"pooqround.json"} ] + }, + { + "id": "coretemp", + "name": "Core Temp Display", + "version": "0.01", + "description": "Display CoreTemp device sensor data", + "icon": "coretemp.png", + "type": "app", + "tags": "health", + "readme": "README.md", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"coretemp.boot.js","url":"boot.js"}, + {"name":"coretemp.app.js","url":"coretemp.js"}, + {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true} + ] } ] diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index 35fa0e386..c2c4ea6be 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -3,3 +3,4 @@ Fix music control 0.03: Handling of message actions (ok/clear) 0.04: Android icon now goes to settings page with 'find phone' +0.05: Fix handling of message actions diff --git a/apps/android/boot.js b/apps/android/boot.js index 97e3a5641..59ffe006d 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -65,7 +65,7 @@ // Message response Bangle.messageResponse = (msg,response) => { if (msg.id=="call") return gbSend({ t: "call", n:response?"ACCEPT":"REJECT" }); - if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS" }); + if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id }); // error/warn here? }; })(); diff --git a/apps/coretemp/ChangeLog b/apps/coretemp/ChangeLog new file mode 100644 index 000000000..c7b309a74 --- /dev/null +++ b/apps/coretemp/ChangeLog @@ -0,0 +1 @@ +0.1: New app diff --git a/apps/coretemp/README.md b/apps/coretemp/README.md new file mode 100644 index 000000000..fac25df21 --- /dev/null +++ b/apps/coretemp/README.md @@ -0,0 +1,20 @@ +# CoreTemp display + +Basic bare-bones example of connecting to a bluetooth [CoreTemp](https://corebodytemp.com/) device and displaying the current body core temperature readings. + +## Usage + +On startup connects to a CoreTemp device (1809/2A1C) and emits a "Core, temp" value for each reading. +The app simply displays these readings on screen. + +## TODO + +* Integrate with other tracking/sports apps to log data. +* Add device selection +* Provide enable/disable option +* Check status, add Retry/reconnect +* Also provide skin temp reading + +## Creator + +Ivor Hewitt diff --git a/apps/coretemp/boot.js b/apps/coretemp/boot.js new file mode 100644 index 000000000..59e227dad --- /dev/null +++ b/apps/coretemp/boot.js @@ -0,0 +1,23 @@ +(function() { + var gatt; + + //Would it be better to scan by uuid rather than name? + NRF.requestDevice({ timeout: 20000, filters: [{ name: 'CORE [a]' }] }).then(function(device) { + return device.gatt.connect(); + }).then(function(g) { + gatt = g; + return gatt.getPrimaryService("1809"); + }).then(function(service) { + return service.getCharacteristic("2A1C"); + }).then(function(characteristic) { + characteristic.on('characteristicvaluechanged', function(event) { + var dv = event.target.value; + var core = (dv.buffer[2]*256+dv.buffer[1])/100; + Bangle.emit('Core',{ + temp:core + }); + }); + return characteristic.startNotifications(); + }).then(function() { + }); +})(); diff --git a/apps/coretemp/coretemp-icon.js b/apps/coretemp/coretemp-icon.js new file mode 100644 index 000000000..5f36b9090 --- /dev/null +++ b/apps/coretemp/coretemp-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///k0DxUFgsDCY8KwAfJlQLHhWglWq1WgBIcCA4QCB1WoComq0+iBYWqCwl//4OBAAQxChWlv/2BYIlCBYUqv9VvQLBwA9BBYWlqtV/QLBGoRIBgQLBr9aBYQ2BBYMKroLBtQLCgALClIKC1AXG1NVuoFBF4sC09V+woCBAJHCgWXq9oPQZrDgWdq9gBZG9rqgCTwSbCgVVqysDBYkK6tWYoa/DkEJ6vaaIgWBaAILCbQhUCBYXoc4wNBBZWqBfBtB1ALKKZILCR4J3FToQLBU4KPEWoQLNZYILIa4NVcYReEcYOnqtaDAbvDgALBcg4EBlNVqtqDoOgd4YoBBYNWytWCwQdCgQLBAAVaBYkA0oLDuwLFkv1BgZGDAAMJuoKCroWEGAOnDAVftShGr////1tDdG14LB+wiEAAdqHAjTHBYgA==")) diff --git a/apps/coretemp/coretemp.js b/apps/coretemp/coretemp.js new file mode 100644 index 000000000..226508c83 --- /dev/null +++ b/apps/coretemp/coretemp.js @@ -0,0 +1,19 @@ +Bangle.setLCDPower(1); +Bangle.setLCDTimeout(0); +var btm = g.getHeight()-1; + +function onCore(c) { + var px = g.getWidth()/2; + g.setFontAlign(0,0); + g.clearRect(0,24,g.getWidth(),80); + var str = c.temp + "C"; + g.setFontVector(40).drawString(str,px,45); +} +Bangle.on('Core', onCore); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +g.reset().setFont("6x8",2).setFontAlign(0,0); +g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 16); diff --git a/apps/coretemp/coretemp.png b/apps/coretemp/coretemp.png new file mode 100644 index 000000000..a573828f8 Binary files /dev/null and b/apps/coretemp/coretemp.png differ diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index c3102b4b9..c414c1ddc 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -3,3 +3,5 @@ 0.03: cycle thru pages 0.04: reset to clock after 2 mins of inactivity 0.05: add Bangle 2 version +0.06: Adds settings page (hide clocks or launchers) +0.06: Adds setting for directly launching app on touch for Bangle 2 diff --git a/apps/dtlaunch/app-b1.js b/apps/dtlaunch/app-b1.js index 9bbf3e219..ec0569127 100644 --- a/apps/dtlaunch/app-b1.js +++ b/apps/dtlaunch/app-b1.js @@ -2,6 +2,11 @@ * */ +var settings = Object.assign({ + showClocks: true, + showLaunchers: true, +}, require('Storage').readJSON("dtlaunch.json", true) || {}); + function wdog(handle,timeout){ if(handle !== undefined){ wdog.handle = handle; @@ -17,7 +22,13 @@ function wdog(handle,timeout){ wdog(load,120000) var s = require("Storage"); -var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)); +var apps = s.list(/\.info$/).map(app=>{ + var a=s.readJSON(app,1); + return a && { + name:a.name, type:a.type, icon:a.icon, sortorder:a.sortorder, src:a.src + };}).filter( + app=>app && (app.type=="app" || (app.type=="clock" && settings.showClocks) || (app.type=="launch" && settings.showLaunchers) || !app.type)); + apps.sort((a,b)=>{ var n=(0|a.sortorder)-(0|b.sortorder); if (n) return n; // do sortorder first diff --git a/apps/dtlaunch/app-b2.js b/apps/dtlaunch/app-b2.js index 674fe3677..800ec456c 100644 --- a/apps/dtlaunch/app-b2.js +++ b/apps/dtlaunch/app-b2.js @@ -2,8 +2,20 @@ * */ +var settings = Object.assign({ + showClocks: true, + showLaunchers: true, + direct: false, +}, require('Storage').readJSON("dtlaunch.json", true) || {}); + var s = require("Storage"); -var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)); +var apps = s.list(/\.info$/).map(app=>{ + var a=s.readJSON(app,1); + return a && { + name:a.name, type:a.type, icon:a.icon, sortorder:a.sortorder, src:a.src + };}).filter( + app=>app && (app.type=="app" || (app.type=="clock" && settings.showClocks) || (app.type=="launch" && settings.showLaunchers) || !app.type)); + apps.sort((a,b)=>{ var n=(0|a.sortorder)-(0|b.sortorder); if (n) return n; // do sortorder first @@ -28,7 +40,7 @@ const YOFF = 30; function draw_icon(p,n,selected) { var x = (n%2)*72+XOFF; var y = n>1?72+YOFF:YOFF; - (selected?g.setColor(g.theme.fgH):g.setColor(g.theme.bg)).fillRect(x+10,y+2,x+60,y+52); + (selected?g.setColor(g.theme.fgH):g.setColor(g.theme.bg)).fillRect(x+11,y+3,x+60,y+52); g.clearRect(x+12,y+4,x+59,y+51); g.setColor(g.theme.fg); try{g.drawImage(apps[p*4+n].icon,x+12,y+4);} catch(e){} @@ -52,7 +64,7 @@ function drawPage(p){ } for (var i=0;i<4;i++) { if (!apps[p*4+i]) return i; - draw_icon(p,i,selected==i); + draw_icon(p,i,selected==i && !settings.direct); } g.flip(); } @@ -81,9 +93,9 @@ Bangle.on("touch",(_,p)=>{ for (i=0;i<4;i++){ if((page*4+i)=0) { - if (selected!=i){ + draw_icon(page,i,true && !settings.direct); + if (selected>=0 || settings.direct) { + if (selected!=i && !settings.direct){ draw_icon(page,selected,false); } else { load(apps[page*4+i].src); diff --git a/apps/dtlaunch/settings-b1.js b/apps/dtlaunch/settings-b1.js new file mode 100644 index 000000000..f3101da16 --- /dev/null +++ b/apps/dtlaunch/settings-b1.js @@ -0,0 +1,33 @@ +(function(back) { + var FILE = "dtlaunch.json"; + + var settings = Object.assign({ + showClocks: true, + showLaunchers: true + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + "" : { "title" : "Desktop launcher" }, + "< Back" : () => back(), + 'Show clocks': { + value: settings.showClocks, + format: v => v?"On":"Off", + onchange: v => { + settings.showClocks = v; + writeSettings(); + } + }, + 'Show launchers': { + value: settings.showLaunchers, + format: v => v?"On":"Off", + onchange: v => { + settings.showLaunchers = v; + writeSettings(); + } + } + }); +}) diff --git a/apps/dtlaunch/settings-b2.js b/apps/dtlaunch/settings-b2.js new file mode 100644 index 000000000..7f667d213 --- /dev/null +++ b/apps/dtlaunch/settings-b2.js @@ -0,0 +1,42 @@ +(function(back) { + var FILE = "dtlaunch.json"; + + var settings = Object.assign({ + showClocks: true, + showLaunchers: true, + direct: false + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + "" : { "title" : "Desktop launcher" }, + "< Back" : () => back(), + 'Show clocks': { + value: settings.showClocks, + format: v => v?"On":"Off", + onchange: v => { + settings.showClocks = v; + writeSettings(); + } + }, + 'Show launchers': { + value: settings.showLaunchers, + format: v => v?"On":"Off", + onchange: v => { + settings.showLaunchers = v; + writeSettings(); + } + }, + 'Direct launch': { + value: settings.direct, + format: v => v?"On":"Off", + onchange: v => { + settings.direct = v; + writeSettings(); + } + } + }); +}) diff --git a/apps/pooqroman/ChangeLog b/apps/pooqroman/ChangeLog index 9debf0efe..c4f3171d3 100644 --- a/apps/pooqroman/ChangeLog +++ b/apps/pooqroman/ChangeLog @@ -1,2 +1,3 @@ -0.01: New App! -0.02: Make internal menu time out + small fixes +0.01: Initial check-in. +0.02: Make internal menu time out + small fixes. +0.03: Autolight feature. diff --git a/apps/pooqroman/README.md b/apps/pooqroman/README.md index b41a4a316..87acea9ca 100644 --- a/apps/pooqroman/README.md +++ b/apps/pooqroman/README.md @@ -13,9 +13,12 @@ you can alter the number of hands on the display. When the watch is unlocked, sl There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky, in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails. -Although we genrally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face. +Although we generally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face. You can also override the system 12/24 hour setting just for this face here, since it's, well, a rather different experience than with numeric displays. +By default, there is a backlight that comes on when you twist your wrist. This, of course, somewhat increases power draw and could be +annoying in an intentionally dark environment, so there is an option to disable it. + One other thing: there's some integration with system timers and alarms; they will show as small pips at the appropriate places in the day around the display. When they come within an hour, the pips turn to crosses relating to the minute hand, and the minute hand turns itself on. When timers are mere seconds away, the display changes again and the second hand activates itself, so you diff --git a/apps/pooqroman/app.js b/apps/pooqroman/app.js index d59d4ef6c..bed8ef3d2 100644 --- a/apps/pooqroman/app.js +++ b/apps/pooqroman/app.js @@ -138,6 +138,10 @@ class RomanOptions extends Options { onchange: x => this.calendric = x, format: x => ['none', 'day', 'date'][x] }, + 'Auto-Illum.': { + init: _ => this.autolight, + onchange: x => this.autolight = x + }, Defaults: _ => {this.reset(); this.interact();} }; } @@ -164,6 +168,7 @@ RomanOptions.defaults = { alarmFg: '#f00', timerFg: '#0f0', activeFg: g.theme.fg2, + autolight: true, }; ////////////////////////////////////////////////////////////////////////////// @@ -663,10 +668,10 @@ class Clock { this.options.on('done', () => this.start()); this.listeners = { - lcdPower: on => on ? this.active() : this.inactive(), - charging: () => {face.doIcons('charging'); this.active();}, - lock: () => {face.doIcons('locked'); this.active();}, + charging: _ => {face.doIcons('charging'); this.active();}, + lock: _ => {face.doIcons('locked'); this.active();}, faceUp: up => {this.conservative = !up; this.active();}, + twist: _ => this.options.autolight && Bangle.setLCDPower(true), drag: e => { if (this.t0) { if (e.b) { @@ -728,7 +733,6 @@ class Clock { } const delay = rate - now % rate + 1; this.refresh = true; - if (rate !== prev) { this.inactive(); this.redraw(rate);