use super::Hwmons;
use crate::parsing::{Error as ParsingError, Parseable, Result as ParsingResult};
use crate::sensors::*;
use std::collections::BTreeMap;
use std::fs::read_to_string;
use std::path::{Path, PathBuf};
fn check_path(path: impl AsRef<Path>) -> ParsingResult<()> {
let path = path.as_ref();
if !path.exists() {
return Err(ParsingError::PathDoesNotExist {
path: path.to_path_buf(),
});
}
if !path.is_dir() {
return Err(ParsingError::InvalidPath { path: path.into() });
}
if let Err(e) = path.metadata() {
match e.kind() {
std::io::ErrorKind::NotFound => {
return Err(ParsingError::PathDoesNotExist { path: path.into() })
}
std::io::ErrorKind::PermissionDenied => {
return Err(ParsingError::InsufficientRights { path: path.into() })
}
_ => return Err(ParsingError::Other { source: e }),
}
}
Ok(())
}
fn get_name(path: impl AsRef<Path>) -> ParsingResult<String> {
use std::io::ErrorKind as IoErrorKind;
let name_path = path.as_ref().join("name");
match read_to_string(&name_path) {
Ok(name) => Ok(name.trim().to_string()),
Err(e) => match e.kind() {
IoErrorKind::NotFound => Err(ParsingError::PathDoesNotExist { path: name_path }),
IoErrorKind::PermissionDenied => {
Err(ParsingError::InsufficientRights { path: name_path })
}
_ => Err(ParsingError::Other { source: e }),
},
}
}
fn init_sensors<S>(hwmon: &Hwmon, start_index: u16) -> ParsingResult<BTreeMap<u16, S>>
where
S: Parseable<Parent = Hwmon>,
{
let mut sensors = BTreeMap::new();
for index in start_index.. {
match S::parse(hwmon, index) {
Ok(sensor) => {
sensors.insert(index, sensor);
}
Err(sensor_error) => match sensor_error {
ParsingError::InsufficientRights { path } => {
return Err(ParsingError::InsufficientRights { path })
}
_ => break,
},
}
}
Ok(sensors)
}
#[derive(Debug, Clone)]
pub struct Hwmon {
name: String,
path: PathBuf,
currents: BTreeMap<u16, CurrentSensorStruct>,
energies: BTreeMap<u16, EnergySensorStruct>,
fans: BTreeMap<u16, FanSensorStruct>,
humidities: BTreeMap<u16, HumiditySensorStruct>,
powers: BTreeMap<u16, PowerSensorStruct>,
pwms: BTreeMap<u16, PwmSensorStruct>,
temps: BTreeMap<u16, TempSensorStruct>,
voltages: BTreeMap<u16, VoltageSensorStruct>,
}
impl Hwmon {
pub fn name(&self) -> &str {
&self.name
}
pub fn path(&self) -> &Path {
&self.path
}
pub fn device_path(&self) -> PathBuf {
self.path().join("device").canonicalize().unwrap()
}
pub fn currents(&self) -> &BTreeMap<u16, impl CurrentSensor + Clone + Send + Sync> {
&self.currents
}
pub fn energies(&self) -> &BTreeMap<u16, impl EnergySensor + Clone + Send + Sync> {
&self.energies
}
pub fn fans(&self) -> &BTreeMap<u16, impl FanSensor + Clone + Send + Sync> {
&self.fans
}
pub fn humidities(&self) -> &BTreeMap<u16, impl HumiditySensor + Clone + Send + Sync> {
&self.humidities
}
pub fn powers(&self) -> &BTreeMap<u16, impl PowerSensor + Clone + Send + Sync> {
&self.powers
}
pub fn pwms(&self) -> &BTreeMap<u16, impl PwmSensor + Clone + Send + Sync> {
&self.pwms
}
pub fn temps(&self) -> &BTreeMap<u16, impl TempSensor + Clone + Send + Sync> {
&self.temps
}
pub fn voltages(&self) -> &BTreeMap<u16, impl VoltageSensor + Clone + Send + Sync> {
&self.voltages
}
pub fn current(&self, index: u16) -> Option<&(impl CurrentSensor + Clone + Send + Sync)> {
self.currents.get(&index)
}
pub fn energy(&self, index: u16) -> Option<&(impl EnergySensor + Clone + Send + Sync)> {
self.energies.get(&index)
}
pub fn fan(&self, index: u16) -> Option<&(impl FanSensor + Clone + Send + Sync)> {
self.fans.get(&index)
}
pub fn humidity(&self, index: u16) -> Option<&(impl HumiditySensor + Clone + Send + Sync)> {
self.humidities.get(&index)
}
pub fn power(&self, index: u16) -> Option<&(impl PowerSensor + Clone + Send + Sync)> {
self.powers.get(&index)
}
pub fn pwm(&self, index: u16) -> Option<&(impl PwmSensor + Clone + Send + Sync)> {
self.pwms.get(&index)
}
pub fn temp(&self, index: u16) -> Option<&(impl TempSensor + Clone + Send + Sync)> {
self.temps.get(&index)
}
pub fn voltage(&self, index: u16) -> Option<&(impl VoltageSensor + Clone + Send + Sync)> {
self.voltages.get(&index)
}
}
#[cfg(feature = "writeable")]
impl Hwmon {
pub fn writeable_currents(
&self,
) -> &BTreeMap<u16, impl WriteableCurrentSensor + Clone + Send + Sync> {
&self.currents
}
pub fn writeable_energies(
&self,
) -> &BTreeMap<u16, impl WriteableEnergySensor + Clone + Send + Sync> {
&self.energies
}
pub fn writeable_fans(&self) -> &BTreeMap<u16, impl WriteableFanSensor + Clone + Send + Sync> {
&self.fans
}
pub fn writeable_humidities(
&self,
) -> &BTreeMap<u16, impl WriteableHumiditySensor + Clone + Send + Sync> {
&self.humidities
}
pub fn writeable_powers(
&self,
) -> &BTreeMap<u16, impl WriteablePowerSensor + Clone + Send + Sync> {
&self.powers
}
pub fn writeable_pwms(&self) -> &BTreeMap<u16, impl WriteablePwmSensor + Clone + Send + Sync> {
&self.pwms
}
pub fn writeable_temps(
&self,
) -> &BTreeMap<u16, impl WriteableTempSensor + Clone + Send + Sync> {
&self.temps
}
pub fn writeable_voltages(
&self,
) -> &BTreeMap<u16, impl WriteableVoltageSensor + Clone + Send + Sync> {
&self.voltages
}
pub fn writeable_current(
&self,
index: u16,
) -> Option<&(impl WriteableCurrentSensor + Clone + Send + Sync)> {
self.currents.get(&index)
}
pub fn writeable_energy(
&self,
index: u16,
) -> Option<&(impl WriteableEnergySensor + Clone + Send + Sync)> {
self.energies.get(&index)
}
pub fn writeable_fan(
&self,
index: u16,
) -> Option<&(impl WriteableFanSensor + Clone + Send + Sync)> {
self.fans.get(&index)
}
pub fn writeable_humidity(
&self,
index: u16,
) -> Option<&(impl WriteableHumiditySensor + Clone + Send + Sync)> {
self.humidities.get(&index)
}
pub fn writeable_power(
&self,
index: u16,
) -> Option<&(impl WriteablePowerSensor + Clone + Send + Sync)> {
self.powers.get(&index)
}
pub fn writeable_pwm(
&self,
index: u16,
) -> Option<&(impl WriteablePwmSensor + Clone + Send + Sync)> {
self.pwms.get(&index)
}
pub fn writeable_temp(
&self,
index: u16,
) -> Option<&(impl WriteableTempSensor + Clone + Send + Sync)> {
self.temps.get(&index)
}
pub fn writeable_voltage(
&self,
index: u16,
) -> Option<&(impl WriteableVoltageSensor + Clone + Send + Sync)> {
self.voltages.get(&index)
}
}
impl Parseable for Hwmon {
type Parent = Hwmons;
fn parse(parent: &Self::Parent, index: u16) -> ParsingResult<Self> {
let path = parent.path().join(format!("hwmon{}", index));
check_path(&path)?;
let mut hwmon = Self {
name: get_name(&path)?,
path,
currents: BTreeMap::new(),
energies: BTreeMap::new(),
fans: BTreeMap::new(),
humidities: BTreeMap::new(),
powers: BTreeMap::new(),
pwms: BTreeMap::new(),
temps: BTreeMap::new(),
voltages: BTreeMap::new(),
};
hwmon.currents = init_sensors(&hwmon, 1)?;
hwmon.energies = init_sensors(&hwmon, 1)?;
hwmon.fans = init_sensors(&hwmon, 1)?;
hwmon.humidities = init_sensors(&hwmon, 1)?;
hwmon.powers = init_sensors(&hwmon, 1)?;
hwmon.pwms = init_sensors(&hwmon, 1)?;
hwmon.temps = init_sensors(&hwmon, 1)?;
hwmon.voltages = init_sensors(&hwmon, 0)?;
Ok(hwmon)
}
}