Save CARBUS Analyzer format

This commit is contained in:
Kanstantsin Shautsou
2020-10-07 02:51:40 +03:00
parent 419ef1248d
commit 10920e17e5
2 changed files with 156 additions and 17 deletions
+153 -15
View File
@@ -3,6 +3,7 @@
#include <QMessageBox>
#include <QProgressDialog>
#include <QDateTime>
#include <QRegularExpression>
#include <QtEndian>
#include <QSettings>
#include <iostream>
@@ -36,6 +37,7 @@ bool FrameFileIO::saveFrameFile(QString &fileName, const QVector<CANFrame>* fram
filters.append(QString(tr("Candump/Kayak (*.log)")));
filters.append(QString(tr("Cabana Log (*.csv *.CSV)")));
filters.append(QString(tr("CANalyzer Ascii Log (*.asc *.ASC)")));
filters.append(QString(tr("CARBUS Analyzer (*.trc *.TRC)")));
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile);
@@ -121,6 +123,11 @@ bool FrameFileIO::saveFrameFile(QString &fileName, const QVector<CANFrame>* fram
if (!filename.contains('.')) filename += ".asc";
result = saveCanalyzerASC(filename, frameCache);
}
if (dialog.selectedNameFilter() == filters[12])
{
if (!filename.contains('.')) filename += ".trc";
result = saveCARBUSAnalzyer(filename, frameCache);
}
progress.cancel();
@@ -751,30 +758,40 @@ bool FrameFileIO::isCARBUSAnalyzerFile(QString filename)
return isMatch;
}
// CARBUS Analayzer trace format:
// CARBUS Analayzer trace format https://canhacker.ru/can-trace-format/ :
// header
//@ TEXT @ 2 @ 64 @ 0 @ 591 @ 38782 @ 00:00:38.782 @
// 2 - format version
//14,687 1 0004 4E0 8 24 00 00 00 00 00 00 00 00000000 $
// timestamp: sec,ms
// timestamp: sec,ms - for version 2
// sec,us - for version 3
bool FrameFileIO::loadCARBUSAnalyzerFile(QString filename, QVector<CANFrame>* frames)
{
QFile *inFile = new QFile(filename);
CANFrame thisFrame;
QString line;
int lineCounter = 0;
bool foundErrors = false;
if (!inFile->open(QIODevice::ReadOnly))
{
delete inFile;
return false;
}
CANFrame thisFrame;
QString line;
int lineCounter = 0;
bool foundErrors = false;
// readLine() works only with "\n" and "\r\n"
QString localReadAll = inFile->readAll().replace("\r", "\r\n");
QTextStream txt(&localReadAll);
line = txt.readLine().toUpper(); //read out the header first and discard it.
line = txt.readLine().toUpper(); //read out the header
int version = 3; // current default
QRegularExpression re("@ TEXT @ (?<version>\\d) @.*");
QRegularExpressionMatch match = re.match(line);
if (match.hasMatch()) {
version = match.captured("version").toInt();
}
while (!txt.atEnd()) {
lineCounter++;
@@ -789,14 +806,18 @@ bool FrameFileIO::loadCARBUSAnalyzerFile(QString filename, QVector<CANFrame>* fr
QList<QString> tokens = line.split(QRegExp("\\s+"));
if (tokens.length() > 3)
{
QString time = tokens[0].replace(",",".");
double timeStamp = time.toDouble() * 1000000.0;
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<int64_t>(timeStamp)));
thisFrame.setFrameId(static_cast<uint32_t>(tokens[3].toInt(nullptr, 16)));
thisFrame.setExtendedFrameFormat(thisFrame.frameId() > 0x7FF);
QString time = tokens[0].replace(",", "");
int64_t timeStamp = time.toInt();
if (version == 2) {
timeStamp *= 1000; // ms -> us
}
thisFrame.isReceived = true;
thisFrame.setFrameType(QCanBusFrame::DataFrame);
thisFrame.bus = 0;
thisFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, static_cast<int64_t>(timeStamp)));
thisFrame.bus = tokens[1].toInt();
thisFrame.setFrameId(static_cast<uint32_t>(tokens[3].toInt(nullptr, 16)));
thisFrame.setExtendedFrameFormat(thisFrame.frameId() > 0x7FF);
int numBytes = tokens[4].toInt(nullptr, 16);
QByteArray bytes(numBytes , 0);
for (int d = 0; d < numBytes; d++)
@@ -810,7 +831,10 @@ bool FrameFileIO::loadCARBUSAnalyzerFile(QString filename, QVector<CANFrame>* fr
thisFrame.setPayload(bytes);
frames->append(thisFrame);
}
else foundErrors = true;
else
{
foundErrors = true;
}
}
}
inFile->close();
@@ -818,6 +842,120 @@ bool FrameFileIO::loadCARBUSAnalyzerFile(QString filename, QVector<CANFrame>* fr
return !foundErrors;
}
QString getCARBUSAnalzyerStr(uint64_t time, QString symbol) {
QString finalStr = "";
QString strTime = QString::number(time);
while (strTime.size() < 5) {
strTime = "0" + strTime;
}
for (int i = 0; i < strTime.size(); ++i ) {
finalStr += strTime.at(i);
if (i == 1) {
finalStr += symbol;
}
}
return finalStr;
}
bool FrameFileIO::saveCARBUSAnalzyer(QString filename, const QVector<CANFrame>* frames)
{
QFile *outFile = new QFile(filename);
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
{
delete outFile;
return false;
}
QTextStream outTextStream(outFile);
int lineCounter = 0;
qint64 minTime = frames->at(0).timeStamp().microSeconds();
qint64 maxTime = minTime;
for (int c = 0; c < frames->count(); c++)
{
if (frames->at(c).timeStamp().microSeconds() < minTime) minTime = frames->at(c).timeStamp().microSeconds();
if (frames->at(c).timeStamp().microSeconds() > maxTime) maxTime = frames->at(c).timeStamp().microSeconds();
}
qint64 totalTime = maxTime - minTime;
// looks like a bug in CARBUS format for 3 version. time is in ms, while packets in us.
totalTime /= 1000;
QTime someTime(0,0,0);
someTime = someTime.addMSecs(totalTime);
// header:
// @see #loadCARBUSAnalyzer()
// 14012 = number of packets
// 15688 = max time - start time in ms
//
// "@ TEXT @ 3 @ 64 @ 0 @ 14012 @ 15688 @ 00:00:15.688 @"
// saving in version format 3 with microseconds in packets time
outTextStream << "@ TEXT @ 3 @ 64 @ 0 @ " << frames->count() << " @ " << totalTime
<<" @ " << someTime.toString("hh:mm:ss.zzz") <<" @\r";
const unsigned char *data;
for (int c = 0; c < frames->count(); c++)
{
lineCounter++;
if (lineCounter > 100)
{
qApp->processEvents();
lineCounter = 0;
}
auto frame = frames->at(c);
uint64_t timeStamp = frame.timeStamp().microSeconds();
QString canId = QString::number(frame.frameId(), 16).toUpper().rightJustified(3, '0').toUtf8();
QString canDlc = QString::number(frame.payload().length()).toUtf8();
QString ascii = "";
QString finalCanData;
data = reinterpret_cast<const unsigned char *>(frame.payload().constData());
for (int d = 0; d < frame.payload().length(); d++)
{
auto octet = data[d];
finalCanData.append(QString::number(octet, 16).toUpper().rightJustified(2, '0').toUtf8());
finalCanData.append(" ");
QString strCode = QString::number(octet, 16);
bool conv;
uint symbolCode = strCode.toInt(&conv, 16);
if ((symbolCode >= 32 && symbolCode < 126)) {
QChar localQChar = QChar(symbolCode);
if (localQChar.toLatin1() != 0) {
ascii += QString::fromLocal8Bit(QByteArray::fromHex(strCode.toLatin1()));
}
} else {
ascii += " ";
}
}
finalCanData = finalCanData.trimmed().leftJustified(23, ' ');
ascii = ascii.leftJustified(8, ' ');
auto seconds = QString::number(timeStamp / 1000000);
auto uSeconds = QString::number(timeStamp % 1000000);
QString localArg = "";
localArg.append(seconds).append(",").append(uSeconds).append("\t")
.append(QString::number(frame.bus)).append("\t") // bus channel
.append("0004").append("\t") // it's CAN frame
.append(canId).append("\t")
.append(canDlc).append("\t")
.append(finalCanData).append("\t")
.append("00000000").append("\t")
.append(ascii).append("\t")
.append("\r");
qDebug() << localArg;
outTextStream << localArg;
}
outFile->close();
delete outFile;
return true;
}
bool FrameFileIO::isCANHackerFile(QString filename)
{
+1
View File
@@ -85,6 +85,7 @@ public:
static bool saveCanDumpFile(QString filename, const QVector<CANFrame> * frames);
static bool saveCabanaFile(QString filename, const QVector<CANFrame>* frames);
static bool saveCanalyzerASC(QString filename, const QVector<CANFrame>* frames);
static bool saveCARBUSAnalzyer(QString filename, const QVector<CANFrame>* frames);
static bool openContinuousNative();
static bool closeContinuousNative();