소스 검색

Implement netspeed

Thomas Dy 9 년 전
부모
커밋
446cf04e63
2개의 변경된 파일92개의 추가작업 그리고 4개의 파일을 삭제
  1. 12 4
      src/main.rs
  2. 80 0
      src/netspeed.rs

+ 12 - 4
src/main.rs

@@ -1,7 +1,9 @@
 mod sensors;
+mod netspeed;
 mod comm;
 
 use comm::{Channel, Message};
+use std::collections::HashMap;
 use std::io;
 use std::sync::mpsc;
 use std::thread;
@@ -10,15 +12,20 @@ fn main() {
     let (tx, rx) = mpsc::channel::<Message>();
     make_thread(&tx, stdin);
     make_thread(&tx, sensors::sensors);
+    make_thread(&tx, netspeed::netspeed);
 
-    let mut data;
+    let mut data = HashMap::new();
 
     loop {
         let msg = rx.recv().unwrap();
+        let empty = "".to_string();
         match msg {
-            Message { text, .. } => data = text,
-        }
-        println!("%{{r}}{}", data);
+            Message { kind, text } => data.insert(kind, text),
+        };
+        println!("%{{r}}{} | {}",
+            data.get("netspeed").unwrap_or(&empty),
+            data.get("sensors").unwrap_or(&empty)
+        );
     }
 }
 
@@ -29,6 +36,7 @@ fn make_thread(tx: &Channel, func: fn(&Channel) -> ()) {
     });
 }
 
+
 fn stdin(tx: &Channel) {
     let mut line = String::new();
     loop {

+ 80 - 0
src/netspeed.rs

@@ -0,0 +1,80 @@
+use comm;
+use comm::Channel;
+use std::fs::File;
+use std::io::prelude::*;
+use std::io;
+use std::thread;
+
+struct StatFiles {
+    rx: File,
+    tx: File
+}
+
+struct Stats {
+    rx: u32,
+    tx: u32
+}
+
+pub fn netspeed(tx: &Channel) {
+    let devices = [ "wlp2s0b1" ];
+    let mut files : Vec<StatFiles> = devices.iter()
+        .flat_map(|dev| open_stats(&dev).ok())
+        .collect();
+
+    let mut prev_stats : Option<Stats> = None;
+    loop {
+        let stats = files
+            .iter_mut()
+            .flat_map(|file| read_stats(file).ok())
+            .fold(Stats { rx: 0, tx: 0 }, |acc, elem| Stats {
+                rx: acc.rx + elem.rx,
+                tx: acc.tx + elem.tx
+            });
+        let output = match prev_stats {
+            Some(pstats) => {
+                let rx = format_bytes(stats.rx - pstats.rx);
+                let tx = format_bytes(stats.tx - pstats.tx);
+                format!("{}↓ {}↑", rx, tx)
+            },
+            None => "?".to_string()
+        };
+        prev_stats = Some(stats);
+        comm::send(tx, "netspeed", &output);
+        thread::sleep_ms(1000);
+    }
+}
+
+fn format_bytes(bytes: u32) -> String {
+    let kib = bytes >> 10;
+    if kib > 1024 {
+        format!("{:.*} M", 1, (kib as f32) / 1024.0)
+    }
+    else {
+        format!("{} K", kib)
+    }
+}
+
+fn open_stats(device: &str) -> Result<StatFiles, io::Error> {
+    let path = format!("/sys/class/net/{}/statistics", device);
+    let rx_file = try!(File::open(format!("{}/rx_bytes", path)));
+    let tx_file = try!(File::open(format!("{}/tx_bytes", path)));
+    Ok(StatFiles {
+        rx: rx_file,
+        tx: tx_file
+    })
+}
+
+fn read_stats(files: &mut StatFiles) -> Result<Stats, io::Error> {
+    Ok(Stats {
+        rx: read_bytes(&mut files.rx),
+        tx: read_bytes(&mut files.tx)
+    })
+}
+
+fn read_bytes(f: &mut File) -> u32 {
+    let mut s = String::new();
+    assert!(f.read_to_string(&mut s).is_ok());
+    let i : u32 = s.trim().parse().unwrap();
+    assert!(f.seek(io::SeekFrom::Start(0)).is_ok());
+    i
+}