Add the ability to load several forms of DBC attributes.

This commit is contained in:
Collin Kidder
2017-01-16 21:00:26 -05:00
parent 74f6d7f947
commit 49b2ac0155
7 changed files with 330 additions and 25 deletions
+60
View File
@@ -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];
}
+10 -1
View File
@@ -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<DBC_ATTRIBUTE_VALUE> 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<DBC_ATTRIBUTE_VALUE> attributes;
DBCSignalHandler *sigHandler;
DBC_SIGNAL* multiplexorSignal;
DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name);
DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx);
};
+239 -7
View File
@@ -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<DBC_ATTRIBUTE> *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);
+5
View File
@@ -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<DBC_ATTRIBUTE> *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
+6 -13
View File
@@ -5,6 +5,8 @@
#include <iostream>
#include "utility.h"
FrameFileIO::FrameFileIO()
{
@@ -872,7 +874,7 @@ bool FrameFileIO::loadIXXATFile(QString filename, QVector<CANFrame>* frames)
QList<QByteArray> 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<CANFrame>* 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<CANFrame>* 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<CANFrame>* frames)
return true;
}
QString FrameFileIO::unQuote(QString inStr)
{
QStringList temp;
temp = inStr.split('\"');
if (temp.length() >= 3)
return temp[1];
return QString("");
}
-3
View File
@@ -50,9 +50,6 @@ public:
static bool saveVehicleSpyFile(QString, const QVector<CANFrame>*);
static bool loadCanDumpFile(QString, QVector<CANFrame>*);
static bool loadPCANFile(QString, QVector<CANFrame>*);
private:
static QString unQuote(QString);
};
#endif // FRAMEFILEIO_H
+9
View File
@@ -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;