From e4a469df8f8ead635508f7e1fba1d0590e4869e8 Mon Sep 17 00:00:00 2001 From: bonchan Date: Sun, 27 Nov 2022 04:20:40 -0300 Subject: [PATCH 1/7] added gpx exporter --- index.html | 2 + js/gpx-exporter.js | 32 ++++++++++++++++ js/main.js | 27 ++++++++++++++ js/webworkers/gpx-export-worker.js | 60 ++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+) create mode 100644 js/gpx-exporter.js create mode 100644 js/webworkers/gpx-export-worker.js diff --git a/index.html b/index.html index e6442d74..ae537ac1 100644 --- a/index.html +++ b/index.html @@ -186,6 +186,7 @@

Welcome to the Enhanced Blackbox Explorer!

Export Workspaces... Export CSV... + Export GPX... Open log file/video @@ -3152,6 +3153,7 @@ + diff --git a/js/gpx-exporter.js b/js/gpx-exporter.js new file mode 100644 index 00000000..5d3ceb3d --- /dev/null +++ b/js/gpx-exporter.js @@ -0,0 +1,32 @@ +"use strict"; + +/** + * @constructor + * @param {FlightLog} flightLog + */ +let GpxExporter = function(flightLog) { + + /** + * @param {function} success is a callback triggered when export is done + */ + function dump(success) { + let frames = _(flightLog.getChunksInTimeRange(flightLog.getMinTime(), flightLog.getMaxTime())) + .map(chunk => chunk.frames).value(), + worker = new Worker("/js/webworkers/gpx-export-worker.js"); + + worker.onmessage = event => { + success(event.data); + worker.terminate(); + }; + worker.postMessage({ + sysConfig: flightLog.getSysConfig(), + fieldNames: flightLog.getMainFieldNames(), + frames: frames, + }); + } + + // exposed functions + return { + dump: dump, + }; +}; \ No newline at end of file diff --git a/js/main.js b/js/main.js index b7a1793b..fdd68d8f 100644 --- a/js/main.js +++ b/js/main.js @@ -940,6 +940,28 @@ function BlackboxLogViewer() { CsvExporter(flightLog, options).dump(onSuccess); } + function exportGpx(file) { + + function onSuccess(data) { + console.debug("Gpx export finished in", (performance.now() - startTime) / 1000, "secs"); + if (!data) { + console.debug("Empty data, nothing to save"); + return; + } + let blob = new Blob([data], {type: 'GPX File'}), + e = document.createEvent('MouseEvents'), + a = document.createElement('a'); + a.download = file || $(".log-filename").text() + ".gpx"; + a.href = window.URL.createObjectURL(blob); + a.dataset.downloadurl = ['GPX File', a.download, a.href].join(':'); + e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + a.dispatchEvent(e); + } + + let startTime = performance.now(); + GpxExporter(flightLog).dump(onSuccess); + } + function newGraphConfig(newConfig) { lastGraphConfig = graphConfig; // Remember the last configuration. graphConfig = newConfig; @@ -1470,6 +1492,11 @@ function BlackboxLogViewer() { exportCsv(); e.preventDefault(); }); + $(".btn-gpx-export").click(function(e) { + setGraphState(GRAPH_STATE_PAUSED); + exportGpx(); + e.preventDefault(); + }); if (FlightLogVideoRenderer.isSupported()) { $(".btn-video-export").click(function(e) { diff --git a/js/webworkers/gpx-export-worker.js b/js/webworkers/gpx-export-worker.js new file mode 100644 index 00000000..e02db20b --- /dev/null +++ b/js/webworkers/gpx-export-worker.js @@ -0,0 +1,60 @@ +importScripts("/node_modules/lodash/lodash.min.js"); + +onmessage = function (event) { + const header = ` + + + + Betaflight Blackbox Explorer + + + `; + + const footer = ""; + + const timeIndex = event.data.fieldNames.indexOf("time"); + const latIndex = event.data.fieldNames.indexOf("GPS_coord[0]"); + const lngIndex = event.data.fieldNames.indexOf("GPS_coord[1]"); + const altitudeIndex = event.data.fieldNames.indexOf("GPS_altitude"); + const speedIndex = event.data.fieldNames.indexOf("GPS_speed"); + const groundCourseIndex = event.data.fieldNames.indexOf("GPS_ground_course"); + const numSatIndex = event.data.fieldNames.indexOf("GPS_numSat"); + + let trkpts = ""; + for (var chunk of event.data.frames) { + for (var frame of chunk) { + if (!frame[latIndex] || !frame[lngIndex]) continue; + const timeMillis = Math.floor(frame[timeIndex] / 1000); + const lat = frame[latIndex] / 10000000; + const lng = frame[lngIndex] / 10000000; + const altitude = frame[altitudeIndex] / 10; + const speed = frame[speedIndex] / 100; + const groundCourse = frame[groundCourseIndex] / 10; + const numSat = frame[numSatIndex]; + + let date = new Date(event.data.sysConfig["Log start datetime"]); + date.setTime(date.getTime() + timeMillis); + + let trkpt = ``; + trkpt += `${altitude}`; + trkpt += ``; + trkpt += `${speed}`; + trkpt += `${groundCourse}`; + trkpt += `${numSat}`; + trkpt += `\n`; + + trkpts += trkpt; + } + } + + let trk = + ` + new + Flight + ${trkpts} + `; + + postMessage(header + "\n" + trk + "\n" + footer); +}; From 1fbd5fd1ea5b58c6b822a216784ed715d47d2d54 Mon Sep 17 00:00:00 2001 From: bonchan Date: Sun, 27 Nov 2022 21:40:15 -0300 Subject: [PATCH 2/7] Added GPX exporter --- css/main.css | 3 ++- js/main.js | 10 ++++----- js/webworkers/gpx-export-worker.js | 34 +++++++++++++++--------------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/css/main.css b/css/main.css index 3cf288e5..dff8f7ba 100644 --- a/css/main.css +++ b/css/main.css @@ -1224,7 +1224,8 @@ html:not(.has-log) #status-bar { } html:not(.has-gps) .view-map, -html:not(.has-gps) .map-container { +html:not(.has-gps) .map-container, +html:not(.has-gps) .btn-gpx-export { display: none !important; } diff --git a/js/main.js b/js/main.js index fdd68d8f..59905c40 100644 --- a/js/main.js +++ b/js/main.js @@ -111,12 +111,12 @@ function BlackboxLogViewer() { animationFrameIsQueued = false, playbackRate = PLAYBACK_DEFAULT_RATE, - + graphZoom = GRAPH_DEFAULT_ZOOM, lastGraphZoom = GRAPH_DEFAULT_ZOOM, // QuickZoom function. - + mapGrapher = new MapGrapher(); - + function createNewBlackboxWindow(fileToOpen) { @@ -309,7 +309,7 @@ function BlackboxLogViewer() { if(flightLog.hasGpsData()) { mapGrapher.resize(width, height); } - + invalidateGraph(); } } @@ -1151,7 +1151,7 @@ function BlackboxLogViewer() { $(".view-map").click(function() { hasMap = !hasMap; - html.toggleClass("has-map", hasMap); + html.toggleClass("has-map", hasMap); prefs.set('hasMap', hasMap); if(flightLog.hasGpsData()) { mapGrapher.initialize(userSettings); diff --git a/js/webworkers/gpx-export-worker.js b/js/webworkers/gpx-export-worker.js index e02db20b..c32cb5ba 100644 --- a/js/webworkers/gpx-export-worker.js +++ b/js/webworkers/gpx-export-worker.js @@ -1,18 +1,19 @@ importScripts("/node_modules/lodash/lodash.min.js"); onmessage = function (event) { - const header = ` - - - - Betaflight Blackbox Explorer - - - `; - - const footer = ""; + const header = ` + + + + + Betaflight Blackbox Explorer + + + `; + + const footer = ``; const timeIndex = event.data.fieldNames.indexOf("time"); const latIndex = event.data.fieldNames.indexOf("GPS_coord[0]"); @@ -49,12 +50,11 @@ onmessage = function (event) { } } - let trk = - ` - new - Flight + let trk = ` + ${trkpts} - `; + +`; postMessage(header + "\n" + trk + "\n" + footer); }; From fce322f973f344b4f2bad56f117972ef3f243ff3 Mon Sep 17 00:00:00 2001 From: bonchan Date: Wed, 30 Nov 2022 15:12:13 -0300 Subject: [PATCH 3/7] fixed sonar duplicated lines --- js/main.js | 39 +++++++++--------------------- js/webworkers/gpx-export-worker.js | 19 +++++++-------- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/js/main.js b/js/main.js index 59905c40..5abcfccf 100644 --- a/js/main.js +++ b/js/main.js @@ -918,47 +918,32 @@ function BlackboxLogViewer() { reader.readAsText(file); } - function exportCsv(file, options={}) { - - function onSuccess(data) { - console.debug("CSV export finished in", (performance.now() - startTime) / 1000, "secs"); + function createExportCallback(fileExtension, fileType, file, startTime) { + const callback = function(data) { + console.debug(`${fileExtension.toUpperCase()} export finished in ${(performance.now() - startTime) / 1000} secs`); if (!data) { console.debug("Empty data, nothing to save"); return; } - let blob = new Blob([data], {type: 'text/csv'}), + let blob = new Blob([data], {type: fileType}), e = document.createEvent('MouseEvents'), a = document.createElement('a'); - a.download = file || $(".log-filename").text() + ".csv"; + a.download = file || $(".log-filename").text() + "." + fileExtension; a.href = window.URL.createObjectURL(blob); - a.dataset.downloadurl = ['text/csv', a.download, a.href].join(':'); + a.dataset.downloadurl = [fileType, a.download, a.href].join(':'); e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); a.dispatchEvent(e); - } + } + return callback; + } - let startTime = performance.now(); + function exportCsv(file, options={}) { + const onSuccess = createExportCallback('csv', 'text/csv', file, performance.now()); CsvExporter(flightLog, options).dump(onSuccess); } function exportGpx(file) { - - function onSuccess(data) { - console.debug("Gpx export finished in", (performance.now() - startTime) / 1000, "secs"); - if (!data) { - console.debug("Empty data, nothing to save"); - return; - } - let blob = new Blob([data], {type: 'GPX File'}), - e = document.createEvent('MouseEvents'), - a = document.createElement('a'); - a.download = file || $(".log-filename").text() + ".gpx"; - a.href = window.URL.createObjectURL(blob); - a.dataset.downloadurl = ['GPX File', a.download, a.href].join(':'); - e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); - a.dispatchEvent(e); - } - - let startTime = performance.now(); + const onSuccess = createExportCallback('gpx', 'GPX File', file, performance.now()); GpxExporter(flightLog).dump(onSuccess); } diff --git a/js/webworkers/gpx-export-worker.js b/js/webworkers/gpx-export-worker.js index c32cb5ba..e3dd955b 100644 --- a/js/webworkers/gpx-export-worker.js +++ b/js/webworkers/gpx-export-worker.js @@ -1,8 +1,7 @@ importScripts("/node_modules/lodash/lodash.min.js"); onmessage = function (event) { - const header = ` - + const header = ` @@ -41,20 +40,20 @@ onmessage = function (event) { let trkpt = ``; trkpt += `${altitude}`; trkpt += ``; - trkpt += `${speed}`; - trkpt += `${groundCourse}`; - trkpt += `${numSat}`; + // trkpt += `${speed}`; + // trkpt += `${groundCourse}`; + // trkpt += `${numSat}`; trkpt += `\n`; trkpts += trkpt; } } - let trk = ` - - ${trkpts} - -`; + let trk = ` + + ${trkpts} + + `; postMessage(header + "\n" + trk + "\n" + footer); }; From bc9c2b17fb31e09ee29e6bcc913fe1b14fcc5193 Mon Sep 17 00:00:00 2001 From: bonchan Date: Wed, 30 Nov 2022 23:08:11 -0300 Subject: [PATCH 4/7] Update js/webworkers/gpx-export-worker.js: proper declaration of loop variables Co-authored-by: haslinghuis --- js/webworkers/gpx-export-worker.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/webworkers/gpx-export-worker.js b/js/webworkers/gpx-export-worker.js index e3dd955b..3e0c178d 100644 --- a/js/webworkers/gpx-export-worker.js +++ b/js/webworkers/gpx-export-worker.js @@ -23,8 +23,8 @@ onmessage = function (event) { const numSatIndex = event.data.fieldNames.indexOf("GPS_numSat"); let trkpts = ""; - for (var chunk of event.data.frames) { - for (var frame of chunk) { + for (const chunk of event.data.frames) { + for (const frame of chunk) { if (!frame[latIndex] || !frame[lngIndex]) continue; const timeMillis = Math.floor(frame[timeIndex] / 1000); const lat = frame[latIndex] / 10000000; From 6067137f85c4390c31ed7d53e2151973108a633a Mon Sep 17 00:00:00 2001 From: bonchan Date: Wed, 30 Nov 2022 23:14:24 -0300 Subject: [PATCH 5/7] removed unused code --- js/webworkers/gpx-export-worker.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/js/webworkers/gpx-export-worker.js b/js/webworkers/gpx-export-worker.js index 3e0c178d..fe972ffa 100644 --- a/js/webworkers/gpx-export-worker.js +++ b/js/webworkers/gpx-export-worker.js @@ -18,9 +18,6 @@ onmessage = function (event) { const latIndex = event.data.fieldNames.indexOf("GPS_coord[0]"); const lngIndex = event.data.fieldNames.indexOf("GPS_coord[1]"); const altitudeIndex = event.data.fieldNames.indexOf("GPS_altitude"); - const speedIndex = event.data.fieldNames.indexOf("GPS_speed"); - const groundCourseIndex = event.data.fieldNames.indexOf("GPS_ground_course"); - const numSatIndex = event.data.fieldNames.indexOf("GPS_numSat"); let trkpts = ""; for (const chunk of event.data.frames) { @@ -30,9 +27,6 @@ onmessage = function (event) { const lat = frame[latIndex] / 10000000; const lng = frame[lngIndex] / 10000000; const altitude = frame[altitudeIndex] / 10; - const speed = frame[speedIndex] / 100; - const groundCourse = frame[groundCourseIndex] / 10; - const numSat = frame[numSatIndex]; let date = new Date(event.data.sysConfig["Log start datetime"]); date.setTime(date.getTime() + timeMillis); @@ -40,9 +34,6 @@ onmessage = function (event) { let trkpt = ``; trkpt += `${altitude}`; trkpt += ``; - // trkpt += `${speed}`; - // trkpt += `${groundCourse}`; - // trkpt += `${numSat}`; trkpt += `\n`; trkpts += trkpt; From ffac50ebe19eb3f2d1005dc172565ccc403c119f Mon Sep 17 00:00:00 2001 From: bonchan Date: Wed, 30 Nov 2022 23:27:05 -0300 Subject: [PATCH 6/7] added missing semicolon --- js/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/main.js b/js/main.js index 5abcfccf..e3d489c7 100644 --- a/js/main.js +++ b/js/main.js @@ -933,7 +933,7 @@ function BlackboxLogViewer() { a.dataset.downloadurl = [fileType, a.download, a.href].join(':'); e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); a.dispatchEvent(e); - } + }; return callback; } From 725ab7206783a05a16d23fa090321784c8550dbb Mon Sep 17 00:00:00 2001 From: bonchan Date: Thu, 1 Dec 2022 01:40:45 -0300 Subject: [PATCH 7/7] added missing end of line & fixed sonar code smell --- js/csv-exporter.js | 2 +- js/gpx-exporter.js | 2 +- js/webworkers/csv-export-worker.js | 2 +- js/webworkers/gpx-export-worker.js | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/js/csv-exporter.js b/js/csv-exporter.js index cb76a196..39980acf 100644 --- a/js/csv-exporter.js +++ b/js/csv-exporter.js @@ -44,4 +44,4 @@ let CsvExporter = function(flightLog, opts={}) { return { dump: dump, }; -}; \ No newline at end of file +}; diff --git a/js/gpx-exporter.js b/js/gpx-exporter.js index 5d3ceb3d..55f2c101 100644 --- a/js/gpx-exporter.js +++ b/js/gpx-exporter.js @@ -29,4 +29,4 @@ let GpxExporter = function(flightLog) { return { dump: dump, }; -}; \ No newline at end of file +}; diff --git a/js/webworkers/csv-export-worker.js b/js/webworkers/csv-export-worker.js index ad734130..dd3d902c 100644 --- a/js/webworkers/csv-export-worker.js +++ b/js/webworkers/csv-export-worker.js @@ -42,4 +42,4 @@ onmessage = function(event) { postMessage(result); -}; \ No newline at end of file +}; diff --git a/js/webworkers/gpx-export-worker.js b/js/webworkers/gpx-export-worker.js index fe972ffa..94d2450b 100644 --- a/js/webworkers/gpx-export-worker.js +++ b/js/webworkers/gpx-export-worker.js @@ -22,7 +22,9 @@ onmessage = function (event) { let trkpts = ""; for (const chunk of event.data.frames) { for (const frame of chunk) { - if (!frame[latIndex] || !frame[lngIndex]) continue; + if (!frame[latIndex] || !frame[lngIndex]) { + continue; + } const timeMillis = Math.floor(frame[timeIndex] / 1000); const lat = frame[latIndex] / 10000000; const lng = frame[lngIndex] / 10000000;