Added decoding support to runtime decode.

This commit is contained in:
2026-03-13 13:30:38 -04:00
parent cb20f5fe55
commit a53a5dfed3
12 changed files with 562 additions and 56 deletions

View File

@@ -3,7 +3,6 @@
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <algorithm>
#include <cctype>
namespace {
@@ -14,11 +13,13 @@ namespace {
*/
std::string TrimText (const std::string &text) {
std::string::size_type begin = 0U;
while ((begin < text.size()) && std::isspace (static_cast<unsigned char> (text[begin])))
while ((begin < text.size()) &&
std::isspace (static_cast<unsigned char> (text[begin])))
++begin;
std::string::size_type end = text.size();
while ((end > begin) && std::isspace (static_cast<unsigned char> (text[end - 1U])))
while ((end > begin) &&
std::isspace (static_cast<unsigned char> (text[end - 1U])))
--end;
return text.substr (begin, end - begin);
@@ -86,13 +87,29 @@ std::vector<std::string> DbcParser::SplitReceivers (const std::string &text) {
return receivers;
}
std::uint32_t DbcParser::TryExtractPgn (std::uint32_t canId, bool &hasPgn) {
void DbcParser::NormalizeCanId (std::uint32_t rawCanId,
std::uint32_t &normalizedCanId,
bool &isExtended) {
/*
* DBC commonly stores extended identifiers with bit 31 set.
* Example:
* raw id = 0x80000000 | actual_29_bit_id
*/
if ((rawCanId & 0x80000000U) != 0U) {
isExtended = true;
normalizedCanId = (rawCanId & 0x1FFFFFFFU);
} else {
isExtended = (rawCanId > 0x7FFU);
normalizedCanId = rawCanId;
}
}
std::uint32_t DbcParser::TryExtractPgn (std::uint32_t canId, bool isExtended, bool &hasPgn) {
hasPgn = false;
/*
* Very simplified J1939 PGN extraction.
* Assumes 29-bit identifier.
*/
if (!isExtended)
return 0U;
if ((canId & 0x1FFFFFFFU) != canId)
return 0U;
@@ -114,20 +131,22 @@ std::uint32_t DbcParser::TryExtractPgn (std::uint32_t canId, bool &hasPgn) {
FrameInfo DbcParser::ParseFrameLine (const std::string &line) {
/*
* Example:
* BO_ 256 EngineData: 8 Vector__XXX
* BO_ 256 EngineData: 8 EEC1
*/
std::istringstream stream (line);
std::string token;
FrameInfo frame;
std::uint32_t rawCanId = 0U;
stream >> token;
if (token != "BO_")
throw std::runtime_error ("Invalid frame line: " + line);
stream >> frame.canId;
stream >> token;
stream >> rawCanId;
NormalizeCanId (rawCanId, frame.canId, frame.isExtended);
stream >> token;
if (token.empty())
throw std::runtime_error ("Missing frame name: " + line);
@@ -143,7 +162,7 @@ FrameInfo DbcParser::ParseFrameLine (const std::string &line) {
}
stream >> frame.transmitter;
frame.pgn = TryExtractPgn (frame.canId, frame.hasPgn);
frame.pgn = TryExtractPgn (frame.canId, frame.isExtended, frame.hasPgn);
return frame;
}
@@ -151,7 +170,7 @@ FrameInfo DbcParser::ParseFrameLine (const std::string &line) {
SignalInfo DbcParser::ParseSignalLine (const std::string &line) {
/*
* Example:
* SG_ EngineSpeed : 0|16@1+ (0.125,0) [0|8000] "rpm" Vector__XXX
* SG_ EngineSpeed : 0|16@1+ (0.125,0) [0|8000] "rpm" ECU1,ECU2
*/
SignalInfo signal;
@@ -258,8 +277,12 @@ void DbcParser::ParseCommentLine (const std::string &line, DbcDatabase &database
stream >> token;
if (token == "BO_") {
std::uint32_t rawCanId = 0U;
std::uint32_t canId = 0U;
stream >> canId;
bool isExtended = false;
stream >> rawCanId;
NormalizeCanId (rawCanId, canId, isExtended);
const std::string::size_type quoteBegin = line.find ('"');
const std::string::size_type quoteEnd = line.rfind ('"');
@@ -269,16 +292,20 @@ void DbcParser::ParseCommentLine (const std::string &line, DbcDatabase &database
(quoteEnd <= quoteBegin))
return;
FrameInfo *frame = FindFrameById (database, canId);
FrameInfo *frame = FindFrameById (database, canId, isExtended);
if (frame != nullptr)
frame->comment = line.substr (quoteBegin + 1U, quoteEnd - quoteBegin - 1U);
} else if (token == "SG_") {
std::uint32_t rawCanId = 0U;
std::uint32_t canId = 0U;
bool isExtended = false;
std::string signalName;
stream >> canId;
stream >> rawCanId;
stream >> signalName;
NormalizeCanId (rawCanId, canId, isExtended);
const std::string::size_type quoteBegin = line.find ('"');
const std::string::size_type quoteEnd = line.rfind ('"');
@@ -287,7 +314,7 @@ void DbcParser::ParseCommentLine (const std::string &line, DbcDatabase &database
(quoteEnd <= quoteBegin))
return;
FrameInfo *frame = FindFrameById (database, canId);
FrameInfo *frame = FindFrameById (database, canId, isExtended);
if (frame != nullptr) {
SignalInfo *signal = FindSignalByName (*frame, signalName);
if (signal != nullptr)
@@ -296,9 +323,12 @@ void DbcParser::ParseCommentLine (const std::string &line, DbcDatabase &database
}
}
FrameInfo *DbcParser::FindFrameById (DbcDatabase &database, std::uint32_t canId) {
FrameInfo *DbcParser::FindFrameById (DbcDatabase &database,
std::uint32_t canId,
bool isExtended) {
for (std::size_t index = 0U; index < database.frames.size(); ++index) {
if (database.frames[index].canId == canId)
if ((database.frames[index].canId == canId) &&
(database.frames[index].isExtended == isExtended))
return &database.frames[index];
}