Add support for more temperature sensors (#18)

This commit is contained in:
ilyazzz 2021-03-07 14:31:50 +02:00 committed by GitHub
parent 7313019305
commit 14121a17f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 32 deletions

View File

@ -186,7 +186,7 @@ fn print_stats(d: &DaemonConnection, gpu_id: u32) {
println!( println!(
"{} {}{}", "{} {}{}",
"Temperature:".green(), "Temperature:".green(),
gpu_stats.gpu_temp.unwrap_or_default().to_string().bold(), gpu_stats.temperatures.get("edge").unwrap().current.to_string().bold(),
"°C".bold(), "°C".bold(),
); );
println!( println!(

View File

@ -1,4 +1,4 @@
use crate::config::{GpuConfig, GpuIdentifier}; use crate::{config::{GpuConfig, GpuIdentifier}, hw_mon::Temperature};
use crate::hw_mon::{HWMon, HWMonError}; use crate::hw_mon::{HWMon, HWMonError};
use pciid_parser::{PciDatabase, VendorData}; use pciid_parser::{PciDatabase, VendorData};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -97,7 +97,7 @@ pub struct GpuStats {
pub mem_total: Option<u64>, pub mem_total: Option<u64>,
pub mem_freq: Option<i64>, pub mem_freq: Option<i64>,
pub gpu_freq: Option<i64>, pub gpu_freq: Option<i64>,
pub gpu_temp: Option<i64>, pub temperatures: HashMap<String, Temperature>,
pub power_avg: Option<i64>, pub power_avg: Option<i64>,
pub power_cap: Option<i64>, pub power_cap: Option<i64>,
pub power_cap_max: Option<i64>, pub power_cap_max: Option<i64>,
@ -348,7 +348,7 @@ impl GpuController {
let ( let (
mem_freq, mem_freq,
gpu_freq, gpu_freq,
gpu_temp, temperatures,
power_avg, power_avg,
power_cap, power_cap,
power_cap_max, power_cap_max,
@ -359,7 +359,7 @@ impl GpuController {
Some(hw_mon) => ( Some(hw_mon) => (
hw_mon.get_mem_freq(), hw_mon.get_mem_freq(),
hw_mon.get_gpu_freq(), hw_mon.get_gpu_freq(),
hw_mon.get_gpu_temp(), hw_mon.get_temps(),
hw_mon.get_power_avg(), hw_mon.get_power_avg(),
hw_mon.get_power_cap(), hw_mon.get_power_cap(),
hw_mon.get_power_cap_max(), hw_mon.get_power_cap_max(),
@ -375,7 +375,7 @@ impl GpuController {
mem_used, mem_used,
mem_freq, mem_freq,
gpu_freq, gpu_freq,
gpu_temp, temperatures,
power_avg, power_avg,
power_cap, power_cap,
power_cap_max, power_cap_max,

View File

@ -1,16 +1,17 @@
use std::{
collections::BTreeMap,
fs,
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
Arc, RwLock,
},
thread,
time::Duration,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock};
use std::time::Duration;
use std::{fs, thread};
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub struct Temperature {
pub current: i64,
pub crit: i64,
pub crit_hyst: i64,
}
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub enum HWMonError { pub enum HWMonError {
@ -101,13 +102,59 @@ impl HWMon {
} }
} }
pub fn get_gpu_temp(&self) -> Option<i64> { pub fn get_temps(&self) -> HashMap<String, Temperature> {
let filename = self.hwmon_path.join("temp1_input"); let mut temps = HashMap::new();
match fs::read_to_string(filename) { for i in 1..3 {
Ok(temp) => Some(temp.trim().parse::<i64>().unwrap() / 1000), let label_filename = self.hwmon_path.join(format!("temp{}_label", i));
Err(_) => None,
match fs::read_to_string(label_filename) {
Ok(label) => {
// If there's a label identifying the sensor, there should always be input and crit files too. But just in case using .unwrap_or_default()
let current = {
let filename = self.hwmon_path.join(format!("temp{}_input", i));
fs::read_to_string(filename)
.unwrap_or_default()
.trim()
.parse::<i64>()
.unwrap_or_default()
/ 1000
};
let crit = {
let filename = self.hwmon_path.join(format!("temp{}_crit", i));
fs::read_to_string(filename)
.unwrap_or_default()
.trim()
.parse::<i64>()
.unwrap_or_default()
/ 1000
};
let crit_hyst = {
let filename = self.hwmon_path.join(format!("temp{}_crit_hyst", i));
fs::read_to_string(filename)
.unwrap_or_default()
.trim()
.parse::<i64>()
.unwrap_or_default()
/ 1000
};
temps.insert(
label.trim().to_string(),
Temperature {
current,
crit,
crit_hyst,
},
);
}
Err(_) => break,
}
} }
temps
} }
pub fn get_voltage(&self) -> Option<i64> { pub fn get_voltage(&self) -> Option<i64> {
@ -187,11 +234,22 @@ impl HWMon {
thread::spawn(move || { thread::spawn(move || {
while s.fan_control.load(Ordering::SeqCst) { while s.fan_control.load(Ordering::SeqCst) {
let curve = s.fan_curve.read().unwrap(); let temps = s.get_temps();
log::trace!("Temps: {:?}", temps);
let edge_temps = temps.get("edge").unwrap();
let temp = edge_temps.current;
if temp >= edge_temps.crit || temp <= edge_temps.crit_hyst {
println!("CRITICAL TEMPERATURE DETECTED! FORCING MAX FAN SPEED");
fs::write(s.hwmon_path.join("pwm1"), 255.to_string())
.expect("Failed to set gpu temp in critical scenario (Warning: GPU Overheating!)");
}
let temp = s.get_gpu_temp().unwrap();
log::trace!("Current gpu temp: {}", temp); log::trace!("Current gpu temp: {}", temp);
let curve = s.fan_curve.read().unwrap();
for (t_low, s_low) in curve.iter() { for (t_low, s_low) in curve.iter() {
match curve.range(t_low..).nth(1) { match curve.range(t_low..).nth(1) {
Some((t_high, s_high)) => { Some((t_high, s_high)) => {
@ -210,7 +268,7 @@ impl HWMon {
break; break;
} }
} }
None => (), None => continue,
} }
} }
drop(curve); //needed to release rwlock so that the curve can be changed drop(curve); //needed to release rwlock so that the curve can be changed

View File

@ -173,8 +173,10 @@ impl StatsGrid {
stats.power_avg.unwrap_or_else(|| 0), stats.power_avg.unwrap_or_else(|| 0),
stats.power_cap.unwrap_or_else(|| 0) stats.power_cap.unwrap_or_else(|| 0)
)); ));
self.gpu_temperature_label if let Some(temp) = stats.temperatures.get("edge") {
.set_markup(&format!("<b>{}°C</b>", stats.gpu_temp.unwrap_or_default())); self.gpu_temperature_label
.set_markup(&format!("<b>{}°C</b>", temp.current));
}
self.gpu_usage_label self.gpu_usage_label
.set_markup(&format!("<b>{}%</b>", stats.gpu_usage.unwrap_or_default())); .set_markup(&format!("<b>{}%</b>", stats.gpu_usage.unwrap_or_default()));
} }

View File

@ -129,10 +129,19 @@ impl ThermalsPage {
} }
pub fn set_thermals_info(&self, stats: &GpuStats) { pub fn set_thermals_info(&self, stats: &GpuStats) {
match stats.gpu_temp { self.temp_label.set_markup(&format!("<b>{}</b>", {
Some(temp) => self.temp_label.set_markup(&format!("<b>{}°C</b>", temp)), let mut temperatures = Vec::new();
None => self.temp_label.set_text("Sensor not found"),
} for (label, temp) in stats.temperatures.iter() {
temperatures.push(format!("{}: {}°C", label, temp.current));
}
if !temperatures.is_empty() {
temperatures.join(" ")
} else {
String::from("No sensors found")
}
}));
match stats.fan_speed { match stats.fan_speed {
Some(fan_speed) => self.fan_speed_label.set_markup(&format!( Some(fan_speed) => self.fan_speed_label.set_markup(&format!(