libfancontrold 0.4.0

Base library for fancontrold.
Documentation
mod error;

pub use error::{Error, Result};

use std::{
    fmt::{Display, Formatter, Result as FmtResult},
    path::{Path, PathBuf},
};

#[cfg(feature = "async")]
use libmedium::{
    hwmon::async_hwmon::Hwmons,
    sensors::async_sensors::{
        fan::AsyncFanSensor as FanSensor, pwm::AsyncWriteablePwmSensor as WriteablePwmSensor,
        temp::AsyncTempSensor as TempSensor,
    },
};

#[cfg(not(feature = "async"))]
use libmedium::{
    hwmon::sync_hwmon::Hwmons,
    sensors::sync_sensors::{fan::FanSensor, pwm::WriteablePwmSensor, temp::TempSensor},
};

use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Ord, PartialOrd)]
pub struct Address {
    hwmon_device_path: PathBuf,
    index: u16,
}

impl Address {
    pub fn new(hwmon_device_path: impl Into<PathBuf>, index: u16) -> Address {
        Address {
            hwmon_device_path: hwmon_device_path.into(),
            index,
        }
    }

    pub fn hwmon_device_path(&self) -> &Path {
        self.hwmon_device_path.as_path()
    }

    pub fn index(&self) -> u16 {
        self.index
    }
}

impl From<&Address> for Address {
    fn from(reference: &Address) -> Self {
        reference.clone()
    }
}

impl Display for Address {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(
            f,
            "{} of hwmon {}",
            self.index,
            self.hwmon_device_path.display()
        )
    }
}

pub trait Addressable {
    fn get_fan(&self, address: &Address) -> Result<Box<dyn FanSensor + Send + Sync>>;
    fn get_pwm(&self, address: &Address) -> Result<Box<dyn WriteablePwmSensor + Send + Sync>>;
    fn get_temp(&self, address: &Address) -> Result<Box<dyn TempSensor + Send + Sync>>;
}

impl Addressable for Hwmons {
    fn get_fan(&self, address: &Address) -> Result<Box<dyn FanSensor + Send + Sync>> {
        let fan: Box<dyn FanSensor + Send + Sync> = self
            .hwmon_by_device_path(address.hwmon_device_path())
            .ok_or_else(|| Error::hwmon_not_found(address.hwmon_device_path()))?
            .fan(address.index())
            .ok_or_else(|| Error::fan_not_found(address))
            .map(|fan| Box::new(fan.to_owned()))?;
        Ok(fan)
    }

    fn get_pwm(&self, address: &Address) -> Result<Box<dyn WriteablePwmSensor + Send + Sync>> {
        let pwm: Box<dyn WriteablePwmSensor + Send + Sync> = self
            .hwmon_by_device_path(address.hwmon_device_path())
            .ok_or_else(|| Error::hwmon_not_found(address.hwmon_device_path()))?
            .writeable_pwm(address.index())
            .ok_or_else(|| Error::pwm_not_found(address))
            .map(|pwm| Box::new(pwm.to_owned()))?;
        Ok(pwm)
    }

    fn get_temp(&self, address: &Address) -> Result<Box<dyn TempSensor + Send + Sync>> {
        let temp: Box<dyn TempSensor + Send + Sync> = self
            .hwmon_by_device_path(address.hwmon_device_path())
            .ok_or_else(|| Error::hwmon_not_found(address.hwmon_device_path()))?
            .temp(address.index())
            .ok_or_else(|| Error::temp_not_found(address))
            .map(|temp| Box::new(temp.to_owned()))?;
        Ok(temp)
    }
}