From ef4e1c3400c103eaf9c71f66a5d9b1905387d174 Mon Sep 17 00:00:00 2001 From: deanlee Date: Wed, 6 Sep 2023 17:59:08 +0800 Subject: [PATCH] build message lookup table in dbc --- can/common.h | 3 +-- can/common.pxd | 4 ++-- can/common_dbc.h | 6 +++++- can/dbc.cc | 14 ++++++++++++++ can/packer.cc | 18 ++++++++++++------ can/packer_pyx.pyx | 35 +++++------------------------------ 6 files changed, 39 insertions(+), 41 deletions(-) diff --git a/can/common.h b/can/common.h index 03b99e5598..ee01eef943 100644 --- a/can/common.h +++ b/can/common.h @@ -92,11 +92,10 @@ class CANPacker { private: const DBC *dbc = NULL; std::map, Signal> signal_lookup; - std::map message_lookup; std::map counters; public: CANPacker(const std::string& dbc_name); - std::vector pack(uint32_t address, const std::vector &values); + std::pair> pack(const std::string &name_or_address, const std::vector &values); Msg* lookup_message(uint32_t address); }; diff --git a/can/common.pxd b/can/common.pxd index 477f71b2d3..b01aa9f4ec 100644 --- a/can/common.pxd +++ b/can/common.pxd @@ -71,5 +71,5 @@ cdef extern from "common.h": void update_strings(vector[string]&, vector[SignalValue]&, bool) except + cdef cppclass CANPacker: - CANPacker(string) - vector[uint8_t] pack(uint32_t, vector[SignalPackValue]&) + CANPacker(string) except + + pair[uint32_t, vector[uint8_t]] pack(const string&, vector[SignalPackValue]&) diff --git a/can/common_dbc.h b/can/common_dbc.h index e8c27278c5..31e1094c18 100644 --- a/can/common_dbc.h +++ b/can/common_dbc.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include #include #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) @@ -61,6 +61,10 @@ struct DBC { std::string name; std::vector msgs; std::vector vals; + std::unordered_map address_to_msg; + std::unordered_map name_to_msg; + + const Msg *findMessage(const std::string &name_or_address) const; }; typedef struct ChecksumState { diff --git a/can/dbc.cc b/can/dbc.cc index 7abe6b679c..0acfde6ed9 100644 --- a/can/dbc.cc +++ b/can/dbc.cc @@ -200,6 +200,8 @@ DBC* dbc_parse_from_stream(const std::string &dbc_name, std::istream &stream, Ch for (auto& m : dbc->msgs) { m.sigs = signals[m.address]; + dbc->address_to_msg[m.address] = &m; + dbc->name_to_msg[m.name] = &m; } for (auto& v : dbc->vals) { v.sigs = signals[v.address]; @@ -256,3 +258,15 @@ std::vector get_dbc_names() { } return dbcs; } + +const Msg* DBC::findMessage(const std::string& name_or_address) const { + auto it = name_to_msg.find(name_or_address); + if (it != name_to_msg.end()) return it->second; + + try { + uint32_t address = std::stoul(name_or_address); + return address_to_msg.at(address); + } catch (std::exception& ex) { + return nullptr; + } +} diff --git a/can/packer.cc b/can/packer.cc index ad762828bc..db39f5b292 100644 --- a/can/packer.cc +++ b/can/packer.cc @@ -30,10 +30,11 @@ void set_value(std::vector &msg, const Signal &sig, int64_t ival) { CANPacker::CANPacker(const std::string& dbc_name) { dbc = dbc_lookup(dbc_name); - assert(dbc); + if (!dbc) { + throw std::runtime_error("Can't find DBC: " + dbc_name); + } for (const auto& msg : dbc->msgs) { - message_lookup[msg.address] = msg; for (const auto& sig : msg.sigs) { signal_lookup[std::make_pair(msg.address, std::string(sig.name))] = sig; } @@ -41,8 +42,13 @@ CANPacker::CANPacker(const std::string& dbc_name) { init_crc_lookup_tables(); } -std::vector CANPacker::pack(uint32_t address, const std::vector &signals) { - std::vector ret(message_lookup[address].size, 0); +std::pair> CANPacker::pack(const std::string &name_or_address, const std::vector &signals) { + auto msg = dbc->findMessage(name_or_address); + if (!msg) { + throw std::runtime_error("Can't find message: " + name_or_address); + } + uint32_t address = msg->address; + std::vector ret(msg->size, 0); // set all values for all given signal/value pairs bool counter_set = false; @@ -89,10 +95,10 @@ std::vector CANPacker::pack(uint32_t address, const std::vectoraddress_to_msg.at(address); } diff --git a/can/packer_pyx.pyx b/can/packer_pyx.pyx index 5133fcc990..ff191a8fae 100644 --- a/can/packer_pyx.pyx +++ b/can/packer_pyx.pyx @@ -1,49 +1,24 @@ # distutils: language = c++ # cython: c_string_encoding=ascii, language_level=3 -from libc.stdint cimport uint8_t from libcpp.vector cimport vector -from libcpp.map cimport map -from libcpp.string cimport string - from .common cimport CANPacker as cpp_CANPacker -from .common cimport dbc_lookup, SignalPackValue, DBC - +from .common cimport SignalPackValue cdef class CANPacker: - cdef: - cpp_CANPacker *packer - const DBC *dbc - map[string, int] name_to_address + cdef cpp_CANPacker *packer def __init__(self, dbc_name): - self.dbc = dbc_lookup(dbc_name) - if not self.dbc: - raise RuntimeError(f"Can't lookup {dbc_name}") - self.packer = new cpp_CANPacker(dbc_name) - for i in range(self.dbc[0].msgs.size()): - msg = self.dbc[0].msgs[i] - self.name_to_address[string(msg.name)] = msg.address - cdef vector[uint8_t] pack(self, addr, values): + cpdef make_can_msg(self, name_or_addr, bus, values): cdef vector[SignalPackValue] values_thing values_thing.reserve(len(values)) cdef SignalPackValue spv - for name, value in values.iteritems(): spv.name = name.encode("utf8") spv.value = value values_thing.push_back(spv) - return self.packer.pack(addr, values_thing) - - cpdef make_can_msg(self, name_or_addr, bus, values): - cdef int addr - if isinstance(name_or_addr, int): - addr = name_or_addr - else: - addr = self.name_to_address[name_or_addr.encode("utf8")] - - cdef vector[uint8_t] val = self.pack(addr, values) - return [addr, 0, (&val[0])[:val.size()], bus] + ret = self.packer.pack(name_or_addr, values_thing) + return [ret.first, 0, (ret.second.data())[:ret.second.size()], bus]