Merge branch 'espruino:master' into master
commit
3fd65260d8
|
|
@ -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},
|
||||
|
|
@ -623,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",
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="table"></div>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
<script>
|
||||
const DB_RECORD_LEN = 4;
|
||||
const DB_RECORDS_PER_HR = 6;
|
||||
const DB_RECORDS_PER_DAY = DB_RECORDS_PER_HR*24 + 1/*summary*/;
|
||||
const DB_RECORDS_PER_MONTH = DB_RECORDS_PER_DAY*31;
|
||||
const DB_HEADER_LEN = 8;
|
||||
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
||||
|
||||
var domTable = document.getElementById("table");
|
||||
|
||||
function saveCSV(data, date, title) {
|
||||
// date = "2021-9"/ etc
|
||||
var csv = "Date,Time,Steps,Heartrate,Movement\n";
|
||||
var f = data;
|
||||
|
||||
var idx = DB_HEADER_LEN;
|
||||
for (var day=0;day<31;day++) {
|
||||
for (var hr=0;hr<24;hr++) { // actually 25, see below
|
||||
for (var m=0;m<DB_RECORDS_PER_HR;m++) {
|
||||
var h = f.substr(idx, DB_RECORD_LEN);
|
||||
if (h!="\xFF\xFF\xFF\xFF") {
|
||||
var h = {
|
||||
day:day+1, hr : hr, min:m*10,
|
||||
steps : (h.charCodeAt(0)<<8) | h.charCodeAt(1),
|
||||
bpm : h.charCodeAt(2),
|
||||
movement : h.charCodeAt(3)
|
||||
};
|
||||
csv += [
|
||||
date + "-" + h.day,
|
||||
h.hr+":"+h.min.toString().padStart(2,0),
|
||||
h.steps,
|
||||
h.bpm||"",
|
||||
h.movement
|
||||
].join(",")+"\n";
|
||||
}
|
||||
idx += DB_RECORD_LEN;
|
||||
}
|
||||
}
|
||||
idx += DB_RECORD_LEN; // +1 because we have an extra record with totals for the end of the day
|
||||
}
|
||||
|
||||
Util.saveCSV(title, csv);
|
||||
}
|
||||
|
||||
function downloadHealth(filename, callback) {
|
||||
Util.showModal("Downloading Track...");
|
||||
Util.readStorage(filename, data => {
|
||||
Util.hideModal();
|
||||
callback(data);
|
||||
});
|
||||
}
|
||||
function getMonthList() {
|
||||
Util.showModal("Loading...");
|
||||
domTable.innerHTML = "";
|
||||
Puck.eval(`require("Storage").list(/^health-.*\\.raw$/)`,files=>{
|
||||
files = files.map(f => {
|
||||
var m = f.match(/^health-([^\.]+)\.raw$/);
|
||||
return {
|
||||
filename : f,
|
||||
date : m[1], // eg 2021-9
|
||||
str : new Date(m[1]).toLocaleString(undefined, {month:'long',year:'numeric'})
|
||||
}
|
||||
})
|
||||
var html = `<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Month</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>\n`;
|
||||
files.forEach(f => {
|
||||
html += `
|
||||
<tr>
|
||||
<td>${f.str}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary" filename="${f.filename}" date="${f.date}" task="downloadcsv">Download CSV</button>
|
||||
<button class="btn btn-default" filename="${f.filename}" date="${f.date}" task="delete">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
if (files.length==0) {
|
||||
html += `
|
||||
<tr>
|
||||
<td>No data recorded</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
html += `
|
||||
</tbody>
|
||||
</table>`;
|
||||
domTable.innerHTML = html;
|
||||
Util.hideModal();
|
||||
var buttons = domTable.querySelectorAll("button");
|
||||
for (var i=0;i<buttons.length;i++) {
|
||||
buttons[i].addEventListener("click",event => {
|
||||
var button = event.currentTarget;
|
||||
var filename = button.getAttribute("filename");
|
||||
var date = button.getAttribute("date");
|
||||
if (!filename || !date) return;
|
||||
var task = button.getAttribute("task");
|
||||
if (task=="delete") {
|
||||
Util.showModal("Deleting...");
|
||||
Util.eraseStorage(filename,()=>{
|
||||
Util.hideModal();
|
||||
getTrackList();
|
||||
});
|
||||
}
|
||||
if (task=="downloadcsv") {
|
||||
downloadHealth(filename, data => saveCSV(data, date, `Bangle.js Health ${date}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
getMonthList();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Use 'recorder.log..' rather than 'record.log..'
|
||||
Fix interface.html
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<b>THIS IS NOT CURRENTLY IMPLEMENTED</b>
|
||||
<div id="tracks"></div>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
|
|
@ -14,14 +13,35 @@ function saveKML(track,title) {
|
|||
var kml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://www.opengis.net/kml/2.2">
|
||||
<Document>
|
||||
<Placemark>
|
||||
<name>${title}</name>
|
||||
<LineString>
|
||||
<coordinates>
|
||||
${track.map(pt=>[pt.lon, pt.lat, pt.alt].join(",")).join("\n ")}
|
||||
</coordinates>
|
||||
</LineString>
|
||||
</Placemark>
|
||||
<Schema id="schema">
|
||||
${track[0].Heartrate!==undefined ? `<gx:SimpleArrayField name="heartrate" type="int">
|
||||
<displayName>Heart Rate</displayName>
|
||||
</gx:SimpleArrayField>`:``}
|
||||
${track[0].Steps!==undefined ? `<gx:SimpleArrayField name="steps" type="int">
|
||||
<displayName>Step Count</displayName>`:``}
|
||||
</gx:SimpleArrayField>
|
||||
</Schema>
|
||||
<Folder>
|
||||
<name>Tracks</name>
|
||||
<Placemark>
|
||||
<name>${title}</name>
|
||||
<gx:Track>
|
||||
${track.map(pt=>` <when>${pt.Time.toISOString()}</when>\n`).join("")}
|
||||
${track.map(pt=>` <gx:coord>${pt.Longitude} ${pt.Latitude} ${pt.Altitude}</gx:coord>\n`).join("")}
|
||||
<ExtendedData>
|
||||
<SchemaData schemaUrl="#schema">
|
||||
|
||||
${track[0].Heartrate!==undefined ? `<gx:SimpleArrayData name="heartrate">
|
||||
${track.map(pt=>` <gx:value>${0|pt.Heartrate}</gx:value>\n`).join("")}
|
||||
</gx:SimpleArrayData>`:``}
|
||||
${track[0].Steps!==undefined ? `<gx:SimpleArrayData name="steps">
|
||||
${track.map(pt=>` <gx:value>${0|pt.Steps}</gx:value>\n`).join("")}
|
||||
</gx:SimpleArrayData>`:``}
|
||||
</SchemaData>
|
||||
</ExtendedData>
|
||||
</gx:Track>
|
||||
</Placemark>
|
||||
</Folder>
|
||||
</Document>
|
||||
</kml>`;
|
||||
var a = document.createElement("a"),
|
||||
|
|
@ -39,6 +59,7 @@ function saveKML(track,title) {
|
|||
|
||||
function saveGPX(track, title) {
|
||||
var gpx = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx creator="Bangle.js" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
|
||||
<gpx creator="Bangle.js" version="1.1">
|
||||
<metadata>
|
||||
<time>${track[0].date.toISOString()}</time>
|
||||
|
|
@ -48,11 +69,19 @@ function saveGPX(track, title) {
|
|||
<trkseg>`;
|
||||
track.forEach(pt=>{
|
||||
gpx += `
|
||||
<trkpt lat="${pt.lat}" lon="${pt.lon}">
|
||||
<ele>${pt.alt}</ele>
|
||||
<time>${pt.date.toISOString()}</time>
|
||||
<trkpt lat="${pt.Latitude}" lon="${pt.Longitude}">
|
||||
<ele>${pt.Altitude}</ele>
|
||||
<time>${pt.Time.toISOString()}</time>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
${pt.Heartrate ? `<gpxtpx:hr>${pt.Heartrate}</gpxtpx:hr>`:``}
|
||||
${""/*<gpxtpx:distance>...</gpxtpx:distance>*/}
|
||||
${""/* <gpxtpx:cad>65</gpxtpx:cad> */}
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>`;
|
||||
});
|
||||
// https://www8.garmin.com/xmlschemas/TrackPointExtensionv1.xsd
|
||||
gpx += `
|
||||
</trkseg>
|
||||
</trk>
|
||||
|
|
@ -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 = `<div class="container">
|
||||
<div class="columns">\n`;
|
||||
trackLines.forEach(l => {
|
||||
var track = trackLineToObject(l, true /*has track number*/);
|
||||
html += `
|
||||
<div class="column col-12">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">Track ${track.number}</div>
|
||||
<div class="card-subtitle text-gray">${track.date.toString().substr(0,24)}</div>
|
||||
</div>
|
||||
<div class="card-image">
|
||||
<iframe
|
||||
width="100%"
|
||||
height="250"
|
||||
frameborder="0" style="border:0"
|
||||
src="https://www.google.com/maps/embed/v1/place?key=AIzaSyBxTcwrrVOh2piz7EmIs1Xn4FsRxJWeVH4&q=${track.lat},${track.lon}&zoom=10" allowfullscreen>
|
||||
</iframe>
|
||||
</div>
|
||||
<div class="card-body"></div>
|
||||
<div class="card-footer">
|
||||
<button class="btn btn-primary" trackid="${track.number}" task="downloadkml">Download KML</button>
|
||||
<button class="btn btn-primary" trackid="${track.number}" task="downloadgpx">Download GPX</button>
|
||||
<button class="btn btn-default" trackid="${track.number}" task="delete">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
if (trackLines.length==0) {
|
||||
html += `
|
||||
<div class="column col-12">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">No tracks</div>
|
||||
<div class="card-subtitle text-gray">No GPS tracks found</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
html += `
|
||||
</div>
|
||||
</div>`;
|
||||
domTracks.innerHTML = html;
|
||||
Util.hideModal();
|
||||
var buttons = domTracks.querySelectorAll("button");
|
||||
for (var i=0;i<buttons.length;i++) {
|
||||
buttons[i].addEventListener("click",event => {
|
||||
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 = `<div class="container">
|
||||
<div class="columns">\n`;
|
||||
trackList.forEach(track => {
|
||||
var trackData = trackLineToObject(track.info.headers, track.info.l);
|
||||
console.log("track", track);
|
||||
console.log("trackData", trackData);
|
||||
html += `
|
||||
<div class="column col-12">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">Track ${track.number}</div>
|
||||
<div class="card-subtitle text-gray">${trackData.Time.toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}</div>
|
||||
</div>
|
||||
${trackData.Latitude ? `
|
||||
<div class="card-image">
|
||||
<iframe
|
||||
width="100%"
|
||||
height="250"
|
||||
frameborder="0" style="border:0"
|
||||
src="https://www.google.com/maps/embed/v1/place?key=AIzaSyBxTcwrrVOh2piz7EmIs1Xn4FsRxJWeVH4&q=${track.lat},${track.lon}&zoom=10" allowfullscreen>
|
||||
</iframe>
|
||||
</div><div class="card-body"></div>` : `<div class="card-body">No GPS info</div>`}
|
||||
<div class="card-footer">
|
||||
${trackData.Latitude ? `
|
||||
<button class="btn btn-primary" filename="${track.filename}" trackid="${track.number}" task="downloadkml">Download KML</button>
|
||||
<button class="btn btn-primary" filename="${track.filename}" trackid="${track.number}" task="downloadgpx">Download GPX</button>
|
||||
` : ``}
|
||||
<button class="btn btn-primary" filename="${track.filename}" trackid="${track.number}" task="downloadcsv">Download CSV</button>
|
||||
<button class="btn btn-default" filename="${track.filename}" trackid="${track.number}" task="delete">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
if (trackList.length==0) {
|
||||
html += `
|
||||
<div class="column col-12">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">No tracks</div>
|
||||
<div class="card-subtitle text-gray">No GPS tracks found</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
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 += `
|
||||
</div>
|
||||
</div>`;
|
||||
domTracks.innerHTML = html;
|
||||
Util.hideModal();
|
||||
var buttons = domTracks.querySelectorAll("button");
|
||||
for (var i=0;i<buttons.length;i++) {
|
||||
buttons[i].addEventListener("click",event => {
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
|
|
|
|||
2
core
2
core
|
|
@ -1 +1 @@
|
|||
Subproject commit 70b49d8dbd2afa76f4485aadf679dc75e0a8b4ac
|
||||
Subproject commit 5ef454a1acce54f6420015b519a7ecf461f9bc37
|
||||
Loading…
Reference in New Issue