155 lines
4.7 KiB
Rust
155 lines
4.7 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
use uuid::Uuid;
|
|
|
|
use crate::model::ScanMode;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum ValueType {
|
|
Null,
|
|
Bool,
|
|
Int,
|
|
UInt,
|
|
Float,
|
|
Text,
|
|
Bytes,
|
|
Array,
|
|
Object,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum PointQuality {
|
|
Good,
|
|
Bad,
|
|
Uncertain,
|
|
Unknown,
|
|
}
|
|
|
|
impl PointQuality {
|
|
pub fn from_status_code(status: &opcua::types::StatusCode) -> Self {
|
|
if status.is_good() {
|
|
Self::Good
|
|
} else if status.is_bad() {
|
|
Self::Bad
|
|
} else if status.is_uncertain() {
|
|
Self::Uncertain
|
|
} else {
|
|
Self::Unknown
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
#[serde(untagged)]
|
|
pub enum DataValue {
|
|
Null,
|
|
Bool(bool),
|
|
Int(i64),
|
|
UInt(u64),
|
|
Float(f64),
|
|
Text(String),
|
|
Bytes(Vec<u8>),
|
|
Array(Vec<DataValue>),
|
|
Object(serde_json::Value),
|
|
}
|
|
|
|
impl DataValue {
|
|
pub fn to_json_value(&self) -> serde_json::Value {
|
|
match self {
|
|
DataValue::Null => serde_json::Value::Null,
|
|
DataValue::Bool(v) => serde_json::Value::Bool(*v),
|
|
DataValue::Int(v) => serde_json::json!(*v),
|
|
DataValue::UInt(v) => serde_json::json!(*v),
|
|
DataValue::Float(v) => serde_json::json!(*v),
|
|
DataValue::Text(v) => serde_json::json!(v),
|
|
DataValue::Bytes(v) => serde_json::json!(v),
|
|
DataValue::Array(v) => {
|
|
serde_json::Value::Array(v.iter().map(DataValue::to_json_value).collect())
|
|
}
|
|
DataValue::Object(v) => v.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct PointMonitorInfo {
|
|
pub protocol: String,
|
|
pub source_id: Uuid,
|
|
pub point_id: Uuid,
|
|
pub client_handle: u32,
|
|
pub scan_mode: ScanMode,
|
|
#[serde(serialize_with = "crate::util::datetime::option_utc_to_local_str")]
|
|
pub timestamp: Option<DateTime<Utc>>,
|
|
pub quality: PointQuality,
|
|
pub value: Option<DataValue>,
|
|
pub value_type: Option<ValueType>,
|
|
pub value_text: Option<String>,
|
|
pub old_value: Option<DataValue>,
|
|
#[serde(serialize_with = "crate::util::datetime::option_utc_to_local_str")]
|
|
pub old_timestamp: Option<DateTime<Utc>>,
|
|
pub value_changed: bool,
|
|
}
|
|
|
|
impl PointMonitorInfo {
|
|
pub fn value_as_json(&self) -> Option<serde_json::Value> {
|
|
self.value.as_ref().map(DataValue::to_json_value)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PointNewValue {
|
|
pub source_id: Uuid,
|
|
pub point_id: Option<Uuid>,
|
|
pub client_handle: u32,
|
|
pub value: Option<DataValue>,
|
|
pub value_type: Option<ValueType>,
|
|
pub value_text: Option<String>,
|
|
pub quality: PointQuality,
|
|
pub protocol: String,
|
|
pub timestamp: Option<DateTime<Utc>>,
|
|
pub scan_mode: ScanMode,
|
|
}
|
|
|
|
|
|
pub fn opcua_variant_to_data(value: &opcua::types::Variant) -> DataValue {
|
|
use opcua::types::Variant;
|
|
|
|
match value {
|
|
Variant::Empty => DataValue::Null,
|
|
Variant::Boolean(v) => DataValue::Bool(*v),
|
|
Variant::SByte(v) => DataValue::Int(*v as i64),
|
|
Variant::Byte(v) => DataValue::UInt(*v as u64),
|
|
Variant::Int16(v) => DataValue::Int(*v as i64),
|
|
Variant::UInt16(v) => DataValue::UInt(*v as u64),
|
|
Variant::Int32(v) => DataValue::Int(*v as i64),
|
|
Variant::UInt32(v) => DataValue::UInt(*v as u64),
|
|
Variant::Int64(v) => DataValue::Int(*v),
|
|
Variant::UInt64(v) => DataValue::UInt(*v),
|
|
Variant::Float(v) => DataValue::Float(*v as f64),
|
|
Variant::Double(v) => DataValue::Float(*v),
|
|
Variant::String(v) => DataValue::Text(v.to_string()),
|
|
Variant::ByteString(v) => DataValue::Bytes(v.value.clone().unwrap_or_default()),
|
|
Variant::Array(v) => {
|
|
DataValue::Array(v.values.iter().map(opcua_variant_to_data).collect())
|
|
}
|
|
_ => DataValue::Text(value.to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn opcua_variant_type(value: &opcua::types::Variant) -> ValueType {
|
|
use opcua::types::Variant;
|
|
match value {
|
|
Variant::Empty => ValueType::Null,
|
|
Variant::Boolean(_) => ValueType::Bool,
|
|
Variant::SByte(_) | Variant::Int16(_) | Variant::Int32(_) | Variant::Int64(_) => ValueType::Int,
|
|
Variant::Byte(_) | Variant::UInt16(_) | Variant::UInt32(_) | Variant::UInt64(_) => ValueType::UInt,
|
|
Variant::Float(_) | Variant::Double(_) => ValueType::Float,
|
|
Variant::String(_) => ValueType::Text,
|
|
Variant::ByteString(_) => ValueType::Bytes,
|
|
Variant::Array(_) => ValueType::Array,
|
|
_ => ValueType::Text,
|
|
}
|
|
}
|