1use std::error::Error;
2use std::path;
3
4pub struct Config {
5 pub acpi_path: path::PathBuf,
6 pub show_battery: bool,
7 pub show_ac_adapter: bool,
8 pub show_thermal_sensors: bool,
9 pub show_cooling_devices: bool,
10 pub detailed: bool,
11 pub units: acpi_client::Units,
12}
13
14pub fn run(cfg: Config) -> Result<(), Box<dyn Error>> {
15 if cfg.show_battery {
16 let batteries: Vec<acpi_client::BatteryInfo> =
17 match acpi_client::get_battery_info(&cfg.acpi_path.join("power_supply")) {
18 Ok(bat) => bat,
19 Err(e) => {
20 eprintln!("Application error: {}", e);
21 std::process::exit(1);
22 }
23 };
24 for bat in batteries {
25 display_battery_info(&bat, cfg.detailed);
26 }
27 }
28 if cfg.show_ac_adapter {
29 let adapters: Vec<acpi_client::ACAdapterInfo> =
30 match acpi_client::get_ac_adapter_info(&cfg.acpi_path.join("power_supply")) {
31 Ok(ac) => ac,
32 Err(e) => {
33 eprintln!("Application error: {}", e);
34 std::process::exit(1);
35 }
36 };
37 for ac in adapters {
38 display_ac_adapter_info(&ac);
39 }
40 }
41 if cfg.show_thermal_sensors {
42 let sensors: Vec<acpi_client::ThermalSensor> =
43 match acpi_client::get_thermal_sensor_info(&cfg.acpi_path.join("thermal"), cfg.units) {
44 Ok(tz) => tz,
45 Err(e) => {
46 eprintln!("Application error: {}", e);
47 std::process::exit(1);
48 }
49 };
50 for tz in sensors {
51 display_thermal_zone_info(&tz, cfg.detailed);
52 }
53 }
54 if cfg.show_cooling_devices {
55 let devices: Vec<acpi_client::CoolingDevice> =
56 match acpi_client::get_cooling_device_info(&cfg.acpi_path.join("thermal")) {
57 Ok(cd) => cd,
58 Err(e) => {
59 eprintln!("Application error: {}", e);
60 std::process::exit(1);
61 }
62 };
63 for cd in devices {
64 display_cooling_device_info(&cd);
65 }
66 }
67
68 Ok(())
69}
70
71fn display_battery_info(bat: &acpi_client::BatteryInfo, detailed: bool) {
72 let state = match &bat.state {
73 acpi_client::ChargingState::Charging => "Charging",
74 acpi_client::ChargingState::Discharging => "Discharging",
75 acpi_client::ChargingState::Full => "Full",
76 };
77 let mut seconds = bat.time_remaining.as_secs();
78 let hours = seconds / 3600;
79 seconds = seconds - hours * 3600;
80 let minutes = seconds / 60;
81 seconds = seconds - minutes * 60;
82 let not_full_string = format!(", {:02}:{:02}:{:02}", hours, minutes, seconds);
83 let charge_time_string = match &bat.state {
84 acpi_client::ChargingState::Charging => {
85 if bat.present_rate > 0 {
86 format!("{} {}", not_full_string, "until charged")
87 } else {
88 format!(", charging at zero rate")
89 }
90 }
91 acpi_client::ChargingState::Discharging => format!("{} {}", not_full_string, "remaining"),
92 _ => String::from(""),
93 };
94 println!(
95 "{}: {}, {:.1}%{}",
96 &bat.name, state, bat.percentage, charge_time_string
97 );
98
99 if detailed {
100 println!(
101 "{}: design capacity {} mAh, last full capacity {} mAh = {}%",
102 &bat.name,
103 bat.design_capacity,
104 bat.last_capacity,
105 (100 * bat.last_capacity) / bat.design_capacity
106 );
107 }
108}
109
110fn display_ac_adapter_info(ac: &acpi_client::ACAdapterInfo) {
111 let status_str = match ac.status {
112 acpi_client::Status::Online => "online",
113 acpi_client::Status::Offline => "offline",
114 };
115 println!("{}: {}", &ac.name, status_str);
116}
117
118fn display_thermal_zone_info(tz: &acpi_client::ThermalSensor, detailed: bool) {
119 let temperature_str = match tz.units {
120 acpi_client::Units::Celsius => "degrees C",
121 acpi_client::Units::Fahrenheit => "degrees F",
122 acpi_client::Units::Kelvin => "kelvin",
123 };
124 println!(
125 "{}: {:.1} {}",
126 &tz.name, tz.current_temperature, temperature_str
127 );
128
129 if detailed {
130 for tp in &tz.trip_points {
131 println!("{}: trip point {} switches to mode {} at temperature {:.1} {}", &tz.name, tp.number, &tp.action_type, tp.temperature, temperature_str);
132 }
133 }
134}
135
136fn display_cooling_device_info(cd: &acpi_client::CoolingDevice) {
137 let state_str = if cd.state.is_some() {
138 format!("{} of {}", cd.state.unwrap().current_state, cd.state.unwrap().max_state)
139 } else {
140 format!("no state information available")
141 };
142 println!("{}: {} {}", &cd.name, &cd.device_type, state_str);
143}