From 49b2ac0155cb1fae07518839cf187ff80729b1f5 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Mon, 16 Jan 2017 21:00:26 -0500 Subject: [PATCH] Add the ability to load several forms of DBC attributes. --- dbc/dbc_classes.cpp | 60 +++++++++++ dbc/dbc_classes.h | 11 +- dbc/dbchandler.cpp | 248 ++++++++++++++++++++++++++++++++++++++++++-- dbc/dbchandler.h | 5 + framefileio.cpp | 19 ++-- framefileio.h | 3 - utility.h | 9 ++ 7 files changed, 330 insertions(+), 25 deletions(-) diff --git a/dbc/dbc_classes.cpp b/dbc/dbc_classes.cpp index 1927ab8..9d0a14e 100644 --- a/dbc/dbc_classes.cpp +++ b/dbc/dbc_classes.cpp @@ -202,3 +202,63 @@ bool DBC_SIGNAL::processAsDouble(const CANFrame &frame, double &outValue) outValue = endResult; return true; } + +DBC_ATTRIBUTE_VALUE *DBC_SIGNAL::findAttrValByName(QString name) +{ + if (attributes.length() == 0) return NULL; + for (int i = 0; i < attributes.length(); i++) + { + if (attributes[i].attrName.compare(name, Qt::CaseInsensitive) == 0) + { + return &attributes[i]; + } + } + return NULL; +} + +DBC_ATTRIBUTE_VALUE *DBC_SIGNAL::findAttrValByIdx(int idx) +{ + if (idx < 0) return NULL; + if (idx >= attributes.count()) return NULL; + return &attributes[idx]; +} + +DBC_ATTRIBUTE_VALUE *DBC_MESSAGE::findAttrValByName(QString name) +{ + if (attributes.length() == 0) return NULL; + for (int i = 0; i < attributes.length(); i++) + { + if (attributes[i].attrName.compare(name, Qt::CaseInsensitive) == 0) + { + return &attributes[i]; + } + } + return NULL; +} + +DBC_ATTRIBUTE_VALUE *DBC_MESSAGE::findAttrValByIdx(int idx) +{ + if (idx < 0) return NULL; + if (idx >= attributes.count()) return NULL; + return &attributes[idx]; +} + +DBC_ATTRIBUTE_VALUE *DBC_NODE::findAttrValByName(QString name) +{ + if (attributes.length() == 0) return NULL; + for (int i = 0; i < attributes.length(); i++) + { + if (attributes[i].attrName.compare(name, Qt::CaseInsensitive) == 0) + { + return &attributes[i]; + } + } + return NULL; +} + +DBC_ATTRIBUTE_VALUE *DBC_NODE::findAttrValByIdx(int idx) +{ + if (idx < 0) return NULL; + if (idx >= attributes.count()) return NULL; + return &attributes[idx]; +} diff --git a/dbc/dbc_classes.h b/dbc/dbc_classes.h index fba92a4..ebd715e 100644 --- a/dbc/dbc_classes.h +++ b/dbc/dbc_classes.h @@ -26,7 +26,7 @@ enum DBC_SIG_VAL_TYPE enum DBC_ATTRIBUTE_VAL_TYPE { - HEX, + QINT, QFLOAT, QSTRING, ENUM @@ -52,6 +52,7 @@ public: class DBC_ATTRIBUTE_VALUE { +public: QString attrName; QVariant value; }; @@ -69,6 +70,9 @@ public: QString name; QString comment; QList attributes; + + DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name); + DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx); }; class DBC_MESSAGE; //forward reference so that DBC_SIGNAL can compile before we get to real definition of DBC_MESSAGE @@ -98,6 +102,8 @@ public: //TODO: this is sloppy. It shouldn't all be public! bool processAsText(const CANFrame &frame, QString &outString); bool processAsInt(const CANFrame &frame, int32_t &outValue); bool processAsDouble(const CANFrame &frame, double &outValue); + DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name); + DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx); }; class DBCSignalHandler; //forward declaration to keep from having to include dbchandler.h in this file and thus create a loop @@ -117,6 +123,9 @@ public: QList attributes; DBCSignalHandler *sigHandler; DBC_SIGNAL* multiplexorSignal; + + DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name); + DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx); }; diff --git a/dbc/dbchandler.cpp b/dbc/dbchandler.cpp index 233adfe..95b0a05 100644 --- a/dbc/dbchandler.cpp +++ b/dbc/dbchandler.cpp @@ -253,6 +253,36 @@ void DBCFile::setAssocBus(int bus) assocBuses = bus; } +DBC_ATTRIBUTE *DBCFile::findAttributeByName(QString name) +{ + if (dbc_attributes.length() == 0) return NULL; + for (int i = 0; i < dbc_attributes.length(); i++) + { + if (dbc_attributes[i].name.compare(name, Qt::CaseInsensitive) == 0) + { + return &dbc_attributes[i]; + } + } + return NULL; +} + +DBC_ATTRIBUTE *DBCFile::findAttributeByIdx(int idx) +{ + if (idx < 0) return NULL; + if (idx >= dbc_attributes.count()) return NULL; + return &dbc_attributes[idx]; +} + +void DBCFile::findAttributesByType(DBC_ATTRIBUTE_TYPE typ, QList *list) +{ + if (!list) return; + list->clear(); + foreach (DBC_ATTRIBUTE attr, dbc_attributes) + { + if (attr.attrType == typ) list->append(attr); + } +} + void DBCFile::loadFile(QString fileName) { QFile *inFile = new QFile(fileName); @@ -260,6 +290,7 @@ void DBCFile::loadFile(QString fileName) QRegularExpression regex; QRegularExpressionMatch match; DBC_MESSAGE *currentMessage = NULL; + DBC_ATTRIBUTE attr; int numSigFaults = 0, numMsgFaults = 0; qDebug() << "DBC File: " << fileName; @@ -527,32 +558,150 @@ void DBCFile::loadFile(QString fileName) if (line.startsWith("BA_DEF_ SG_ ")) { qDebug() << "Found a SG attribute line"; - regex.setPattern("^BA\\_DEF\\_ SG\\_ +\\\"([A-Za-z0-9\-_]+)\\\" +(.+);"); - match = regex.match(line); - //captured 1 is the name of the attribute to set up - //captured 2 is the type of signal attribute to create. - if (match.hasMatch()) - { + if (parseAttribute(line.right(line.length() - 12), attr)) + { + qDebug() << "Success"; + attr.attrType = SIG; + dbc_attributes.append(attr); } } if (line.startsWith("BA_DEF_ BO_ ")) //definition of a message attribute { + qDebug() << "Found a BO attribute line"; + if (parseAttribute(line.right(line.length() - 12), attr)) + { + qDebug() << "Success"; + attr.attrType = MESSAGE; + dbc_attributes.append(attr); + } } if (line.startsWith("BA_DEF_ BU_ ")) //definition of a node attribute { + qDebug() << "Found a BU attribute line"; + if (parseAttribute(line.right(line.length() - 12), attr)) + { + qDebug() << "Success"; + attr.attrType = NODE; + dbc_attributes.append(attr); + } } if (line.startsWith("BA_DEF_DEF_ ")) //definition of default value for an attribute - { - + { + regex.setPattern("^BA\\_DEF\\_DEF\\_ \\\"*(\\w+)\\\"* \\\"*(\\w*)\\\"*"); + match = regex.match(line); + //captured 1 is the name of the attribute + //captured 2 is the default value for that attribute + if (match.hasMatch()) + { + qDebug() << "Found an attribute default value line, searching for an attribute named " << match.captured(1); + DBC_ATTRIBUTE *found = findAttributeByName(match.captured(1)); + if (found) + { + found->defaultValue = match.captured(2); + qDebug() << "Matched an attribute. Setting default value to " << found->defaultValue; + } + } } + //BA_ "GenMsgCycleTime" BO_ 101 100; if (line.startsWith("BA_ ")) //set value of attribute { + regex.setPattern("^BA\\_ \\\"*(\\w+)\\\"* BO\\_ (\\d+) \\\"*(\\w+)\\\"*"); + match = regex.match(line); + //captured 1 is the attribute name + //captured 2 is the message ID number (frame ID) + //captured 3 is the attribute value + if (match.hasMatch()) + { + qDebug() << "Found an attribute setting line for a message"; + DBC_ATTRIBUTE *foundAttr = findAttributeByName(match.captured(1)); + if (foundAttr) + { + qDebug() << "That attribute does exist"; + DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toInt()); + if (foundMsg) + { + qDebug() << "It references a valid, registered message"; + DBC_ATTRIBUTE_VALUE *foundAttrVal = foundMsg->findAttrValByName(match.captured(1)); + if (foundAttrVal) foundAttrVal->value = match.captured(3); + else + { + DBC_ATTRIBUTE_VALUE val; + val.attrName = match.captured(1); + val.value = match.captured(3); + foundMsg->attributes.append(val); + } + } + } + } + regex.setPattern("^BA\\_ \\\"*(\\w+)\\\"* SG\\_ (\\d+) \\\"*(\\w+)\\\"* \\\"*(\\w+)\\\"*"); + match = regex.match(line); + //captured 1 is the attribute name + //captured 2 is the message ID number (frame ID) + //captured 3 is the signal name to bind to + //captured 4 is the attribute value + if (match.hasMatch()) + { + qDebug() << "Found an attribute setting line for a signal"; + DBC_ATTRIBUTE *foundAttr = findAttributeByName(match.captured(1)); + if (foundAttr) + { + qDebug() << "That attribute does exist"; + DBC_MESSAGE *foundMsg = messageHandler->findMsgByID(match.captured(2).toInt()); + if (foundMsg) + { + qDebug() << "It references a valid, registered message"; + DBC_SIGNAL *foundSig = foundMsg->sigHandler->findSignalByName(match.captured(3)); + if (foundSig) + { + DBC_ATTRIBUTE_VALUE *foundAttrVal = foundSig->findAttrValByName(match.captured(1)); + if (foundAttrVal) foundAttrVal->value = match.captured(3); + else + { + DBC_ATTRIBUTE_VALUE val; + val.attrName = match.captured(1); + val.value = match.captured(3); + foundSig->attributes.append(val); + } + } + } + } + } + + regex.setPattern("^BA\\_ \\\"*(\\w+)\\\"* BU\\_ \\\"*(\\w+)\\\"* \\\"*(\\w+)\\\"*"); + match = regex.match(line); + //captured 1 is the attribute name + //captured 2 is the name of the node + //captured 3 is the attribute value + if (match.hasMatch()) + { + qDebug() << "Found an attribute setting line for a node"; + DBC_ATTRIBUTE *foundAttr = findAttributeByName(match.captured(1)); + if (foundAttr) + { + qDebug() << "That attribute does exist"; + DBC_NODE *foundNode = findNodeByName(match.captured(2)); + if (foundNode) + { + qDebug() << "References a valid node name"; + DBC_ATTRIBUTE_VALUE *foundAttrVal = foundNode->findAttrValByName(match.captured(1)); + if (foundAttrVal) foundAttrVal->value = match.captured(3); + else + { + DBC_ATTRIBUTE_VALUE val; + val.attrName = match.captured(1); + val.value = match.captured(3); + foundNode->attributes.append(val); + } + } + } + + } } } if (numSigFaults > 0 || numMsgFaults > 0) @@ -574,6 +723,89 @@ void DBCFile::loadFile(QString fileName) assocBuses = -1; } +bool DBCFile::parseAttribute(QString inpString, DBC_ATTRIBUTE &attr) +{ + bool goodAttr = false; + QRegularExpression regex; + QRegularExpressionMatch match; + + regex.setPattern("\\\"*(\\w+)\\\"* \\\"*(\\w+)\\\"* (\\d+) (\\d+)"); + match = regex.match(inpString); + //captured 1 is the name of the attribute to set up + //captured 2 is the type of signal attribute to create. + //captured 3 is the lower bound value for this attribute + //captured 4 is the upper bound value for this attribute + if (match.hasMatch()) + { + qDebug() << "Parsing an attribute with low/high values"; + attr.name = match.captured(1); + QString typ = match.captured(2); + attr.attrType = SIG; + attr.lower = 0; + attr.upper = 0; + attr.valType = QSTRING; + if (!typ.compare("INT", Qt::CaseInsensitive)) + { + qDebug() << "INT attribute named " << attr.name; + attr.valType = QINT; + attr.lower = match.captured(3).toInt(); + attr.upper = match.captured(4).toInt(); + goodAttr = true; + } + if (!typ.compare("FLOAT", Qt::CaseInsensitive)) + { + qDebug() << "FLOAT attribute named " << attr.name; + attr.valType = QFLOAT; + attr.lower = match.captured(3).toDouble(); + attr.upper = match.captured(4).toDouble(); + goodAttr = true; + } + if (!typ.compare("STRING", Qt::CaseInsensitive)) + { + qDebug() << "STRING attribute named " << attr.name; + attr.valType = QSTRING; + goodAttr = true; + } + } + else + { + regex.setPattern("\\\"*(\\w+)\\\"* \\\"*(\\w+)\\\"*"); + match = regex.match(inpString); + //Same as above but no upper/lower bound values. + if (match.hasMatch()) + { + qDebug() << "Parsing an attribute without boundaries"; + attr.name = match.captured(1); + QString typ = match.captured(2); + attr.lower = 0; + attr.upper = 0; + attr.attrType = SIG; + + if (!typ.compare("INT", Qt::CaseInsensitive)) + { + qDebug() << "INT attribute named " << attr.name; + attr.valType = QINT; + goodAttr = true; + } + + if (!typ.compare("FLOAT", Qt::CaseInsensitive)) + { + qDebug() << "FLOAT attribute named " << attr.name; + attr.valType = QFLOAT; + goodAttr = true; + } + + if (!typ.compare("STRING", Qt::CaseInsensitive)) + { + qDebug() << "STRING attribute named " << attr.name; + attr.valType = QSTRING; + goodAttr = true; + } + } + } + return goodAttr; +} + void DBCFile::saveFile(QString fileName) { QFile *outFile = new QFile(fileName); diff --git a/dbc/dbchandler.h b/dbc/dbchandler.h index 318f745..0b3c2f3 100644 --- a/dbc/dbchandler.h +++ b/dbc/dbchandler.h @@ -55,6 +55,9 @@ public: DBCFile& operator=(const DBCFile& cpy); DBC_NODE *findNodeByName(QString name); DBC_NODE *findNodeByIdx(int idx); + DBC_ATTRIBUTE *findAttributeByName(QString name); + DBC_ATTRIBUTE *findAttributeByIdx(int idx); + void findAttributesByType(DBC_ATTRIBUTE_TYPE typ, QList *list); void saveFile(QString); void loadFile(QString); QString getFullFilename(); @@ -70,6 +73,8 @@ private: QString fileName; QString filePath; int assocBuses; //-1 = all buses, 0 = first bus, 1 = second bus, etc. + + bool parseAttribute(QString inpString, DBC_ATTRIBUTE &attr); }; class DBCHandler: public QObject diff --git a/framefileio.cpp b/framefileio.cpp index 9589ad0..1a1c313 100644 --- a/framefileio.cpp +++ b/framefileio.cpp @@ -5,6 +5,8 @@ #include +#include "utility.h" + FrameFileIO::FrameFileIO() { @@ -872,7 +874,7 @@ bool FrameFileIO::loadIXXATFile(QString filename, QVector* frames) QList tokens = line.split(','); if (line.length() >= 5) { - QString timePortion = unQuote(tokens[0]); + QString timePortion = Utility::unQuote(tokens[0]); QStringList timeToks = timePortion.split(':'); if (timeToks.length() >= 3) { @@ -885,8 +887,8 @@ bool FrameFileIO::loadIXXATFile(QString filename, QVector* frames) foundErrors = true; } thisFrame.timestamp = timeStamp; - thisFrame.ID = unQuote(tokens[1]).toInt(NULL, 16); - QString tempStr = unQuote(tokens[2]).toUpper(); + thisFrame.ID = Utility::unQuote(tokens[1]).toInt(NULL, 16); + QString tempStr = Utility::unQuote(tokens[2]).toUpper(); if (tempStr.length() > 0) { if (tempStr.at(0) == 'S') thisFrame.extended = false; @@ -901,7 +903,7 @@ bool FrameFileIO::loadIXXATFile(QString filename, QVector* frames) thisFrame.isReceived = true; thisFrame.bus = 0; - QStringList dataToks = unQuote(tokens[4]).simplified().split(' '); + QStringList dataToks = Utility::unQuote(tokens[4]).simplified().split(' '); thisFrame.len = dataToks.length(); for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = dataToks[d].toInt(NULL, 16); frames->append(thisFrame); @@ -1481,12 +1483,3 @@ bool FrameFileIO::loadCanDumpFile(QString filename, QVector* frames) return true; } - -QString FrameFileIO::unQuote(QString inStr) -{ - QStringList temp; - temp = inStr.split('\"'); - if (temp.length() >= 3) - return temp[1]; - return QString(""); -} diff --git a/framefileio.h b/framefileio.h index 0c45515..d22e423 100644 --- a/framefileio.h +++ b/framefileio.h @@ -50,9 +50,6 @@ public: static bool saveVehicleSpyFile(QString, const QVector*); static bool loadCanDumpFile(QString, QVector*); static bool loadPCANFile(QString, QVector*); - -private: - static QString unQuote(QString); }; #endif // FRAMEFILEIO_H diff --git a/utility.h b/utility.h index e2792ad..fd81b29 100644 --- a/utility.h +++ b/utility.h @@ -13,6 +13,15 @@ public: static bool decimalMode; + static QString unQuote(QString inStr) + { + QStringList temp; + temp = inStr.split('\"'); + if (temp.length() >= 3) + return temp[1]; + return inStr; + } + static uint64_t ParseStringToNum(QByteArray input) { uint64_t temp = 0;