diff --git a/Cargo.toml b/Cargo.toml index 9784ea8c..2eab2b22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,9 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cursive = "0.13" +futures-preview = "0.3.0-alpha.18" heim = "0.0.7" +heim-common = "0.0.7" +sysinfo = "0.9.4" +tokio = "0.2.0-alpha.4" tui = "0.6.2" diff --git a/src/main.rs b/src/main.rs index bae91631..91fbecba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,31 +1,46 @@ use sysinfo::{System, SystemExt}; + mod widgets; use widgets::{cpu, disks, mem, network, processes, temperature}; -fn main() { - // Initialize - let mut system = System::new(); - let refresh_interval = 10; +mod window; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Initialize + let refresh_interval = 1; // TODO: Make changing this possible! + let mut sys = System::new(); + + let mut list_of_timed_processes : Vec = Vec::new(); - // Start loop (TODO: do that) loop { - system.refresh_system(); - system.refresh_processes(); - system.refresh_disk_list(); - system.refresh_disks(); - system.refresh_network(); + sys.refresh_system(); // Get data, potentially store? - //let list_of_processes = processes::get_sorted_processes_list(processes::ProcessSorting::NAME, true, &system); - let list_of_disks = disks::get_disk_usage_list(&system); + //let list_of_processes = processes::get_sorted_processes_list(processes::ProcessSorting::NAME, true); + + let list_of_disks = disks::get_disk_usage_list().await?; for disk in list_of_disks { - println!("{} is mounted on {}: {}/{}", disk.name, disk.mount_point, disk.avail_space, disk.total_space); + println!("{} is mounted on {}: {}/{} free.", disk.name, disk.mount_point, disk.avail_space as f64, disk.total_space as f64); + // TODO: Check if this is valid } - // Draw using cursive + list_of_timed_processes.push(cpu::get_cpu_data_list(&sys)); + if !list_of_timed_processes.is_empty() { + let current_cpu_time = list_of_timed_processes.last().unwrap().time; + for cpu in &list_of_timed_processes.last().unwrap().processor_list { + println!("CPU {} has {}% usage at timestamp {:?}!", cpu.cpu_name, cpu.cpu_usage, current_cpu_time); + } + } + + // Send to drawing module + window::draw_terminal(); // Repeat on interval std::thread::sleep(std::time::Duration::from_secs(refresh_interval)); } + + // TODO: Exit on quit command/ctrl-c + Ok(()) } diff --git a/src/widgets/cpu.rs b/src/widgets/cpu.rs index ef83d29f..d462c2a7 100644 --- a/src/widgets/cpu.rs +++ b/src/widgets/cpu.rs @@ -1,22 +1,32 @@ use sysinfo::{ProcessorExt, System, SystemExt}; -pub struct TimedCPUData { +pub struct CPUData { pub cpu_name : Box, pub cpu_usage : u32, +} + +pub struct TimedCPUPackagesStruct { + pub processor_list : Vec, pub time : std::time::SystemTime, } -pub fn get_cpu_data_list(sys : &System) -> Vec { +pub fn get_cpu_data_list(sys : &System) -> TimedCPUPackagesStruct { let cpu_data = sys.get_processor_list(); let mut cpu_vec = Vec::new(); for cpu in cpu_data { - cpu_vec.push(TimedCPUData { + cpu_vec.push(CPUData { cpu_name : Box::from(cpu.get_name()), cpu_usage : (cpu.get_cpu_usage() * 100_f32).ceil() as u32, - time : std::time::SystemTime::now(), }) } - cpu_vec + TimedCPUPackagesStruct { + processor_list : cpu_vec, + time : std::time::SystemTime::now(), + } +} + +pub fn clear_old_cpu_data() -> bool { + true } diff --git a/src/widgets/disks.rs b/src/widgets/disks.rs index 9ce4ab46..e21f3e13 100644 --- a/src/widgets/disks.rs +++ b/src/widgets/disks.rs @@ -1,24 +1,53 @@ -use sysinfo::{System, SystemExt, Disk, DiskExt}; +use heim_common::prelude::StreamExt; -pub struct DiskInfo<'a> { - pub name: &'a str, - pub mount_point: &'a str, - pub avail_space: u64, - pub total_space: u64, +pub struct DiskInfo { + pub name : Box, + pub mount_point : Box, + pub avail_space : u64, + pub total_space : u64, } -pub fn get_disk_usage_list(sys: &System) -> Vec { - let result_disks = sys.get_disks(); - let mut vec_disks : Vec = Vec::new(); +pub struct IOInfo { + pub name : Box, + pub read_bytes : u64, + pub write_bytes : u64, +} - for disk in result_disks { - vec_disks.push(DiskInfo { - name: disk.get_name().to_str().unwrap(), - mount_point: disk.get_mount_point().to_str().unwrap(), - avail_space: disk.get_available_space(), - total_space: disk.get_total_space(), - }); +pub async fn get_io_usage_list() -> Result, heim::Error> { + let mut io_list : Vec = Vec::new(); + let mut counters = heim::disk::io_counters(); + while let Some(counter) = counters.next().await { + dbg!(counter?); } - vec_disks + println!("\n\n--- Per physical disk ---\n"); + + let mut counters = heim::disk::io_counters_physical(); + while let Some(counter) = counters.next().await { + dbg!(counter?); + } + + Ok(io_list) +} + +pub async fn get_disk_usage_list() -> Result, heim::Error> { + let mut vec_disks : Vec = Vec::new(); + let mut partitions_stream = heim::disk::partitions_physical(); + + while let Some(part) = partitions_stream.next().await { + let part = part?; + let usage = heim::disk::usage(part.mount_point().to_path_buf()).await?; + + println!( + "{:<17} {:<10} {:<10} {:<10} {:<10} {}", + part.device().unwrap().to_str().unwrap(), + usage.total().get::(), + usage.used().get::(), + usage.free().get::(), + part.file_system().as_str(), + part.mount_point().to_string_lossy(), + ); + } + + Ok(vec_disks) } diff --git a/src/widgets/processes.rs b/src/widgets/processes.rs index 4d38fc03..7a4653ba 100644 --- a/src/widgets/processes.rs +++ b/src/widgets/processes.rs @@ -1,6 +1,5 @@ -use sysinfo::{ProcessExt, ProcessStatus, System, SystemExt}; +use heim_common::prelude::StreamExt; -// TODO: Fix this - CPU Up, and CPU Down! pub enum ProcessSorting { CPU, MEM, @@ -10,73 +9,52 @@ pub enum ProcessSorting { // Possible process info struct? #[derive(Debug)] -pub struct ProcessInfo<'a> { - pid: u32, - cpu_usage: f32, - mem_usage: u64, - uptime: u64, - command: &'a str, - //status: &'a str, +pub struct ProcessInfo { + pid : u32, + cpu_usage : f32, + mem_usage : u64, + uptime : u64, + command : Box, // TODO: Env? } -fn get_status(status: ProcessStatus) -> &'static str { - match status { - ProcessStatus::Idle => "Idle", - ProcessStatus::Run => "Run", - ProcessStatus::Sleep => "Sleep", - ProcessStatus::Zombie => "Zombie", - ProcessStatus::Tracing => "Tracing", - ProcessStatus::Dead => "Dead", - _ => "Unknown", - } -} - -fn get_ordering(a_val: T, b_val: T, reverse_order: bool) -> std::cmp::Ordering { +fn get_ordering(a_val : T, b_val : T, reverse_order : bool) -> std::cmp::Ordering { if a_val > b_val { if reverse_order { std::cmp::Ordering::Less - } else { + } + else { std::cmp::Ordering::Greater } - } else if a_val < b_val { + } + else if a_val < b_val { if reverse_order { std::cmp::Ordering::Greater - } else { + } + else { std::cmp::Ordering::Less } - } else { + } + else { std::cmp::Ordering::Equal } } -pub fn get_sorted_processes_list(sorting_method: ProcessSorting, reverse_order: bool, sys: &System) { - let process_hashmap = sys.get_process_list(); +pub async fn get_sorted_processes_list(sorting_method : ProcessSorting, reverse_order : bool) -> Vec { + let mut process_stream = heim::process::processes(); // TODO: Evaluate whether this is too slow! // TODO: Should I filter out blank command names? - let mut process_vector: Vec = process_hashmap.iter().map(|(_, process)| process.clone()).collect(); + + let mut process_vector : Vec = Vec::new(); + while let Some(process) = process_stream.next().await {} match sorting_method { - ProcessSorting::CPU => process_vector.sort_by(|a, b| get_ordering(a.cpu_usage(), b.cpu_usage(), reverse_order)), - ProcessSorting::MEM => process_vector.sort_by(|a, b| get_ordering(a.memory(), b.memory(), reverse_order)), - ProcessSorting::PID => process_vector.sort_by(|a, b| get_ordering(a.pid(), b.pid(), reverse_order)), - ProcessSorting::NAME => process_vector.sort_by(|a, b| get_ordering(a.name(), b.name(), reverse_order)), + ProcessSorting::CPU => process_vector.sort_by(|a, b| get_ordering(1, 2, reverse_order)), + ProcessSorting::MEM => process_vector.sort_by(|a, b| get_ordering(1, 2, reverse_order)), + ProcessSorting::PID => process_vector.sort_by(|a, b| get_ordering(1, 2, reverse_order)), + ProcessSorting::NAME => process_vector.sort_by(|a, b| get_ordering(1, 2, reverse_order)), } - let mut formatted_vector: Vec = Vec::new(); - for process in &mut process_vector { - formatted_vector.push(ProcessInfo { - cpu_usage: process.cpu_usage(), - command: process.name(), - mem_usage: process.memory(), - uptime: process.start_time(), - pid: process.pid() as u32, - }); - } - - // TODO: For debugging, remove. - for process in formatted_vector { - println!("{:?}", process); - } + process_vector } diff --git a/src/window/mod.rs b/src/window/mod.rs index e04802fd..9b34bb7a 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -1 +1,14 @@ -use cursive::Cursive; \ No newline at end of file +use std::io; +use tui::{ + backend::Backend, + layout::{Constraint, Direction, Layout, Rect}, + style::{Color, Modifier, Style}, + widgets::{ + canvas::{Canvas, Line, Map, MapResolution, Rectangle}, + Axis, Borders, Chart, List, + }, + Frame, Terminal, +}; + +pub fn draw_terminal() { +}