use std::sync::Arc;
use crate::schema::control::Control as ControlSchema;
#[cfg(feature = "chassis")]
use crate::schema::control_collection::ControlCollection as ControlCollectionSchema;
use crate::Error;
use crate::NvBmc;
use crate::Resource;
use crate::ResourceSchema;
use nv_redfish_core::Bmc;
use nv_redfish_core::EntityTypeRef as _;
use nv_redfish_core::ModificationResponse;
use nv_redfish_core::NavProperty;
#[cfg(any(
feature = "chassis",
feature = "memory",
feature = "storages",
feature = "processors"
))]
use crate::schema::environment_metrics::EnvironmentMetrics;
#[cfg(any(
feature = "chassis",
feature = "memory",
feature = "storages",
feature = "processors"
))]
use crate::core::ODataId;
pub use crate::schema::control::ControlMode;
pub use crate::schema::control::ControlType;
pub use crate::schema::control::ControlUpdate;
pub use crate::schema::control::ImplementationType;
pub use crate::schema::control::SetPointType;
#[cfg(feature = "chassis")]
pub struct ControlCollection<B: Bmc> {
bmc: NvBmc<B>,
collection: Arc<ControlCollectionSchema>,
}
#[cfg(feature = "chassis")]
impl<B: Bmc> ControlCollection<B> {
pub(crate) async fn new(
bmc: &NvBmc<B>,
nav: &NavProperty<ControlCollectionSchema>,
) -> Result<Self, Error<B>> {
nav.get(bmc.as_ref())
.await
.map_err(Error::Bmc)
.map(|collection| Self {
bmc: bmc.clone(),
collection,
})
}
#[must_use]
pub fn raw(&self) -> Arc<ControlCollectionSchema> {
self.collection.clone()
}
pub async fn members(&self) -> Result<Vec<Control<B>>, Error<B>> {
let mut controls = Vec::with_capacity(self.collection.members.len());
for control in &self.collection.members {
controls.push(Control::new(&self.bmc, control).await?);
}
Ok(controls)
}
}
pub struct Control<B: Bmc> {
bmc: NvBmc<B>,
data: Arc<ControlSchema>,
}
impl<B: Bmc> Control<B> {
pub(crate) async fn new(
bmc: &NvBmc<B>,
nav: &NavProperty<ControlSchema>,
) -> 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<ControlSchema> {
self.data.clone()
}
pub async fn update(
&self,
update: &ControlUpdate,
) -> Result<ModificationResponse<Self>, Error<B>> {
self.bmc
.as_ref()
.update::<_, NavProperty<ControlSchema>>(self.data.odata_id(), self.data.etag(), update)
.await
.map_err(Error::Bmc)?
.try_map_entity_async(|nav| async move { Self::new(&self.bmc, &nav).await })
.await
}
}
impl<B: Bmc> Resource for Control<B> {
fn resource_ref(&self) -> &ResourceSchema {
&self.data.as_ref().base
}
}
#[cfg(any(
feature = "chassis",
feature = "memory",
feature = "storages",
feature = "processors"
))]
pub(crate) async fn extract_environment_power_limit_control<B: Bmc>(
bmc: &NvBmc<B>,
metrics_ref: &NavProperty<EnvironmentMetrics>,
) -> Result<Option<Control<B>>, Error<B>> {
let metrics = metrics_ref.get(bmc.as_ref()).await.map_err(Error::Bmc)?;
let Some(Some(uri)) = metrics
.power_limit_watts
.as_ref()
.and_then(|control| control.data_source_uri.as_ref())
else {
return Ok(None);
};
let control_ref = NavProperty::<ControlSchema>::new_reference(ODataId::from(uri.clone()));
Control::new(bmc, &control_ref).await.map(Some)
}