From 9be483861819c37a2df68c3b3162e87e8b0d7959 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Sat, 7 Oct 2017 22:15:21 -0400 Subject: [PATCH] Added "continuous logging" functionality. This is useful if you're having stability troubles and/or are worried about crashes. With traditional logging you can lose your capture if the program, CAN adapter, or computer crash before you've saved. With continuous logging the file is flushed to disk every couple of seconds so you won't lose more than a few seconds of log even during a crash. --- config.h | 2 +- framefileio.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++- framefileio.h | 9 ++++- mainwindow.cpp | 51 +++++++++++++++++++++++---- mainwindow.h | 4 +++ ui/mainwindow.ui | 25 ++++++++++++++ 6 files changed, 170 insertions(+), 10 deletions(-) diff --git a/config.h b/config.h index 1c2fbc8..26a8afa 100644 --- a/config.h +++ b/config.h @@ -1,7 +1,7 @@ #ifndef CONFIG #define CONFIG -#define VERSION 176 +#define VERSION 177 //try to keep this in sync. //SavvyCAN will complain if you connect a GVRET board with a revision diff --git a/framefileio.cpp b/framefileio.cpp index dcb20a4..f350e43 100644 --- a/framefileio.cpp +++ b/framefileio.cpp @@ -7,9 +7,10 @@ #include "utility.h" +QFile FrameFileIO::continuousFile; + FrameFileIO::FrameFileIO() { - } bool FrameFileIO::saveFrameFile(QString &fileName, const QVector* frameCache) @@ -611,6 +612,92 @@ bool FrameFileIO::saveNativeCSVFile(QString filename, const QVector* f return true; } +bool FrameFileIO::openContinuousNative() +{ + QString filename; + QFileDialog dialog(qApp->activeWindow()); + + QStringList filters; + filters.append(QString(tr("GVRET Logs (*.csv *.CSV)"))); + + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setNameFilters(filters); + dialog.setViewMode(QFileDialog::Detail); + dialog.setAcceptMode(QFileDialog::AcceptSave); + + if (dialog.exec() == QDialog::Accepted) + { + filename = dialog.selectedFiles()[0]; + continuousFile.setFileName(filename); + + if (!continuousFile.open(QIODevice::WriteOnly | QIODevice::Text)) + { + return false; + } + continuousFile.write("Time Stamp,ID,Extended,Dir,Bus,LEN,D1,D2,D3,D4,D5,D6,D7,D8"); + continuousFile.write("\n"); + return true; + } + return false; +} + +bool FrameFileIO::closeContinuousNative() +{ + if (continuousFile.isOpen()) + { + continuousFile.close(); + return true; + } + return false; +} + +bool FrameFileIO::writeContinuousNative(const QVector* frames, int beginningFrame) +{ + if (!continuousFile.isOpen()) return false; + qDebug() << "Bgn: " << beginningFrame << " Count: " << frames->count(); + for (int c = beginningFrame; c < frames->count(); c++) + { + continuousFile.write(QString::number(frames->at(c).timestamp).toUtf8()); + continuousFile.putChar(44); + + continuousFile.write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8()); + continuousFile.putChar(44); + + if (frames->at(c).extended) continuousFile.write("true,"); + else continuousFile.write("false,"); + + if (frames->at(c).isReceived) continuousFile.write("Rx,"); + else continuousFile.write("Tx,"); + + continuousFile.write(QString::number(frames->at(c).bus).toUtf8()); + continuousFile.putChar(44); + + continuousFile.write(QString::number(frames->at(c).len).toUtf8()); + continuousFile.putChar(44); + + for (unsigned int temp = 0; temp < 8; temp++) + { + if (temp < frames->at(c).len) + continuousFile.write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8()); + else + continuousFile.write("00"); + continuousFile.putChar(44); + } + + continuousFile.write("\n"); + } + return true; +} + +bool FrameFileIO::flushContinuousNative() +{ + if (continuousFile.isOpen()) + { + return continuousFile.flush(); + } + return false; +} + bool FrameFileIO::loadGenericCSVFile(QString filename, QVector* frames) { QFile *inFile = new QFile(filename); diff --git a/framefileio.h b/framefileio.h index 8d51cf6..c5c9ecc 100644 --- a/framefileio.h +++ b/framefileio.h @@ -42,7 +42,7 @@ public: static bool loadCanDumpFile(QString, QVector*); static bool loadPCANFile(QString, QVector*); static bool loadKvaserFile(QString, QVector*, bool); - static bool saveCRTDFile(QString, const QVector*); + static bool saveCRTDFile(QString, const QVector*); static bool saveNativeCSVFile(QString, const QVector*); static bool saveGenericCSVFile(QString, const QVector*); static bool saveLogFile(QString, const QVector*); @@ -51,6 +51,13 @@ public: static bool saveIXXATFile(QString, const QVector*); static bool saveCANDOFile(QString, const QVector*); static bool saveVehicleSpyFile(QString, const QVector*); + static bool openContinuousNative(); + static bool closeContinuousNative(); + static bool writeContinuousNative(const QVector*, int); + static bool flushContinuousNative(); + +private: + static QFile continuousFile; }; #endif // FRAMEFILEIO_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 1a45190..fa970ee 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -8,15 +8,8 @@ #include "utility.h" /* -Compile for all platforms and create release and make Win32 binary. - Some notes on things I'd like to put into the program but haven't put on github (yet) -Single / Multi state - The goal is to find bits that change based on toggles or discrete state items (shifters, etc) - -fuzzy scope - Try to find potential places where a given value might be stored - offer guesses and the program tries to find candidates for you -or, try to find things that appear to be multi-byte integers - Allow scripts to read/write signals from DBC files allow scripts to load DBC files in support of the script - maybe the graphing system too. */ @@ -88,6 +81,8 @@ MainWindow::MainWindow(QWidget *parent) : inhibitFilterUpdate = false; rxFrames = 0; framesPerSec = 0; + continuousLogging = false; + continuousLogFlushCounter = 0; connect(ui->actionSetup, SIGNAL(triggered(bool)), SLOT(showConnectionSettingsWindow())); connect(ui->actionOpen_Log_File, &QAction::triggered, this, &MainWindow::handleLoadFile); @@ -128,6 +123,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->actionMotorControlConfig, &QAction::triggered, this, &MainWindow::showMCConfigWindow); connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow); connect(ui->actionSignal_Viewer, &QAction::triggered, this, &MainWindow::showSignalViewer); + connect(ui->actionSave_Continuous_Logfile, &QAction::triggered, this, &MainWindow::handleContinousLogging); connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames); @@ -413,6 +409,30 @@ void MainWindow::tickGUIUpdate() if (model->needsFilterRefresh()) updateFilterList(); + if (continuousLogging) + { + const QVector *modelFrames = model->getListReference(); + FrameFileIO::writeContinuousNative(modelFrames, modelFrames->count() - rxFrames); + + continuousLogFlushCounter++; + if ((continuousLogFlushCounter % 3) == 0) + { + if (ui->lblContMsg->text().length() > 2) + { + ui->lblContMsg->setText(""); + } + else + { + ui->lblContMsg->setText("CONTINUOUS LOGGING"); + } + } + if (continuousLogFlushCounter > 8) + { + continuousLogFlushCounter = 0; + FrameFileIO::flushContinuousNative(); + } + } + rxFrames = 0; //} } @@ -493,6 +513,23 @@ void MainWindow::handleSaveFile() } } +void MainWindow::handleContinousLogging() +{ + continuousLogging = !continuousLogging; + + if (continuousLogging) + { + ui->actionSave_Continuous_Logfile->setText(tr("Cease Continuous Logging")); + FrameFileIO::openContinuousNative(); + } + else + { + ui->actionSave_Continuous_Logfile->setText(tr("Start Continuous Logging")); + ui->lblContMsg->setText(""); + FrameFileIO::closeContinuousNative(); + } +} + void MainWindow::handleSaveFilteredFile() { QString filename; diff --git a/mainwindow.h b/mainwindow.h index 920ba9a..9e70597 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -58,6 +58,7 @@ private slots: void handleSaveFilteredFile(); void handleSaveFilters(); void handleLoadFilters(); + void handleContinousLogging(); void showGraphingWindow(); void showFrameDataAnalysis(); void clearFrames(); @@ -132,6 +133,9 @@ private: bool bDirty; //have frames been added or subtracted since the last save/load? bool useFiltered; //should sub-windows use the unfiltered or filtered frames list? + bool continuousLogging; + int continuousLogFlushCounter; + //References to other windows we can display GraphingWindow *graphingWindow; FrameInfoWindow *frameInfoWindow; diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index 38ae67c..630c24b 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -49,6 +49,24 @@ + + + + + 11 + 75 + true + true + + + + + + + Qt::AlignCenter + + + @@ -240,6 +258,8 @@ + + @@ -428,6 +448,11 @@ Signal Viewer + + + Start Continuous Logging + +