Skip to content

Commit

Permalink
Add canstatsrb for socketcan statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelbuesing committed Oct 1, 2020
1 parent 1095553 commit 9bb3aca
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 0 deletions.
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,45 @@ OPTIONS:
ARGS:
<CAN_INTERFACE> Only generate messages for the given receiver (receiving node)
```
# Canstatsrb

A tool that collects statistics about received frames and the messages by message id.

## Interface
```
canstatsrb 1.0.0
SocketCAN message statistics
USAGE:
canstatsrb <can-interface>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
ARGS:
<can-interface> socketcan CAN interface e.g. vcan0
```

## Output Example
```
RX Total: 6410
EFF Total: 3697 ERR: 0 RTR: 0
SFF Total: 2713 ERR: 0 RTR: 0
Messages by CAN ID
32 → # 107
113 → # 93
152 → # 95
161 → # 99
163 → # 95
290 → # 115
341 → # 85
367 → # 83
383 → # 104
489 → # 92
504 → # 94
548 → # 107
549 → # 111
626 → # 88
```
102 changes: 102 additions & 0 deletions examples/canstatsrb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use core::fmt::Display;
use futures::prelude::*;
use futures_util::compat::Stream01CompatExt;
use std::{collections::HashMap, fmt};
use structopt::StructOpt;
use tokio_socketcan;

#[derive(Debug, StructOpt)]
#[structopt(name = "canstatsrb", about = "SocketCAN message statistics")]
struct Opt {
/// Set can interface
#[structopt(help = "socketcan CAN interface e.g. vcan0")]
can_interface: String,
}

#[derive(Default, Debug)]
struct Stats {
msg_ids: HashMap<u32, u64>,
rx_frames: u64,
eff_frames_total: u64,
eff_frames_err: u64,
eff_frames_rtr: u64,
sff_frames_total: u64,
sff_frames_err: u64,
sff_frames_rtr: u64,
}

impl Display for Stats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "RX Total: {}", self.rx_frames)?;

write!(f, "EFF Total: {}\t", self.eff_frames_total)?;
write!(f, "ERR: {}\t", self.eff_frames_err)?;
writeln!(f, "RTR: {}", self.eff_frames_rtr)?;

write!(f, "SFF Total: {}\t", self.sff_frames_total)?;
write!(f, "ERR: {}\t", self.sff_frames_err)?;
writeln!(f, "RTR: {}", self.sff_frames_rtr)?;
writeln!(f, "Messages by CAN ID")?;

let mut count_vec: Vec<(&u32, &u64)> = self.msg_ids.iter().collect();
count_vec.sort_by(|a, b| a.0.cmp(b.0));
for (ref id, ref count) in &count_vec {
writeln!(f, "{: ^10} → #{: ^7}", id, count)?;
}
Ok(())
}
}

#[tokio::main]
async fn main() -> std::io::Result<()> {
let opt = Opt::from_args();

let mut socket_rx = tokio_socketcan::CANSocket::open(&opt.can_interface)
.unwrap()
.compat();

let mut stats: Stats = Default::default();

while let Some(socket_result) = socket_rx.next().await {
match socket_result {
Ok(frame) => {
stats.rx_frames += 1;

if frame.is_extended() {
stats.sff_frames_total += 1;

if frame.is_error() {
stats.sff_frames_err += 1;
}

if frame.is_rtr() {
stats.sff_frames_rtr += 1;
}
} else {
stats.eff_frames_total += 1;

if frame.is_error() {
stats.eff_frames_err += 1;
}

if frame.is_rtr() {
stats.eff_frames_rtr += 1;
}
}

stats
.msg_ids
.entry(frame.id())
.and_modify(|e| *e += 1)
.or_insert(1);

println!("{}", stats);
}
Err(err) => {
eprintln!("IO error: {}", err);
}
}
}

Ok(())
}

0 comments on commit 9bb3aca

Please sign in to comment.