Live can
This commit is contained in:
+106
-57
@@ -30,16 +30,11 @@ struct FrameOutput {
|
||||
error_frames: Vec<ErrorFrame>,
|
||||
}
|
||||
|
||||
fn frame_worker(
|
||||
mmap: &[u8],
|
||||
dbc: &Dbc,
|
||||
) -> FrameOutput {
|
||||
let mut channel_data = HashMap::<CanId, Vec<CanFrame>>::new();
|
||||
let mut metadatas = HashMap::<CanId, MessageMetadata>::new();
|
||||
|
||||
let mut unknown_ids = HashSet::<CanId>::new();
|
||||
let mut error_frames = Vec::<ErrorFrame>::new();
|
||||
|
||||
/// Build the LD metadata for a single CAN id from the DBC, applying the
|
||||
/// project's `ld_*`/`Frequency` attribute defaults. Returns `None` when the
|
||||
/// id is not described by the DBC (an "unknown" id). Shared by the ASC decode
|
||||
/// path and the live-CAN path so both produce identical metadata.
|
||||
pub fn build_message_metadata(dbc: &Dbc, id: CanId) -> Option<MessageMetadata> {
|
||||
let get_default = |name: &str| match dbc
|
||||
.attribute_defaults
|
||||
.iter()
|
||||
@@ -56,57 +51,66 @@ fn frame_worker(
|
||||
let default_scale = get_default("ld_scale");
|
||||
let default_decimal_places = get_default("ld_decimal_places");
|
||||
|
||||
let mut add_metadata = |id| {
|
||||
let msg = match dbc.messages.iter().find(|x| x.id.raw() == id) {
|
||||
Some(msg) => msg,
|
||||
None => {
|
||||
unknown_ids.insert(id);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let signals = &msg.signals;
|
||||
let mut signals_meta = Vec::<SignalMetadata>::new();
|
||||
for signal in signals {
|
||||
let decimal_places = dbc
|
||||
.attribute_values_signal
|
||||
.iter()
|
||||
.find(|x| {
|
||||
x.message_id.raw() == id
|
||||
&& x.signal_name == signal.name
|
||||
&& x.name == "ld_decimal_places"
|
||||
})
|
||||
.map_or(default_decimal_places, |x| match x.value {
|
||||
can_dbc::AttributeValue::Uint(val) => val,
|
||||
_ => panic!("Bad ld_decimal_places value type, expected Uint."),
|
||||
});
|
||||
|
||||
signals_meta.push(SignalMetadata {
|
||||
shift: default_shift as u16,
|
||||
scale: default_scale as u16,
|
||||
decimal_places: decimal_places as u16,
|
||||
name: signal.name.clone(),
|
||||
unit: signal.unit.clone(),
|
||||
signal: signal.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let frequency = dbc
|
||||
.attribute_values_message
|
||||
let msg = dbc.messages.iter().find(|x| x.id.raw() == id)?;
|
||||
let signals = &msg.signals;
|
||||
let mut signals_meta = Vec::<SignalMetadata>::new();
|
||||
for signal in signals {
|
||||
let decimal_places = dbc
|
||||
.attribute_values_signal
|
||||
.iter()
|
||||
.find(|x| x.message_id.raw() == id && x.name == "Frequency")
|
||||
.map_or(default_freqency, |x| match x.value {
|
||||
.find(|x| {
|
||||
x.message_id.raw() == id
|
||||
&& x.signal_name == signal.name
|
||||
&& x.name == "ld_decimal_places"
|
||||
})
|
||||
.map_or(default_decimal_places, |x| match x.value {
|
||||
can_dbc::AttributeValue::Uint(val) => val,
|
||||
_ => panic!("Bad Frequency value type, expected Uint."),
|
||||
_ => panic!("Bad ld_decimal_places value type, expected Uint."),
|
||||
});
|
||||
|
||||
metadatas.insert(
|
||||
id,
|
||||
MessageMetadata {
|
||||
id,
|
||||
frequency: frequency as u16,
|
||||
signals: signals_meta,
|
||||
},
|
||||
);
|
||||
signals_meta.push(SignalMetadata {
|
||||
shift: default_shift as u16,
|
||||
scale: default_scale as u16,
|
||||
decimal_places: decimal_places as u16,
|
||||
name: signal.name.clone(),
|
||||
unit: signal.unit.clone(),
|
||||
signal: signal.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
let frequency = dbc
|
||||
.attribute_values_message
|
||||
.iter()
|
||||
.find(|x| x.message_id.raw() == id && x.name == "Frequency")
|
||||
.map_or(default_freqency, |x| match x.value {
|
||||
can_dbc::AttributeValue::Uint(val) => val,
|
||||
_ => panic!("Bad Frequency value type, expected Uint."),
|
||||
});
|
||||
|
||||
Some(MessageMetadata {
|
||||
id,
|
||||
frequency: frequency as u16,
|
||||
signals: signals_meta,
|
||||
})
|
||||
}
|
||||
|
||||
fn frame_worker(
|
||||
mmap: &[u8],
|
||||
dbc: &Dbc,
|
||||
) -> FrameOutput {
|
||||
let mut channel_data = HashMap::<CanId, Vec<CanFrame>>::new();
|
||||
let mut metadatas = HashMap::<CanId, MessageMetadata>::new();
|
||||
|
||||
let mut unknown_ids = HashSet::<CanId>::new();
|
||||
let mut error_frames = Vec::<ErrorFrame>::new();
|
||||
|
||||
let mut add_metadata = |id| match build_message_metadata(dbc, id) {
|
||||
Some(meta) => {
|
||||
metadatas.insert(id, meta);
|
||||
}
|
||||
None => {
|
||||
unknown_ids.insert(id);
|
||||
}
|
||||
};
|
||||
|
||||
// Caller has aligned the chunk to line boundaries, so we always start at
|
||||
@@ -171,6 +175,51 @@ pub struct DecodeResult {
|
||||
pub info: DecodeProcessInfo,
|
||||
}
|
||||
|
||||
impl DecodeResult {
|
||||
/// An empty result suitable for incrementally accumulating live CAN
|
||||
/// frames via [`DecodeResult::push_live`]. The `info` fields that only
|
||||
/// make sense for the file-based decode are zeroed.
|
||||
pub fn empty() -> Self {
|
||||
DecodeResult {
|
||||
data: HashMap::new(),
|
||||
metadata: HashMap::new(),
|
||||
info: DecodeProcessInfo {
|
||||
unknown_ids: HashSet::new(),
|
||||
error_frames: Vec::new(),
|
||||
date: chrono::DateTime::from_timestamp(0, 0).unwrap().naive_utc(),
|
||||
thread_count: 0,
|
||||
page_size: 0,
|
||||
pages_per_chunk: 0,
|
||||
chunk_size: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Append a single live frame, lazily resolving its metadata from the DBC
|
||||
/// the first time an id is seen. Frames are expected to arrive in
|
||||
/// non-decreasing timestamp order (as they do off a live bus), so no
|
||||
/// re-sorting is performed — `compute_signal` consumes them in order.
|
||||
pub fn push_live(&mut self, dbc: &Dbc, frame: CanFrame) {
|
||||
match self.data.get_mut(&frame.can_id) {
|
||||
Some(vec) => vec.push(frame),
|
||||
None => {
|
||||
let id = frame.can_id;
|
||||
self.data.insert(id, vec![frame]);
|
||||
if !self.metadata.contains_key(&id) {
|
||||
match build_message_metadata(dbc, id) {
|
||||
Some(meta) => {
|
||||
self.metadata.insert(id, meta);
|
||||
}
|
||||
None => {
|
||||
self.info.unknown_ids.insert(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode(dbc: &Dbc,
|
||||
asc_path: &Path) -> DecodeResult {
|
||||
let thread_count = std::thread::available_parallelism().unwrap().get();
|
||||
|
||||
Reference in New Issue
Block a user