-
Notifications
You must be signed in to change notification settings - Fork 5
Parsing message #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parsing message #12
Changes from all commits
8895220
55ff2d2
079a46b
339d427
ed42851
f031db6
6d26e81
ea8404c
e09a41c
baca5f7
39f8f90
80f60f4
a7b9a75
26bb483
eb12351
e2ec1de
25f17ce
3af2c0c
d00599c
2fd90e0
deba3da
c883074
876bab9
ca34f24
f7f5741
4dc7dfe
e9e307e
c4d55af
f65b85b
70d8510
117deb6
b7d7585
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#include <libdbc/exceptions/error.hpp> | ||
#include <libdbc/utils/utils.hpp> | ||
#include <libdbc/dbc.hpp> | ||
#include <fast_float/fast_float.h> | ||
|
||
#include <regex> | ||
|
||
|
@@ -28,12 +29,12 @@ const auto whiteSpace = "\\s"; | |
|
||
namespace libdbc { | ||
|
||
DbcParser::DbcParser() : version(""), nodes(), | ||
DbcParser::DbcParser() : version(""), nodes(), | ||
version_re("^(VERSION)\\s\"(.*)\""), bit_timing_re("^(BS_:)"), | ||
name_space_re("^(NS_)\\s\\:"), node_re("^(BU_:)\\s((?:[\\w]+?\\s?)*)"), | ||
message_re("^(BO_)\\s(\\d+)\\s(\\w+)\\:\\s(\\d+)\\s(\\w+|Vector__XXX)"), | ||
// NOTE: No multiplex support yet | ||
signal_re(std::string(whiteSpace) + | ||
signal_re(std::string("^") + whiteSpace + | ||
signalIdentifierPattern + | ||
whiteSpace + | ||
namePattern + | ||
|
@@ -57,11 +58,13 @@ namespace libdbc { | |
|
||
} | ||
|
||
void DbcParser::parse_file(const std::string& file) { | ||
void DbcParser::parse_file(const std::string& file) { | ||
std::ifstream s(file.c_str()); | ||
std::string line; | ||
std::vector<std::string> lines; | ||
|
||
messages.clear(); | ||
|
||
parse_dbc_header(s); | ||
|
||
parse_dbc_nodes(s); | ||
|
@@ -71,8 +74,7 @@ namespace libdbc { | |
lines.push_back(line); | ||
} | ||
|
||
parse_dbc_messages(lines); | ||
|
||
parse_dbc_messages(lines); | ||
} | ||
|
||
std::string DbcParser::get_version() const { | ||
|
@@ -87,6 +89,13 @@ namespace libdbc { | |
return messages; | ||
} | ||
|
||
Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t id, const std::vector<uint8_t>& data, std::vector<double>& out_values) { | ||
for (const auto& message: messages) { | ||
if (message.id() == id) | ||
return message.parseSignals(data, out_values); | ||
} | ||
return Message::ParseSignalsStatus::ErrorUnknownID; | ||
} | ||
|
||
void DbcParser::parse_dbc_header(std::istream& file_stream) { | ||
std::string line; | ||
|
@@ -150,17 +159,21 @@ namespace libdbc { | |
bool is_bigendian = (std::stoul(match.str(5)) == 0); | ||
bool is_signed = (match.str(6) == "-"); | ||
// Alternate groups because a group is for the decimal portion | ||
double factor = std::stod(match.str(7)); | ||
double offset = std::stod(match.str(9)); | ||
double min = std::stod(match.str(11)); | ||
double max = std::stod(match.str(13)); | ||
double factor; | ||
fast_float::from_chars(match.str(7).data(), match.str(7).data() + match.str(7).size(), factor); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think i commented on the bitstream but do we need this library as well? If this gets you going I am good with it. I might come back and rework it out if the single header fails with the new libraries. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the problem is you have to convert the values to a double, but std::stod considers localization. I did not find another way, and this library is way faster than the std lib, and is only a single header There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah gotcha. I didn't realize that #8 mattered with this. Learned something new on that. |
||
double offset; | ||
fast_float::from_chars(match.str(9).data(), match.str(9).data() + match.str(9).size(), offset); | ||
double min; | ||
fast_float::from_chars(match.str(11).data(), match.str(11).data() + match.str(11).size(), min); | ||
double max; | ||
fast_float::from_chars(match.str(13).data(), match.str(13).data() + match.str(13).size(), max); | ||
std::string unit = match.str(15); | ||
|
||
std::vector<std::string> receivers; | ||
utils::String::split(match.str(16), receivers, ','); | ||
|
||
Signal sig(name, is_multiplexed, start_bit, size, is_bigendian, is_signed, factor, offset, min, max, unit, receivers); | ||
messages.back().signals.push_back(sig); | ||
messages.back().appendSignal(sig); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,73 @@ | ||
#include <algorithm> | ||
#include <libdbc/message.hpp> | ||
|
||
namespace libdbc { | ||
Message::Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node) : | ||
id(id), name(name), size(size), node(node) {} | ||
m_id(id), m_name(name), m_size(size), m_node(node) {} | ||
|
||
bool Message::operator==(const Message& rhs) const { | ||
return (this->id == rhs.id) && (this->name == rhs.name) && | ||
(this->size == rhs.size) && (this->node == rhs.node); | ||
} | ||
return (m_id == rhs.id()) && (m_name == rhs.m_name) && | ||
(m_size == rhs.m_size) && (m_node == rhs.m_node); | ||
} | ||
|
||
Message::ParseSignalsStatus Message::parseSignals(const std::vector<uint8_t>& data, std::vector<double>& values) const { | ||
int size = data.size(); | ||
if (size > 8) | ||
return ParseSignalsStatus::ErrorMessageToLong; // not supported yet | ||
|
||
uint64_t data_little_endian = 0; | ||
uint64_t data_big_endian = 0; | ||
for (int i=0; i < size; i++) { | ||
data_little_endian |= ((uint64_t)data[i]) << i * 8; | ||
data_big_endian = (data_big_endian << 8) | (uint64_t)data[i]; | ||
} | ||
|
||
// TODO: does this also work on a big endian machine? | ||
|
||
const uint32_t len = size * 8; | ||
uint64_t v = 0; | ||
for (const auto& signal: m_signals) { | ||
if (signal.is_bigendian) { | ||
uint32_t start_bit = 8* (signal.start_bit / 8) + (7 - (signal.start_bit % 8)); // Calculation taken from python CAN | ||
v = data_big_endian << start_bit; | ||
v = v >> (len - signal.size); | ||
} else { | ||
const uint32_t shiftLeft = (len - (signal.size + signal.start_bit)); | ||
v = data_little_endian << shiftLeft; | ||
v = v >> (shiftLeft + signal.start_bit); | ||
} | ||
|
||
if (signal.is_signed && signal.size > 1) { | ||
switch (signal.size) { | ||
case 8: values.push_back((int8_t)v * signal.factor + signal.offset); break; | ||
case 16: values.push_back((int16_t)v * signal.factor + signal.offset); break; | ||
case 32: values.push_back((int32_t)v * signal.factor + signal.offset); break; | ||
case 64: values.push_back((int64_t)v * signal.factor + signal.offset); break; | ||
default: return ParseSignalsStatus::ErrorInvalidConversion; | ||
} | ||
} else | ||
values.push_back(v * signal.factor + signal.offset); | ||
} | ||
return ParseSignalsStatus::Success; | ||
} | ||
|
||
void Message::appendSignal(const Signal& signal) { | ||
m_signals.push_back(signal); | ||
} | ||
|
||
const std::vector<Signal> Message::signals() const { | ||
return m_signals; | ||
} | ||
|
||
uint32_t Message::id() const { | ||
return m_id; | ||
} | ||
|
||
std::ostream& operator<< (std::ostream &out, const Message& msg) { | ||
out << "Message: {id: " << msg.id << ", "; | ||
out << "name: " << msg.name << ", "; | ||
out << "size: " << msg.size << ", "; | ||
out << "node: " << msg.node << "}"; | ||
std::ostream& operator<< (std::ostream &out, const Message& msg) { | ||
out << "Message: {id: " << msg.id() << ", "; | ||
out << "name: " << msg.m_name << ", "; | ||
out << "size: " << msg.m_size << ", "; | ||
out << "node: " << msg.m_node << "}"; | ||
return out; | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.