can_viewer/
decode.rs

1//! CAN frame decoding using DBC definitions.
2
3use crate::dto::{CanFrameDto, DecodedSignalDto};
4use dbc_rs::Dbc;
5
6/// Result of decoding a frame - either signals or an error message.
7pub enum DecodeResult {
8    Signals(Vec<DecodedSignalDto>),
9    Error(String),
10}
11
12/// Decode a CAN frame using dbc-rs, returning signals or an error.
13pub fn decode_frame(frame: &CanFrameDto, dbc: &Dbc) -> DecodeResult {
14    let decoded = match dbc.decode(frame.can_id, &frame.data, frame.is_extended) {
15        Ok(signals) => signals,
16        Err(e) => {
17            let msg = format!(
18                "Frame 0x{:X}: {} (DLC={}, data={} bytes)",
19                frame.can_id,
20                e,
21                frame.dlc,
22                frame.data.len()
23            );
24            log::warn!("Decode error: {}", msg);
25            return DecodeResult::Error(msg);
26        }
27    };
28
29    // Get message name for the signals
30    let message_name = dbc
31        .messages()
32        .find_by_id(if frame.is_extended {
33            frame.can_id | 0x80000000
34        } else {
35            frame.can_id
36        })
37        .map(|m| m.name())
38        .unwrap_or("Unknown");
39
40    DecodeResult::Signals(
41        decoded
42            .iter()
43            .map(|sig| DecodedSignalDto::from_dbc_signal(sig, frame.timestamp, message_name))
44            .collect(),
45    )
46}