Added support for loading/saving trace files. Presumably this format
is from Vector in some fashion.
This commit is contained in:
+181
@@ -19,6 +19,7 @@ QString FrameFileIO::loadFrameFile(QVector<CANFrame>* frameCache)
|
|||||||
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
||||||
filters.append(QString(tr("BusMaster Log (*.log)")));
|
filters.append(QString(tr("BusMaster Log (*.log)")));
|
||||||
filters.append(QString(tr("Microchip Log (*.can)")));
|
filters.append(QString(tr("Microchip Log (*.can)")));
|
||||||
|
filters.append(QString(tr("Vector trace files (*.trace)")));
|
||||||
|
|
||||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
dialog.setNameFilters(filters);
|
dialog.setNameFilters(filters);
|
||||||
@@ -43,6 +44,7 @@ QString FrameFileIO::loadFrameFile(QVector<CANFrame>* frameCache)
|
|||||||
if (dialog.selectedNameFilter() == filters[2]) result = loadGenericCSVFile(filename, frameCache);
|
if (dialog.selectedNameFilter() == filters[2]) result = loadGenericCSVFile(filename, frameCache);
|
||||||
if (dialog.selectedNameFilter() == filters[3]) result = loadLogFile(filename, frameCache);
|
if (dialog.selectedNameFilter() == filters[3]) result = loadLogFile(filename, frameCache);
|
||||||
if (dialog.selectedNameFilter() == filters[4]) result = loadMicrochipFile(filename, frameCache);
|
if (dialog.selectedNameFilter() == filters[4]) result = loadMicrochipFile(filename, frameCache);
|
||||||
|
if (dialog.selectedNameFilter() == filters[5]) result = loadTraceFile(filename, frameCache);
|
||||||
|
|
||||||
progress.cancel();
|
progress.cancel();
|
||||||
|
|
||||||
@@ -658,3 +660,182 @@ bool FrameFileIO::saveMicrochipFile(QString filename, const QVector<CANFrame>* f
|
|||||||
delete outFile;
|
delete outFile;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
; CAN Logger trace file
|
||||||
|
; Device Serial Number :
|
||||||
|
; Start Time : Tue, Nov 17, 2015 :: 11:19:59
|
||||||
|
;
|
||||||
|
; Column description :
|
||||||
|
; ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
;
|
||||||
|
; + Message Number
|
||||||
|
; |
|
||||||
|
; | + Time Stamp (ms)
|
||||||
|
; | |
|
||||||
|
; | | + Message ID (hex)
|
||||||
|
; | | |
|
||||||
|
; | | | + Data Length Code
|
||||||
|
; | | | |
|
||||||
|
; | | | | + Data Bytes (hex)
|
||||||
|
; | | | | |
|
||||||
|
;---+----- -----+------ ----+--- + -+ -- -- -- -- -- -- --
|
||||||
|
0 00:00:00:0008 00000268 8 55 00 84 03 A8 0D 38 00
|
||||||
|
1 00:00:00:0021 0000000E 8 1F D3 3F FF 08 FF E0 CB
|
||||||
|
|
||||||
|
It appears that all lines that start in a semicolon are comments
|
||||||
|
The rest of the lines need the whitespace stripped from beginning and end
|
||||||
|
and then it appears to be tab delimited. The first field is a sequence number
|
||||||
|
and irrelevant. The second field is a funky timestamp, then message id, etc as
|
||||||
|
shown in the file comments. The bytes seem to be space delimited and in hex
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool FrameFileIO::loadTraceFile(QString filename, QVector<CANFrame>* frames)
|
||||||
|
{
|
||||||
|
QFile *inFile = new QFile(filename);
|
||||||
|
CANFrame thisFrame;
|
||||||
|
QByteArray line;
|
||||||
|
long long timeStamp = 0;
|
||||||
|
int lineCounter = 0;
|
||||||
|
|
||||||
|
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
delete inFile;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!inFile->atEnd()) {
|
||||||
|
lineCounter++;
|
||||||
|
if (lineCounter > 100)
|
||||||
|
{
|
||||||
|
qApp->processEvents();
|
||||||
|
lineCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = inFile->readLine();
|
||||||
|
line = line.trimmed();
|
||||||
|
if (line.length() > 2)
|
||||||
|
{
|
||||||
|
if (line.startsWith(";"))
|
||||||
|
{
|
||||||
|
// a comment. Ignore it.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QList<QByteArray> tokens = line.split('\t');
|
||||||
|
|
||||||
|
QList<QByteArray> timestampToks = tokens[1].split(':');
|
||||||
|
|
||||||
|
timeStamp = timestampToks[0].toInt() * 1000000ul * 60 * 60;
|
||||||
|
timeStamp += timestampToks[1].toInt() * 1000000ul * 60;
|
||||||
|
timeStamp += timestampToks[2].toInt() * 1000000ul;
|
||||||
|
timeStamp += timestampToks[3].toInt() * 100;
|
||||||
|
|
||||||
|
thisFrame.timestamp = timeStamp;
|
||||||
|
|
||||||
|
thisFrame.ID = tokens[2].toLong(NULL, 16);
|
||||||
|
if (thisFrame.ID <= 0x7FF) thisFrame.extended = false;
|
||||||
|
else thisFrame.extended = true;
|
||||||
|
thisFrame.bus = 0;
|
||||||
|
thisFrame.len = tokens[3].toInt();
|
||||||
|
|
||||||
|
QList<QByteArray> dataToks = tokens[4].split(' ');
|
||||||
|
for (int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = (unsigned char)dataToks[d].toInt(NULL, 16);
|
||||||
|
frames->append(thisFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inFile->close();
|
||||||
|
delete inFile;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FrameFileIO::saveTraceFile(QString filename, const QVector<CANFrame> * frames)
|
||||||
|
{
|
||||||
|
QFile *outFile = new QFile(filename);
|
||||||
|
QDateTime timestamp;
|
||||||
|
int lineCounter = 0;
|
||||||
|
uint64_t tempTime;
|
||||||
|
int tempTimePiece;
|
||||||
|
|
||||||
|
timestamp = QDateTime::currentDateTime();
|
||||||
|
|
||||||
|
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
delete outFile;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile->write("; SavvyCAN CAN Logger trace file\n");
|
||||||
|
outFile->write("; Device Serial Number : 0000 \n");
|
||||||
|
outFile->write("; Start Time : ");
|
||||||
|
outFile->write(timestamp.toString("ddd, MMM dd, yyyy :: h:m:s\n").toUtf8());
|
||||||
|
outFile->write(";\n");
|
||||||
|
outFile->write("; Column description :\n");
|
||||||
|
outFile->write("; ~~~~~~~~~~~~~~~~~~~~~\n");
|
||||||
|
outFile->write(";\n");
|
||||||
|
outFile->write("; + Message Number\n");
|
||||||
|
outFile->write("; |\n");
|
||||||
|
outFile->write("; | + Time Stamp (ms)\n");
|
||||||
|
outFile->write("; | |\n");
|
||||||
|
outFile->write("; | | + Message ID (hex)\n");
|
||||||
|
outFile->write("; | | |\n");
|
||||||
|
outFile->write("; | | | + Data Length Code\n");
|
||||||
|
outFile->write("; | | | |\n");
|
||||||
|
outFile->write("; | | | | + Data Bytes (hex)\n");
|
||||||
|
outFile->write("; | | | | |\n");
|
||||||
|
outFile->write(";---+----- -----+------ ----+--- + -+ -- -- -- -- -- -- --\n");
|
||||||
|
|
||||||
|
|
||||||
|
for (int c = 0; c < frames->count(); c++)
|
||||||
|
{
|
||||||
|
lineCounter++;
|
||||||
|
if ((lineCounter % 100) == 0)
|
||||||
|
{
|
||||||
|
qApp->processEvents();
|
||||||
|
//lineCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//1F D3 3F FF 08 FF E0 CB
|
||||||
|
outFile->write(QString::number(lineCounter).rightJustified(10, ' ').toUtf8());
|
||||||
|
outFile->write("\t");
|
||||||
|
|
||||||
|
tempTime = frames->at(c).timestamp;
|
||||||
|
tempTimePiece = tempTime / 1000000ul / 60 / 60;
|
||||||
|
tempTime -= tempTimePiece * 1000000ul * 60 * 60;
|
||||||
|
outFile->write(QString::number(tempTimePiece).rightJustified(2, '0').toUtf8());
|
||||||
|
outFile->write(":");
|
||||||
|
|
||||||
|
tempTimePiece = tempTime / 1000000ul / 60;
|
||||||
|
tempTime -= tempTimePiece * 1000000ul * 60;
|
||||||
|
outFile->write(QString::number(tempTimePiece).rightJustified(2, '0').toUtf8());
|
||||||
|
outFile->write(":");
|
||||||
|
|
||||||
|
tempTimePiece = tempTime / 1000000ul;
|
||||||
|
tempTime -= tempTimePiece * 1000000ul;
|
||||||
|
outFile->write(QString::number(tempTimePiece).rightJustified(2, '0').toUtf8());
|
||||||
|
outFile->write(":");
|
||||||
|
|
||||||
|
tempTimePiece = tempTime / 100;
|
||||||
|
outFile->write(QString::number(tempTimePiece).rightJustified(4, '0').toUtf8());
|
||||||
|
outFile->write("\t");
|
||||||
|
|
||||||
|
outFile->write(QString::number(frames->at(c).ID, 16).toUpper().rightJustified(8, '0').toUtf8() + "\t");
|
||||||
|
|
||||||
|
outFile->write(QString::number(frames->at(c).len).toUtf8() + "\t");
|
||||||
|
|
||||||
|
for (int temp = 0; temp < frames->at(c).len; temp++)
|
||||||
|
{
|
||||||
|
outFile->write(QString::number(frames->at(c).data[temp], 16).toUpper().rightJustified(2, '0').toUtf8());
|
||||||
|
outFile->putChar(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile->write("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
outFile->close();
|
||||||
|
delete outFile;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ public:
|
|||||||
static bool loadGenericCSVFile(QString, QVector<CANFrame>*);
|
static bool loadGenericCSVFile(QString, QVector<CANFrame>*);
|
||||||
static bool loadLogFile(QString, QVector<CANFrame>*);
|
static bool loadLogFile(QString, QVector<CANFrame>*);
|
||||||
static bool loadMicrochipFile(QString, QVector<CANFrame>*);
|
static bool loadMicrochipFile(QString, QVector<CANFrame>*);
|
||||||
|
static bool loadTraceFile(QString, QVector<CANFrame>*);
|
||||||
static bool saveCRTDFile(QString, const QVector<CANFrame>*);
|
static bool saveCRTDFile(QString, const QVector<CANFrame>*);
|
||||||
static bool saveNativeCSVFile(QString, const QVector<CANFrame>*);
|
static bool saveNativeCSVFile(QString, const QVector<CANFrame>*);
|
||||||
static bool saveGenericCSVFile(QString, const QVector<CANFrame>*);
|
static bool saveGenericCSVFile(QString, const QVector<CANFrame>*);
|
||||||
static bool saveLogFile(QString, const QVector<CANFrame>*);
|
static bool saveLogFile(QString, const QVector<CANFrame>*);
|
||||||
static bool saveMicrochipFile(QString, const QVector<CANFrame>*);
|
static bool saveMicrochipFile(QString, const QVector<CANFrame>*);
|
||||||
|
static bool saveTraceFile(QString, const QVector<CANFrame>*);
|
||||||
static QString loadFrameFile(QVector<CANFrame>*);
|
static QString loadFrameFile(QVector<CANFrame>*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -455,6 +455,7 @@ void MainWindow::handleLoadFile()
|
|||||||
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
||||||
filters.append(QString(tr("BusMaster Log (*.log)")));
|
filters.append(QString(tr("BusMaster Log (*.log)")));
|
||||||
filters.append(QString(tr("Microchip Log (*.can)")));
|
filters.append(QString(tr("Microchip Log (*.can)")));
|
||||||
|
filters.append(QString(tr("Vector Trace Files (*.trace)")));
|
||||||
|
|
||||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
dialog.setNameFilters(filters);
|
dialog.setNameFilters(filters);
|
||||||
@@ -483,6 +484,7 @@ void MainWindow::handleLoadFile()
|
|||||||
if (dialog.selectedNameFilter() == filters[2]) result = FrameFileIO::loadGenericCSVFile(filename, &tempFrames);
|
if (dialog.selectedNameFilter() == filters[2]) result = FrameFileIO::loadGenericCSVFile(filename, &tempFrames);
|
||||||
if (dialog.selectedNameFilter() == filters[3]) result = FrameFileIO::loadLogFile(filename, &tempFrames);
|
if (dialog.selectedNameFilter() == filters[3]) result = FrameFileIO::loadLogFile(filename, &tempFrames);
|
||||||
if (dialog.selectedNameFilter() == filters[4]) result = FrameFileIO::loadMicrochipFile(filename, &tempFrames);
|
if (dialog.selectedNameFilter() == filters[4]) result = FrameFileIO::loadMicrochipFile(filename, &tempFrames);
|
||||||
|
if (dialog.selectedNameFilter() == filters[5]) result = FrameFileIO::loadTraceFile(filename, &tempFrames);
|
||||||
|
|
||||||
progress.cancel();
|
progress.cancel();
|
||||||
|
|
||||||
@@ -515,6 +517,7 @@ void MainWindow::handleSaveFile()
|
|||||||
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
||||||
filters.append(QString(tr("BusMaster Log (*.log)")));
|
filters.append(QString(tr("BusMaster Log (*.log)")));
|
||||||
filters.append(QString(tr("Microchip Log (*.can)")));
|
filters.append(QString(tr("Microchip Log (*.can)")));
|
||||||
|
filters.append(QString(tr("Vector Trace Files (*.trace)")));
|
||||||
|
|
||||||
dialog.setFileMode(QFileDialog::AnyFile);
|
dialog.setFileMode(QFileDialog::AnyFile);
|
||||||
dialog.setNameFilters(filters);
|
dialog.setNameFilters(filters);
|
||||||
@@ -562,6 +565,12 @@ void MainWindow::handleSaveFile()
|
|||||||
result = FrameFileIO::saveMicrochipFile(filename, frames);
|
result = FrameFileIO::saveMicrochipFile(filename, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dialog.selectedNameFilter() == filters[5])
|
||||||
|
{
|
||||||
|
if (!filename.contains('.')) filename += ".trace";
|
||||||
|
result = FrameFileIO::saveTraceFile(filename, frames);
|
||||||
|
}
|
||||||
|
|
||||||
progress.cancel();
|
progress.cancel();
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
@@ -585,6 +594,7 @@ void MainWindow::handleSaveFilteredFile()
|
|||||||
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
filters.append(QString(tr("Generic ID/Data CSV (*.csv)")));
|
||||||
filters.append(QString(tr("BusMaster Log (*.log)")));
|
filters.append(QString(tr("BusMaster Log (*.log)")));
|
||||||
filters.append(QString(tr("Microchip Log (*.log)")));
|
filters.append(QString(tr("Microchip Log (*.log)")));
|
||||||
|
filters.append(QString(tr("Vector Trace Files (*.trace)")));
|
||||||
|
|
||||||
dialog.setFileMode(QFileDialog::AnyFile);
|
dialog.setFileMode(QFileDialog::AnyFile);
|
||||||
dialog.setNameFilters(filters);
|
dialog.setNameFilters(filters);
|
||||||
@@ -632,6 +642,12 @@ void MainWindow::handleSaveFilteredFile()
|
|||||||
result = FrameFileIO::saveMicrochipFile(filename, frames);
|
result = FrameFileIO::saveMicrochipFile(filename, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dialog.selectedNameFilter() == filters[5])
|
||||||
|
{
|
||||||
|
if (!filename.contains('.')) filename += ".trace";
|
||||||
|
result = FrameFileIO::saveTraceFile(filename, frames);
|
||||||
|
}
|
||||||
|
|
||||||
progress.cancel();
|
progress.cancel();
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
|
|||||||
Reference in New Issue
Block a user