Workstation.UaClient 3.2.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Workstation.UaClient --version 3.2.1                
NuGet\Install-Package Workstation.UaClient -Version 3.2.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Workstation.UaClient" Version="3.2.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Workstation.UaClient --version 3.2.1                
#r "nuget: Workstation.UaClient, 3.2.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Workstation.UaClient as a Cake Addin
#addin nuget:?package=Workstation.UaClient&version=3.2.1

// Install Workstation.UaClient as a Cake Tool
#tool nuget:?package=Workstation.UaClient&version=3.2.1                

robot

opc-ua-client

Actions Status

Communicate using OPC Unified Architecture and Visual Studio. With this library, your app can browse, read, write and subscribe to the live data published by the OPC UA servers on your network.

Supports .NET Core, Universal Windows Platform (UWP), Windows Presentation Framework (WPF) and Xamarin applications.

Getting Started

Install package Workstation.UaClient from Nuget to get the latest release for your hmi project.

Here's an example of reading the variable ServerStatus from a public OPC UA server.

using System;
using System.Threading.Tasks;
using Workstation.ServiceModel.Ua;
using Workstation.ServiceModel.Ua.Channels;
					
public class Program
{
    /// <summary>
    /// Connects to server and reads the current ServerState. 
    /// </summary>
    public static async Task Main()
    {
        // describe this client application.
        var clientDescription = new ApplicationDescription
        {
            ApplicationName = "Workstation.UaClient.FeatureTests",
            ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.UaClient.FeatureTests",
            ApplicationType = ApplicationType.Client
        };

        // create a 'ClientSessionChannel', a client-side channel that opens a 'session' with the server.
        var channel = new ClientSessionChannel(
            clientDescription,
            null, // no x509 certificates
            new AnonymousIdentity(), // no user identity
            "opc.tcp://opcua.rocks:4840", // the public endpoint of a server at opcua.rocks.
            SecurityPolicyUris.None); // no encryption
        try
        {
            // try opening a session and reading a few nodes.
            await channel.OpenAsync();

            Console.WriteLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'.");
            Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'.");
            Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'.");
            Console.WriteLine($"UserIdentityToken: '{channel.UserIdentity}'.");

            // build a ReadRequest. See 'OPC UA Spec Part 4' paragraph 5.10.2
            var readRequest = new ReadRequest {
                // set the NodesToRead to an array of ReadValueIds.
                NodesToRead = new[] {
                    // construct a ReadValueId from a NodeId and AttributeId.
                    new ReadValueId {
                        // you can parse the nodeId from a string.
                        // e.g. NodeId.Parse("ns=2;s=Demo.Static.Scalar.Double")
                        NodeId = NodeId.Parse(VariableIds.Server_ServerStatus),
                        // variable class nodes have a Value attribute.
                        AttributeId = AttributeIds.Value
                    }
                }
            };
            // send the ReadRequest to the server.
            var readResult = await channel.ReadAsync(readRequest);

            // DataValue is a class containing value, timestamps and status code.
            // the 'Results' array returns DataValues, one for every ReadValueId.
            var serverStatus = readResult.Results[0].GetValueOrDefault<ServerStatusDataType>();

            Console.WriteLine("\nServer status:");
            Console.WriteLine("  ProductName: {0}", serverStatus.BuildInfo.ProductName);
            Console.WriteLine("  SoftwareVersion: {0}", serverStatus.BuildInfo.SoftwareVersion);
            Console.WriteLine("  ManufacturerName: {0}", serverStatus.BuildInfo.ManufacturerName);
            Console.WriteLine("  State: {0}", serverStatus.State);
            Console.WriteLine("  CurrentTime: {0}", serverStatus.CurrentTime);

            Console.WriteLine($"\nClosing session '{channel.SessionId}'.");
            await channel.CloseAsync();
        }
        catch(Exception ex)
        {
		 	 await channel.AbortAsync();
            Console.WriteLine(ex.Message);
        }
    }
}

// Server status:
//   ProductName: open62541 OPC UA Server
//   SoftwareVersion: 1.0.0-rc5-52-g04067153-dirty
//   ManufacturerName: open62541
//   State: Running

Model, View, ViewModel (MVVM)

For HMI applications, you can use XAML bindings to connect your UI elements to live data.

First add a UaApplication instance and initialize it during startup:

public partial class App : Application
{
    private UaApplication application;

    protected override void OnStartup(StartupEventArgs e)
    {
        // Build and run an OPC UA application instance.
        this.application = new UaApplicationBuilder()
            .SetApplicationUri($"urn:{Dns.GetHostName()}:Workstation.StatusHmi")
            .SetDirectoryStore($"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Workstation.StatusHmi\\pki")
            .SetIdentity(this.ShowSignInDialog)
            .Build();

        this.application.Run();

        // Create and show the main view.
        var view = new MainView();
        view.Show();
    }
	...
}

Then any view model can be transformed into a OPC UA subscription.

[Subscription(endpointUrl: "opc.tcp://localhost:48010", publishingInterval: 500, keepAliveCount: 20)]
public class MainViewModel : SubscriptionBase
{
    /// <summary>
    /// Gets the value of ServerServerStatus.
    /// </summary>
    [MonitoredItem(nodeId: "i=2256")]
    public ServerStatusDataType ServerServerStatus
    {
        get { return this.serverServerStatus; }
        private set { this.SetValue(ref this.serverServerStatus, value); }
    }

    private ServerStatusDataType serverServerStatus;
}

Configure EndpointUrl at runtime (MVVM)

You can use a configuration file to replace all instances of an EndpointUrl at runtime. Use this approach to specify different endpoints for development versus production.

using Microsoft.Extensions.Configuration;

var config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appSettings.json", true)
    .Build();

var app = new UaApplicationBuilder()
    ...
    .AddMappedEndpoints(config)
    .Build();

[Subscription(endpointUrl: "MainPLC", publishingInterval: 500, keepAliveCount: 20)]
public class MainViewModel : SubscriptionBase
{
    /// <summary>
    /// Gets the value of ServerServerStatus.
    /// </summary>
    [MonitoredItem(nodeId: "i=2256")]
    public ServerStatusDataType ServerServerStatus
    {
        get { return this.serverServerStatus; }
        private set { this.SetValue(ref this.serverServerStatus, value); }
    }

    private ServerStatusDataType serverServerStatus;
}

appSettings.json

{
  "MappedEndpoints": [
    {
      "RequestedUrl": "MainPLC",
      "Endpoint": {
        "EndpointUrl": "opc.tcp://192.168.1.100:48010",
        "SecurityPolicyUri": "http://opcfoundation.org/UA/SecurityPolicy#None"
      }
    }
  ]
}
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Workstation.UaClient:

Package Downloads
Jaahas.OpcUa.JsonEncoding

OPC UA JSON encoder and decoder for Workstation.UaClient

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on Workstation.UaClient:

Repository Stars
convertersystems/opc-ua-samples
Sample HMIs using OPC Unified Architecture (OPC UA) and Visual Studio.
Version Downloads Last updated
3.2.3 30,986 2/14/2024
3.2.2 2,263 1/7/2024
3.2.1 12,837 8/29/2023
3.2.0 7,871 1/16/2023
3.1.1 78,774 9/14/2021
3.1.0 31,506 5/29/2021
3.0.2 2,596 3/7/2021
3.0.1 1,016 2/27/2021
3.0.0 18,911 10/31/2020
2.6.0 8,543 6/21/2020
2.5.2 16,753 3/26/2020
2.5.1 2,476 2/9/2020
2.5.0 5,581 9/25/2019
2.4.0 14,494 8/18/2019
2.3.0 1,894 7/4/2019
2.2.2 1,728 4/12/2019
2.2.1 65,507 11/24/2018
2.1.1 5,122 9/21/2017
2.1.0 1,056 9/20/2017
2.0.2 2,554 7/21/2017
2.0.1 1,120 7/17/2017
2.0.0 1,299 6/2/2017
2.0.0-RC6 1,021 5/9/2017
2.0.0-RC5 916 5/9/2017
2.0.0-RC4 932 5/6/2017
2.0.0-RC3 939 4/30/2017
2.0.0-RC2 980 4/25/2017
2.0.0-RC1 942 4/19/2017
1.5.12 1,218 4/21/2017
1.5.11 1,041 4/13/2017
1.5.10 1,006 4/13/2017
1.5.9 1,179 4/4/2017
1.5.8 1,091 3/23/2017
1.5.7 1,083 3/11/2017
1.5.6 1,120 2/10/2017
1.5.5 1,256 1/28/2017
1.5.4 1,081 1/27/2017
1.5.3 1,073 1/26/2017
1.5.2 1,198 1/11/2017
1.5.1 1,295 12/18/2016
1.5.0 1,129 12/13/2016
1.4.2 1,137 12/3/2016
1.4.1 1,211 11/12/2016
1.4.0 1,135 10/10/2016
1.3.3 1,131 8/29/2016
1.3.2 1,019 8/26/2016
1.3.1 1,039 8/18/2016
1.3.0 1,055 8/14/2016
1.2.2 1,029 8/6/2016
1.2.1 1,387 7/30/2016
1.2.0 1,032 7/24/2016
1.1.0 1,047 7/15/2016
1.0.2 1,053 7/10/2016
1.0.1 1,004 7/2/2016
1.0.0 1,124 6/29/2016