use std::{marker::PhantomData, time::Duration};
use crate::{
DataType as _, MonitoredItemAttribute, MonitoredItemKind, MonitoringFilter, attributes, ua,
};
use super::{DataChange, Unknown};
#[derive(Debug)]
pub struct MonitoredItemCreateRequestBuilder<K: MonitoredItemKind> {
node_ids: Vec<ua::NodeId>,
attribute_id: ua::AttributeId,
monitoring_mode: Option<ua::MonitoringMode>,
#[expect(clippy::option_option, reason = "implied default vs. unset")]
sampling_interval: Option<Option<Duration>>,
filter: Option<Box<dyn MonitoringFilter>>,
queue_size: Option<u32>,
discard_oldest: Option<bool>,
_kind: PhantomData<K>,
}
impl MonitoredItemCreateRequestBuilder<DataChange<attributes::Value>> {
pub fn new(node_ids: impl IntoIterator<Item = ua::NodeId>) -> Self {
Self {
node_ids: node_ids.into_iter().collect(),
attribute_id: ua::AttributeId::VALUE,
monitoring_mode: None,
sampling_interval: None,
filter: None,
queue_size: None,
discard_oldest: None,
_kind: PhantomData,
}
}
}
impl<K: MonitoredItemKind> MonitoredItemCreateRequestBuilder<K> {
#[must_use]
pub fn attribute<T: MonitoredItemAttribute>(
self,
attribute: T,
) -> MonitoredItemCreateRequestBuilder<T::Kind> {
let Self {
node_ids,
attribute_id: _,
monitoring_mode,
sampling_interval,
filter,
queue_size,
discard_oldest,
_kind,
} = self;
MonitoredItemCreateRequestBuilder {
node_ids,
attribute_id: attribute.id(),
monitoring_mode,
sampling_interval,
filter,
queue_size,
discard_oldest,
_kind: PhantomData,
}
}
#[must_use]
pub fn attribute_id(
self,
attribute_id: ua::AttributeId,
) -> MonitoredItemCreateRequestBuilder<Unknown> {
let Self {
node_ids,
attribute_id: _,
monitoring_mode,
sampling_interval,
filter,
queue_size,
discard_oldest,
_kind,
} = self;
MonitoredItemCreateRequestBuilder {
node_ids,
attribute_id,
monitoring_mode,
sampling_interval,
filter,
queue_size,
discard_oldest,
_kind: PhantomData,
}
}
#[must_use]
pub fn monitoring_mode(mut self, monitoring_mode: ua::MonitoringMode) -> Self {
self.monitoring_mode = Some(monitoring_mode);
self
}
#[must_use]
#[expect(
clippy::missing_const_for_fn,
reason = "Might become non-const by internal changes in the future."
)]
pub fn sampling_interval(mut self, sampling_interval: Option<Duration>) -> Self {
self.sampling_interval = Some(sampling_interval);
self
}
#[must_use]
pub fn filter(mut self, filter: impl MonitoringFilter) -> Self {
self.filter = Some(Box::new(filter));
self
}
#[must_use]
#[expect(
clippy::missing_const_for_fn,
reason = "Might become non-const by internal changes in the future."
)]
pub fn queue_size(mut self, queue_size: u32) -> Self {
self.queue_size = Some(queue_size);
self
}
#[must_use]
#[expect(
clippy::missing_const_for_fn,
reason = "Might become non-const by internal changes in the future."
)]
pub fn discard_oldest(mut self, discard_oldest: bool) -> Self {
self.discard_oldest = Some(discard_oldest);
self
}
#[must_use]
pub fn node_ids(&self) -> &[ua::NodeId] {
self.node_ids.as_slice()
}
#[must_use]
pub fn build(self, subscription_id: ua::SubscriptionId) -> ua::CreateMonitoredItemsRequest {
let Self {
node_ids,
attribute_id,
monitoring_mode,
sampling_interval,
filter,
queue_size,
discard_oldest,
_kind: _,
} = self;
let items_to_create = node_ids
.into_iter()
.map(|node_id| {
let mut request = ua::MonitoredItemCreateRequest::default()
.with_node_id(&node_id)
.with_attribute_id(&attribute_id);
if let Some(monitoring_mode) = monitoring_mode.as_ref() {
request = request.with_monitoring_mode(monitoring_mode);
}
if let Some(&sampling_interval) = sampling_interval.as_ref() {
request = request.with_sampling_interval(sampling_interval);
}
if let Some(filter) = filter.as_ref() {
request = request.with_filter(filter);
}
if let Some(&queue_size) = queue_size.as_ref() {
request = request.with_queue_size(queue_size);
}
if let Some(&discard_oldest) = discard_oldest.as_ref() {
request = request.with_discard_oldest(discard_oldest);
}
request
})
.collect::<Vec<_>>();
ua::CreateMonitoredItemsRequest::init()
.with_subscription_id(subscription_id)
.with_items_to_create(&items_to_create)
}
}
#[cfg(feature = "tokio")]
impl<K: MonitoredItemKind> From<crate::async_monitored_item::MonitoredItemBuilder<K>>
for MonitoredItemCreateRequestBuilder<K>
{
fn from(deprecated: crate::async_monitored_item::MonitoredItemBuilder<K>) -> Self {
let crate::async_monitored_item::MonitoredItemBuilder {
node_ids,
attribute_id,
monitoring_mode,
sampling_interval,
filter,
queue_size,
discard_oldest,
_kind: _,
} = deprecated;
Self {
node_ids,
attribute_id,
monitoring_mode,
sampling_interval,
filter,
queue_size,
discard_oldest,
_kind: PhantomData,
}
}
}