#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use crate::{
api_test::{HardwareType, Sensor, SensorType},
wmic::{Hardware, HardwareMonitor},
};
use e_utils::{
cmd::{Cmd, ExeType},
AnyResult,
};
use std::{collections::HashMap, str::FromStr as _};
use wmi::{COMLibrary, Variant, WMIConnection};
pub type RawQuery = HashMap<String, Variant>;
#[derive(Clone, Debug)]
pub struct OHM(WMIConnection);
impl OHM {
pub const EXE: &'static str = "OpenHardwareMonitor.exe";
pub const DIR: &'static str = "plugins/OHM";
pub fn get(&self) -> &WMIConnection {
&self.0
}
fn build_query(&self, hw_type: HardwareType) -> String {
if hw_type == HardwareType::ALL {
Self::HW_QUERY.to_string()
} else {
format!("{} WHERE HardwareType='{}'", Self::HW_QUERY, hw_type)
}
}
fn build_sensor_query(&self, sensor_type: &SensorType) -> String {
if sensor_type == &SensorType::ALL {
String::new()
} else {
format!("AND SensorType='{}'", sensor_type)
}
}
pub async fn a_query(&self, hw_type: HardwareType, sensor_type: SensorType) -> AnyResult<Vec<Sensor>> {
let hws = self
.get()
.async_raw_query(self.build_query(hw_type))
.await?
.into_iter()
.map(|mut hw: Hardware<HardwareType>| {
hw.HardwareType = HardwareType::from_str(&hw._HardwareType).unwrap_or(HardwareType::Unknown);
hw
})
.collect::<Vec<_>>();
let st_query = self.build_sensor_query(&sensor_type);
let mut sensors = Vec::new();
for hw in hws {
let query = format!("{} WHERE Parent='{}' {}", Self::SENSOR_QUERY, hw.Identifier, st_query);
sensors.extend(self.get().async_raw_query(query).await?.into_iter().map(|mut sensor: Sensor| {
sensor.SensorType = SensorType::from_str(&sensor._SensorType).unwrap_or(SensorType::Unknown);
sensor
}));
}
if sensors.is_empty() {
return Err("No sensors found".into());
}
Ok(sensors)
}
pub fn query(&self, hw_type: HardwareType, sensor_type: SensorType) -> AnyResult<Vec<Sensor>> {
let hws = self
.get()
.raw_query(self.build_query(hw_type))?
.into_iter()
.map(|mut hw: Hardware<HardwareType>| {
hw.HardwareType = HardwareType::from_str(&hw._HardwareType).unwrap_or(HardwareType::Unknown);
hw
})
.collect::<Vec<_>>();
let st_query = self.build_sensor_query(&sensor_type);
let mut sensors = Vec::new();
for hw in hws {
let query = format!("{} WHERE Parent='{}' {}", Self::SENSOR_QUERY, hw.Identifier, st_query);
sensors.extend(self.get().raw_query(query)?.into_iter().map(|mut sensor: Sensor| {
sensor.SensorType = SensorType::from_str(&sensor._SensorType).unwrap_or(SensorType::Unknown);
sensor
}));
}
if sensors.is_empty() {
return Err("No sensors found".into());
}
Ok(sensors)
}
}
impl HardwareMonitor for OHM {
type HWType = HardwareType;
type SensorType = Sensor;
const CON_QUERY: &'static str = "ROOT\\OpenHardwareMonitor";
const HW_QUERY: &'static str = "SELECT * FROM Hardware";
const SENSOR_QUERY: &'static str = "SELECT * FROM Sensor";
fn new() -> AnyResult<Self> {
let com_con = COMLibrary::new()?;
let wmi = WMIConnection::with_namespace_path(Self::CON_QUERY, com_con)?;
Ok(OHM(wmi))
}
fn test(count: u64) -> AnyResult<()> {
for i in 1..=count {
match Self::new() {
Ok(api) => {
let has_value = [
(HardwareType::CPU, SensorType::Clock),
(HardwareType::ALL, SensorType::Temperature),
(HardwareType::ALL, SensorType::Fan),
]
.into_iter()
.any(|(hw_type, sensor_type)| {
api
.query(hw_type, sensor_type)
.ok()
.and_then(|v| v.first().cloned())
.map(|v| v.Value != 0.0)
.unwrap_or(false)
});
if has_value {
crate::dp(format!("Loading... ({}%/{}%)", count, count));
crate::dp("OpenHardwareMonitor ready");
return Ok(());
}
}
Err(e) => crate::wp(e.to_string()),
}
crate::dp(format!("Loading... ({}%/{}%)", i, count));
std::thread::sleep(std::time::Duration::from_millis(200));
}
Err("OpenHardwareMonitor load timeout".into())
}
fn stop() -> AnyResult<()> {
if cfg!(target_os = "windows") {
let res = Cmd::new("sc")
.set_type(ExeType::Cmd)
.args(&["config", "WinRing0_1_2_0", "start=", "disabled"])
.output()?;
crate::dp(format!("OHM [OpenHardwareMonitorLib.sys WinRing0_1_2_0] disable: {}", res.stdout));
let res = Cmd::new("sc").set_type(ExeType::Cmd).args(&["stop", "WinRing0_1_2_0"]).output()?;
crate::dp(format!("OHM [OpenHardwareMonitorLib.sys WinRing0_1_2_0] stop: {}", res.stdout));
}
Ok(())
}
fn clean() -> AnyResult<()> {
if cfg!(target_os = "windows") {
let res = Cmd::new("sc").set_type(ExeType::Cmd).args(&["delete", "WinRing0_1_2_0"]).output()?;
crate::dp(format!("OHM [OpenHardwareMonitorLib.sys WinRing0_1_2_0] delete: {}", res.stdout));
}
Ok(())
}
}