Merge pull request #1 from collin80/master

Pull upstream changes
This commit is contained in:
tcfx44
2024-07-04 01:17:37 +03:00
committed by GitHub
150 changed files with 10525 additions and 3258 deletions
+376 -208
View File
@@ -369,16 +369,6 @@ bool FrameFileIO::autoDetectLoadFile(QString filename, QVector<CANFrame>* frames
}
}
qDebug() << "Attempting lawicel";
if (isLawicelFile(filename))
{
if (loadLawicelFile(filename, frames))
{
qDebug() << "Loaded as lawicel successfully!";
return true;
}
}
qDebug() << "Attempting 'CARBUS Analyzer'";
if (isCARBUSAnalyzerFile(filename))
{
@@ -494,6 +484,16 @@ bool FrameFileIO::autoDetectLoadFile(QString filename, QVector<CANFrame>* frames
}
}
qDebug() << "Attempting lawicel";
if (isLawicelFile(filename))
{
if (loadLawicelFile(filename, frames))
{
qDebug() << "Loaded as lawicel successfully!";
return true;
}
}
qDebug() << "Attempting generic CSV";
if (isGenericCSVFile(filename))
{
@@ -867,7 +867,7 @@ bool FrameFileIO::loadCARBUSAnalyzerFile(QString filename, QVector<CANFrame>* fr
line = txt.readLine().simplified();
if (line.length() > 2)
{
QList<QString> tokens = line.split(QRegExp("\\s+"));
QList<QString> tokens = line.split(QRegularExpression("\\s+"));
if (tokens.length() > 3)
{
QString time = tokens[0].replace(",", "");
@@ -1054,7 +1054,7 @@ bool FrameFileIO::isCANHackerFile(QString filename)
// CANHacker trace format
// Time ID DLC Data Comment
// 00.000 00004000 8 36 47 19 43 01 00 00 80
// 00[.|,]000 00004000 8 36 47 19 43 01 00 00 80
bool FrameFileIO::loadCANHackerFile(QString filename, QVector<CANFrame>* frames)
{
QFile *inFile = new QFile(filename);
@@ -1062,6 +1062,9 @@ bool FrameFileIO::loadCANHackerFile(QString filename, QVector<CANFrame>* frames)
QByteArray line;
int lineCounter = 0;
bool foundErrors = false;
int addendumTime = 0;
double previousTime = 0;
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
{
@@ -1086,6 +1089,11 @@ bool FrameFileIO::loadCANHackerFile(QString filename, QVector<CANFrame>* frames)
if (tokens.length() > 3)
{
int idxOfDecimal = tokens[0].indexOf('.');
// If no dot is found, try comma
if(idxOfDecimal == -1)
{
idxOfDecimal = tokens[0].indexOf(',');
}
if (idxOfDecimal > -1) {
//int decimalPlaces = tokens[0].length() - tokens[0].indexOf('.') - 1;
//the result of the above is the # of digits after the decimal.
@@ -1097,7 +1105,11 @@ bool FrameFileIO::loadCANHackerFile(QString filename, QVector<CANFrame>* frames)
multiplier = 1; //special case. Assume no decimal means microseconds
}
//qDebug() << "decimal places " << decimalPlaces;
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<uint64_t>(tokens[0].toDouble() * multiplier)));
if (previousTime > tokens[0].toDouble()) {
addendumTime += 60;
}
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<uint64_t>((tokens[0].toDouble() + addendumTime) * multiplier)));
previousTime = tokens[0].toDouble();
thisFrame.setFrameId( static_cast<uint32_t>(tokens[1].toInt(nullptr, 16)) );
thisFrame.setExtendedFrameFormat((thisFrame.frameId() > 0x7FF));
thisFrame.isReceived = true;
@@ -1369,8 +1381,17 @@ bool FrameFileIO::isPCANFile(QString filename)
;---+-- ------+------ +- --+----- +- +- +- +- -- -- -- -- -- -- --
0-6 8-20 22-23 25-32 34-35 37-38 40-? two chars each + space
Both versions are supported now but rather lazily. Very many aspects of the file are ignored.
Version 2.1
; Message Time Type ID Rx/Tx
; Number Offset | Bus [hex] | Reserved
; | [ms] | | | | | Data Length Code
; | | | | | | | | Data [hex] ...
; | | | | | | | | |
;---+--- ------+------ +- +- --+----- +- +- +--- +- -- -- -- -- -- -- --
0 1 2 3 4 5 6 7 8 +
It seems as if Version 2 files might be able to store other protocols like ISO-TP or J1939
*/
bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
{
@@ -1395,10 +1416,14 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
lineCounter = 0;
}
line = inFile->readLine();
if (line.startsWith(";$FILEVERSION=2.0")) fileVersion = 20;
if (line.startsWith(";$FILEVERSION=1.3")) fileVersion = 13;
if (line.startsWith(";$FILEVERSION=1.1")) fileVersion = 11;
if (line.startsWith(';')) continue;
if (line.startsWith(';'))
{
if (line.contains("$FILEVERSION=2.1")) fileVersion = 21;
if (line.contains("$FILEVERSION=2.0")) fileVersion = 20;
if (line.contains("$FILEVERSION=1.3")) fileVersion = 13;
if (line.contains("$FILEVERSION=1.1")) fileVersion = 11;
continue;
}
if (line.length() > 41)
{
line = line.simplified();
@@ -1459,7 +1484,7 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
if (tokens.length() > 6)
{
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<uint64_t>(tokens[1].toDouble() * 1000.0)));
thisFrame.setFrameId(tokens[3].toUInt(nullptr, 16));
thisFrame.setFrameId(tokens[4].toUInt(nullptr, 16));
if (thisFrame.frameId() < 0x1FFFFFFF)
{
int numBytes = tokens[6].toInt();
@@ -1538,6 +1563,58 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector<CANFrame>* frames)
}
}
}
/*
Version 2.1
; Message Time Type ID Rx/Tx
; Number Offset | Bus [hex] | Reserved
; | [ms] | | | | | Data Length Code
; | | | | | | | | Data [hex] ...
; | | | | | | | | |
;---+--- ------+------ +- +- --+----- +- +- +--- +- -- -- -- -- -- -- --
0 1 2 3 4 5 6 7 8 +
*/
else if (fileVersion == 21)
{
if (tokens.length() > 7)
{
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<uint64_t>(tokens[1].toDouble() * 1000.0)));
thisFrame.setFrameId(tokens[4].toUInt(nullptr, 16));
if (thisFrame.frameId() < 0x1FFFFFFF)
{
int numBytes = tokens[7].toInt();
QByteArray bytes(numBytes, 0);
//qDebug() << thisFrame.payload().length();
thisFrame.isReceived = true;
thisFrame.bus = tokens[3].toInt();
if (thisFrame.frameId() > 0x10000000)
{
thisFrame.setExtendedFrameFormat(true);
}
else
{
thisFrame.setExtendedFrameFormat(false);
}
if (tokens[2] == "R")
{
thisFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
}
else
{
thisFrame.setFrameType(QCanBusFrame::DataFrame);
for (int d = 0; d < numBytes; d++)
{
if (tokens[d + 8] != "")
{
bytes[d] = static_cast<char>(tokens[d + 8].toInt(nullptr, 16));
}
else bytes[d] = 0;
}
}
thisFrame.setPayload(bytes);
frames->append(thisFrame);
}
}
}
}
//else foundErrors = true;
}
@@ -1551,9 +1628,9 @@ bool FrameFileIO::isCanalyzerASC(QString filename)
{
QFile *inFile = new QFile(filename);
QByteArray line;
int lineCounter = 0;
//int lineCounter = 0;
//bool inHeader = true;
bool isMatch = true;
bool inHeader = true;
QList<QByteArray> tokens;
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
@@ -1596,15 +1673,23 @@ bool FrameFileIO::isCanalyzerASC(QString filename)
//There tends to be four lines of header first. The last of which starts with // so first burn off lines
//until a line starting with // is seen, then the rest are formatted like this:
//Version 8.0:
// 47.971842 2 248 Rx d 8 FF FF FF FF FF FF FF FF
//version 8.1
//47244640.194244 CANFD 1 Rx 122 0 0 6 6 00 00 18 12 D2 00 0 0 200000 0 0 0 0 0
//That can be simplified to look like this:
//47.971842 2 248 Rx d 8 FF FF FF FF FF FF FF FF
//version 8.1
//47244640.194244 CANFD 1 Rx 122 0 0 6 6 00 00 18 12 D2 00 0 0 200000 0 0 0 0 0
//Which is then easy to parse by splitting on the spaces
//Time bus id dir ? len databytes (Ver 8.0)
//Time type bus dir ID ? ? length length bytes then many values of unknown type (ver 8.1)
//Version 9.0
//0.001371 CANFD 1 Rx 171 A0066_Unknown 0 0 8 8 00 00 07 76 23 00 00 00 230199 119 220000 62e7 46500250 460a0250 20011736 20010205
//Version 16.0.0
//0.008600 1 358 Rx d 8 04 03 50 01 F0 40 54 2C Length = 233910 BitCount = 121 ID = 856
//Version 17.3.0
//0.001684 CANFD 1 Rx 65b 1 0 d 32 f1 01 00 00 50 00 00 00 00 00 00 00 00 00 00 40 00 88 f5 77 17 78 00 00 c0 03 00 00 00 00 00 00 213797 356 303000 11729 46500250 4b140250 20011736 2001040d
//Time bus id dir ? len databytes (Ver 8.0)
//Time bus id dir ? len databytes (addl info) (ver 16.0)
//Time type bus dir ID ? ? length length (bytes) (many values of unknown type) (ver 8.1)
//Time type bus dir ID SignalName ? ? length length bytes (then many values of unknown type)(ver 9.0)
//Time Type Bus Dir ID ? ? (length) (Real Length) (bytes) (many values of unknown type) (Ver 17.3)
//0 1 2 3 4 5 6 7 8 9 10
//This seems like a rather eclectic mix. It's almost arbitrary!
bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
{
QFile *inFile = new QFile(filename);
@@ -1638,7 +1723,6 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
{
if (line.startsWith("//"))
{
// version 8.1.0
line = line.right(line.length() - 11);
QList<QByteArray> versionTokens = line.split('.');
if (versionTokens.length() > 2)
@@ -1646,6 +1730,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
verMajor = versionTokens[0].toInt();
verMinor = versionTokens[1].toInt();
verRevision = versionTokens[2].toInt();
qDebug() << "Major: " << verMajor << " Minor:" << verMinor << " Rev:" << verRevision;
}
}
if (line.startsWith("//") || lineCounter > 4)
@@ -1655,115 +1740,135 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
}
}
if (inHeader) continue;
if (line.length() > 2)
if (line.length() > 2 && !line.startsWith("//"))
{
tokens = line.simplified().split(' ');
if (verMajor == 8 && verMinor == 0)
if (tokens[0].contains("Begin")) continue; //probably begin triggerblock but we're ignoring that.
//try to do some investigating to see if this line is a CAN frame or not. The file format has many other potential line types it seems...
if (tokens.length() > 5)
{
if (tokens.length() > 5)
if (tokens[3].toUpper().startsWith("RX") || tokens[3].toUpper().startsWith("TX"))
{
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<uint64_t>(tokens[0].toDouble() * 1000000.0)));
if (tokens[2].endsWith('x'))
if (tokens[1].contains("CAN")) //the different format I haven't seen a whole lot of, seems to support CANFD in this format
{
QByteArray copied_id = tokens[2];
copied_id.chop(1);
thisFrame.setFrameId(copied_id.toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(true);
if (tokens[4].endsWith('x'))
{
QByteArray copied_id = tokens[4];
copied_id.chop(1);
thisFrame.setFrameId(copied_id.toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(true);
}
else
{
thisFrame.setFrameId(tokens[4].toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(thisFrame.frameId() > 0x7FF); //some .asc files have extended IDs without 'x'
}
int payloadLen = tokens[8].toInt();
qDebug() << "PayloadLen: " << payloadLen << " Tokens: " << tokens;
QByteArray bytes(payloadLen, 0);
if (payloadLen > 64)
{
qDebug() << "Payload length too long. Original line: " << line;
return false;
}
if (payloadLen < 0)
{
qDebug() << "Payload length negative! Original line: " << line;
return false;
}
thisFrame.isReceived = tokens[3].toUpper().contains("RX");
thisFrame.bus = tokens[2].toInt();
if (tokens[5].at(0) >= '0' && tokens[5].at(0) <= '9')
{
for (int d = 9; d < (9 + payloadLen); d++)
{
if (tokens.count() > d)
{
bytes[d - 9] = static_cast<char>(tokens[d].toInt(nullptr, 16));
}
else //expected byte wasn't there to read. Set it zero and set error flag
{
bytes[d - 9] = 0;
foundErrors = true;
qDebug() << "D:" << d << " Count:" << tokens.count();
qDebug() << "Expected byte missing! Original line: " << line;
}
}
thisFrame.setPayload(bytes);
}
else
{
for (int d = 10; d < (10 + payloadLen); d++)
{
if (tokens.count() > d)
{
bytes[d - 10] = static_cast<char>(tokens[d].toInt(nullptr, 16));
}
else //expected byte wasn't there to read. Set it zero and set error flag
{
bytes[d - 10] = 0;
foundErrors = true;
qDebug() << "D:" << d << " Count:" << tokens.count();
qDebug() << "Expected byte missing! Original line: " << line;
}
}
thisFrame.setPayload(bytes);
}
}
else
{
thisFrame.setFrameId(tokens[2].toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(thisFrame.frameId() > 0x7FF); //some .asc files have extended IDs without 'x'
}
int payloadLen = tokens[5].toInt();
QByteArray bytes(payloadLen, 0);
if (payloadLen > 8)
{
qDebug() << "Payload length too long. Original line: " << line;
return false;
}
if (payloadLen < 0)
{
qDebug() << "Payload length negative! Original line: " << line;
return false;
}
thisFrame.isReceived = tokens[3].toUpper().contains("RX");
thisFrame.bus = tokens[1].toInt();
if (tokens[4] == "r") thisFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
for (int d = 6; d < (6 + payloadLen); d++)
{
if (tokens.count() > d)
int payloadLen = tokens[5].toInt();
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<uint64_t>(tokens[0].toDouble() * 1000000.0)));
if (tokens[2].endsWith('x'))
{
bytes[d - 6] = static_cast<char>(tokens[d].toInt(nullptr, 16));
QByteArray copied_id = tokens[2];
copied_id.chop(1);
thisFrame.setFrameId(copied_id.toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(true);
}
else //expected byte wasn't there to read. Set it zero and set error flag
else
{
bytes[d - 6] = 0;
foundErrors = true;
qDebug() << "D:" << d << " Count:" << tokens.count();
qDebug() << "Expected byte missing! Original line: " << line;
thisFrame.setFrameId(tokens[2].toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(thisFrame.frameId() > 0x7FF); //some .asc files have extended IDs without 'x'
}
QByteArray bytes(payloadLen, 0);
if (payloadLen > 8)
{
qDebug() << "Payload length too long. Original line: " << line;
return false;
}
if (payloadLen < 0)
{
qDebug() << "Payload length negative! Original line: " << line;
return false;
}
thisFrame.isReceived = tokens[3].toUpper().contains("RX");
thisFrame.bus = tokens[1].toInt();
if (tokens[4] == "r") thisFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
for (int d = 6; d < (6 + payloadLen); d++)
{
if (tokens.count() > d)
{
bytes[d - 6] = static_cast<char>(tokens[d].toInt(nullptr, 16));
}
else //expected byte wasn't there to read. Set it zero and set error flag
{
bytes[d - 6] = 0;
foundErrors = true;
qDebug() << "D:" << d << " Count:" << tokens.count();
qDebug() << "Expected byte missing! Original line: " << line;
}
}
thisFrame.setPayload(bytes);
}
thisFrame.setPayload(bytes);
frames->append(thisFrame);
}
frames->append(thisFrame);
}
if (verMajor == 8 && verMinor == 1)
{
if (tokens.length() > 5)
{
//47244640.194244 CANFD 1 Rx 122 0 0 6 6 00 00 18 12 D2 00 0 0 200000 0 0 0 0 0
//Time type bus dir ID ? ? length length bytes then many values of unknown type (ver 8.1)
// 0 1 2 3 4 5 6 7 8 9-
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<uint64_t>(tokens[0].toDouble() * 1000000.0)));
if (tokens[4].endsWith('x'))
{
QByteArray copied_id = tokens[4];
copied_id.chop(1);
thisFrame.setFrameId(copied_id.toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(true);
}
else
{
thisFrame.setFrameId(tokens[4].toUInt(nullptr, 16));
thisFrame.setExtendedFrameFormat(thisFrame.frameId() > 0x7FF); //some .asc files have extended IDs without 'x'
}
int payloadLen = tokens[8].toInt();
QByteArray bytes(payloadLen, 0);
if (payloadLen > 8)
{
qDebug() << "Payload length too long. Original line: " << line;
return false;
}
if (payloadLen < 0)
{
qDebug() << "Payload length negative! Original line: " << line;
return false;
}
thisFrame.isReceived = tokens[3].toUpper().contains("RX");
thisFrame.bus = tokens[2].toInt();
if (tokens[5] == "r") thisFrame.setFrameType(QCanBusFrame::RemoteRequestFrame);
for (int d = 9; d < (9 + payloadLen); d++)
{
if (tokens.count() > d)
{
bytes[d - 9] = static_cast<char>(tokens[d].toInt(nullptr, 16));
}
else //expected byte wasn't there to read. Set it zero and set error flag
{
bytes[d - 9] = 0;
foundErrors = true;
qDebug() << "D:" << d << " Count:" << tokens.count();
qDebug() << "Expected byte missing! Original line: " << line;
}
}
thisFrame.setPayload(bytes);
}
frames->append(thisFrame);
}
}
//else foundErrors = true;
@@ -2000,6 +2105,9 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector<CANFrame>* frames)
if (tokens[2].toUpper().contains("TRUE")) thisFrame.setExtendedFrameFormat(true);
else thisFrame.setExtendedFrameFormat(false);
//fix for faulty files that fail to set the extended flag when they should
if (thisFrame.frameId() > 0x7FF) thisFrame.setExtendedFrameFormat(true);
thisFrame.setFrameType(QCanBusFrame::DataFrame);
if (fileVersion == 1)
@@ -2294,11 +2402,16 @@ bool FrameFileIO::loadGenericCSVFile(QString filename, QVector<CANFrame>* frames
else thisFrame.setExtendedFrameFormat(false);
thisFrame.bus = 0;
thisFrame.setFrameType(QCanBusFrame::DataFrame);
QList<QByteArray> dataTok = tokens[1].split(' ');
QByteArray bytes(dataTok.length(), 0);
for (int d = 0; d < dataTok.length(); d++) bytes[d] = static_cast<char>(dataTok[d].toInt(nullptr, 16));
thisFrame.setPayload(bytes);
frames->append(thisFrame);
if (tokens.length() > 1)
{
QList<QByteArray> dataTok = tokens[1].split(' ');
int dLen = dataTok.length();
if (dLen > 8) dLen = 8;
QByteArray bytes(dLen, 0);
for (int d = 0; d < dLen; d++) bytes[d] = static_cast<char>(dataTok[d].toInt(nullptr, 16));
thisFrame.setPayload(bytes);
frames->append(thisFrame);
}
}
else foundErrors = true;
}
@@ -3468,9 +3581,9 @@ bool FrameFileIO::isCanDumpFile(QString filename)
QFile *inFile = new QFile(filename);
QByteArray line;
QList<QByteArray> tokens;
QRegExp timeExp("^\\((\\S+)\\)$");
QRegExp IdValExp("^(\\S+)#(\\S+)$");
QRegExp valExp("(\\S{2})");
QRegularExpression timeExp(QRegularExpression::anchoredPattern("^\\((\\S+)\\)$")); //anchored pattern causes exact match
QRegularExpression IdValExp(QRegularExpression::anchoredPattern("^(\\S+)#(\\S+)$"));
QRegularExpression valExp("(\\S{2})");
int lineCounter = 0;
int pos = 0;
bool isMatch = true;
@@ -3495,11 +3608,13 @@ bool FrameFileIO::isCanDumpFile(QString filename)
tokens = line.simplified().split(' ');
if(tokens.count() < 3) isMatch = false;
/* timestamp */
ret = timeExp.exactMatch(tokens[0]);
if(!ret) isMatch = false;
/* timestamp */
QRegularExpressionMatch timeExpMatched = timeExp.match(tokens[0]);
if(!timeExpMatched.hasMatch()) {
isMatch = false;
}
/*uint64_t timestamp = (uint64_t)*/(timeExp.cap(1).toDouble(&ret) /** (double)1000000.0*/);
/*uint64_t timestamp = (uint64_t)*/(timeExpMatched.captured(1).toDouble(&ret) /** (double)1000000.0*/);
if(!ret) isMatch = false;
if (line.contains('[')) //the expanded format
@@ -3529,17 +3644,19 @@ bool FrameFileIO::isCanDumpFile(QString filename)
isMatch = false;
continue;
}
ret = IdValExp.exactMatch(tokens[2]);
if(!ret)
QRegularExpressionMatch IdValExpMatched = IdValExp.match(tokens[2]);
if(!IdValExpMatched.hasMatch())
{
isMatch = false;
continue;
}
/* ID */
/*int ID = */IdValExp.cap(1).toInt(&ret, 16);
/*int ID = */IdValExpMatched.captured(1).toInt(&ret, 16);
QString val= IdValExp.cap(2);
QString val= IdValExpMatched.captured(2);
pos = 0;
int len = 0;
@@ -3553,22 +3670,23 @@ bool FrameFileIO::isCanDumpFile(QString filename)
} else {
/* val byte per byte */
int lng = 0;
while ((pos = valExp.indexIn(val, pos)) != -1)
{
QRegularExpressionMatch valExpMatch;
QRegularExpressionMatchIterator i = valExp.globalMatch(val);
while (i.hasNext()) {
valExpMatch = i.next();
lng++;
if (lng > 8)
{
isMatch = false;
break;
}
/*int data = */valExp.cap(1).toInt(&ret, 16);
/*int data = */valExpMatch.captured(1).toInt(&ret, 16);
if(!ret)
{
isMatch = false;
break;
}
pos += valExp.matchedLength();
}
}
}
@@ -3595,11 +3713,10 @@ bool FrameFileIO::loadCanDumpFile(QString filename, QVector<CANFrame>* frames)
CANFrame thisFrame;
QByteArray line;
QList<QByteArray> tokens;
QRegExp timeExp("^\\((\\S+)\\)$");
QRegExp IdValExp("^(\\S+)#(\\S+)$");
QRegExp valExp("(\\S{2})");
QRegularExpression timeExp(QRegularExpression::anchoredPattern("^\\((\\S+)\\)$")); //anchored pattern causes exact match
QRegularExpression IdValExp(QRegularExpression::anchoredPattern("^(\\S+)#(\\S+)$"));
QRegularExpression valExp("(\\S{2})");
int lineCounter = 0;
int pos = 0;
bool ret;
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
@@ -3625,8 +3742,8 @@ bool FrameFileIO::loadCanDumpFile(QString filename, QVector<CANFrame>* frames)
if(tokens.count()<3) continue;
/* timestamp */
ret = timeExp.exactMatch(tokens[0]);
if(!ret) continue;
QRegularExpressionMatch timeExpMatched = timeExp.match(tokens[0]);
if(!timeExpMatched.hasMatch()) continue;
//Sort out the bus
std::string busString = tokens[1].toStdString();
@@ -3647,7 +3764,7 @@ bool FrameFileIO::loadCanDumpFile(QString filename, QVector<CANFrame>* frames)
thisFrame.bus = busNum;
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, (uint64_t)(timeExp.cap(1).toDouble(&ret) * (double)1000000.0)));
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, (uint64_t)(timeExpMatched.captured(1).toDouble(&ret) * (double)1000000.0)));
if(!ret) continue;
if (line.contains('[')) //the expanded format (second one from the above list)
@@ -3670,24 +3787,26 @@ bool FrameFileIO::loadCanDumpFile(QString filename, QVector<CANFrame>* frames)
{
/* ID & value */
//qDebug() << tokens[2];
ret = IdValExp.exactMatch(tokens[2]);
if(!ret)
QRegularExpressionMatch IdValExpMatched = IdValExp.match(tokens[2]);
if(!IdValExpMatched.hasMatch())
{
qDebug() << "ID regex didn't match!";
continue;
}
/* ID */
thisFrame.setFrameId(static_cast<uint32_t>(IdValExp.cap(1).toInt(&ret, 16)));
if (IdValExp.cap(1).length() > 3) {
thisFrame.setFrameId(static_cast<uint32_t>(IdValExpMatched.captured(1).toInt(&ret, 16)));
if (IdValExpMatched.captured(1).length() > 3)
{
thisFrame.setExtendedFrameFormat(true);
} else {
}
else
{
thisFrame.setExtendedFrameFormat(false);
}
QString val= IdValExp.cap(2);
QString val = IdValExpMatched.captured(2);
pos = 0;
QByteArray bytes;
if (val.startsWith("R") && val.at(1).isDigit()) {
thisFrame.payload().resize( val.at(1).toLatin1() - '0' );
@@ -3695,12 +3814,13 @@ bool FrameFileIO::loadCanDumpFile(QString filename, QVector<CANFrame>* frames)
} else {
thisFrame.setFrameType(QCanBusFrame::DataFrame);
/* val byte per byte */
while ((pos = valExp.indexIn(val, pos)) != -1)
QRegularExpressionMatch valExpMatch;
QRegularExpressionMatchIterator i = valExp.globalMatch(val);
while (i.hasNext())
{
bytes.append((char)valExp.cap(1).toInt(&ret, 16));
valExpMatch = i.next();
bytes.append((char)valExpMatch.captured(1).toInt(&ret, 16));
if(!ret) continue;
pos += valExp.matchedLength();
}
}
thisFrame.setPayload(bytes);
@@ -4159,8 +4279,8 @@ bool FrameFileIO::loadTeslaAPFile(QString filename, QVector<CANFrame>* frames)
CANFrame thisFrame;
int lineCounter = 0;
QByteArray data;
int timeOffset = 0;
int64_t lastTimeStamp = 0;
//int timeOffset = 0;
//int64_t lastTimeStamp = 0;
bool foundErrors = false;
thisFrame.setFrameType(QCanBusFrame::DataFrame);
TeslaAPCANRecord record;
@@ -4217,7 +4337,7 @@ bool FrameFileIO::isCLX000File(QString filename) {
}
QTextStream fileStream(inFile.get());
bool foundErrors = false;
//bool foundErrors = false;
// Contains 16 lines of header prior to (potential) data.
QString headerLine;
@@ -4269,7 +4389,7 @@ bool FrameFileIO::isCLX000File(QString filename) {
qDebug() << "Could not decode time format" << headerLine << "using pattern" << timeFormatPattern;
return false;
}
auto timeFormat = matchTimeFormat.captured("timeFormat").front().digitValue();
//auto timeFormat = matchTimeFormat.captured("timeFormat").front().digitValue();
headerLine = fileStream.readLine();
QString const timeSeparatorPattern = "# Time separator: \"(?<timeSeparator>[" + validSeparators + "]?)\"";
@@ -4279,7 +4399,7 @@ bool FrameFileIO::isCLX000File(QString filename) {
qDebug() << "Could not decode time format" << headerLine << "using pattern" << timeSeparatorPattern;
return false;
}
QChar timeSeparator = matchTimeSeparator.captured("timeSeparator").front();
//QChar timeSeparator = matchTimeSeparator.captured("timeSeparator").front();
headerLine = fileStream.readLine();
QString const timeSeparatorMsPattern = "# Time separator ms: \"(?<timeSeparatorMs>[" + validSeparators + "]?)\"";
@@ -4289,7 +4409,7 @@ bool FrameFileIO::isCLX000File(QString filename) {
qDebug() << "Could not decode time format ms" << headerLine << "using pattern" << timeSeparatorMsPattern;
return false;
}
QChar timeSeparatorMs = matchTimeSeparatorMs.captured("timeSeparatorMs").front();
//QChar timeSeparatorMs = matchTimeSeparatorMs.captured("timeSeparatorMs").front();
headerLine = fileStream.readLine();
QString const dateSeparatorPattern = "# Date separator: \"(?<dateSeparator>[" + validSeparators + "]?)\"";
@@ -4299,7 +4419,7 @@ bool FrameFileIO::isCLX000File(QString filename) {
qDebug() << "Could not decode time format ms" << headerLine << "using pattern" << dateSeparatorPattern;
return false;
}
QChar dateSeparator = matchDateSeparator.captured("dateSeparator").front();
//QChar dateSeparator = matchDateSeparator.captured("dateSeparator").front();
headerLine = fileStream.readLine();
QString const timeDateSeparatorPattern = "# Time and date separator: \"(?<timeDateSeparator>[" + validSeparators + "]?)\"";
@@ -4309,7 +4429,7 @@ bool FrameFileIO::isCLX000File(QString filename) {
qDebug() << "Could not decode time format ms" << headerLine << "using pattern" << timeDateSeparatorPattern;
return false;
}
QChar timeDateSeparator = matchTimeDateSeparator.captured("timeDateSeparator").front();
//QChar timeDateSeparator = matchTimeDateSeparator.captured("timeDateSeparator").front();
// Skip remaining header lines.
fileStream.readLine();
@@ -4373,7 +4493,7 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
return false;
}
QString const validSeparators(" -~");
QString const validSeparators(" -~;");
// Decode separators and format for later decoding.
headerLine = fileStream.readLine();
@@ -4480,6 +4600,7 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
}
// Fallthrough
[[fallthrough]];
}
case 5: {
// Handle month.
@@ -4490,6 +4611,7 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
}
// Fallthrough
[[fallthrough]];
}
case 4: {
// Handle day.
@@ -4500,6 +4622,7 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
}
// Fallthrough
[[fallthrough]];
}
case 3: {
// Handle hours.
@@ -4510,6 +4633,7 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
}
// Fallthrough
[[fallthrough]];
}
case 2: {
// Handle minutes.
@@ -4520,6 +4644,7 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
}
// Fallthrough
[[fallthrough]];
}
case 1: {
// Handle seconds.
@@ -4530,6 +4655,7 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
}
// Fallthrough
[[fallthrough]];
}
case 0: {
// Handle milliseconds.
@@ -4576,17 +4702,34 @@ bool FrameFileIO::loadCLX000File(QString filename, QVector<CANFrame>* frames) {
currentFrame.setFrameType(QCanBusFrame::DataFrame);
currentFrame.bus = 0;
currentTime = currentTime.addYears(res.captured("year").toUInt());
currentTime = currentTime.addMonths(res.captured("month").toUInt());
currentTime = currentTime.addDays(res.captured("day").toUInt());
currentTime = currentTime.addSecs(
res.captured("hours").toUInt() * 60 * 60 +
res.captured("minutes").toUInt() * 60 +
res.captured("seconds").toUInt()
);
currentTime = currentTime.addMSecs(res.captured("ms").toUInt());
//currentTime is already initialized with startDate so it already has year,month,etc filled out.
//For each timestamp on the line we need to figure out how it differs from the already set time
//and move the timestamp accordingly.
if (res.captured("year").length() > 0)
{
//for all of these, only add the difference not the whole value!
currentTime = currentTime.addYears(res.captured("year").toUInt() - startDate.date().year());
}
currentFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, currentTime.toMSecsSinceEpoch()));
if (res.captured("month").length() > 0)
{
currentTime = currentTime.addMonths(res.captured("month").toUInt() - startDate.date().month());
}
if (res.captured("day").length() > 0)
{
currentTime = currentTime.addMonths(res.captured("day").toUInt() - startDate.date().day());
}
unsigned int seconds = res.captured("hours").toUInt() * 60 * 60 + res.captured("minutes").toUInt() * 60 +
res.captured("seconds").toUInt() - (startDate.time().msecsSinceStartOfDay() / 1000);
currentTime = currentTime.addSecs(seconds);
currentTime = currentTime.addMSecs(res.captured("ms").toUInt() - (startDate.time().msecsSinceStartOfDay() % 1000));
//time is stored in microseconds so we need to get the timestamp as milliseconds since the epoch
//then multiplyby 1000 to get microseconds since the epoch.
currentFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, currentTime.toMSecsSinceEpoch() * 1000));
if(res.captured("type").length() != 0) {
auto frameType = res.captured("type").toUInt();
@@ -4652,7 +4795,7 @@ bool FrameFileIO::isCANServerFile(QString filename)
{
//qDebug() << "header: " << headerData;
//We have enough bytes to make up our header. Lets check if it matches
if (headerData == "CANSERVER_v2_CANSERVER")
if (headerData == "CANSERVER_v2_CANSERVER" || headerData == "CANSERVER_v3_CANSERVER")
{
isMatch = true;
}
@@ -4694,6 +4837,7 @@ bool FrameFileIO::loadCANServerFile(QString filename, QVector<CANFrame>* frames)
//Skip the header
bool fileIsGood = false;
uint8_t logVersion = 1;
QByteArray headerData = inFile->read(22);
if (headerData.length() == 22)
{
@@ -4701,13 +4845,19 @@ bool FrameFileIO::loadCANServerFile(QString filename, QVector<CANFrame>* frames)
//We have enough bytes to make up our header. Lets check if it matches
if (headerData == "CANSERVER_v2_CANSERVER")
{
logVersion = 1;
fileIsGood = true;
}
else if (headerData == "CANSERVER_v3_CANSERVER")
{
logVersion = 2;
fileIsGood = true;
}
}
if (fileIsGood)
{
uint64_t lastFrameTime = 0;
//uint64_t lastFrameTime = 0;
uint8_t data[1];
while (!inFile->atEnd())
@@ -4725,7 +4875,13 @@ bool FrameFileIO::loadCANServerFile(QString filename, QVector<CANFrame>* frames)
{
if (possibleHeaderData == "ANSERVER_v2_CANSERVER" )
{
//We found another header. Lets just ignore things and move on
//We found another header (in this case a version 1 format). Lets just ignore things and move on
logVersion = 1;
}
else if (possibleHeaderData == "ANSERVER_v3_CANSERVER" )
{
//We found another header (in this case a version 2 format). Lets just ignore things and move on
logVersion = 2;
}
else
{
@@ -4734,10 +4890,10 @@ bool FrameFileIO::loadCANServerFile(QString filename, QVector<CANFrame>* frames)
}
}
}
else if (data[0] == 0xCD)
else if ((logVersion == 1 && data[0] == 0xCD) || (logVersion == 2 && data[0] == 0xD0))
{
//Log mark message
//Log mark message (the same format in v1 or v2. Just a different identifier byte)
//Read in the size of the mark
uint8_t markSize[1];
inFile->read((char*)&markSize, 1);
@@ -4758,9 +4914,9 @@ bool FrameFileIO::loadCANServerFile(QString filename, QVector<CANFrame>* frames)
frames->append(markFrame);
*/
}
else if (data[0] == 0xCE)
else if ((logVersion == 1 && data[0] == 0xCE) || (logVersion == 2 && data[0] == 0xA0))
{
//Timesync message
//Timesync message (v1 log format)
framedata_U timesyncvalue;
::memset(timesyncvalue.data, 0, sizeof(timesyncvalue.data));
inFile->read(timesyncvalue.data, 8);
@@ -4769,39 +4925,54 @@ bool FrameFileIO::loadCANServerFile(QString filename, QVector<CANFrame>* frames)
//qDebug() << "Found a time sync message: " << timesyncvalue.u64;
timeStampBase = timesyncvalue.u64;
}
else if (data[0] == 0xCF)
else if ((logVersion == 1 && data[0] == 0xCF) || (logVersion == 2 && (data[0] & 0xF0) == 0xB0))
{
if (frameCounter++ > 100)
// Can frame format (either a v1 or a v2)
if (frameCounter++ > 10000)
{
qApp->processEvents();
frameCounter = 0;
}
//CAN Frame
uint8_t frameheaderdata[5];
inFile->read((char*)frameheaderdata, 5);
//The frame time offset is how long since the last time sync message (now in ms) this frame is
uint8_t byte1 = frameheaderdata[0];
uint8_t byte2 = frameheaderdata[1];
uint16_t frametimeoffset = ((uint16_t)byte2 << 8) | byte1;
uint32_t frametimeoffset = 0;
if (logVersion == 1)
{
//The frame time offset is how long since the last time sync message (now in ms) this frame is
frametimeoffset = ((uint16_t)frameheaderdata[1] << 8) | frameheaderdata[0];
frametimeoffset *= 1000;
}
else if (logVersion == 2)
{
frametimeoffset = (data[0] & 0x0F) + (frameheaderdata[0] << 4) + (frameheaderdata[1] << 12) + (((frameheaderdata[2] & 0xF8) >> 3) << 20);
}
byte1 = frameheaderdata[2];
byte2 = frameheaderdata[3];
uint16_t messageId = ((uint16_t)byte2 << 8) | byte1;
uint8_t framelength = frameheaderdata[4] & 0x0F;
uint8_t busid = frameheaderdata[4] >> 4;
uint16_t messageId = 0;
if (logVersion == 1)
{
messageId = ((uint16_t)frameheaderdata[3] << 8) | frameheaderdata[2];
}
else if (logVersion == 2)
{
messageId = ((frameheaderdata[2] & 0x07) << 8) + (frameheaderdata[3] & 0xFF);
}
uint8_t framelength = (frameheaderdata[4] & 0x0F);
uint8_t busid = (frameheaderdata[4] & 0xF0) >> 4;
framelength = framelength > 8 ? 8 : framelength;
//Now that we have a length lets read those bytes
::memset(framedata.data, 0, sizeof(framedata.data));
inFile->read(framedata.data, framelength);
if (framelength > 0)
{
inFile->read(framedata.data, framelength);
}
//Setup the frame object and populate it
CANFrame thisFrame;
thisFrame.setFrameType(QCanBusFrame::DataFrame);
@@ -4811,11 +4982,8 @@ bool FrameFileIO::loadCANServerFile(QString filename, QVector<CANFrame>* frames)
uint64_t frameTime = timeStampBase;
uint64_t frameoffset = frametimeoffset;
frameoffset *= 1000;
frameTime += frameoffset;
lastFrameTime = frameTime;
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, frameTime));
QByteArray bytes(framelength,0);