Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ <h1>Welcome to the Enhanced Blackbox Explorer!</h1>
<a class="btn btn-primary btn-workspaces-export" data-toggle="tooltip" title="Export your workspace configurations to file">
Export Workspaces...</a>
<a class="btn btn-primary btn-csv-export" data-toggle="tooltip" title="Export your current graphs to CSV file"> Export CSV...</a>
<a class="btn btn-primary btn-gpx-export" data-toggle="tooltip" title="Export your flight to GPX file"> Export GPX...</a>
<span class="btn btn-primary btn-file" data-toggle="tooltip" title="Open another log file, video file, exported workspace file or configuration dump file">
Open log file/video
<input type="file" class="file-open" accept=".bbl,.txt,.cfl,.bfl,.log,.avi,.mov,.mp4,.mpeg,.json" multiple />
Expand Down Expand Up @@ -3152,6 +3153,7 @@ <h4 class="modal-title">Advanced User Settings</h4>
<script src="js/graph_spectrum.js"></script>
<script src="js/sticks.js"></script>
<script src="js/csv-exporter.js"></script>
<script src="js/gpx-exporter.js"></script>
<script src="js/gui.js"></script>
<script src="js/header_dialog.js"></script>
<script src="js/keys_dialog.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion js/csv-exporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ let CsvExporter = function(flightLog, opts={}) {
return {
dump: dump,
};
};
};
32 changes: 32 additions & 0 deletions js/gpx-exporter.js
Original file line number Diff line number Diff line change
@@ -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,
};
};
40 changes: 26 additions & 14 deletions js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

Expand Down Expand Up @@ -309,7 +309,7 @@ function BlackboxLogViewer() {
if(flightLog.hasGpsData()) {
mapGrapher.resize(width, height);
}

invalidateGraph();
}
}
Expand Down Expand Up @@ -918,28 +918,35 @@ 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) {
const onSuccess = createExportCallback('gpx', 'GPX File', file, performance.now());
GpxExporter(flightLog).dump(onSuccess);
}

function newGraphConfig(newConfig) {
lastGraphConfig = graphConfig; // Remember the last configuration.
graphConfig = newConfig;
Expand Down Expand Up @@ -1129,7 +1136,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);
Expand Down Expand Up @@ -1470,6 +1477,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) {
Expand Down
2 changes: 1 addition & 1 deletion js/webworkers/csv-export-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ onmessage = function(event) {

postMessage(result);

};
};
52 changes: 52 additions & 0 deletions js/webworkers/gpx-export-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
importScripts("/node_modules/lodash/lodash.min.js");

onmessage = function (event) {
const header = `<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd" xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2"
version="1.1"
creator="https://github.com/betaflight/blackbox-log-viewer">
<metadata>
<author>
<name>Betaflight Blackbox Explorer</name>
<link href="https://github.com/betaflight/blackbox-log-viewer"></link>
</author>
</metadata>`;

const footer = `</gpx>`;

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");

let trkpts = "";
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;
const lng = frame[lngIndex] / 10000000;
const altitude = frame[altitudeIndex] / 10;

let date = new Date(event.data.sysConfig["Log start datetime"]);
date.setTime(date.getTime() + timeMillis);

let trkpt = `<trkpt lat="${lat}" lon="${lng}">`;
trkpt += `<ele>${altitude}</ele>`;
trkpt += `<time>${date.toISOString()}</time>`;
trkpt += `</trkpt>\n`;

trkpts += trkpt;
}
}

let trk = ` <trk>
<trkseg>
${trkpts}
</trkseg>
</trk>`;

postMessage(header + "\n" + trk + "\n" + footer);
};