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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cats-configurator",
"version": "0.3.8",
"version": "0.3.9",
"private": true,
"scripts": {
"start": "vue-cli-service electron:serve",
Expand Down
50 changes: 43 additions & 7 deletions src/modules/flightlog.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,60 @@
import fs from "fs";
import path from "path";
import { dialog } from "electron";
import { formatDateTime } from "@/utils/date.js";
import { flightLogFilename } from "./ipc.js";

export function exportFlightLogToCSVs(flightLog) {
const flightLogDir = "flight-log-export"
let flightLogSections = ["imu", "baro", "flightInfo", "orientationInfo", "filteredDataInfo", "gnssInfo", "flightStates", "eventInfo", "voltageInfo"];

if (!fs.existsSync(flightLogDir)) {
fs.mkdirSync(flightLogDir);
let paths = dialog.showOpenDialogSync({ properties: ["openDirectory"] });

if (!paths) {
throw new Error("No directory selected for export.");
}

const userFolderPath = path.join(paths[0]);
const exportFolderPath = `${userFolderPath}/${flightLogFilename}_export_${formatDateTime(new Date())}`;

fs.mkdirSync(`${exportFolderPath}`);

for (let flightLogSection of flightLogSections) {
fs.writeFile(`${flightLogDir}/${flightLogSection}.csv`, objectArrayToCSV(flightLogSection, flightLog[flightLogSection]), "utf8", function (err) {
fs.writeFile(`${exportFolderPath}/${flightLogSection}.csv`, objectArrayToCSV(flightLogSection, flightLog[flightLogSection]), "utf8", function (err) {
if (err) {
console.log("An error occurred while writing CSV object to file.");
return console.log(err);
throw new Error(`An error occurred while writing CSV object to file.`);
}
console.log("CSV file has been saved.");
});
}
}

export function exportFlightLogChartsToHTML(flightLogChartsHTML) {
let paths = dialog.showOpenDialogSync({ properties: ["openDirectory"] });

if (!paths) {
throw new Error("No directory selected for export.");
}

const exportFolderPath = path.join(paths[0]);

const flightLogHtmlDocument = `
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.plot.ly/plotly-2.18.2.min.js"></script>
</head>
<body>
${flightLogChartsHTML}
</body>
</html>
`;

fs.writeFile(`${exportFolderPath}/${flightLogFilename}_plots_${formatDateTime(new Date())}.html`, flightLogHtmlDocument, 'utf8', function (err) {
if (err) {
throw new Error(`An error occurred while writing HTML Object to File.`);
}
});
}

export function exportJSON(flightLog) {
fs.writeFile("flightlog.json", JSON.stringify(flightLog), "utf8", function (err) {
if (err) {
Expand Down
43 changes: 20 additions & 23 deletions src/modules/ipc.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { ipcMain, dialog } from "electron";
import fs from "fs";
import { parseFlightLog } from "./logparser.js"
import { exportFlightLogToCSVs } from "./flightlog.js"
import { exportFlightLogToCSVs, exportFlightLogChartsToHTML } from "./flightlog.js"
import { connect, disconnect, command, cliCommand, getList } from "./serial.js";
import { getFilename } from "../utils/file.js";

export let flightLogFilename = "";

export function subscribeListeners() {
ipcMain.on("BOARD:CONFIG", async (event, key) => {
Expand Down Expand Up @@ -59,6 +62,8 @@ export function subscribeListeners() {
return
}

flightLogFilename = getFilename(file.slice(0, -4)); // Remove the .cfl extension

let data = fs.readFileSync(file, { encoding: "binary" });
if (!data || !data.length) {
event.sender.send("LOAD_FLIGHTLOG", { error: "File is empty" });
Expand All @@ -70,29 +75,21 @@ export function subscribeListeners() {
});

ipcMain.on("EXPORT_FLIGHTLOG_CSVS", (event, flightLog) => {
exportFlightLogToCSVs(flightLog)
event.sender.send("EXPORT_FLIGHTLOG_CSVS");
});

ipcMain.on("EXPORT_FLIGHTLOG_HTML", (event, flightLogHtmlStr) => {

flightLogHtmlStr = `
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.plot.ly/plotly-2.18.2.min.js"></script>
</head>
<body>
` + flightLogHtmlStr + "</body></html>"
fs.writeFile("plots.html", flightLogHtmlStr, 'utf8', function (err) {
if (err) {
console.log("An error occurred while writing CSV Object to File.");
return console.log(err);
}
console.log("HTML file has been saved.");
});
try {
exportFlightLogToCSVs(flightLog)
event.sender.send("EXPORT_FLIGHTLOG_CSVS");
} catch (error) {
event.sender.send("EXPORT_FLIGHTLOG_CSVS", { error: error.message });
}
});

event.sender.send("EXPORT_FLIGHTLOG_HTML");
ipcMain.on("EXPORT_FLIGHTLOG_HTML", (event, flightLogChartsHTML) => {
try {
exportFlightLogChartsToHTML(flightLogChartsHTML);
event.sender.send("EXPORT_FLIGHTLOG_HTML");
} catch (error) {
event.sender.send("EXPORT_FLIGHTLOG_HTML", { error: error.message });
}
});

ipcMain.on("BOARD:RESET_CONFIG", () => {
Expand Down
2 changes: 0 additions & 2 deletions src/modules/logparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ function scaleAndOffsetFlightLog(flightLog) {

scaleProperty(flightLog.voltageInfo, 'voltage', 1000)

console.log(flightLog)

return flightLog;
}

Expand Down
10 changes: 8 additions & 2 deletions src/modules/serial.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,12 @@ function onData(data) {
if (currentCommand === "dump") {
if (data === "#Configuration dump") return;
else if (data === "#End of configuration dump") {
saveDumpDataToFile(backupConfig.trim());
sendToRenderer("BOARD:DUMP");
try {
saveDumpDataToFile(backupConfig.trim());
sendToRenderer("BOARD:DUMP");
} catch (error) {
return sendToRenderer("BOARD:DUMP", { error: error.message });
}
backupConfig = "";
} else backupConfig += data + "\n";

Expand Down Expand Up @@ -294,6 +298,8 @@ function saveDumpDataToFile(data) {
if (paths) {
const file = path.join(paths[0], "backup_cats_config.txt");
fs.writeFileSync(file, data);
} else {
throw new Error("No directory selected for backup.");
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ export default new Vuex.Store({
showSuccessSnackbar({ commit }, message) {
commit("SHOW_SNACKBAR", { message, color: "success" });
},
showErrorSnackbar({ commit }, message) {
commit("SHOW_SNACKBAR", { message, color: "error" });
},
hideSnackbar({ commit }) {
commit("HIDE_SNACKBAR");
},
Expand Down
15 changes: 15 additions & 0 deletions src/utils/date.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function formatDateTime(date) {
if (!(date instanceof Date)) {
console.error("Invalid date object provided.");
return "";
}

const options = { year: "numeric", month: "2-digit", day: "2-digit" };
const formattedDate = date
.toLocaleDateString("en-US", options)
.replace(/\//g, "");

const formattedTime = date.toLocaleTimeString("en-UK").replace(/:/g, "");

return `${formattedDate}_${formattedTime}`;
}
13 changes: 13 additions & 0 deletions src/utils/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export function getFilename(filePath) {
// Use a regex to split by either / or \ (to handle both Unix and Windows paths)
// Then pop the last element
const parts = filePath.split(/[\\/]/);
const filename = parts.pop();

// Handle cases where the path might end with a slash, resulting in an empty string
if (filename === '' && parts.length > 0) {
return parts.pop(); // Get the name of the directory itself
}

return filename;
}
13 changes: 9 additions & 4 deletions src/views/Config.vue
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,14 @@ export default {
},
mounted() {
this.init();
window.renderer.on("BOARD:DUMP", () => {
window.renderer.on("BOARD:DUMP", (result) => {
this.backupLoading = false
this.showSuccessSnackbar("Backup created!");
if (result?.error) {
this.showErrorSnackbar(`${result.error}`);
return;
} else {
this.showSuccessSnackbar("Backup created!");
}
});
window.renderer.on("BOARD:RESTORE", () => {
this.restoreLoading = false;
Expand All @@ -441,7 +446,7 @@ export default {
clearInterval(this.timer);
},
methods: {
...mapActions(["setChangedTab", "showSuccessSnackbar"]),
...mapActions(["setChangedTab", "showSuccessSnackbar", "showErrorSnackbar"]),
init() {
getConfigs();
this.getInfo();
Expand Down Expand Up @@ -480,7 +485,7 @@ export default {
},
resetConfig() {
const confirmed = window.confirm(
"Configuration is about to be reseted,\nwould you like to proceed?"
"Configuration is about to be reset to default values,\nwould you like to proceed?"
);

if (confirmed) {
Expand Down
20 changes: 15 additions & 5 deletions src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,27 @@ export default {

if (el) makePlots(flightLog, el, this.useImperialUnits);
});
window.renderer.on("EXPORT_FLIGHTLOG_CSVS", (flightLog) => {
window.renderer.on("EXPORT_FLIGHTLOG_CSVS", (result) => {
this.exportButtonLoading = false;
this.showSuccessSnackbar("Flight log CSVs exported!");
if (result?.error) {
this.showErrorSnackbar(`${result.error}`);
return;
} else {
this.showSuccessSnackbar("Flight log CSVs exported!");
}
});
window.renderer.on("EXPORT_FLIGHTLOG_HTML", (flightLog) => {
window.renderer.on("EXPORT_FLIGHTLOG_HTML", (result) => {
this.exportButtonLoading = false;
this.showSuccessSnackbar("Flight log HTML plots exported!");
if (result?.error) {
this.showErrorSnackbar(`${result.error}`);
return;
} else {
this.showSuccessSnackbar("Flight log HTML plots exported!");
}
});
},
methods: {
...mapActions(["showSuccessSnackbar"]),
...mapActions(["showSuccessSnackbar", "showErrorSnackbar"]),
loadFlightLog(file) {
this.loadButtonLoading = true;
this.flightLog = null
Expand Down
Loading