From a87e105432f443dd2969a2c1557c514110cb3b93 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Mon, 24 Jan 2022 19:10:55 +0100 Subject: [PATCH 01/16] Update ChangeLog --- apps/impwclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/impwclock/ChangeLog b/apps/impwclock/ChangeLog index 7bc119426..6555fcc8f 100644 --- a/apps/impwclock/ChangeLog +++ b/apps/impwclock/ChangeLog @@ -2,3 +2,4 @@ 0.02: Stopped watchface from flashing every interval 0.03: Move to Bangle.setUI to launcher support 0.04: Tweaks for compatibility with BangleJS2 +0.05: Time-word now readable on Bangle.js 2 From 5360bfb5a9e55c2366ad2a00837e0e800cb7d46f Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Mon, 24 Jan 2022 19:11:19 +0100 Subject: [PATCH 02/16] Update metadata.json --- apps/impwclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/impwclock/metadata.json b/apps/impwclock/metadata.json index 6bf5183f4..120fbe795 100644 --- a/apps/impwclock/metadata.json +++ b/apps/impwclock/metadata.json @@ -1,7 +1,7 @@ { "id": "impwclock", "name": "Imprecise Word Clock", - "version": "0.04", + "version": "0.05", "description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.", "icon": "clock-impword.png", "type": "clock", From d17f60554dc0dc5db761e96c395503b4965ffb06 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Mon, 24 Jan 2022 19:12:15 +0100 Subject: [PATCH 03/16] Update clock-impword.js Time-word now readable on Bangle.js 2 --- apps/impwclock/clock-impword.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/impwclock/clock-impword.js b/apps/impwclock/clock-impword.js index 8bb5da6ba..c42dbda44 100644 --- a/apps/impwclock/clock-impword.js +++ b/apps/impwclock/clock-impword.js @@ -46,7 +46,7 @@ const dy = big ? 22 : 16; const fontSize = big ? 3 : 2; // "6x8" const passivColor = 0x3186 /*grey*/ ; const activeColorNight = 0xF800 /*red*/ ; -const activeColorDay = 0xFFFF /* white */; +const activeColorDay = g.theme.fg; var hidxPrev; var showDigitalTime = false; From 98583540277cb7615d8ae9722885cf7315bcbc71 Mon Sep 17 00:00:00 2001 From: storm64 Date: Tue, 25 Jan 2022 00:17:43 +0100 Subject: [PATCH 04/16] sleepphasealarm: Update app.js Make app compatible with Bangle.js 2: - check hardware - _drawString(s, x, y)_: removed _x_, always centered - _drawString(s, y)_: _g.reset()_ before _g.clearRect(...)_ - adjust heights for Bangle.js 2 for each _drawString(s, y)_ call - _drawApp()_: on Bangle.js 2's always on display save energy by drawing time only at every next minute - _drawTime()_: hide seconds on Bangle.js 2 (only refreshed every minute) - _drawApp()_: add _"Alarm at "_ to distinct from actual time (no difference in seconds) - execute _load()_ on Bangle.js 2's BTN --- apps/sleepphasealarm/app.js | 41 ++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index 0de0b9afc..90a6599a4 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -1,3 +1,4 @@ +const BANGLEJS2 = process.env.HWVERSION == 2; //# check for bangle 2 const alarms = require("Storage").readJSON("alarm.json",1)||[]; const active = alarms.filter(a=>a.on); @@ -52,21 +53,21 @@ active.forEach(alarm => { } }); -function drawString(s, x, y) { - g.clearRect(0,y-15,239,y+15); - g.reset(); - g.setFont("Vector",20); - g.setFontAlign(0,0); // align right bottom - g.drawString(s, x, y); +function drawString(s, y) { //# replaced x: always centered + g.reset(); //# moved up to prevent blue background + g.clearRect(0, y - 12, 239, y + 8); //# minimized upper+lower clearing + g.setFont("Vector", 20); + g.setFontAlign(0, 0); // align centered + g.drawString(s, g.getWidth() / 2, y); //# set x to center } function drawApp() { - g.clearRect(0,24,239,215); + g.clearRect(0,24,239,215); //# no problem var alarmHour = nextAlarm.getHours(); var alarmMinute = nextAlarm.getMinutes(); if (alarmHour < 10) alarmHour = "0" + alarmHour; if (alarmMinute < 10) alarmMinute = "0" + alarmMinute; - const s = alarmHour + ":" + alarmMinute + "\n\n"; + const s = "Alarm at " + alarmHour + ":" + alarmMinute + "\n\n"; //# make distinct to time E.showMessage(s, "Sleep Phase Alarm"); function drawTime() { @@ -78,12 +79,20 @@ function drawApp() { if (nowHour < 10) nowHour = "0" + nowHour; if (nowMinute < 10) nowMinute = "0" + nowMinute; if (nowSecond < 10) nowSecond = "0" + nowSecond; - const time = nowHour + ":" + nowMinute + ":" + nowSecond; - drawString(time, 120, 140); + const time = nowHour + ":" + nowMinute + (BANGLEJS2 ? "" : ":" + nowSecond); //# hide seconds on bangle 2 + drawString(time, BANGLEJS2 ? 85 : 140); //# remove x, adjust height } } - setInterval(drawTime, 500); // 2Hz + if (BANGLEJS2) { + drawTime(); + setTimeout(_ => { + drawTime(); + setInterval(drawTime, 60000); + }, 60000 - Date.now() % 60000); //# every new minute on bangle 2 + } else { + setInterval(drawTime, 500); // 2Hz + } } var buzzCount = 19; @@ -104,8 +113,8 @@ function buzz() { var minAlarm = new Date(); var measure = true; if (nextAlarm !== undefined) { + Bangle.loadWidgets(); //# correct widget load draw order Bangle.drawWidgets(); - Bangle.loadWidgets(); // minimum alert 30 minutes early minAlarm.setTime(nextAlarm.getTime() - (30*60*1000)); @@ -116,7 +125,7 @@ if (nextAlarm !== undefined) { if (swest !== undefined) { if (Bangle.isLCDOn()) { - drawString(swest ? "Sleep" : "Awake", 120, 180); + drawString(swest ? "Sleep" : "Awake", BANGLEJS2 ? 150 : 180); //# remove x, adjust height } } @@ -133,6 +142,6 @@ if (nextAlarm !== undefined) { E.showMessage('No Alarm'); setTimeout(load, 1000); } -// BTN2 to menu, BTN3 to main -setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); -setWatch(() => load(), BTN3, { repeat: false, edge: "falling" }); +// BTN2 to menu, BTN3 to main # on bangle 2 only BTN to main +if (!BANGLEJS2) setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" }); +setWatch(() => load(), BANGLEJS2 ? BTN : BTN3, { repeat: false, edge: "falling" }); From 5846b7d5064cea3d3c343445d72e6dfa33d0989a Mon Sep 17 00:00:00 2001 From: storm64 Date: Tue, 25 Jan 2022 00:20:59 +0100 Subject: [PATCH 05/16] sleepphasealarm: Update metadata.json Add Bangle.js 2 support, increment version. --- apps/sleepphasealarm/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sleepphasealarm/metadata.json b/apps/sleepphasealarm/metadata.json index f74c97b54..ed0f21028 100644 --- a/apps/sleepphasealarm/metadata.json +++ b/apps/sleepphasealarm/metadata.json @@ -2,11 +2,11 @@ "id": "sleepphasealarm", "name": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm", - "version": "0.02", + "version": "0.03", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "icon": "app.png", "tags": "alarm", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ {"name":"sleepphasealarm.app.js","url":"app.js"}, {"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true} From 40820960f69103946245157bf9a400bec2260221 Mon Sep 17 00:00:00 2001 From: storm64 Date: Tue, 25 Jan 2022 00:23:36 +0100 Subject: [PATCH 06/16] sleepphasealarm: Update ChangeLog --- apps/sleepphasealarm/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index 47448167e..2168f2339 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Respect Quiet Mode +0.03: Add compatibility for Bangle.js 2, added "Alarm at " for the alarm time From 5718e31d3cbe0ad1fc6079ba1aa7d9888f4d4fb1 Mon Sep 17 00:00:00 2001 From: storm64 Date: Tue, 25 Jan 2022 00:35:40 +0100 Subject: [PATCH 07/16] sleepphasealarm: Update ChangeLog --- apps/sleepphasealarm/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index 2168f2339..dbc3a0b82 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -1,3 +1,3 @@ 0.01: New App! 0.02: Respect Quiet Mode -0.03: Add compatibility for Bangle.js 2, added "Alarm at " for the alarm time +0.03: Add compatibility for Bangle.js 2 and new firmware, added "Alarm at " for the alarm time From 67b10536c1638c4ebd0415f5b8271133e02c438c Mon Sep 17 00:00:00 2001 From: storm64 Date: Tue, 25 Jan 2022 00:39:37 +0100 Subject: [PATCH 08/16] sleepphasealarm: Update app.js Make app compatible with _E.showMessage(...)_ on new firmware: - adjust actual time height to be drawn above the alarm time from _E.showMessage(...)_ --- apps/sleepphasealarm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index 90a6599a4..39f9b59db 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -80,7 +80,7 @@ function drawApp() { if (nowMinute < 10) nowMinute = "0" + nowMinute; if (nowSecond < 10) nowSecond = "0" + nowSecond; const time = nowHour + ":" + nowMinute + (BANGLEJS2 ? "" : ":" + nowSecond); //# hide seconds on bangle 2 - drawString(time, BANGLEJS2 ? 85 : 140); //# remove x, adjust height + drawString(time, BANGLEJS2 ? 85 : 105); //# remove x, adjust height for bangle 2 an newer firmware } } From d8db49967118d5531559288bc899e3956c25d803 Mon Sep 17 00:00:00 2001 From: jeffyactive Date: Tue, 25 Jan 2022 09:47:25 -0500 Subject: [PATCH 09/16] Move persistent settings to flash memory --- apps/sensible/metadata.json | 3 ++- apps/sensible/sensible.js | 35 +++++++++++++++++------------------ apps/sensible/settings.json | 6 ++++++ 3 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 apps/sensible/settings.json diff --git a/apps/sensible/metadata.json b/apps/sensible/metadata.json index df0421441..5e90fbcaf 100644 --- a/apps/sensible/metadata.json +++ b/apps/sensible/metadata.json @@ -20,6 +20,7 @@ "readme": "README.md", "storage": [ { "name": "sensible.app.js", "url": "sensible.js" }, - { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } + { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true }, + { "name": "sensible.json", "url": "settings.json", "noOverwrite": true } ] } diff --git a/apps/sensible/sensible.js b/apps/sensible/sensible.js index 73c348556..6f367be31 100644 --- a/apps/sensible/sensible.js +++ b/apps/sensible/sensible.js @@ -1,5 +1,5 @@ /** - * Copyright reelyActive 2021 + * Copyright reelyActive 2021-2022 * We believe in an open Internet of Things */ @@ -7,6 +7,7 @@ // Non-user-configurable constants const APP_ID = 'sensible'; const ESPRUINO_COMPANY_CODE = 0x0590; +const SETTINGS_FILENAME = 'sensible.json'; const APP_ADVERTISING_DATA = [ 0x12, 0xff, 0x90, 0x05, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x7d ]; @@ -19,16 +20,12 @@ let isBarMenu = false; let isGpsMenu = false; let isHrmMenu = false; let isMagMenu = false; -let isBarEnabled = true; -let isGpsEnabled = true; -let isHrmEnabled = true; -let isMagEnabled = true; let isNewAccData = false; let isNewBarData = false; let isNewGpsData = false; let isNewHrmData = false; let isNewMagData = false; - +let settings = require('Storage').readJSON(SETTINGS_FILENAME); // Menus @@ -51,9 +48,10 @@ let accMenu = { let barMenu = { "": { "title" : "- Barometer -" }, "State": { - value: isBarEnabled, + value: settings.isBarEnabled, format: v => v ? "On" : "Off", - onchange: v => { isBarEnabled = v; Bangle.setBarometerPower(v, APP_ID); } + onchange: v => { settings.isBarEnabled = v; + Bangle.setBarometerPower(v, APP_ID); } }, "Altitude": { value: null }, "Press": { value: null }, @@ -63,9 +61,9 @@ let barMenu = { let gpsMenu = { "": { "title" : "- GPS -" }, "State": { - value: isGpsEnabled, + value: settings.isGpsEnabled, format: v => v ? "On" : "Off", - onchange: v => { isGpsEnabled = v; Bangle.setGPSPower(v, APP_ID); } + onchange: v => { settings.isGpsEnabled = v; Bangle.setGPSPower(v, APP_ID); } }, "Lat": { value: null }, "Lon": { value: null }, @@ -77,9 +75,9 @@ let gpsMenu = { let hrmMenu = { "": { "title" : "- Heart Rate -" }, "State": { - value: isHrmEnabled, + value: settings.isHrmEnabled, format: v => v ? "On" : "Off", - onchange: v => { isHrmEnabled = v; Bangle.setHRMPower(v, APP_ID); } + onchange: v => { settings.isHrmEnabled = v; Bangle.setHRMPower(v, APP_ID); } }, "BPM": { value: null }, "Confidence": { value: null }, @@ -88,9 +86,10 @@ let hrmMenu = { let magMenu = { "": { "title" : "- Magnetometer -" }, "State": { - value: isMagEnabled, + value: settings.isMagEnabled, format: v => v ? "On" : "Off", - onchange: v => { isMagEnabled = v; Bangle.setCompassPower(v, APP_ID); } + onchange: v => { settings.isMagEnabled = v; + Bangle.setCompassPower(v, APP_ID); } }, "x": { value: null }, "y": { value: null }, @@ -260,9 +259,9 @@ Bangle.on('mag', function(newMag) { // On start: enable sensors and display main menu g.clear(); -Bangle.setBarometerPower(isBarEnabled, APP_ID); -Bangle.setGPSPower(isGpsEnabled, APP_ID); -Bangle.setHRMPower(isHrmEnabled, APP_ID); -Bangle.setCompassPower(isMagEnabled, APP_ID); +Bangle.setBarometerPower(settings.isBarEnabled, APP_ID); +Bangle.setGPSPower(settings.isGpsEnabled, APP_ID); +Bangle.setHRMPower(settings.isHrmEnabled, APP_ID); +Bangle.setCompassPower(settings.isMagEnabled, APP_ID); E.showMenu(mainMenu); setInterval(transmitUpdatedSensorData, 1000); \ No newline at end of file diff --git a/apps/sensible/settings.json b/apps/sensible/settings.json new file mode 100644 index 000000000..90340a201 --- /dev/null +++ b/apps/sensible/settings.json @@ -0,0 +1,6 @@ +{ + "isBarEnabled": false, + "isGpsEnabled": false, + "isHrmEnabled": false, + "isMagEnabled": false +} \ No newline at end of file From bf5e16b2b43ebd2ca80e9e8fceee8683aa7a0426 Mon Sep 17 00:00:00 2001 From: jeffyactive Date: Tue, 25 Jan 2022 10:03:44 -0500 Subject: [PATCH 10/16] Move settings file to data rather than storage --- apps/sensible/metadata.json | 6 ++++-- apps/sensible/sensible.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/sensible/metadata.json b/apps/sensible/metadata.json index 5e90fbcaf..f88b34fa3 100644 --- a/apps/sensible/metadata.json +++ b/apps/sensible/metadata.json @@ -20,7 +20,9 @@ "readme": "README.md", "storage": [ { "name": "sensible.app.js", "url": "sensible.js" }, - { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true }, - { "name": "sensible.json", "url": "settings.json", "noOverwrite": true } + { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } +], +"data": [ + { "name": "sensible.data.json", "url": "settings.json", "storageFile": true } ] } diff --git a/apps/sensible/sensible.js b/apps/sensible/sensible.js index 6f367be31..ad2c0a1b8 100644 --- a/apps/sensible/sensible.js +++ b/apps/sensible/sensible.js @@ -7,7 +7,7 @@ // Non-user-configurable constants const APP_ID = 'sensible'; const ESPRUINO_COMPANY_CODE = 0x0590; -const SETTINGS_FILENAME = 'sensible.json'; +const SETTINGS_FILENAME = 'sensible.data.json'; const APP_ADVERTISING_DATA = [ 0x12, 0xff, 0x90, 0x05, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x7d ]; From 80a66f641411e8f92030cdca965682b7e7d7d304 Mon Sep 17 00:00:00 2001 From: jeffyactive Date: Tue, 25 Jan 2022 10:22:24 -0500 Subject: [PATCH 11/16] Write settings to persistent storage --- apps/sensible/sensible.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/apps/sensible/sensible.js b/apps/sensible/sensible.js index ad2c0a1b8..39366b547 100644 --- a/apps/sensible/sensible.js +++ b/apps/sensible/sensible.js @@ -50,8 +50,7 @@ let barMenu = { "State": { value: settings.isBarEnabled, format: v => v ? "On" : "Off", - onchange: v => { settings.isBarEnabled = v; - Bangle.setBarometerPower(v, APP_ID); } + onchange: v => { updateSetting('isBarEnabled', v); } }, "Altitude": { value: null }, "Press": { value: null }, @@ -63,7 +62,7 @@ let gpsMenu = { "State": { value: settings.isGpsEnabled, format: v => v ? "On" : "Off", - onchange: v => { settings.isGpsEnabled = v; Bangle.setGPSPower(v, APP_ID); } + onchange: v => { updateSetting('isGpsEnabled', v); } }, "Lat": { value: null }, "Lon": { value: null }, @@ -77,7 +76,7 @@ let hrmMenu = { "State": { value: settings.isHrmEnabled, format: v => v ? "On" : "Off", - onchange: v => { settings.isHrmEnabled = v; Bangle.setHRMPower(v, APP_ID); } + onchange: v => { updateSetting('isHrmEnabled', v); } }, "BPM": { value: null }, "Confidence": { value: null }, @@ -88,8 +87,7 @@ let magMenu = { "State": { value: settings.isMagEnabled, format: v => v ? "On" : "Off", - onchange: v => { settings.isMagEnabled = v; - Bangle.setCompassPower(v, APP_ID); } + onchange: v => { updateSetting('isMagEnabled', v); } }, "x": { value: null }, "y": { value: null }, @@ -189,6 +187,23 @@ function toByteArray(value, numberOfBytes, isSigned) { } +// Enable the sensors as per the current settings +function enableSensors() { + Bangle.setBarometerPower(settings.isBarEnabled, APP_ID); + Bangle.setGPSPower(settings.isGpsEnabled, APP_ID); + Bangle.setHRMPower(settings.isHrmEnabled, APP_ID); + Bangle.setCompassPower(settings.isMagEnabled, APP_ID); +} + + +// Update the given setting and write to persistent storage +function updateSetting(name, value) { + settings[name] = value; + require('Storage').writeJSON(SETTINGS_FILENAME, settings); + enableSensors(); +} + + // Update acceleration Bangle.on('accel', function(newAcc) { acc = newAcc; @@ -259,9 +274,6 @@ Bangle.on('mag', function(newMag) { // On start: enable sensors and display main menu g.clear(); -Bangle.setBarometerPower(settings.isBarEnabled, APP_ID); -Bangle.setGPSPower(settings.isGpsEnabled, APP_ID); -Bangle.setHRMPower(settings.isHrmEnabled, APP_ID); -Bangle.setCompassPower(settings.isMagEnabled, APP_ID); +enableSensors(); E.showMenu(mainMenu); setInterval(transmitUpdatedSensorData, 1000); \ No newline at end of file From cf8e6fbb4c033b9021396884c51db84ccb248a97 Mon Sep 17 00:00:00 2001 From: jeffyactive Date: Tue, 25 Jan 2022 10:30:26 -0500 Subject: [PATCH 12/16] Established UPDATE_MILLISECONDS as constant --- apps/sensible/sensible.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/sensible/sensible.js b/apps/sensible/sensible.js index 39366b547..8ec7d93d4 100644 --- a/apps/sensible/sensible.js +++ b/apps/sensible/sensible.js @@ -8,6 +8,7 @@ const APP_ID = 'sensible'; const ESPRUINO_COMPANY_CODE = 0x0590; const SETTINGS_FILENAME = 'sensible.data.json'; +const UPDATE_MILLISECONDS = 1000; const APP_ADVERTISING_DATA = [ 0x12, 0xff, 0x90, 0x05, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x7d ]; @@ -121,7 +122,7 @@ function transmitUpdatedSensorData() { isNewMagData = false; } - let interval = 1000 / data.length; + let interval = UPDATE_MILLISECONDS / data.length; NRF.setAdvertising(data, { showName: false, interval: interval }); } @@ -276,4 +277,4 @@ Bangle.on('mag', function(newMag) { g.clear(); enableSensors(); E.showMenu(mainMenu); -setInterval(transmitUpdatedSensorData, 1000); \ No newline at end of file +setInterval(transmitUpdatedSensorData, UPDATE_MILLISECONDS); \ No newline at end of file From 2f092e43266b771da623380fd6ce3cb0c86614dc Mon Sep 17 00:00:00 2001 From: jeffyactive Date: Tue, 25 Jan 2022 10:51:06 -0500 Subject: [PATCH 13/16] Added Pareto Anywhere screenshot --- apps/sensible/README.md | 4 +++- apps/sensible/screenshot-pareto-anywhere.png | Bin 0 -> 46492 bytes 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 apps/sensible/screenshot-pareto-anywhere.png diff --git a/apps/sensible/README.md b/apps/sensible/README.md index fcff3b0f9..c6a843ce1 100644 --- a/apps/sensible/README.md +++ b/apps/sensible/README.md @@ -5,7 +5,9 @@ Collect all the sensor data from the Bangle.js 2, display the live readings in m ## Usage -The advertising packets will be recognised by [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source middleware and any other program which observes the standard packet types. Also convenient for testing individual sensors of the Bangle.js 2 via the menu interface. +The advertising packets will be recognised by [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source middleware and any other program which observes the standard packet types. See our [Bangle.js Development Guide](https://reelyactive.github.io/diy/banglejs-dev/) for details. Also convenient for testing individual sensors of the Bangle.js 2 via the menu interface. + +![SensiBLE in Pareto Anywhere](/apps/sensible/screenshot-pareto-anywhere.png) ## Features diff --git a/apps/sensible/screenshot-pareto-anywhere.png b/apps/sensible/screenshot-pareto-anywhere.png new file mode 100644 index 0000000000000000000000000000000000000000..c411bca8a729f9d0915e05246df9557959e72dc9 GIT binary patch literal 46492 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 Date: Tue, 25 Jan 2022 10:56:51 -0500 Subject: [PATCH 14/16] Controls section includes persistent storage of settings --- apps/sensible/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sensible/README.md b/apps/sensible/README.md index c6a843ce1..6babc2f3c 100644 --- a/apps/sensible/README.md +++ b/apps/sensible/README.md @@ -24,7 +24,7 @@ in the menu display, and broadcasts all sensor data readings _except_ accelerati ## Controls -Browse and control sensors using the standard Espruino menu interface. +Browse and control sensors using the standard Espruino menu interface. By default, all sensors _except_ the accelerometer are disabled. Sensors can be individually enabled/disabled via the menu. These settings are written to persistent storage (flash) and will be applied each time the SensiBLE app is loaded. ## Requests From 9dbc182d994f3c9cda1d72b24a2df45e8e4c3773 Mon Sep 17 00:00:00 2001 From: jeffyactive Date: Tue, 25 Jan 2022 10:59:05 -0500 Subject: [PATCH 15/16] Version bump --- apps/sensible/ChangeLog | 3 ++- apps/sensible/metadata.json | 52 ++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/apps/sensible/ChangeLog b/apps/sensible/ChangeLog index 33e44b70c..0699954d7 100644 --- a/apps/sensible/ChangeLog +++ b/apps/sensible/ChangeLog @@ -2,4 +2,5 @@ 0.02: Corrected variable initialisation 0.03: Advertise app name, added screenshots 0.04: Advertise bar, GPS, HRM and mag services -0.05: Refactored for efficiency, corrected sensor value inaccuracies \ No newline at end of file +0.05: Refactored for efficiency, corrected sensor value inaccuracies +0.06: User settings are written to persistent storage, loaded on app start \ No newline at end of file diff --git a/apps/sensible/metadata.json b/apps/sensible/metadata.json index f88b34fa3..6715e2538 100644 --- a/apps/sensible/metadata.json +++ b/apps/sensible/metadata.json @@ -1,28 +1,28 @@ { -"id": "sensible", -"name": "SensiBLE", -"shortName": "SensiBLE", -"version": "0.05", -"description": "Collect, display and advertise real-time sensor data.", -"icon": "sensible.png", -"screenshots": [ - { "url": "screenshot-top.png" }, - { "url": "screenshot-acc.png" }, - { "url": "screenshot-bar.png" }, - { "url": "screenshot-gps.png" }, - { "url": "screenshot-hrm.png" }, - { "url": "screenshot-mag.png" } -], -"type": "app", -"tags": "tool,sensors,bluetooth", -"supports" : [ "BANGLEJS2" ], -"allow_emulator": true, -"readme": "README.md", -"storage": [ - { "name": "sensible.app.js", "url": "sensible.js" }, - { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } -], -"data": [ - { "name": "sensible.data.json", "url": "settings.json", "storageFile": true } -] + "id": "sensible", + "name": "SensiBLE", + "shortName": "SensiBLE", + "version": "0.06", + "description": "Collect, display and advertise real-time sensor data.", + "icon": "sensible.png", + "screenshots": [ + { "url": "screenshot-top.png" }, + { "url": "screenshot-acc.png" }, + { "url": "screenshot-bar.png" }, + { "url": "screenshot-gps.png" }, + { "url": "screenshot-hrm.png" }, + { "url": "screenshot-mag.png" } + ], + "type": "app", + "tags": "tool,sensors,bluetooth", + "supports" : [ "BANGLEJS2" ], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + { "name": "sensible.app.js", "url": "sensible.js" }, + { "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true } + ], + "data": [ + { "name": "sensible.data.json", "url": "settings.json", "storageFile": true } + ] } From d83bcbc96b66dfd82418f4521c254c26bd1fc809 Mon Sep 17 00:00:00 2001 From: jeffyactive Date: Tue, 25 Jan 2022 11:03:36 -0500 Subject: [PATCH 16/16] Corrected path to screenshot --- apps/sensible/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sensible/README.md b/apps/sensible/README.md index 6babc2f3c..8bf21ae8a 100644 --- a/apps/sensible/README.md +++ b/apps/sensible/README.md @@ -7,7 +7,7 @@ Collect all the sensor data from the Bangle.js 2, display the live readings in m The advertising packets will be recognised by [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source middleware and any other program which observes the standard packet types. See our [Bangle.js Development Guide](https://reelyactive.github.io/diy/banglejs-dev/) for details. Also convenient for testing individual sensors of the Bangle.js 2 via the menu interface. -![SensiBLE in Pareto Anywhere](/apps/sensible/screenshot-pareto-anywhere.png) +![SensiBLE in Pareto Anywhere](/BangleApps/apps/sensible/screenshot-pareto-anywhere.png) ## Features