Extends the code generation capability of cantools, which outputs C sources from DBC frame definitions, to create idiomatic C++ interfaces for using CAN message types.
In package.xml, you'll need this as a build_depend.
In your CMakeLists.txt:
find_package(dbc_gen_cpp REQUIRED)
...
generate_dbc_cpp(my_can_library_name
DBC ${CMAKE_CURRENT_SOURCE_DIR}/database.dbc
)
...
target_link_libraries(my_library PUBLIC my_can_library_name)Message structs are defined in the library name's namespace.
They can be implicitly converted to can_frame from <linux/can.h>
#include "my_can_library_name/my_can_library_name.hpp"
...
my_can_library_name::MessageName message{value};
my_can_socket->send(message);
can_frame frame = message;
my_can_socket->send(frame);
A helper class dbc_gen_cpp::CANHandler is provided.
Simply register a handler function for a type via set_handler, then forward all can_frames received to the handle() method to trigger the registered handler functions with the typed structs.
dbc_gen_cpp::CANHandler handler;
handler.set_handler<my_can_library_name::MessageName>(
[](const my_can_library_name::MessageName & message) {
printf('Received MessageName (value %f)\n', message.value);
});
my_can_socket.on_receive(
[&](can_frame frame) {
handler.handle(frame);
});DBC files indicate whether a message uses Standard CAN or J1939 via the two lines below. The first line defines the attribute itself. The second line is applied per message and should appear once for each message that is intended to be treated as J1939, using that message’s specific CAN ID.
BA_DEF_ BO_ "VFrameFormat" ENUM "StandardCAN","ExtendedCAN","reserved","J1939PG";
BA_ "VFrameFormat" BO_ 2364539904 3;
The following will only be defined if a message is labeled as J1939 in the DBC:
- static constexpr uint32_t Pgn
- static constexpr uint8_t DefaultPriority = 3;
- static constexpr uint8_t SourceAddress = 37;
- static constexpr bool IsPduBroadcast = true;
The following will only be defined if the message is J1939 and it's of type PDU1 (destination specific):
- static constexpr uint8_t DefaultDestinationAddress
Note: If you want to safely test if a message is of the J1939 Standard, use the variable
IsJ1939.
- When passing a can frame into the explicit constructor, it will only check if the PGN of the incoming frame matches, instead of the whole CAN ID.
Since dbc_gen_cpp provides mostly functionality via the install/ space with CMake functions and a Python package with importlib-registered Jinja templates, it's not possible to test the full usage of that package internally.
test_dbc_gen_cpp is fully dedicated to providing tests, it is not meant to be used as a dependency by any package.