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.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CONFIG
|
#ifndef CONFIG
|
||||||
#define CONFIG
|
#define CONFIG
|
||||||
|
|
||||||
#define VERSION 176
|
#define VERSION 177
|
||||||
|
|
||||||
//try to keep this in sync.
|
//try to keep this in sync.
|
||||||
//SavvyCAN will complain if you connect a GVRET board with a revision
|
//SavvyCAN will complain if you connect a GVRET board with a revision
|
||||||
|
|||||||
+88
-1
@@ -7,9 +7,10 @@
|
|||||||
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
QFile FrameFileIO::continuousFile;
|
||||||
|
|
||||||
FrameFileIO::FrameFileIO()
|
FrameFileIO::FrameFileIO()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrameFileIO::saveFrameFile(QString &fileName, const QVector<CANFrame>* frameCache)
|
bool FrameFileIO::saveFrameFile(QString &fileName, const QVector<CANFrame>* frameCache)
|
||||||
@@ -611,6 +612,92 @@ bool FrameFileIO::saveNativeCSVFile(QString filename, const QVector<CANFrame>* f
|
|||||||
return true;
|
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<CANFrame>* 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<CANFrame>* frames)
|
bool FrameFileIO::loadGenericCSVFile(QString filename, QVector<CANFrame>* frames)
|
||||||
{
|
{
|
||||||
QFile *inFile = new QFile(filename);
|
QFile *inFile = new QFile(filename);
|
||||||
|
|||||||
@@ -51,6 +51,13 @@ public:
|
|||||||
static bool saveIXXATFile(QString, const QVector<CANFrame>*);
|
static bool saveIXXATFile(QString, const QVector<CANFrame>*);
|
||||||
static bool saveCANDOFile(QString, const QVector<CANFrame>*);
|
static bool saveCANDOFile(QString, const QVector<CANFrame>*);
|
||||||
static bool saveVehicleSpyFile(QString, const QVector<CANFrame>*);
|
static bool saveVehicleSpyFile(QString, const QVector<CANFrame>*);
|
||||||
|
static bool openContinuousNative();
|
||||||
|
static bool closeContinuousNative();
|
||||||
|
static bool writeContinuousNative(const QVector<CANFrame>*, int);
|
||||||
|
static bool flushContinuousNative();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QFile continuousFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FRAMEFILEIO_H
|
#endif // FRAMEFILEIO_H
|
||||||
|
|||||||
+44
-7
@@ -8,15 +8,8 @@
|
|||||||
#include "utility.h"
|
#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)
|
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 read/write signals from DBC files
|
||||||
allow scripts to load DBC files in support of the script - maybe the graphing system too.
|
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;
|
inhibitFilterUpdate = false;
|
||||||
rxFrames = 0;
|
rxFrames = 0;
|
||||||
framesPerSec = 0;
|
framesPerSec = 0;
|
||||||
|
continuousLogging = false;
|
||||||
|
continuousLogFlushCounter = 0;
|
||||||
|
|
||||||
connect(ui->actionSetup, SIGNAL(triggered(bool)), SLOT(showConnectionSettingsWindow()));
|
connect(ui->actionSetup, SIGNAL(triggered(bool)), SLOT(showConnectionSettingsWindow()));
|
||||||
connect(ui->actionOpen_Log_File, &QAction::triggered, this, &MainWindow::handleLoadFile);
|
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->actionMotorControlConfig, &QAction::triggered, this, &MainWindow::showMCConfigWindow);
|
||||||
connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow);
|
connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow);
|
||||||
connect(ui->actionSignal_Viewer, &QAction::triggered, this, &MainWindow::showSignalViewer);
|
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);
|
connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames);
|
||||||
|
|
||||||
@@ -413,6 +409,30 @@ void MainWindow::tickGUIUpdate()
|
|||||||
|
|
||||||
if (model->needsFilterRefresh()) updateFilterList();
|
if (model->needsFilterRefresh()) updateFilterList();
|
||||||
|
|
||||||
|
if (continuousLogging)
|
||||||
|
{
|
||||||
|
const QVector<CANFrame> *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;
|
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()
|
void MainWindow::handleSaveFilteredFile()
|
||||||
{
|
{
|
||||||
QString filename;
|
QString filename;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ private slots:
|
|||||||
void handleSaveFilteredFile();
|
void handleSaveFilteredFile();
|
||||||
void handleSaveFilters();
|
void handleSaveFilters();
|
||||||
void handleLoadFilters();
|
void handleLoadFilters();
|
||||||
|
void handleContinousLogging();
|
||||||
void showGraphingWindow();
|
void showGraphingWindow();
|
||||||
void showFrameDataAnalysis();
|
void showFrameDataAnalysis();
|
||||||
void clearFrames();
|
void clearFrames();
|
||||||
@@ -132,6 +133,9 @@ private:
|
|||||||
bool bDirty; //have frames been added or subtracted since the last save/load?
|
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 useFiltered; //should sub-windows use the unfiltered or filtered frames list?
|
||||||
|
|
||||||
|
bool continuousLogging;
|
||||||
|
int continuousLogFlushCounter;
|
||||||
|
|
||||||
//References to other windows we can display
|
//References to other windows we can display
|
||||||
GraphingWindow *graphingWindow;
|
GraphingWindow *graphingWindow;
|
||||||
FrameInfoWindow *frameInfoWindow;
|
FrameInfoWindow *frameInfoWindow;
|
||||||
|
|||||||
@@ -49,6 +49,24 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblContMsg">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>11</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<italic>true</italic>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item alignment="Qt::AlignHCenter">
|
<item alignment="Qt::AlignHCenter">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -240,6 +258,8 @@
|
|||||||
<addaction name="actionOpen_Log_File"/>
|
<addaction name="actionOpen_Log_File"/>
|
||||||
<addaction name="actionSave_Filtered_Log_File"/>
|
<addaction name="actionSave_Filtered_Log_File"/>
|
||||||
<addaction name="actionSave_Log_File"/>
|
<addaction name="actionSave_Log_File"/>
|
||||||
|
<addaction name="actionSave_Continuous_Logfile"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionLoad_Filter_Definition"/>
|
<addaction name="actionLoad_Filter_Definition"/>
|
||||||
<addaction name="actionSave_Filter_Definition"/>
|
<addaction name="actionSave_Filter_Definition"/>
|
||||||
@@ -428,6 +448,11 @@
|
|||||||
<string>Signal Viewer</string>
|
<string>Signal Viewer</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionSave_Continuous_Logfile">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start Continuous Logging</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
Reference in New Issue
Block a user