Default temp input

This commit is contained in:
Adrian Woźniak 2021-08-21 19:12:17 +02:00
parent 806e8da4ee
commit a68eeda117
No known key found for this signature in database
GPG Key ID: 0012845A89C7352B
8 changed files with 63 additions and 46 deletions

View File

@ -3,3 +3,4 @@
cargo build --release
strip target/x86_64-unknown-linux-musl/release/amdfand
upx --best --lzma target/x86_64-unknown-linux-musl/release/amdfand

View File

@ -130,15 +130,11 @@ impl LogLevel {
#[derive(Serialize, Deserialize, Debug)]
pub struct Config {
log_level: LogLevel,
cards: Vec<Card>,
speed_matrix: Vec<MatrixPoint>,
temp_input: Option<String>,
}
impl Config {
pub fn cards(&self) -> &[Card] {
&self.cards
}
pub fn speed_for_temp(&self, temp: f64) -> f64 {
let idx = match self.speed_matrix.iter().rposition(|p| p.temp <= temp) {
Some(idx) => idx,
@ -162,6 +158,10 @@ impl Config {
self.log_level
}
pub fn temp_input(&self) -> Option<&str> {
self.temp_input.as_deref()
}
fn min_speed(&self) -> f64 {
self.speed_matrix.first().map(|p| p.speed).unwrap_or(0f64)
}
@ -175,7 +175,6 @@ impl Default for Config {
fn default() -> Self {
Self {
log_level: LogLevel::Error,
cards: vec![Card(0)],
speed_matrix: vec![
MatrixPoint {
temp: 4f64,
@ -210,6 +209,7 @@ impl Default for Config {
speed: 100f64,
},
],
temp_input: Some(String::from("temp1_input")),
}
}
}

View File

@ -6,23 +6,20 @@ use crate::FanMode;
/// Change card fan mode to either automatic or manual
pub fn run(switcher: Switcher, mode: FanMode, config: Config) -> std::io::Result<()> {
let mut controllers = crate::utils::controllers(&config, true)?;
let mut hw_mons = crate::utils::hw_mons(&config, true)?;
let cards = match switcher.card {
Some(card_id) => match controllers
.iter()
.position(|hw_mon| *hw_mon.card == card_id)
{
Some(card) => vec![controllers.remove(card)],
Some(card_id) => match hw_mons.iter().position(|hw_mon| **hw_mon.card() == card_id) {
Some(card) => vec![hw_mons.remove(card)],
None => {
eprintln!("Card does not exists. Available cards: ");
for hw_mon in controllers {
eprintln!(" * {}", *hw_mon.card);
for hw_mon in hw_mons {
eprintln!(" * {}", *hw_mon.card());
}
return Err(not_found());
}
},
None => controllers,
None => hw_mons,
};
for hw_mon in cards {

View File

@ -1,7 +1,7 @@
use std::str::FromStr;
use crate::config::Config;
use crate::utils::controllers;
use crate::utils::hw_mons;
use crate::AmdFanError;
#[derive(Debug)]
@ -45,11 +45,11 @@ pub fn run(monitor: Monitor, config: Config) -> std::io::Result<()> {
}
pub fn verbose(config: Config) -> std::io::Result<()> {
let mut controllers = controllers(&config, true)?;
let mut controllers = hw_mons(&config, true)?;
loop {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
for hw_mon in controllers.iter_mut() {
println!("Card {:3}", hw_mon.card.to_string().replace("card", ""));
println!("Card {:3}", hw_mon.card().to_string().replace("card", ""));
println!(" MIN | MAX | PWM | %");
let min = hw_mon.pwm_min();
let max = hw_mon.pwm_max();
@ -87,13 +87,13 @@ pub fn verbose(config: Config) -> std::io::Result<()> {
}
pub fn short(config: Config) -> std::io::Result<()> {
let mut controllers = controllers(&config, true)?;
let mut controllers = hw_mons(&config, true)?;
loop {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
for hw_mon in controllers.iter_mut() {
println!(
"Card {:3} | Temp | MIN | MAX | PWM | %",
hw_mon.card.to_string().replace("card", "")
hw_mon.card().to_string().replace("card", "")
);
let min = hw_mon.pwm_min();
let max = hw_mon.pwm_max();

View File

@ -5,7 +5,7 @@ use crate::io_err::not_found;
/// Start service which will change fan speed according to config and GPU temperature
pub fn run(config: Config) -> std::io::Result<()> {
let mut controllers = crate::utils::controllers(&config, true)?;
let mut controllers = crate::utils::hw_mons(&config, true)?;
if controllers.is_empty() {
return Err(not_found());
}
@ -13,8 +13,8 @@ pub fn run(config: Config) -> std::io::Result<()> {
loop {
for hw_mon in controllers.iter_mut() {
let gpu_temp = hw_mon.max_gpu_temp().unwrap_or_default();
log::debug!("Current {} temperature: {}", hw_mon.card, gpu_temp);
let last = *cache.entry(*hw_mon.card).or_insert(1_000f64);
log::debug!("Current {} temperature: {}", hw_mon.card(), gpu_temp);
let last = *cache.entry(**hw_mon.card()).or_insert(1_000f64);
if (last - gpu_temp).abs() < 0.001f64 {
log::debug!("Temperature didn't change");
@ -26,7 +26,7 @@ pub fn run(config: Config) -> std::io::Result<()> {
if let Err(e) = hw_mon.set_speed(speed) {
log::error!("Failed to change speed to {}. {:?}", speed, e);
}
cache.insert(*hw_mon.card, gpu_temp);
cache.insert(**hw_mon.card(), gpu_temp);
}
std::thread::sleep(std::time::Duration::from_secs(4));
}

View File

@ -1,7 +1,7 @@
use crate::config::Card;
use crate::config::{Card, Config};
use crate::io_err::{invalid_input, not_found};
use crate::utils::linear_map;
use crate::{AmdFanError, HwMon, HW_MON_DIR, ROOT_DIR};
use crate::{AmdFanError, HW_MON_DIR, ROOT_DIR};
/// pulse width modulation fan control minimum level (0)
const PULSE_WIDTH_MODULATION_MIN: &str = "pwm1_min";
@ -19,10 +19,27 @@ const PULSE_WIDTH_MODULATION_MODE: &str = "pwm1_enable";
const PULSE_WIDTH_MODULATION_AUTO: &str = "2";
const PULSE_WIDTH_MODULATION_MANUAL: &str = "1";
#[derive(Debug)]
pub struct HwMon {
/// HW MOD cord (ex. card0)
card: Card,
/// MW MOD name (ex. hwmod0)
name: String,
/// Minimal modulation (between 0-255)
pwm_min: Option<u32>,
/// Maximal modulation (between 0-255)
pwm_max: Option<u32>,
/// List of available temperature inputs for current HW MOD
temp_inputs: Vec<String>,
/// Preferred temperature input
temp_input: Option<String>,
}
impl HwMon {
pub fn new(card: &Card, name: &str) -> Self {
pub fn new(card: &Card, name: &str, config: &Config) -> Self {
Self {
card: *card,
temp_input: config.temp_input().map(String::from),
name: String::from(name),
pwm_min: None,
pwm_max: None,
@ -31,6 +48,12 @@ impl HwMon {
}
pub fn max_gpu_temp(&self) -> std::io::Result<f64> {
if let Some(input) = self.temp_input.as_deref() {
return self
.read_gpu_temp(input)
.map(|temp| temp as f64 / 1000f64)
.map_err(|_| invalid_input());
}
let mut results = Vec::with_capacity(self.temp_inputs.len());
for name in self.temp_inputs.iter() {
results.push(self.read_gpu_temp(name).unwrap_or(0));
@ -63,6 +86,11 @@ impl HwMon {
})
}
#[inline]
pub(crate) fn card(&self) -> &Card {
&self.card
}
#[inline]
pub(crate) fn name(&self) -> std::io::Result<String> {
self.read("name")
@ -190,7 +218,7 @@ fn hw_mon_dir_path(card: &Card, name: &str) -> std::path::PathBuf {
hw_mon_dirs_path(card).join(name)
}
pub(crate) fn open_hw_mon(card: Card) -> std::io::Result<HwMon> {
pub(crate) fn open_hw_mon(card: Card, config: &Config) -> std::io::Result<HwMon> {
let read_path = hw_mon_dirs_path(&card);
let entries = std::fs::read_dir(read_path)?;
let name = entries
@ -206,5 +234,5 @@ pub(crate) fn open_hw_mon(card: Card) -> std::io::Result<HwMon> {
.take(1)
.last()
.ok_or_else(not_found)?;
Ok(HwMon::new(&card, &name))
Ok(HwMon::new(&card, &name, config))
}

View File

@ -3,7 +3,7 @@ use std::io::ErrorKind;
use gumdrop::Options;
use crate::config::{load_config, Card};
use crate::config::load_config;
mod config;
mod fan;
@ -47,15 +47,6 @@ impl std::fmt::Display for AmdFanError {
}
}
#[derive(Debug)]
pub struct HwMon {
card: Card,
name: String,
pwm_min: Option<u32>,
pwm_max: Option<u32>,
temp_inputs: Vec<String>,
}
pub enum FanMode {
Manual,
Automatic,
@ -86,7 +77,7 @@ fn main() -> std::io::Result<()> {
let opts: Opts = Opts::parse_args_default_or_exit();
if opts.version {
println!("{}", env!("CARGO_PKG_VERSION"));
println!("amdfand {}", env!("CARGO_PKG_VERSION"));
std::process::exit(0);
}
@ -102,12 +93,12 @@ fn main() -> std::io::Result<()> {
}
Some(fan::FanCommand::Available(_)) => {
println!("Available cards");
utils::controllers(&config, false)?
utils::hw_mons(&config, false)?
.into_iter()
.for_each(|hw_mon| {
println!(
" * {:6>} - {}",
hw_mon.card,
hw_mon.card(),
hw_mon.name().unwrap_or_default()
);
});

View File

@ -1,5 +1,6 @@
use crate::config::{Card, Config};
use crate::{hw_mon, HwMon, ROOT_DIR};
use crate::hw_mon::HwMon;
use crate::{hw_mon, ROOT_DIR};
/// linear mapping from the xrange to the yrange
pub fn linear_map(x: f64, x1: f64, x2: f64, y1: f64, y2: f64) -> f64 {
@ -19,11 +20,10 @@ pub fn read_cards() -> std::io::Result<Vec<Card>> {
/// Wrap cards in HW Mon manipulator and
/// filter cards so only amd and listed in config cards are accessible
pub fn controllers(config: &Config, filter: bool) -> std::io::Result<Vec<HwMon>> {
pub fn hw_mons(config: &Config, filter: bool) -> std::io::Result<Vec<HwMon>> {
Ok(read_cards()?
.into_iter()
.filter(|card| !filter || config.cards().iter().any(|name| **name == **card))
.filter_map(|card| hw_mon::open_hw_mon(card).ok())
.filter_map(|card| hw_mon::open_hw_mon(card, config).ok())
.filter(|hw_mon| !filter || { hw_mon.is_amd() })
.filter(|hw_mon| !filter || hw_mon.name_is_amd())
.collect())