mod message_info;
mod signal_info;
pub use message_info::MessageInfo;
pub use signal_info::SignalInfo;
use crate::DataType;
use crate::blocks::ConversionBlock;
pub fn signal_to_data_type(signal: &dbc_rs::Signal) -> DataType {
let length = signal.length();
let is_le = signal.byte_order() == dbc_rs::ByteOrder::LittleEndian;
let is_unsigned = signal.is_unsigned();
match (is_unsigned, is_le, length) {
(true, true, 1..=64) => DataType::UnsignedIntegerLE,
(true, false, 1..=64) => DataType::UnsignedIntegerBE,
(false, true, 1..=64) => DataType::SignedIntegerLE,
(false, false, 1..=64) => DataType::SignedIntegerBE,
_ => DataType::ByteArray,
}
}
pub fn signal_to_bit_count(signal: &dbc_rs::Signal) -> u32 {
let length = signal.length();
match length {
0..=8 => 8,
9..=16 => 16,
17..=32 => 32,
_ => 64,
}
}
#[allow(dead_code)] pub fn signal_to_conversion(signal: &dbc_rs::Signal) -> Option<ConversionBlock> {
let factor = signal.factor();
let offset = signal.offset();
if factor == 1.0 && offset == 0.0 {
return None;
}
Some(ConversionBlock::linear(offset, factor))
}
pub fn signal_to_conversion_with_range(signal: &dbc_rs::Signal) -> Option<ConversionBlock> {
let factor = signal.factor();
let offset = signal.offset();
let min = signal.min();
let max = signal.max();
if factor == 1.0 && offset == 0.0 && min == 0.0 && max == 0.0 {
return None;
}
let mut conv = ConversionBlock::linear(offset, factor);
if min != 0.0 || max != 0.0 {
conv = conv.with_physical_range(min, max);
}
Some(conv)
}
#[allow(dead_code)] pub fn extract_message_info(dbc: &dbc_rs::Dbc) -> alloc::vec::Vec<MessageInfo> {
dbc.messages()
.iter()
.filter(|m| m.signals().iter().next().is_some()) .map(MessageInfo::from_message)
.collect()
}
use alloc::string::String;
use alloc::vec::Vec;
#[allow(dead_code)] pub fn value_descriptions_to_mapping<'a>(
descriptions: impl Iterator<Item = (i64, &'a str)>,
default_text: &str,
) -> (Vec<(i64, String)>, String) {
let mapping: Vec<(i64, String)> = descriptions.map(|(v, t)| (v, String::from(t))).collect();
(mapping, String::from(default_text))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_signal_to_data_type_unsigned_le() {
let dbc = dbc_rs::Dbc::parse(
r#"VERSION "1.0"
BU_:
BO_ 100 TestMsg: 8 Vector__XXX
SG_ TestSig : 0|16@1+ (1,0) [0|65535] "" Vector__XXX
"#,
)
.unwrap();
let msg = dbc.messages().find_by_id(100).unwrap();
let sig = msg.signals().find("TestSig").unwrap();
let dt = signal_to_data_type(sig);
assert!(matches!(dt, DataType::UnsignedIntegerLE));
}
#[test]
fn test_signal_to_conversion_identity() {
let dbc = dbc_rs::Dbc::parse(
r#"VERSION "1.0"
BU_:
BO_ 100 TestMsg: 8 Vector__XXX
SG_ TestSig : 0|16@1+ (1,0) [0|65535] "" Vector__XXX
"#,
)
.unwrap();
let msg = dbc.messages().find_by_id(100).unwrap();
let sig = msg.signals().find("TestSig").unwrap();
assert!(signal_to_conversion(sig).is_none());
}
#[test]
fn test_signal_to_conversion_linear() {
let dbc = dbc_rs::Dbc::parse(
r#"VERSION "1.0"
BU_:
BO_ 100 TestMsg: 8 Vector__XXX
SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm" Vector__XXX
"#,
)
.unwrap();
let msg = dbc.messages().find_by_id(100).unwrap();
let sig = msg.signals().find("RPM").unwrap();
let conv = signal_to_conversion(sig);
assert!(conv.is_some());
let conv = conv.unwrap();
assert_eq!(conv.values.len(), 2);
assert_eq!(conv.values[0], 0.0); assert_eq!(conv.values[1], 0.25); }
#[test]
fn test_signal_info_conversion() {
let dbc = dbc_rs::Dbc::parse(
r#"VERSION "1.0"
BU_:
BO_ 100 TestMsg: 8 Vector__XXX
SG_ Temp : 0|8@1- (0.5,-40) [-40|85] "C" Vector__XXX
"#,
)
.unwrap();
let msg = dbc.messages().find_by_id(100).unwrap();
let sig = msg.signals().find("Temp").unwrap();
let info = SignalInfo::from_signal(sig);
assert_eq!(info.name, "Temp");
assert_eq!(info.unit, Some(String::from("C")));
assert_eq!(info.factor, 0.5);
assert_eq!(info.offset, -40.0);
assert_eq!(info.min, -40.0);
assert_eq!(info.max, 85.0);
assert!(!info.unsigned);
assert_eq!(info.raw_to_physical(0), -40.0);
assert_eq!(info.raw_to_physical(160), 40.0); }
#[test]
fn test_message_info() {
let dbc = dbc_rs::Dbc::parse(
r#"VERSION "1.0"
BU_: ECM
BO_ 256 Engine: 8 ECM
SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm" Vector__XXX
SG_ Temp : 16|8@1- (1,-40) [-40|215] "C" Vector__XXX
"#,
)
.unwrap();
let msg = dbc.messages().find_by_id(256).unwrap();
let info = MessageInfo::from_message(msg);
assert_eq!(info.id, 256);
assert_eq!(info.name, "Engine");
assert_eq!(info.dlc, 8);
assert_eq!(info.sender, "ECM");
assert_eq!(info.signal_count(), 2);
assert!(!info.is_extended);
}
}