From 102b1b2ddb229e929e1fdb1995e01e9f23d920bb Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 2 Nov 2021 15:36:19 +0000 Subject: [PATCH 1/4] update default BG2 theme colour --- apps/setting/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 0c2930086..0decb5313 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -193,7 +193,7 @@ function showThemeMenu() { 'Light BW': ()=>{ upd({ fg:cl("#000"), bg:cl("#fff"), - fg2:cl("#00f"), bg2:cl("#0ff"), + fg2:cl("#000"), bg2:cl("#cff"), fgH:cl("#000"), bgH:cl("#0ff"), dark:false }); From ca4bef7a1cac03a652440d121128864efbf3546c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 2 Nov 2021 16:19:32 +0000 Subject: [PATCH 2/4] Add ability to download health info --- apps.json | 1 + apps/health/interface.html | 133 +++++++++++++++++++++++++++++++++++++ apps/health/lib.js | 1 - core | 2 +- 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 apps/health/interface.html diff --git a/apps.json b/apps.json index 35d95d9a7..03e20050e 100644 --- a/apps.json +++ b/apps.json @@ -55,6 +55,7 @@ "tags": "tool,system,health", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", + "interface": "interface.html", "storage": [ {"name":"health.app.js","url":"app.js"}, {"name":"health.img","url":"app-icon.js","evaluate":true}, diff --git a/apps/health/interface.html b/apps/health/interface.html new file mode 100644 index 000000000..f04857926 --- /dev/null +++ b/apps/health/interface.html @@ -0,0 +1,133 @@ + + + + + +
+ + + + + diff --git a/apps/health/lib.js b/apps/health/lib.js index 20d73a907..70305bff8 100644 --- a/apps/health/lib.js +++ b/apps/health/lib.js @@ -16,7 +16,6 @@ function getRecordIdx(d) { // Read all records from the given month exports.readAllRecords = function(d, cb) { - var rec = getRecordIdx(d); var fn = getRecordFN(d); var f = require("Storage").read(fn); if (f===undefined) return; diff --git a/core b/core index 70b49d8db..5ef454a1a 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 70b49d8dbd2afa76f4485aadf679dc75e0a8b4ac +Subproject commit 5ef454a1acce54f6420015b519a7ecf461f9bc37 From 47ba763a9d24cd59e0b57549a3d7bcefb54c7aa2 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 2 Nov 2021 20:06:27 +0000 Subject: [PATCH 3/4] recorder 0.02: Use 'recorder.log..' rather than 'record.log..' + Fix interface.html --- apps.json | 2 +- apps/recorder/ChangeLog | 2 + apps/recorder/app.js | 8 +- apps/recorder/interface.html | 272 ++++++++++++++++++++++------------- apps/recorder/widget.js | 2 +- 5 files changed, 183 insertions(+), 103 deletions(-) diff --git a/apps.json b/apps.json index 1a79e59f4..35fe0b49a 100644 --- a/apps.json +++ b/apps.json @@ -624,7 +624,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.01", + "version": "0.02", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", diff --git a/apps/recorder/ChangeLog b/apps/recorder/ChangeLog index 5560f00bc..bf90d0384 100644 --- a/apps/recorder/ChangeLog +++ b/apps/recorder/ChangeLog @@ -1 +1,3 @@ 0.01: New App! +0.02: Use 'recorder.log..' rather than 'record.log..' + Fix interface.html diff --git a/apps/recorder/app.js b/apps/recorder/app.js index 9b9c06c78..ac3e391fc 100644 --- a/apps/recorder/app.js +++ b/apps/recorder/app.js @@ -13,7 +13,7 @@ function loadSettings() { var changed = false; if (!settings.file) { changed = true; - settings.file = "record.log0.csv"; + settings.file = "recorder.log0.csv"; } if (!Array.isArray(settings.record)) { settings.record = ["gps"]; @@ -31,7 +31,7 @@ function updateSettings() { } function getTrackNumber(filename) { - return parseInt(filename.match(/^record\.log(.*)\.csv$/)[1]||0); + return parseInt(filename.match(/^recorder\.log(.*)\.csv$/)[1]||0); } function showMainMenu() { @@ -73,7 +73,7 @@ function showMainMenu() { step: 1, onchange: v => { settings.recording = false; // stop recording if we change anything - settings.file = "record.log"+v+".csv"; + settings.file = "recorder.log"+v+".csv"; updateSettings(); } }, @@ -105,7 +105,7 @@ function viewTracks() { '': { 'title': 'Tracks' } }; var found = false; - require("Storage").list(/^record\.log.*\.csv$/,{sf:true}).forEach(filename=>{ + require("Storage").list(/^recorder\.log.*\.csv$/,{sf:true}).forEach(filename=>{ found = true; menu["Track "+getTrackNumber(filename)] = ()=>viewTrack(filename,false); }); diff --git a/apps/recorder/interface.html b/apps/recorder/interface.html index 2ae1c3e71..eca13d263 100644 --- a/apps/recorder/interface.html +++ b/apps/recorder/interface.html @@ -3,7 +3,6 @@ - THIS IS NOT CURRENTLY IMPLEMENTED
@@ -14,14 +13,35 @@ function saveKML(track,title) { var kml = ` - - ${title} - - - ${track.map(pt=>[pt.lon, pt.lat, pt.alt].join(",")).join("\n ")} - - - + +${track[0].Heartrate!==undefined ? ` + Heart Rate + `:``} +${track[0].Steps!==undefined ? ` + Step Count`:``} + + + + Tracks + + ${title} + +${track.map(pt=>` ${pt.Time.toISOString()}\n`).join("")} +${track.map(pt=>` ${pt.Longitude} ${pt.Latitude} ${pt.Altitude}\n`).join("")} + + + +${track[0].Heartrate!==undefined ? ` +${track.map(pt=>` ${0|pt.Heartrate}\n`).join("")} + `:``} +${track[0].Steps!==undefined ? ` +${track.map(pt=>` ${0|pt.Steps}\n`).join("")} + `:``} + + + + + `; var a = document.createElement("a"), @@ -39,6 +59,7 @@ function saveKML(track,title) { function saveGPX(track, title) { var gpx = ` + @@ -48,11 +69,19 @@ function saveGPX(track, title) { `; track.forEach(pt=>{ gpx += ` - - ${pt.alt} - + + ${pt.Altitude} + + + + ${pt.Heartrate ? `${pt.Heartrate}`:``} + ${""/*...*/} + ${""/* 65 */} + + `; }); + // https://www8.garmin.com/xmlschemas/TrackPointExtensionv1.xsd gpx += ` @@ -70,104 +99,153 @@ function saveGPX(track, title) { }, 0); } -function trackLineToObject(l, hasTrackNumber) { +function saveCSV(track, title) { + var headers = Object.keys(track[0]); + var csv = headers.join(",")+"\n"; + track.forEach(t=>{ + csv += headers.map(k=>{ + if (t[k] instanceof Date) return t[k].toISOString(); + return t[k]; + }).join(",")+"\n"; + }); + Util.saveCSV(title, csv); +} + +function trackLineToObject(headers, l) { var t = l.trim().split(","); - var n = hasTrackNumber ? 1 : 0; - var o = { - date : new Date(parseInt(t[n+0])), - lat : parseFloat(t[n+1]), - lon : parseFloat(t[n+2]), - alt : parseFloat(t[n+3]) - }; - if (hasTrackNumber) - o.number = t[0]; + var o = {}; + headers.forEach((header,i) => o[header] = t[i]); + if (o.Time) o.Time = new Date(o.Time*1000); return o; } -function downloadTrack(trackid, callback) { +function downloadTrack(filename, callback) { Util.showModal("Downloading Track..."); - Util.readStorageFile(`.gpsrc${trackid.toString(36)}`,data=>{ + Util.readStorageFile(filename,data=>{ Util.hideModal(); - var track = data.trim().split("\n").map(l=>trackLineToObject(l,false)); + var lines = data.trim().split("\n"); + var headers = lines.shift().split(","); + var track = lines.map(l=>trackLineToObject(headers, l)); callback(track); }); } + function getTrackList() { - Util.showModal("Loading Tracks..."); + Util.showModal("Loading Track List..."); domTracks.innerHTML = ""; - Puck.write(`\x10(function() { - Bluetooth.println(""); - for (var n=0;n<36;n++) { - var f = require("Storage").open(".gpsrc"+n.toString(36),"r"); - var l = f.readLine(); - Bluetooth.println((l!==undefined) ? (n + "," + l.trim()) : ""); - } - })()\n`,tracklist=>{ - var trackLines = tracklist.trim().split("\n").filter(l=>l!=""); - var html = `
-
\n`; - trackLines.forEach(l => { - var track = trackLineToObject(l, true /*has track number*/); - html += ` -
-
-
Track ${track.number}
-
${track.date.toString().substr(0,24)}
-
-
- -
-
- -
- `; - }); - if (trackLines.length==0) { - html += ` -
-
-
No tracks
-
No GPS tracks found
-
-
- `; - } - html += ` -
-
`; - domTracks.innerHTML = html; - Util.hideModal(); - var buttons = domTracks.querySelectorAll("button"); - for (var i=0;i { - var button = event.currentTarget; - var trackid = parseInt(button.getAttribute("trackid")); - var task = button.getAttribute("task"); - if (task=="delete") { - Util.showModal("Deleting Track..."); - Util.eraseStorageFile(`.gpsrc${trackid.toString(36)}`,()=>{ - Util.hideModal(); - getTrackList(); + Puck.eval(`require("Storage").list(/^recorder\\.log.*\\.csv$/,{sf:1})`,files=>{ + var trackList = []; + var promise = Promise.resolve(); + /* For each file ask Bangle.js for info. Since we now start recording even + before we have a GPS trace, we get the Bangle to do a *quick* search for us + to see if it found any data first. */ + files.forEach(filename => { + promise = promise.then(()=>new Promise(resolve => { + var trackNo = filename.match(/^recorder\.log(.*)\.csv$/)[1]; + Util.showModal(`Loading Track ${trackNo}...`); + Puck.eval(`(function(fn) { + var f = require("Storage").open(fn,"r"); + var headers = f.readLine(); + var data = f.readLine(); + var lIdx = headers.split(",").indexOf("Latitude"); + if (lIdx >= 0) { + var tries = 100; + var l = data; + while (l && l.split(",")[lIdx]=="" && tries++) + l = f.readLine(); + if (l) data = l; + } + return {headers:headers,l:data}; +})(${JSON.stringify(filename)})`, trackInfo=>{ + console.log(filename," => ",trackInfo); + trackInfo.headers = trackInfo.headers.split(","); + trackList.push({ + filename : filename, + number : trackNo, + info : trackInfo }); + resolve(); + }); + })); + }); + // ================================================ + // When 'promise' completes we now have all the info in trackList + promise.then(() => { + var html = `
+
\n`; + trackList.forEach(track => { + var trackData = trackLineToObject(track.info.headers, track.info.l); + console.log("track", track); + console.log("trackData", trackData); + html += ` +
+
+
Track ${track.number}
+
${trackData.Time.toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}
+
+${trackData.Latitude ? ` +
+ +
` : `
No GPS info
`} + +
+ `; + }); + if (trackList.length==0) { + html += ` +
+
+
No tracks
+
No GPS tracks found
+
+
+ `; } - if (task=="downloadkml") { - downloadTrack(trackid, track => saveKML(track, `Bangle.js Track ${trackid}`)); - } - if (task=="downloadgpx") { - downloadTrack(trackid, track => saveGPX(track, `Bangle.js Track ${trackid}`)); - } - }); - } - }) + html += ` +
+
`; + domTracks.innerHTML = html; + Util.hideModal(); + var buttons = domTracks.querySelectorAll("button"); + for (var i=0;i { + var button = event.currentTarget; + var filename = button.getAttribute("filename"); + var trackid = parseInt(button.getAttribute("trackid")); + if (!filename || trackid===undefined) return; + var task = button.getAttribute("task"); + if (task=="delete") { + Util.showModal("Deleting Track..."); + Util.eraseStorageFile(filename,()=>{ + Util.hideModal(); + getTrackList(); + }); + } + if (task=="downloadkml") { + downloadTrack(filename, track => saveKML(track, `Bangle.js Track ${trackid}`)); + } + if (task=="downloadgpx") { + downloadTrack(filename, track => saveGPX(track, `Bangle.js Track ${trackid}`)); + } + if (task=="downloadcsv") { + downloadTrack(filename, track => saveCSV(track, `Bangle.js Track ${trackid}`)); + } + }); + } + }); + }); } function onInit() { diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index df0be1d20..09893bbb7 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -7,7 +7,7 @@ function loadSettings() { var settings = require("Storage").readJSON("recorder.json",1)||{}; settings.period = settings.period||10; - if (!settings.file || !settings.file.startsWith("record.log")) + if (!settings.file || !settings.file.startsWith("recorder.log")) settings.recording = false; return settings; } From ab3de04c2deaa14265d8887446d5824aa5e2f360 Mon Sep 17 00:00:00 2001 From: Filipe Fradique Date: Thu, 4 Nov 2021 05:36:09 +0000 Subject: [PATCH 4/4] Fixed wrong day being displayed in nifty clocks --- apps/ffcniftya/app.js | 2 +- apps/ffcniftyb/app.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 0b8865bec..31742f64a 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -27,7 +27,7 @@ function draw() { const hour = d02(now.getHours() - (is12Hour && now.getHours() > 12 ? 12 : 0)); const minutes = d02(now.getMinutes()); - const day = d02(now.getDay()); + const day = d02(now.getDate()); const month = d02(now.getMonth() + 1); const year = now.getFullYear(); diff --git a/apps/ffcniftyb/app.js b/apps/ffcniftyb/app.js index 58bf0b24b..75d217ab4 100644 --- a/apps/ffcniftyb/app.js +++ b/apps/ffcniftyb/app.js @@ -31,7 +31,7 @@ function renderText(g) { const hour = d02(now.getHours() - (is12Hour && now.getHours() > 12 ? 12 : 0)); const minutes = d02(now.getMinutes()); - const day = d02(now.getDay()); + const day = d02(now.getDate()); const month = d02(now.getMonth() + 1); const year = now.getFullYear();