#dlt #packet-parser #diagnostics #serialization #trace #log #autosar

no-std dlt_parse

一个用于解析 "诊断日志和跟踪" 网络协议(目前不包括有效载荷解释)的库

20 个不稳定版本 (9 个破坏性更新)

0.10.0 2024年5月2日
0.9.3 2024年3月27日
0.9.2 2024年2月26日
0.9.1 2023年9月25日
0.1.0 2019年2月10日

#111 in 解析器实现

Download history 61/week @ 2024-05-03 4/week @ 2024-05-10 12/week @ 2024-05-17 44/week @ 2024-05-24 16/week @ 2024-05-31 19/week @ 2024-06-07 26/week @ 2024-06-14 63/week @ 2024-06-21 21/week @ 2024-06-28 48/week @ 2024-07-05 4/week @ 2024-07-12 311/week @ 2024-07-26 41/week @ 2024-08-02 32/week @ 2024-08-09 22/week @ 2024-08-16

每月406次下载

MIT/Apache

1.5MB
28K SLoC

Crates.io docs.rs build status github build status gitlab codecov

dlt_parse

一个用于基本解析和写入 DLT(诊断日志和跟踪)数据包的零分配 Rust 库。目前仅支持解析和写入头部以及解析详细消息。

用法

默认情况下,禁用了 serde,如果将 dlt_parse 作为依赖项添加到您的 Cargo.toml,则启用了 std

[dependencies]
dlt_parse = "0.10.0"

如果您还想使用 serde 支持,您必须激活 serde 功能

[dependencies]
dlt_parse = { version = "0.10.0", features = ["serde"] }

如果您想以 no_std 模式使用该包,您必须禁用默认功能

[dependencies]
dlt_parse = { version = "0.10.0", default-features = false }

什么是 dlt_parse?

dlt_parse 是一个库,旨在为 DLT(诊断日志和跟踪)数据包提供序列化和反序列化函数。它应该能够尽可能快地分析 DLT 数据包的记录,以及编写将 DLT 数据包发送到网络的服务器。

一些关键点包括

  • 它是完全用 Rust 编写的,并且经过彻底测试。
  • 特别注重不使用分配或系统调用。
  • 可以在 no-std 环境中使用该包。
  • 该软件包仍在开发中,将会继续变化。

示例:序列化和切片/反序列化 DLT 数据包

在此示例中,将一个非详细 DLT 数据包进行序列化和反序列化。具体来说,将序列化的数据包转换为 DltPacketSlice。这有利于,在访问有效载荷或头部中的特定字段时,不需要反序列化所有字段。请注意,还可以使用 DltHeader::read 函数完全反序列化 DLT 头部。如果大多数头部字段都会使用,这可能是合理的。

use self::dlt_parse::{DltHeader, DltLogLevel, DltExtendedHeader, SliceIterator};

let header = {
    let mut header = DltHeader {
        is_big_endian: true, // payload & message id are encoded with big endian
        message_counter: 0,
        length: 0,
        ecu_id: None,
        session_id: None,
        timestamp: None,
        extended_header: Some(DltExtendedHeader::new_non_verbose_log(
            DltLogLevel::Debug,
            [b'a', b'p', b'p', b'i'],// application id
            [b'c', b't', b'x', b'i'],// context id
        ))
    };
    header.length = header.header_len() + 4 + 4; // header + message id + payload

    header
};

// buffer to store serialized header & payload
let mut buffer = Vec::<u8>::with_capacity(usize::from(header.length));
buffer.extend_from_slice(&header.to_bytes());

// write payload (message id 1234 & non verbose payload)
{
    // for write_all
    use std::io::Write;

    // write the message id & payload
    buffer.write_all(&1234u32.to_be_bytes()).unwrap(); // message id
    buffer.write_all(&[5,6,7,9]); // payload
}

// packets can contain multiple dlt messages, iterate through them
for dlt_message in SliceIterator::new(&buffer) {
    match dlt_message {
        Ok(dlt_slice) => {
            // check what type of message was received
            match dlt_slice.typed_payload() {
                Ok(typed_payload) => {
                    use dlt_parse::DltTypedPayload::*;
                    match typed_payload {
                        UnknownNv(p) => {
                            println!(
                                "non verbose message 0x{:x} (unknown) with {} bytes of payload.",
                                p.msg_id,
                                p.payload.len(),
                            );
                        }
                        LogNv(p) => {
                            println!(
                                "non verbose log message 0x{:x} with log level {:?} and {} bytes of payload.",
                                p.msg_id,
                                p.log_level,
                                p.payload.len(),
                            );
                        }
                        LogV(p) => {
                            println!(
                                "verbose log message with log level {:?} and values:",
                                p.log_level
                            );
                            for value in p.iter {
                                println!("  {:?}", value);
                            }
                        }
                        TraceNv(p) => {
                            println!(
                                "non verbose trace message 0x{:x} of type {:?} and {} bytes of payload.",
                                p.msg_id,
                                p.trace_type,
                                p.payload.len(),
                            );
                        }
                        TraceV(p) => {
                            println!(
                                "verbose trace message with of type {:?} and values:",
                                p.trace_type
                            );
                            for value in p.iter {
                                println!("  {:?}", value);
                            }
                        }
                        NetworkNv(p) => {
                            println!(
                                "non verbose network message 0x{:x} of type {:?} and {} bytes of payload.",
                                p.msg_id,
                                p.net_type,
                                p.payload.len(),
                            );
                        }
                        NetworkV(p) => {
                            println!(
                                "verbose network message with of type {:?} and values:",
                                p.net_type
                            );
                            for value in p.iter {
                                println!("  {:?}", value);
                            }
                        }
                        ControlNv(p) => {
                            println!("non verbose control message {:?} with service id: {} and {} bytes of payload.", p.msg_type, p.service_id, p.payload.len());
                        }
                        ControlV(p) => {
                            println!("verbose control message {:?} with values:", p.msg_type);
                            for value in p.iter {
                                println!("  {:?}", value);
                            }
                        }
                    }
                }
                Err(err) => {
                    println!("message with payload error received: {}", err);
                }
            }
        },
        Err(err) => {
            //error parsing the dlt packet
            println!("ERROR: {:?}", err);
        }
    }
}

包括解析以太网和 UDP 头部的完整示例,可以在 examples/print_messages_ids.rs 中找到

参考

许可

根据您的选择,本作品受Apache License 2.0或MIT许可协议的许可。相应的许可文本可在LICENSE-APACHE文件和LICENSE-MIT文件中找到。

贡献

除非您明确声明,否则您有意提交以包含在本作品中的任何贡献,均应按照上述许可协议进行许可,无需任何额外条款或条件。

依赖项