Crate opcua_client

Source
Expand description

The OPC UA Client module contains the functionality necessary for a client to connect to an OPC UA server, authenticate itself, send messages, receive responses, get values, browse the address space and provide callbacks for things to be propagated to the client.

A client has to specify the endpoint description they wish to connect to, security policy and other configurable options, e.g. paths to PKI keys. All of this is encapsulated in a Client object.

One of these may be made programatically using a ClientBuilder or from a preexisting ClientConfig which can be loaded fully or partially from disk. Use the way that suits you.

Once the Client is created it can connect to a server by creating a Session. Multiple sessions can be created from the same client. Functions on the Session correspond to OPC UA services so it can be used to:

  • Discover endpoints
  • Activate a session
  • Create / modify / delete subscriptions
  • Create / modify / delete monitored items
  • Read and write values
  • Browse the address space
  • Add or remove nodes

Functionality is synchronous and housekeeping such as renewing the active session and sending publish requests is handled automatically.

Data change and event notifications are via asynchronous callbacks.

§Example

Here is a complete example of a client that connects to the samples/simple-server, subscribes to some values and prints out changes to those values. This example corresponds to the one described in the in docs/client.md tutorial.

use std::sync::Arc;
use std::time::Duration;
// You can also refer to these through aliases `opcua::client` and `opcua::types`.
use opcua_client::{ClientBuilder, IdentityToken, Session, DataChangeCallback, MonitoredItem};
use opcua_types::{
    EndpointDescription, MessageSecurityMode, UserTokenPolicy, StatusCode,
    NodeId, TimestampsToReturn, MonitoredItemCreateRequest, DataValue
};

#[tokio::main]
async fn main() {
    let mut client = ClientBuilder::new()
        .application_name("My First Client")
        .application_uri("urn:MyFirstClient")
        .create_sample_keypair(true)
        .trust_server_certs(false)
        .session_retry_limit(3)
        .client().unwrap();

    // Create an endpoint. The EndpointDescription can be made from a tuple consisting of
    // the endpoint url, security policy, message security mode and user token policy.
    let endpoint: EndpointDescription = ("opc.tcp://localhost:4855/", "None", MessageSecurityMode::None, UserTokenPolicy::anonymous()).into();

    // Create the session and event loop
    let (session, event_loop) = client.connect_to_matching_endpoint(endpoint, IdentityToken::Anonymous).await.unwrap();
    let handle = event_loop.spawn();

    session.wait_for_connection().await;

    // Create a subscription and monitored items
    if subscribe_to_values(&session).await.is_ok() {
        handle.await.unwrap();
    } else {
        println!("Error creating subscription");
    }
}

async fn subscribe_to_values(session: &Session) -> Result<(), StatusCode> {
    // Create a subscription polling every 2s with a callback
    let subscription_id = session.create_subscription(
        Duration::from_secs(2),
        10,
        30,
        0,
        0,
        true,
        DataChangeCallback::new(
            |value, monitored_item| {
                println!("Data change from server:");
                print_value(value, monitored_item);
            }
        )
    ).await?;
    // Create some monitored items
    let items_to_create: Vec<MonitoredItemCreateRequest> = ["v1", "v2", "v3", "v4"].iter()
        .map(|v| NodeId::new(2, *v).into()).collect();
    let _ = session.create_monitored_items(subscription_id, TimestampsToReturn::Both, items_to_create).await?;
    Ok(())
}

fn print_value(data_value: DataValue, item: &MonitoredItem) {
   let node_id = &item.item_to_monitor().node_id;
   if let Some(ref value) = data_value.value {
       println!("Item \"{}\", Value = {:?}", node_id, value);
   } else {
       println!("Item \"{}\", Value not found, error: {}", node_id, data_value.status.as_ref().unwrap());
   }
}

Modules§

browser
This module contains a utility for recursively browsing the node hierarchy in a flexible, efficient, and reliable manner.
custom_types
Contains the DataTypeTreeBuilder, a utility for constructing a DataTypeTree that can be used to support custom types on the server with DynamicTypeLoader.
services
This module contains request builders for most OPC-UA services. Typically you can just use the methods on super::Session, but if you need to specify diagnostics, set a custom timeout, or do other header manipulation, you must use the raw request builders. Note that these let you pass a session manually, in this case you are responsible for passing a valid session matching the secure channel.

Structs§

AsyncSecureChannel
Wrapper around an open secure channel
Client
Wrapper around common data for generating sessions and performing requests with one-shot connections.
ClientBuilder
Client builder.
ClientConfig
Client OPC UA configuration
ClientEndpoint
Describes an endpoint, it’s url security policy, mode and user token
ClientUserToken
User token in client configuration.
DataChangeCallback
A wrapper around a data change callback that implements OnSubscriptionNotification
DefaultRetryPolicy
A simple default retry policy. This will retry using the given ExponentialBackoff if the error matches one of the following status codes:
EventCallback
A wrapper around an event callback that implements OnSubscriptionNotification
ExponentialBackoff
A type implementing [Iterator<Item = Option<Duration>] with simple exponential backoff.
MonitoredItem
Client-side representation of a monitored item.
Session
An OPC-UA session. This session provides methods for all supported services that require an open session.
SessionBuilder
Type-state builder for a session and session event loop. To use, you will typically first call SessionBuilder::with_endpoints to set a list of available endpoints, then one of the connect_to methods, then finally SessionBuilder::build.
SessionEventLoop
The session event loop drives the client. It must be polled for anything to happen at all.
SessionRetryPolicy
Session retry policy.
Subscription
Client-side representation of a subscription.
SubscriptionCallbacks
A convenient wrapper around a set of callback functions that implements OnSubscriptionNotification

Enums§

HistoryReadAction
Enumeration used with Session::history_read()
HistoryUpdateAction
Enumeration used with Session::history_update()
IdentityToken
Client-side identity token representation.
SessionActivity
Periodic activity performed by the session.
SessionConnectMode
When the session connects to the server, this describes how that happened, whether a new session was created, or an old session was reactivated.
SessionPollResult
A list of possible events that happens while polling the session. The client can use this list to monitor events such as disconnects, publish failures, etc.
SubscriptionActivity
An event on the subscription event loop.

Constants§

ANONYMOUS_USER_TOKEN_ID
Token ID of the anonymous user token.

Traits§

OnSubscriptionNotification
A set of callbacks for notifications on a subscription. You may implement this on your own struct, or simply use SubscriptionCallbacks for a simple collection of closures.
RequestRetryPolicy
Trait for generic retry policies, used with Session::send_with_retry. For simple use cases you can use DefaultRetryPolicy.
UARequest
Trait for a type that can be sent as an OPC-UA request.