Expand description
Rust wrapper for the open62541 library.
§Examples
§Client: Connect to server
Use AsyncClient
to asynchronously connect to an OPC UA server:
use open62541::AsyncClient;
let client = AsyncClient::new("opc.tcp://opcuademo.sterfive.com:26543")?;
This requires an async runtime such as tokio
.
§Client: Read node’s value attribute
Read a variable node’s value attribute with AsyncClient::read_value()
:
use open62541::ua;
let node_id = ua::NodeId::numeric(0, 2258); // Server/ServerStatus/CurrentTime
let value = client.read_value(&node_id).await?;
println!("Received value: {value:?}");
Use AsyncClient::read_attribute()
and related methods to read other attributes other than
the value.
§Client: Watch node for changes in value attribute
Subscribe to a node’s value by creating a subscription with
AsyncClient::create_subscription()
and adding monitored items to it with
AsyncSubscription::create_monitored_item()
:
// Create subscription that receives the updates.
let subscription = client.create_subscription().await?;
// Create monitored item to receive node updates.
let mut monitored_item = subscription.create_monitored_item(&node_id).await?;
while let Some(value) = monitored_item.next().await {
println!("Received value: {value:?}");
}
§Server: Run server
Create an OPC UA server with Server::new()
. When instantiating a server, you receive a
ServerRunner
along with the Server
. Use it to run the server until interrupted:
use open62541::Server;
let (server, runner) = Server::new();
// Define data nodes on `server`.
runner.run()?;
By default, ServerRunner::run()
runs on the current thread. Use
thread::spawn()
to run it in a different thread.
§Server: Define object and managed variable nodes
Define nodes with Server::add_object_node()
and related methods:
use open62541::{ObjectNode, ua, VariableNode};
use open62541_sys::{
UA_NS0ID_BASEDATAVARIABLETYPE, UA_NS0ID_FOLDERTYPE, UA_NS0ID_OBJECTSFOLDER,
UA_NS0ID_ORGANIZES, UA_NS0ID_STRING,
};
let object_node_id = server.add_object_node(ObjectNode {
requested_new_node_id: None,
parent_node_id: ua::NodeId::ns0(UA_NS0ID_OBJECTSFOLDER),
reference_type_id: ua::NodeId::ns0(UA_NS0ID_ORGANIZES),
browse_name: ua::QualifiedName::new(1, "SomeFolder"),
type_definition: ua::NodeId::ns0(UA_NS0ID_FOLDERTYPE),
attributes: ua::ObjectAttributes::default(),
})?;
let variable_node_id = server.add_variable_node(VariableNode {
requested_new_node_id: None,
parent_node_id: object_node_id,
reference_type_id: ua::NodeId::ns0(UA_NS0ID_ORGANIZES),
browse_name: ua::QualifiedName::new(1, "SomeVariable"),
type_definition: ua::NodeId::ns0(UA_NS0ID_BASEDATAVARIABLETYPE),
attributes: ua::VariableAttributes::default()
.with_data_type(&ua::NodeId::ns0(UA_NS0ID_STRING)),
})?;
server.write_value(
&variable_node_id,
&ua::Variant::scalar(ua::String::new("Lorem Ipsum")?),
)?;
Nodes may also be added (and removed) while the server is running.
§Server: Define data source variable nodes (callback-driven)
Implement DataSource
for custom types to enable callback-driven read and write access
through OPC UA variables.
Use DataSourceReadContext
and DataSourceWriteContext
to set the value to return to the
client, or access the incoming value received from the client:
use open62541::{DataSource, DataSourceReadContext, DataSourceResult, DataSourceWriteContext};
struct SomeDataSource {
some_value: u32,
}
impl DataSource for SomeDataSource {
fn read(&mut self, ctx: &mut DataSourceReadContext) -> DataSourceResult {
let value = format!("This is #{value}", value = self.some_value);
ctx.set_variant(ua::Variant::scalar(ua::String::new(&value)?));
Ok(())
}
fn write(&mut self, ctx: &mut DataSourceWriteContext) -> DataSourceResult {
println!("Received value: {value:?}", value = ctx.value());
self.some_value += 1;
Ok(())
}
}
let variable_node = VariableNode {
requested_new_node_id: None,
parent_node_id: object_node_id,
reference_type_id: ua::NodeId::ns0(UA_NS0ID_ORGANIZES),
browse_name: ua::QualifiedName::new(1, "SomeVariable"),
type_definition: ua::NodeId::ns0(UA_NS0ID_BASEDATAVARIABLETYPE),
attributes: ua::VariableAttributes::default()
.with_data_type(&ua::NodeId::ns0(UA_NS0ID_STRING))
.with_access_level(
&ua::AccessLevel::NONE
.with_current_read(true)
.with_current_write(true),
),
};
let variable_node_id = server.add_data_source_variable_node(
variable_node,
SomeDataSource { some_value: 0 },
)?;
Modules§
- Thin wrappers for
open62541_sys
types.
Structs§
- Connected OPC UA client (with asynchronous API).
- Monitored item (with asynchronous API).
- Subscription (with asynchronous API).
- Type-erased one-shot callback.
- Type-erased stream sender.
- Connected OPC UA client.
- Builder for
Client
. - Context when
DataSource
is being read from. - Context when
DataSource
is being written to. - Typed variant of
ua::DataValue
. - Default server access control.
- Default server access control with login callback.
- Context when
MethodCallback
is being called. - OPC UA server.
- Builder for
Server
. - Type-erased user data.
- Sentinel for type-erased user data.
Enums§
- Error type used in this crate.
- Scalar value.
- Value of
ua::Variant
.
Constants§
- IANA-assigned OPC UA port number.
Traits§
- Server access control.
- Node attribute.
- Server node attributes.
- Custom certificate verification.
- Data source with callbacks.
- Transparent wrapper for OPC UA data type.
- Method callback.
Type Aliases§
- Result type for browsing.
- Result from
DataSource
operations. - Result from
MethodCallback
operations. - Result type used in this crate.