Skip to content

Commit

Permalink
macOS daemon fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Levminer committed Aug 12, 2024
1 parent 08fdfc6 commit d9a96b0
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 0 deletions.
10 changes: 10 additions & 0 deletions platforms/cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "cores_cli"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hardwareinfo = { path = "../unix/hardwareinfo" }
ratatui = "0.27.0"
251 changes: 251 additions & 0 deletions platforms/cli/src/main
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
use hardwareinfo::{refresh_hardware_info, Data, HardwareInfo, Networks, System};
use ratatui::{
backend::CrosstermBackend,
crossterm::{
event::{self, KeyCode, KeyEventKind},
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
ExecutableCommand,
},
layout::{Alignment, Constraint, Direction, Layout},
style::{Color, Style, Stylize},
symbols::{self, border},
text::{Line, Text},
widgets::{
block::{Position, Title},
Block, Borders, Gauge, LineGauge, Paragraph, Tabs,
},
Terminal,
};
use std::io::{stdout, Result};

struct AppState {
current_tab: usize,
}

fn main() -> Result<()> {
stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
terminal.clear()?;

// get version from Cargo.toml
let version = std::env!("CARGO_PKG_VERSION");

let mut data = Data {
first_run: true,
sys: System::new_all(),
network: Networks::new_with_refreshed_list(),
hw_info: HardwareInfo::default(),
};

let mut app_state = AppState { current_tab: 0 };

loop {
data.sys.refresh_all();
std::thread::sleep(hardwareinfo::MINIMUM_CPU_UPDATE_INTERVAL);
data.sys.refresh_all();
data.network.refresh();

refresh_hardware_info(&mut data);

let title = Title::from(format!(" Cores {} ", version));
let os = Title::from(format!(
" {} ",
data.hw_info.system.os.name.to_string().yellow()
));
let instructions = Title::from(Line::from(vec![
" Navigate with ".into(),
"<Left>".blue().bold(),
" and ".into(),
"<Right>".blue().bold(),
" Quit ".into(),
"<Q> ".blue().bold(),
]));

let cpu_name = Paragraph::new(Text::from(vec![Line::from(vec![
" CPU: ".into(),
data.hw_info.cpu.name.to_string().bold(),
format!(
" ({}C/{}T)",
data.hw_info.cpu.info.core_count, data.hw_info.cpu.info.thread_count
)
.into(),
])]));

let ram_name = Paragraph::new(Text::from(vec![Line::from(vec![
" RAM: ".into(),
"Generic Memory".to_string().bold(),
format!(
" ({}GB)",
(data.hw_info.ram.load[0].value + data.hw_info.ram.load[1].value)
)
.into(),
])]));

let interface_name = Paragraph::new(Text::from(vec![Line::from(vec![
" Network: ".into(),
data.hw_info.system.network.interfaces[0]
.name
.to_string()
.bold(),
])]));

let cpu_usage = Gauge::default()
.block(Block::bordered().title("CPU Usage"))
.gauge_style(Style::default().fg(Color::Cyan).bg(Color::Black))
.percent(data.hw_info.cpu.max_load as u16);

let ram_usage = Gauge::default()
.block(Block::bordered().title("Memory Usage"))
.gauge_style(Style::default().fg(Color::Cyan).bg(Color::Black))
.percent(data.hw_info.ram.load[2].value as u16);

let virtual_ram_usage = Gauge::default()
.block(Block::bordered().title("Virtual Memory Usage"))
.gauge_style(Style::default().fg(Color::Cyan).bg(Color::Black))
.percent(data.hw_info.ram.load[5].value as u16);

let download_speed = Gauge::default()
.block(Block::bordered().title("Download Speed"))
.gauge_style(Style::default().fg(Color::Cyan).bg(Color::Black))
.percent(data.hw_info.system.network.interfaces[0].throughput_download as u16 / 5);

let upload_speed = Gauge::default()
.block(Block::bordered().title("Upload Speed"))
.gauge_style(Style::default().fg(Color::Cyan).bg(Color::Black))
.percent(data.hw_info.system.network.interfaces[0].throughput_upload as u16 / 5);

terminal.draw(|frame| {
let main_container = Block::bordered()
.title(title.alignment(Alignment::Left))
.title(os.alignment(Alignment::Right))
.title(
instructions
.alignment(Alignment::Center)
.position(Position::Bottom),
)
.border_set(border::THICK);

// Get the inner area of the outer block
let inner_area = main_container.inner(frame.size());

// Render the main container
frame.render_widget(main_container, frame.size());

let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Length(2), Constraint::Min(0)].as_ref())
.split(inner_area);

let titles = vec!["Home", "Debug"];
let tabs = Tabs::new(titles)
.block(Block::default().borders(ratatui::widgets::Borders::NONE))
.select(app_state.current_tab)
.style(Style::default().fg(Color::White))
.highlight_style(Style::default().fg(Color::Cyan));

frame.render_widget(tabs, chunks[0]);

match app_state.current_tab {
0 => {
// Main layout covering the inner area with 3-way split
let layout = Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage(33),
Constraint::Percentage(34),
Constraint::Percentage(33),
])
.split(chunks[1]);

let cpu_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1),
Constraint::Length(3),
Constraint::Fill(100),
])
.split(layout[0]);

let ram_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(1),
Constraint::Length(3),
Constraint::Length(3),
])
.split(layout[1]);

frame.render_widget(cpu_name.clone(), cpu_layout[0]);
frame.render_widget(cpu_usage.clone(), cpu_layout[1]);

frame.render_widget(ram_name.clone(), ram_layout[0]);
frame.render_widget(ram_usage.clone(), ram_layout[1]);
frame.render_widget(virtual_ram_usage.clone(), ram_layout[2]);

frame.render_widget(interface_name.clone(), ram_layout[3]);
frame.render_widget(download_speed.clone(), ram_layout[4]);
frame.render_widget(upload_speed.clone(), ram_layout[5]);

// Create a layout for core gauges
let num_cores = data.hw_info.cpu.load.len();
let core_constraints = vec![Constraint::Length(3); num_cores];
let core_layout = Layout::default()
.direction(Direction::Vertical)
.constraints(core_constraints)
.split(cpu_layout[2]);

// Render a gauge for each core
for (i, core) in data.hw_info.cpu.load.iter().enumerate() {
let core_gauge = LineGauge::default()
.block(
Block::default()
.borders(Borders::ALL)
.title(format!("Core #{}", i))
.title_alignment(Alignment::Left),
)
.filled_style(Style::default().fg(Color::Cyan).bg(Color::Black))
.line_set(symbols::line::THICK)
.ratio(core.value as f64 / 100.0);

frame.render_widget(core_gauge, core_layout[i]);
}
}
1 => {
let layout = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.split(chunks[1]);

let debug = Paragraph::new(Text::from(vec![format!(
"CPU: {} Load: {}%",
data.hw_info.cpu.name,
data.hw_info.cpu.max_load.floor()
)
.into()]));

frame.render_widget(debug, layout[0]);
}
_ => {}
}
})?;

if event::poll(std::time::Duration::from_secs(5))? {
if let event::Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => break,
KeyCode::Left => app_state.current_tab = (app_state.current_tab + 2) % 3,
KeyCode::Right => app_state.current_tab = (app_state.current_tab + 1) % 3,
_ => {}
}
}
}
}

stdout().execute(LeaveAlternateScreen)?;
disable_raw_mode()?;
Ok(())
}
12 changes: 12 additions & 0 deletions platforms/unix/hardwareinfo/src/mac/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub fn macos_hardware_info(data: &mut Data) {
let metrics = sampler.get_metrics(100).unwrap();

if data.first_run {
data.hw_info.cpu.info[0].manufacturer_name = "Apple".to_string();
data.hw_info.cpu.info[0].socket_designation = soc.mac_model.clone();
data.hw_info.gpu.name = soc.chip_name.clone();
data.hw_info.system.motherboard.name = soc.mac_model.clone();

Expand All @@ -30,6 +32,13 @@ pub fn macos_hardware_info(data: &mut Data) {
max: (metrics.gpu_power as f64).fmt_num(),
});

data.hw_info.gpu.clock.push(CoresSensor {
name: "SOC".to_string(),
value: (metrics.gpu_usage.0 as f64).fmt_num(),
min: (metrics.gpu_usage.0 as f64).fmt_num(),
max: (metrics.gpu_usage.0 as f64).fmt_num(),
});

data.hw_info.cpu.temperature.push(CoresSensor {
name: "SOC".to_string(),
value: (metrics.temp.cpu_temp_avg as f64).fmt_num(),
Expand Down Expand Up @@ -58,6 +67,7 @@ pub fn macos_hardware_info(data: &mut Data) {
let prev_cpu_temp = data.hw_info.cpu.temperature[0].clone();
let prev_cpu_power = data.hw_info.cpu.power[0].clone();
let prev_gpu_load = data.hw_info.gpu.load[0].clone();
let prev_gpu_clock = data.hw_info.gpu.clock[0].clone();

data.hw_info.gpu.temperature[0] =
compare_sensor(&prev_gpu_temp, (metrics.temp.gpu_temp_avg as f64).fmt_num());
Expand All @@ -72,5 +82,7 @@ pub fn macos_hardware_info(data: &mut Data) {
(metrics.gpu_usage.1 as f64 * 100.0).fmt_num(),
);
data.hw_info.gpu.max_load = (data.hw_info.gpu.load[0].value as f64).fmt_num();
data.hw_info.gpu.clock[0] =
compare_sensor(&prev_gpu_clock, (metrics.gpu_usage.0 as f64).fmt_num());
}
}

0 comments on commit d9a96b0

Please sign in to comment.