pub struct Server(/* private fields */);Expand description
OPC UA server.
This represents an OPC UA server. Nodes can be added through the several methods below.
Note: The server must be started with ServerRunner::run() before it can accept connections
from clients.
Implementations§
Source§impl Server
impl Server
Sourcepub fn new() -> (Self, ServerRunner)
pub fn new() -> (Self, ServerRunner)
Creates default server.
If you need more control over the initialization, use ServerBuilder instead, and turn it
into Server by calling build().
§Errors
§Panics
Sourcepub fn add_namespace(&self, namespace_uri: &str) -> u16
pub fn add_namespace(&self, namespace_uri: &str) -> u16
Adds a new namespace to the server. Returns the index of the new namespace.
If the namespace already exists, it is not re-created but its index is returned.
§Panics
The namespace URI must not contain any NUL bytes.
§Examples
let ns_index = server.add_namespace("http://hmi-project.com/UA/");
// Application URI takes index 1, new namespaces start at index 2.
assert!(ns_index >= 2);Sourcepub fn get_namespace_by_name(&self, namespace_uri: &String) -> Option<u16>
pub fn get_namespace_by_name(&self, namespace_uri: &String) -> Option<u16>
Looks up namespace by its URI.
This returns the found namespace index.
§Examples
let ns_index = server.add_namespace("http://hmi-project.com/UA/");
let ns_uri = ua::String::new("http://hmi-project.com/UA/").unwrap();
assert_eq!(server.get_namespace_by_name(&ns_uri), Some(ns_index));Sourcepub fn get_namespace_by_index(&self, namespace_index: u16) -> Option<String>
pub fn get_namespace_by_index(&self, namespace_index: u16) -> Option<String>
Looks up namespace by its index.
This returns the found namespace URI.
§Examples
let ns_index = server.add_namespace("http://hmi-project.com/UA/");
let ns_uri = ua::String::new("http://hmi-project.com/UA/").unwrap();
assert_eq!(server.get_namespace_by_index(ns_index), Some(ns_uri));Namespace index 0 is always the OPC UA namespace with a fixed URI:
let ns_uri = ua::String::new("http://opcfoundation.org/UA/").unwrap();
assert_eq!(server.get_namespace_by_index(0), Some(ns_uri));Sourcepub fn add_node<T: Attributes>(&self, node: Node<T>) -> Result<NodeId>
pub fn add_node<T: Attributes>(&self, node: Node<T>) -> Result<NodeId>
Adds node to address space.
This returns the node ID that was actually inserted (when no explicit requested new node ID
was given in node).
§Errors
This fails when the node cannot be added.
Sourcepub fn add_object_node(&self, object_node: ObjectNode) -> Result<NodeId>
pub fn add_object_node(&self, object_node: ObjectNode) -> Result<NodeId>
Adds object node to address space.
This returns the node ID that was actually inserted (when no explicit requested new node ID
was given in node).
§Errors
This fails when the node cannot be added.
Sourcepub fn add_variable_node(&self, variable_node: VariableNode) -> Result<NodeId>
pub fn add_variable_node(&self, variable_node: VariableNode) -> Result<NodeId>
Adds variable node to address space.
This returns the node ID that was actually inserted (when no explicit requested new node ID
was given in node).
§Errors
This fails when the node cannot be added.
Sourcepub fn add_data_source_variable_node(
&self,
variable_node: VariableNode,
data_source: impl DataSource + 'static,
) -> Result<NodeId>
pub fn add_data_source_variable_node( &self, variable_node: VariableNode, data_source: impl DataSource + 'static, ) -> Result<NodeId>
Adds variable node with data source to address space.
This returns the node ID that was actually inserted (when no explicit requested new node ID
was given in node).
§Errors
This fails when the node cannot be added.
Sourcepub fn add_method_node(
&self,
method_node: MethodNode,
callback: impl MethodCallback + 'static,
) -> Result<(NodeId, (NodeId, NodeId))>
pub fn add_method_node( &self, method_node: MethodNode, callback: impl MethodCallback + 'static, ) -> Result<(NodeId, (NodeId, NodeId))>
Adds method node to address space.
This returns the node ID that was actually inserted (when no explicit requested new node ID
was given in node), along with the node IDs for the input and output argument nodes.
§Errors
This fails when the node cannot be added.
Sourcepub fn delete_node(&self, node_id: &NodeId) -> Result<()>
pub fn delete_node(&self, node_id: &NodeId) -> Result<()>
Deletes node from address space.
This also deletes all references leading to the node.
§Errors
This fails when the node cannot be deleted.
Sourcepub fn add_reference(
&self,
source_id: &NodeId,
reference_type_id: &NodeId,
target_id: &ExpandedNodeId,
is_forward: bool,
) -> Result<()>
pub fn add_reference( &self, source_id: &NodeId, reference_type_id: &NodeId, target_id: &ExpandedNodeId, is_forward: bool, ) -> Result<()>
Adds a reference from one node to another.
§Errors
This fails when adding the reference fails.
§Examples
use open62541_sys::{UA_NS0ID_ORGANIZES};
// let parent_one_node_id = server.add_node(/* snip */)?;
// let parent_two_node_id = server.add_node(/* snip */)?;
let variable_node_id = server.add_node(Node::new(
parent_one_node_id.clone(),
ua::NodeId::ns0(UA_NS0ID_ORGANIZES),
ua::QualifiedName::new(1, "Variable"),
ua::VariableAttributes::init(),
))?;
// This makes the variable available in two parents.
server.add_reference(
&parent_two_node_id,
&ua::NodeId::ns0(UA_NS0ID_ORGANIZES),
&variable_node_id.clone().into_expanded_node_id(),
true,
)?;
// Duplicating an existing reference is not allowed.
let error = server.add_reference(
&parent_one_node_id,
&ua::NodeId::ns0(UA_NS0ID_ORGANIZES),
&variable_node_id.clone().into_expanded_node_id(),
true,
).unwrap_err();
assert_eq!(error.status_code(), ua::StatusCode::BADDUPLICATEREFERENCENOTALLOWED);Sourcepub fn delete_reference(
&self,
source_node_id: &NodeId,
reference_type_id: &NodeId,
target_node_id: &ExpandedNodeId,
is_forward: bool,
delete_bidirectional: bool,
) -> Result<()>
pub fn delete_reference( &self, source_node_id: &NodeId, reference_type_id: &NodeId, target_node_id: &ExpandedNodeId, is_forward: bool, delete_bidirectional: bool, ) -> Result<()>
Sourcepub fn create_event(&self, event_type: &NodeId) -> Result<NodeId>
pub fn create_event(&self, event_type: &NodeId) -> Result<NodeId>
Creates an event.
This returns the ua::NodeId of the created event.
§Errors
This fails when the event could not be created.
Sourcepub fn trigger_event(
&self,
event_node_id: &NodeId,
origin_id: &NodeId,
delete_event_node: bool,
) -> Result<EventId>
pub fn trigger_event( &self, event_node_id: &NodeId, origin_id: &NodeId, delete_event_node: bool, ) -> Result<EventId>
Triggers an event.
This returns the ua::EventId of the new event.
§Errors
This fails when the event could not be triggered.
Sourcepub fn browse(
&self,
max_references: usize,
browse_description: &BrowseDescription,
) -> BrowseResult
pub fn browse( &self, max_references: usize, browse_description: &BrowseDescription, ) -> BrowseResult
Browses specific node.
Use ua::BrowseDescription::default() to set sensible defaults to
browse a specific node’s children (forward references of the HierarchicalReferences type)
like this:
use open62541_sys::UA_NS0ID_SERVER_SERVERSTATUS;
let node_id = ua::NodeId::ns0(UA_NS0ID_SERVER_SERVERSTATUS);
let browse_description = ua::BrowseDescription::default().with_node_id(&node_id);
let (references, continuation_point) = server.browse(1000, &browse_description)?;§Errors
This fails when the node does not exist or it cannot be browsed.
Sourcepub fn browse_next(
&self,
continuation_point: &ContinuationPoint,
) -> BrowseResult
pub fn browse_next( &self, continuation_point: &ContinuationPoint, ) -> BrowseResult
Sourcepub fn browse_recursive(
&self,
browse_description: &BrowseDescription,
) -> Result<Array<ExpandedNodeId>>
pub fn browse_recursive( &self, browse_description: &BrowseDescription, ) -> Result<Array<ExpandedNodeId>>
Browses nodes recursively.
This is a non-standard version of the Browse service that recurses into child nodes. This
handles possible loops (that can occur for non-hierarchical references) and adds every node
at most once to the resulting list.
Nodes are only added if they match the NodeClassMask in the BrowseDescription. However,
child nodes are still recursed into if the NodeClass does not match. So it is possible,
for example, to get all VariableNodes below a certain ObjectNode, with additional
objects in the hierarchy below.
§Errors
This fails when the browsing was not successful.
§Examples
use open62541_sys::UA_NS0ID_SERVER_SERVERSTATUS;
let targets = server.browse_recursive(
&ua::BrowseDescription::default().with_node_id(
&ua::NodeId::ns0(UA_NS0ID_SERVER_SERVERSTATUS),
),
)?;
// Browse above returns the expected number of well-known nodes.
assert_eq!(targets.len(), 12);Sourcepub fn browse_simplified_browse_path(
&self,
origin: &NodeId,
browse_path: &[QualifiedName],
) -> Result<Array<BrowsePathTarget>>
pub fn browse_simplified_browse_path( &self, origin: &NodeId, browse_path: &[QualifiedName], ) -> Result<Array<BrowsePathTarget>>
Browses simplified browse path.
This specifies a relative path using ua::QualifiedName instead of ua::RelativePath,
using forward references and subtypes of HierarchicalReferences, matching the defaults of
ua::BrowseDescription. All nodes followed by browse_path shall be of the node classes
Object or Variable.
See translate_browse_path_to_node_ids() if you
need more control over the references involved.
§Errors
This fails when the browsing was not successful.
§Examples
use open62541_sys::{
UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME,
};
let target_name_1 = ua::QualifiedName::new(0, "BuildInfo");
let target_name_2 = ua::QualifiedName::new(0, "ProductName");
let targets = server.browse_simplified_browse_path(
&ua::NodeId::ns0(UA_NS0ID_SERVER_SERVERSTATUS),
&[target_name_1, target_name_2],
)?;
// Translation above returns a single target.
assert_eq!(targets.len(), 1);
let target = &targets[0];
// The given path leads to the right node ID.
assert_eq!(
target.target_id(),
&ua::NodeId::ns0(UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME)
.into_expanded_node_id()
);
// All relative path elements were processed.
assert_eq!(target.remaining_path_index(), None);Sourcepub fn translate_browse_path_to_node_ids(
&self,
browse_path: &BrowsePath,
) -> Result<Array<BrowsePathTarget>>
pub fn translate_browse_path_to_node_ids( &self, browse_path: &BrowsePath, ) -> Result<Array<BrowsePathTarget>>
Translates browse path to node IDs.
§Errors
An error will be returned if the translation was not successful.
§Examples
use open62541_sys::{
UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME,
};
let target_name_1 = ua::QualifiedName::new(0, "BuildInfo");
let target_name_2 = ua::QualifiedName::new(0, "ProductName");
let targets = server.translate_browse_path_to_node_ids(&ua::BrowsePath::init()
.with_starting_node(&ua::NodeId::ns0(UA_NS0ID_SERVER_SERVERSTATUS))
.with_relative_path(&ua::RelativePath::init()
.with_elements(&[
ua::RelativePathElement::init().with_target_name(&target_name_1),
ua::RelativePathElement::init().with_target_name(&target_name_2),
])
)
)?;
// Translation above returns a single target.
assert_eq!(targets.len(), 1);
let target = &targets[0];
// The given path leads to the right node ID.
assert_eq!(
target.target_id(),
&ua::NodeId::ns0(UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME)
.into_expanded_node_id()
);
// All relative path elements were processed.
assert_eq!(target.remaining_path_index(), None);Sourcepub fn read_attribute<T: Attribute>(
&self,
node_id: &NodeId,
attribute: T,
) -> Result<DataValue<T::Value>>
pub fn read_attribute<T: Attribute>( &self, node_id: &NodeId, attribute: T, ) -> Result<DataValue<T::Value>>
Reads node attribute.
This method supports static dispatch to the correct value type at compile time and can be used in two ways:
- Use statically known attribute type
_Tfromua::AttributeIdto get correct value type directly. - Use dynamic
ua::AttributeIdvalue and handle the resultingua::Variant.
§Errors
This fails when the node does not exist or the attribute cannot be read.
§Examples
let node_id = ua::NodeId::ns0(UA_NS0ID_SERVER_SERVERSTATUS);
// Use static dispatch to get expected value type directly:
let browse_name = server
.read_attribute(&node_id, ua::AttributeId::BROWSENAME_T)?
.into_value();
// The type of `browse_name` is `ua::QualifiedName` here.
assert_eq!(browse_name, ua::QualifiedName::new(0, "ServerStatus"));
// Use dynamic attribute and unwrap `ua::Variant` manually:
let attribute_id: ua::AttributeId = ua::AttributeId::BROWSENAME;
let browse_name = server.read_attribute(&node_id, &attribute_id)?.into_value();
// The type of `browse_name` is `ua::Variant` here.
let browse_name = browse_name.to_scalar::<ua::QualifiedName>().unwrap();
assert_eq!(browse_name, ua::QualifiedName::new(0, "ServerStatus"));Sourcepub fn write_value(&self, node_id: &NodeId, value: &Variant) -> Result<()>
pub fn write_value(&self, node_id: &NodeId, value: &Variant) -> Result<()>
Writes node value.
§Errors
This fails when the node does not exist or its value attribute cannot be written.
Sourcepub fn write_data_value(
&self,
node_id: &NodeId,
value: &DataValue,
) -> Result<()>
pub fn write_data_value( &self, node_id: &NodeId, value: &DataValue, ) -> Result<()>
Writes a DataValue to a node.
§Errors
This fails when the node does not exist or its value attribute cannot be written.
Sourcepub fn read_object_property(
&self,
object_id: &NodeId,
property_name: &QualifiedName,
) -> Result<Variant>
pub fn read_object_property( &self, object_id: &NodeId, property_name: &QualifiedName, ) -> Result<Variant>
Sourcepub fn write_object_property(
&self,
object_id: &NodeId,
property_name: &QualifiedName,
value: &Variant,
) -> Result<()>
pub fn write_object_property( &self, object_id: &NodeId, property_name: &QualifiedName, value: &Variant, ) -> Result<()>
Writes object property.
The property is represented as a VariableNode with a HasProperty reference from the
ObjectNode. The VariableNode is identified by its BrowseName. Writing the property
sets the value attribute of the VariableNode.
§Errors
This fails when writing the object property was not successful.
§Examples
server.write_object_property(
&object_node_id,
&ua::QualifiedName::new(1, "SomeVariable"),
&ua::Variant::scalar(ua::String::new("LoremIpsum")?),
)?;Sourcepub unsafe fn statistics(&self) -> ServerStatistics
pub unsafe fn statistics(&self) -> ServerStatistics
Gets server statistics.
§Safety
This must only be called when no other server operations are underway, on this instance or any of its clones (including background activity). In other words, you must have exclusive access to the underlying server and it must not be operating.