use crate::resource::ResetType;
use crate::schema::power_supply::PowerSupply as PowerSupplySchema;
use crate::schema::power_supply_metrics::PowerSupplyMetrics;
use crate::Error;
use crate::NvBmc;
use crate::Resource;
use crate::ResourceSchema;
use nv_redfish_core::Bmc;
use nv_redfish_core::ModificationResponse;
use nv_redfish_core::NavProperty;
use std::sync::Arc;
#[cfg(feature = "sensors")]
use crate::extract_sensor_uris;
#[cfg(feature = "oem-delta")]
use crate::oem::delta::DeltaPowerSupply;
#[cfg(feature = "sensors")]
use crate::sensor::SensorLink;
#[cfg(feature = "oem-delta")]
use std::convert::identity;
pub struct PowerSupply<B: Bmc> {
bmc: NvBmc<B>,
data: Arc<PowerSupplySchema>,
}
impl<B: Bmc> PowerSupply<B> {
pub(crate) async fn new(
bmc: &NvBmc<B>,
nav: &NavProperty<PowerSupplySchema>,
) -> Result<Self, Error<B>> {
nav.get(bmc.as_ref())
.await
.map_err(Error::Bmc)
.map(|data| Self {
bmc: bmc.clone(),
data,
})
}
#[must_use]
pub fn raw(&self) -> Arc<PowerSupplySchema> {
self.data.clone()
}
pub async fn reset(
&self,
reset_type: Option<ResetType>,
) -> Result<ModificationResponse<()>, Error<B>>
where
B::Error: nv_redfish_core::ActionError,
{
let actions = self
.data
.actions
.as_ref()
.ok_or(Error::ActionNotAvailable)?;
if actions.reset.is_none() {
return Err(Error::ActionNotAvailable);
}
actions
.reset(self.bmc.as_ref(), reset_type)
.await
.map_err(Error::Bmc)
}
pub async fn metrics(&self) -> Result<Option<Arc<PowerSupplyMetrics>>, Error<B>> {
if let Some(metrics_ref) = &self.data.metrics {
metrics_ref
.get(self.bmc.as_ref())
.await
.map_err(Error::Bmc)
.map(Some)
} else {
Ok(None)
}
}
#[cfg(feature = "sensors")]
pub async fn metrics_sensor_links(&self) -> Result<Vec<SensorLink<B>>, Error<B>> {
let sensor_refs = if let Some(metrics_ref) = &self.data.metrics {
metrics_ref
.get(self.bmc.as_ref())
.await
.map_err(Error::Bmc)
.map(|m| {
extract_sensor_uris!(m,
single: input_voltage,
single: input_current_amps,
single: input_power_watts,
single: energyk_wh,
single: frequency_hz,
single: output_power_watts,
single: temperature_celsius,
single: fan_speed_percent,
vec: rail_voltage,
vec: rail_current_amps,
vec: rail_power_watts,
vec: fan_speeds_percent
)
})?
} else {
Vec::new()
};
Ok(sensor_refs
.into_iter()
.map(|r| SensorLink::new(&self.bmc, r))
.collect())
}
#[cfg(feature = "oem-delta")]
pub fn oem_delta(&self) -> Result<Option<DeltaPowerSupply<B>>, Error<B>> {
self.data
.base
.base
.oem
.as_ref()
.map(DeltaPowerSupply::new)
.transpose()
.map(|v| v.and_then(identity))
}
}
impl<B: Bmc> Resource for PowerSupply<B> {
fn resource_ref(&self) -> &ResourceSchema {
&self.data.as_ref().base
}
}