use opcua_types::{
AttributeId, DataEncoding, DataValue, DateTime, DiagnosticBits, DiagnosticInfo, NodeId,
NumericRange, ReadValueId, StatusCode, WriteValue,
};
use super::IntoResult;
#[derive(Debug, Clone)]
pub struct ParsedReadValueId {
pub node_id: NodeId,
pub attribute_id: AttributeId,
pub index_range: NumericRange,
pub data_encoding: DataEncoding,
}
impl ParsedReadValueId {
pub fn parse(val: ReadValueId) -> Result<Self, StatusCode> {
let attribute_id = AttributeId::from_u32(val.attribute_id)
.map_err(|_| StatusCode::BadAttributeIdInvalid)?;
Ok(Self {
node_id: val.node_id,
attribute_id,
index_range: val.index_range,
data_encoding: DataEncoding::from_browse_name(val.data_encoding)?,
})
}
pub fn null() -> Self {
Self {
node_id: NodeId::null(),
attribute_id: AttributeId::NodeId,
index_range: NumericRange::None,
data_encoding: DataEncoding::Binary,
}
}
pub fn is_null(&self) -> bool {
self.node_id.is_null()
}
}
impl Default for ParsedReadValueId {
fn default() -> Self {
Self::null()
}
}
#[derive(Debug)]
pub struct ReadNode {
node: ParsedReadValueId,
pub(crate) result: DataValue,
diagnostic_bits: DiagnosticBits,
diagnostic_info: Option<DiagnosticInfo>,
}
impl ReadNode {
pub(crate) fn new(node: ReadValueId, diagnostic_bits: DiagnosticBits) -> Self {
let mut status = StatusCode::BadNodeIdUnknown;
let node = match ParsedReadValueId::parse(node) {
Ok(r) => r,
Err(e) => {
status = e;
ParsedReadValueId::null()
}
};
Self {
node,
result: DataValue {
status: Some(status),
server_timestamp: Some(DateTime::now()),
..Default::default()
},
diagnostic_bits,
diagnostic_info: None,
}
}
pub fn status(&self) -> StatusCode {
self.result.status()
}
pub fn node(&self) -> &ParsedReadValueId {
&self.node
}
pub fn set_result(&mut self, result: DataValue) {
self.result = result;
}
pub fn set_error(&mut self, status: StatusCode) {
self.result = DataValue {
status: Some(status),
server_timestamp: Some(DateTime::now()),
..Default::default()
}
}
pub fn diagnostic_bits(&self) -> DiagnosticBits {
self.diagnostic_bits
}
pub fn set_diagnostic_info(&mut self, diagnostic_info: DiagnosticInfo) {
self.diagnostic_info = Some(diagnostic_info);
}
}
impl IntoResult for ReadNode {
type Result = DataValue;
fn into_result(self) -> (Self::Result, Option<DiagnosticInfo>) {
(self.result, self.diagnostic_info)
}
}
#[derive(Debug, Clone)]
pub struct ParsedWriteValue {
pub node_id: NodeId,
pub attribute_id: AttributeId,
pub index_range: NumericRange,
pub value: DataValue,
}
impl ParsedWriteValue {
pub fn parse(val: WriteValue) -> Result<Self, StatusCode> {
let attribute_id = AttributeId::from_u32(val.attribute_id)
.map_err(|_| StatusCode::BadAttributeIdInvalid)?;
Ok(Self {
node_id: val.node_id,
attribute_id,
index_range: val.index_range,
value: val.value,
})
}
pub fn null() -> Self {
Self {
node_id: NodeId::null(),
attribute_id: AttributeId::NodeId,
index_range: NumericRange::None,
value: DataValue::null(),
}
}
pub fn is_null(&self) -> bool {
self.node_id.is_null()
}
}
impl Default for ParsedWriteValue {
fn default() -> Self {
Self::null()
}
}
#[derive(Debug)]
pub struct WriteNode {
value: ParsedWriteValue,
diagnostic_bits: DiagnosticBits,
status: StatusCode,
diagnostic_info: Option<DiagnosticInfo>,
}
impl WriteNode {
pub(crate) fn new(value: WriteValue, diagnostic_bits: DiagnosticBits) -> Self {
let mut status = StatusCode::BadNodeIdUnknown;
let value = match ParsedWriteValue::parse(value) {
Ok(r) => r,
Err(e) => {
status = e;
ParsedWriteValue::null()
}
};
Self {
value,
status,
diagnostic_bits,
diagnostic_info: None,
}
}
pub fn status(&self) -> StatusCode {
self.status
}
pub fn set_status(&mut self, status: StatusCode) {
self.status = status;
}
pub fn value(&self) -> &ParsedWriteValue {
&self.value
}
pub fn diagnostic_bits(&self) -> DiagnosticBits {
self.diagnostic_bits
}
pub fn set_diagnostic_info(&mut self, diagnostic_info: DiagnosticInfo) {
self.diagnostic_info = Some(diagnostic_info);
}
}
impl IntoResult for WriteNode {
type Result = StatusCode;
fn into_result(self) -> (Self::Result, Option<DiagnosticInfo>) {
(self.status(), self.diagnostic_info)
}
}