Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ use can_dbc::MultiplexIndicator::{
MultiplexedSignal, Multiplexor, MultiplexorAndMultiplexedSignal, Plain,
};
use can_dbc::ValueType::Signed;
use can_dbc::{Dbc, Message, MessageId, Signal, Transmitter, ValDescription, ValueDescription};
use can_dbc::{
AttributeValue, Dbc, Message, MessageId, Signal, Transmitter, ValDescription, ValueDescription,
};
use heck::ToSnakeCase;
use quote::ToTokens;
use typed_builder::TypedBuilder;
Expand Down Expand Up @@ -134,6 +136,13 @@ impl Config<'_> {
writeln!(w, "use bitvec::prelude::*;")?;
writeln!(w, "#[allow(unused_imports)]")?;
writeln!(w, "use embedded_can::{{Id, StandardId, ExtendedId}};")?;
if get_relevant_messages(&dbc).any(|m| {
message_attr(&dbc, m.id, "GenMsgCycleTime")
.and_then(attr_value_u64)
.is_some()
}) {
writeln!(w, "use core::time::Duration;")?;
}

self.impl_arbitrary.fmt_cfg(&mut w, |w| {
writeln!(w, "use arbitrary::{{Arbitrary, Unstructured}};")
Expand Down Expand Up @@ -278,6 +287,11 @@ impl Config<'_> {
)?;
writeln!(w)?;

writeln!(w, "pub const MESSAGE_SIZE: usize = {};", msg.size)?;
writeln!(w)?;

Self::render_cycle_time(&mut w, msg, dbc)?;

for signal in &msg.signals {
let typ = ValType::from_signal(signal);
if typ != ValType::Bool {
Expand Down Expand Up @@ -414,6 +428,23 @@ impl Config<'_> {
Ok(())
}

/// Emit the cycle time as a constant for messages that have an assigned
/// `GenMsgCycleTime` (`BA_`) attribute.
fn render_cycle_time(w: &mut impl Write, msg: &Message, dbc: &Dbc) -> Result<()> {
let Some(ms) = message_attr(dbc, msg.id, "GenMsgCycleTime").and_then(attr_value_u64) else {
return Ok(());
};
writeln!(
w,
"/// Message cycle time (from the `GenMsgCycleTime` attribute)."
)?;
writeln!(
w,
"pub const MESSAGE_CYCLE_TIME: Duration = Duration::from_millis({ms});"
)?;
Ok(())
}

fn render_signal(
&self,
w: &mut impl Write,
Expand Down Expand Up @@ -1322,6 +1353,23 @@ fn message_ignored(message: &Message) -> bool {
message.name == "VECTOR__INDEPENDENT_SIG_MSG"
}

/// Look up an assigned message-level (`BO_`) attribute value.
fn message_attr<'a>(dbc: &'a Dbc, id: MessageId, name: &str) -> Option<&'a AttributeValue> {
dbc.attribute_values_message
.iter()
.find(|a| a.message_id == id && a.name == name)
.map(|a| &a.value)
}

/// Interpret an attribute value as a non-negative integer, if it is one.
fn attr_value_u64(value: &AttributeValue) -> Option<u64> {
match value {
AttributeValue::Uint(v) => Some(*v),
AttributeValue::Int(v) => u64::try_from(*v).ok(),
AttributeValue::Double(_) | AttributeValue::String(_) => None,
}
}

impl Config<'_> {
/// Generate Rust structs matching DBC input description and return as String
pub fn generate(self) -> Result<String> {
Expand Down
9 changes: 9 additions & 0 deletions testing/can-messages/tests/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,12 @@ fn test_extended_id() {
Id::Extended(ExtendedId::new(0x1234).unwrap())
);
}

#[test]
fn test_message_size() {
assert_eq!(Foo::MESSAGE_SIZE, 4);
assert_eq!(MsgExtendedId::MESSAGE_SIZE, 8);

let m = Foo::new(0.0, 0.0).unwrap();
assert_eq!(m.raw().len(), Foo::MESSAGE_SIZE);
}
2 changes: 2 additions & 0 deletions tests-snapshots/canpy/DBC_template.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl CanMultiplexed {
pub const MESSAGE_ID: embedded_can::Id = Id::Extended(unsafe {
ExtendedId::new_unchecked(0x10e1)
});
pub const MESSAGE_SIZE: usize = 2;
pub const VALUE1_MIN: u8 = 0_u8;
pub const VALUE1_MAX: u8 = 0_u8;
pub const VALUE0_MIN: u8 = 0_u8;
Expand Down Expand Up @@ -454,6 +455,7 @@ impl CanMessage {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x4d2)
});
pub const MESSAGE_SIZE: usize = 8;
pub const SIGNAL1_MIN: u64 = 0_u64;
pub const SIGNAL1_MAX: u64 = 100_u64;
pub const SIGNAL0_MIN: i32 = 0_i32;
Expand Down
1 change: 1 addition & 0 deletions tests-snapshots/dbc-cantools/BU_BO_REL_.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl Control {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x1)
});
pub const MESSAGE_SIZE: usize = 7;
pub const STATE_MIN: u8 = 0_u8;
pub const STATE_MAX: u8 = 100_u8;
/// Construct new CONTROL from values
Expand Down
1 change: 1 addition & 0 deletions tests-snapshots/dbc-cantools/BU_BO_REL_Message.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl Message1 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x1)
});
pub const MESSAGE_SIZE: usize = 7;
pub const SIGNAL_1_MIN: u8 = 0_u8;
pub const SIGNAL_1_MAX: u8 = 100_u8;
/// Construct new message_1 from values
Expand Down
1 change: 1 addition & 0 deletions tests-snapshots/dbc-cantools/CamelCaseEmpty.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl Message1 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x400)
});
pub const MESSAGE_SIZE: usize = 5;
/// Construct new Message1 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 5] };
Expand Down
18 changes: 18 additions & 0 deletions tests-snapshots/dbc-cantools/abs.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl Bremse33 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x343)
});
pub const MESSAGE_SIZE: usize = 8;
pub const WHLSPEED_FL_MIN: f32 = 0_f32;
pub const WHLSPEED_FL_MAX: f32 = 100_f32;
pub const WHLSPEED_FR_MIN: f32 = 0_f32;
Expand Down Expand Up @@ -369,6 +370,7 @@ impl Bremse10 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x140)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new BREMSE_10 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down Expand Up @@ -439,6 +441,7 @@ impl Bremse11 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x141)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new BREMSE_11 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down Expand Up @@ -509,6 +512,7 @@ impl Bremse12 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x142)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new BREMSE_12 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down Expand Up @@ -579,6 +583,7 @@ impl Bremse13 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x143)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new BREMSE_13 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down Expand Up @@ -649,6 +654,7 @@ impl DrsRxId0 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x75)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new DRS_RX_ID0 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down Expand Up @@ -719,6 +725,7 @@ impl Mm510Tx1 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x70)
});
pub const MESSAGE_SIZE: usize = 8;
pub const YAW_RATE_MIN: f32 = -163.84_f32;
pub const YAW_RATE_MAX: f32 = 163.83_f32;
pub const AY1_MIN: f32 = -4.1768_f32;
Expand Down Expand Up @@ -877,6 +884,7 @@ impl Mm510Tx2 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x80)
});
pub const MESSAGE_SIZE: usize = 8;
pub const ROLL_RATE_MIN: f32 = -163.84_f32;
pub const ROLL_RATE_MAX: f32 = 163.835_f32;
pub const AX1_MIN: f32 = -4.1768_f32;
Expand Down Expand Up @@ -1035,6 +1043,7 @@ impl Mm510Tx3 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x576)
});
pub const MESSAGE_SIZE: usize = 8;
pub const AZ_MIN: f32 = -4.1768_f32;
pub const AZ_MAX: f32 = 4.1765_f32;
/// Construct new MM5_10_TX3 from values
Expand Down Expand Up @@ -1149,6 +1158,7 @@ impl Bremse2 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x24a)
});
pub const MESSAGE_SIZE: usize = 8;
pub const WHLSPEED_FL_BREMSE2_MIN: f32 = 0_f32;
pub const WHLSPEED_FL_BREMSE2_MAX: f32 = 100_f32;
pub const WHLSPEED_FR_BREMSE2_MIN: f32 = 0_f32;
Expand Down Expand Up @@ -1399,6 +1409,7 @@ impl AbsSwitch {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x24c)
});
pub const MESSAGE_SIZE: usize = 8;
pub const ABS_SWITCHPOSITION_MIN: u8 = 0_u8;
pub const ABS_SWITCHPOSITION_MAX: u8 = 11_u8;
/// Construct new ABS_Switch from values
Expand Down Expand Up @@ -1516,6 +1527,7 @@ impl Bremse30 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x340)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new BREMSE_30 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down Expand Up @@ -1586,6 +1598,7 @@ impl Bremse31 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x341)
});
pub const MESSAGE_SIZE: usize = 8;
pub const IDLE_TIME_MIN: u16 = 0_u16;
pub const IDLE_TIME_MAX: u16 = 0_u16;
/// Construct new BREMSE_31 from values
Expand Down Expand Up @@ -1701,6 +1714,7 @@ impl Bremse32 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x342)
});
pub const MESSAGE_SIZE: usize = 8;
pub const ACC_FA_MIN: f32 = 0_f32;
pub const ACC_FA_MAX: f32 = 10_f32;
pub const ACC_RA_MIN: f32 = 0_f32;
Expand Down Expand Up @@ -2086,6 +2100,7 @@ impl Bremse51 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x541)
});
pub const MESSAGE_SIZE: usize = 8;
pub const AX1_ABS_INT_MIN: f32 = -4.1768_f32;
pub const AX1_ABS_INT_MAX: f32 = 4.1736697_f32;
pub const AY1_ABS_INT_MIN: f32 = -4.1768_f32;
Expand Down Expand Up @@ -2391,6 +2406,7 @@ impl Bremse52 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x542)
});
pub const MESSAGE_SIZE: usize = 8;
pub const MPLX_SW_INFO_MIN: u8 = 0_u8;
pub const MPLX_SW_INFO_MAX: u8 = 255_u8;
pub const SW_VERSION_HIGH_UPPER_MIN: u8 = 0_u8;
Expand Down Expand Up @@ -4522,6 +4538,7 @@ impl Bremse50 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x560)
});
pub const MESSAGE_SIZE: usize = 8;
pub const BRAKE_BAL_AT50_MIN: f32 = 0_f32;
pub const BRAKE_BAL_AT50_MAX: f32 = 100_f32;
pub const BRAKE_BAL_AT50_ADVICE_MIN: u8 = 0_u8;
Expand Down Expand Up @@ -4779,6 +4796,7 @@ impl Bremse53 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x5c0)
});
pub const MESSAGE_SIZE: usize = 8;
pub const SWITCH_POSITION_MIN: u8 = 1_u8;
pub const SWITCH_POSITION_MAX: u8 = 12_u8;
pub const P_FA_MIN: f32 = -42.5_f32;
Expand Down
2 changes: 2 additions & 0 deletions tests-snapshots/dbc-cantools/add_two_dbc_files_1.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl M1 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x1)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new M1 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down Expand Up @@ -140,6 +141,7 @@ impl M2 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x2)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new M2 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down
1 change: 1 addition & 0 deletions tests-snapshots/dbc-cantools/add_two_dbc_files_2.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl M1 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x2)
});
pub const MESSAGE_SIZE: usize = 8;
/// Construct new M1 from values
pub fn new() -> Result<Self, CanError> {
let res = Self { raw: [0u8; 8] };
Expand Down
4 changes: 4 additions & 0 deletions tests-snapshots/dbc-cantools/attribute_Event.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::ops::BitOr;
use bitvec::prelude::*;
#[allow(unused_imports)]
use embedded_can::{Id, StandardId, ExtendedId};
use core::time::Duration;
/// All messages
#[allow(
clippy::absurd_extreme_comparisons,
Expand Down Expand Up @@ -69,6 +70,9 @@ impl Inv2EventMsg1 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x4d2)
});
pub const MESSAGE_SIZE: usize = 8;
/// Message cycle time (from the `GenMsgCycleTime` attribute).
pub const MESSAGE_CYCLE_TIME: Duration = Duration::from_millis(0);
pub const THE_SIGNAL_MIN: i8 = 0_i8;
pub const THE_SIGNAL_MAX: i8 = 0_i8;
/// Construct new INV2EventMsg1 from values
Expand Down
5 changes: 5 additions & 0 deletions tests-snapshots/dbc-cantools/attributes.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::ops::BitOr;
use bitvec::prelude::*;
#[allow(unused_imports)]
use embedded_can::{Id, StandardId, ExtendedId};
use core::time::Duration;
/// All messages
#[allow(
clippy::absurd_extreme_comparisons,
Expand Down Expand Up @@ -73,6 +74,9 @@ impl TheMessage {
pub const MESSAGE_ID: embedded_can::Id = Id::Extended(unsafe {
ExtendedId::new_unchecked(0x39)
});
pub const MESSAGE_SIZE: usize = 8;
/// Message cycle time (from the `GenMsgCycleTime` attribute).
pub const MESSAGE_CYCLE_TIME: Duration = Duration::from_millis(1000);
pub const THE_SIGNAL_MIN: i8 = 0_i8;
pub const THE_SIGNAL_MAX: i8 = 0_i8;
/// Construct new TheMessage from values
Expand Down Expand Up @@ -189,6 +193,7 @@ impl TheOtherMessage {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x2a)
});
pub const MESSAGE_SIZE: usize = 8;
pub const THE_SIGNAL_MIN: i8 = 0_i8;
pub const THE_SIGNAL_MAX: i8 = 0_i8;
/// Construct new TheOtherMessage from values
Expand Down
5 changes: 5 additions & 0 deletions tests-snapshots/dbc-cantools/attributes_relation.snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::ops::BitOr;
use bitvec::prelude::*;
#[allow(unused_imports)]
use embedded_can::{Id, StandardId, ExtendedId};
use core::time::Duration;
/// All messages
#[allow(
clippy::absurd_extreme_comparisons,
Expand Down Expand Up @@ -70,6 +71,9 @@ impl Message2 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x53)
});
pub const MESSAGE_SIZE: usize = 8;
/// Message cycle time (from the `GenMsgCycleTime` attribute).
pub const MESSAGE_CYCLE_TIME: Duration = Duration::from_millis(50);
pub const SIGNAL_2_MIN: i8 = 0_i8;
pub const SIGNAL_2_MAX: i8 = 0_i8;
/// Construct new Message_2 from values
Expand Down Expand Up @@ -187,6 +191,7 @@ impl Message1 {
pub const MESSAGE_ID: embedded_can::Id = Id::Standard(unsafe {
StandardId::new_unchecked(0x52)
});
pub const MESSAGE_SIZE: usize = 8;
pub const SIGNAL_1_MIN: i8 = 0_i8;
pub const SIGNAL_1_MAX: i8 = 0_i8;
/// Construct new Message_1 from values
Expand Down
Loading