Crates.io | dbcc |
lib.rs | dbcc |
version | 2.2.1 |
source | src |
created_at | 2019-04-09 20:47:41.131497 |
updated_at | 2020-11-05 11:32:47.563438 |
description | Compiles `data base CAN` (dbc) files into Rust code. |
homepage | https://github.com/marcelbuesing/dbcc |
repository | https://github.com/marcelbuesing/dbcc.git |
max_upload_size | |
id | 126884 |
size | 3,111,071 |
=============
dbcc can translate data base CAN
files into Rust code.
The generated code allows interacting with CAN signals in a type safe manner by e.g. matching against signal value enum types.
Furthermore it provides a convenient way to use SocketCAN BCM Sockets, via tokio streams, to filter for a specified message by can identifier.
Install
cargo install dbcc
Generate code using the CLI.
dbcc --input dbcc --with-tokio -i examples/j1939.dbc > examples/gen/j1939.rs
For warnings during the generation run with:
RUST_LOG=info dbcc --with-tokio -i examples/j1939.dbc > examples/gen/j1939.rs
Generate code at build time. Add the following to your build.rs. Adapt the dbc input path and target path according to your needs.
use dbcc::{DbccOpt, can_code_gen};
use can_dbc;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
fn main() -> std::io::Result<()> {
let dbcs = &[
("./dbcs/j1939.dbc", "./src/lib.rs"),
];
generate_code_for_dbc(dbcs)?;
Ok(())
}
fn generate_code_for_dbc<P: AsRef<Path>>(input_output: &[(P, P)]) -> std::io::Result<()> {
for (input_path, output_path) in input_output {
let mut f = File::open(input_path).expect("Failed to open input file");
let mut buffer = Vec::new();
f.read_to_end(&mut buffer).expect("Failed to read file");
let opt = DbccOpt {
with_tokio: true,
};
let dbc_content = can_dbc::DBC::from_slice(&buffer).expect("Failed to read DBC file");
let code = can_code_gen(&opt, &dbc_content).expect("Failed to generate rust code");
let mut f = File::create(output_path)?;
f.write_all(&code.to_string().into_bytes())?;
}
Ok(())
}
src/
folder.Cargo.toml
[dependencies]
byteorder = "1.2"
/// If you are using Rust 2018 no `external crate byteorder;` is necessary
/// Generated module
mod j1939;
fn main() {
// J1939 - Operators External Light Controls Message Id
let can_message_id = 2365443326u32;
// can frame data field (0-8 bytes)
let can_frame_data: Vec<u8> = vec![0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
// CAN Message ID constant from generated code
if can_message_id == j1939::MESSAGE_ID_OEL {
// J1939 - Operators External Light Controls Message
let oel = j1939::Oel::new(can_frame_data);
// Signal indicate the selected position of the operator's hazard light switch.
match oel.hazardlightswitch() {
j1939::HazardLightSwitch2365443326::HazardLampsToBeFlashing => println!("Hazard Lamps To Be Flashing"),
j1939::HazardLightSwitch2365443326::HazardLampsToBeOff => println!("Hazard Lamps To Be Off"),
j1939::HazardLightSwitch2365443326::NotAvailable => println!("Not available"),
j1939::HazardLightSwitch2365443326::Error => println!("Error"),
j1939::HazardLightSwitch2365443326::XValue(_) => unreachable!(),
}
}
}
--with-tokio
flag when invoking dbcc.src/
folder.Cargo.toml
[dependencies]
byteorder = "1.3"
futures = "0.3"
tokio = "0.3"
tokio-socketcan-bcm = "1.0"
mod j1939;
use futures::future::Future;
use futures::stream::Stream;
use std::io;
use std::time::Duration;
use tokio;
fn main() -> io::Result<()> {
let ival = Duration::from_secs(0);
let f = j1939::Oel::stream("vcan0", &ival, &ival)?
.for_each(|oel| {
// Signal indicates the selected position of the operator's hazard light switch.
match oel.hazardlightswitch() {
j1939::HazardLightSwitch2365443326::HazardLampsToBeFlashing => {
println!("Hazard Lamps To Be Flashing")
}
j1939::HazardLightSwitch2365443326::HazardLampsToBeOff => {
println!("Hazard Lamps To Be Off")
}
j1939::HazardLightSwitch2365443326::NotAvailable => println!("Not available"),
j1939::HazardLightSwitch2365443326::Error => println!("Error"),
j1939::HazardLightSwitch2365443326::XValue(_) => unreachable!(),
}
Ok(())
});
tokio::run(f.map_err(|_| ()));
Ok(())
}
Recommendation: Value descriptions aka VAL_ ...
should contain only
alphanumeric characters or underscores and should start with an alphabetic character.
E.g. VAL_ 100 "111 Wunderschön Inc" 255
should be VAL_ 100 " Wunderschoen Inc 111" 255
X
if the name does not start with an alphabetic character._
are replaced with an X
XValue(f64)
variant is added to each enum since value descriptions often do not cover all possibilities.