mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
Add support for more temperature sensors (#18)
This commit is contained in:
parent
7313019305
commit
14121a17f2
@ -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!(
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
@ -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!(
|
||||||
|
Loading…
Reference in New Issue
Block a user