# Getting started

> Tutorial: Set up your first client with the OPC UA .NET SDK: import the namespace, connect, and disconnect again, also for OPC Classic servers.

> This content was machine translated and may contain errors. [Read in German](https://www.traeger.de/docs/development/opcua/client/getting-started)

**Sample applications:**

- Client.Temperature ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Scenarios/Client.Temperature), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Scenarios/Client.Temperature)): This sample demonstrates how to connect to an OPC UA server and read the value of a node once per second.
- Server.Temperature ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Scenarios/Server.Temperature), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Scenarios/Server.Temperature)): This sample demonstrates how to setup an OPC UA server that provides a temperature node and updates its value once per second.

## Prerequisites

- **Target framework:** .NET or .NET Framework 4.7.2 or later, all supported frameworks under [Target frameworks](https://www.traeger.de/en/docs/development/opcua/requirements#target-frameworks)
- **NuGet package:** `Opc.UaFx.Client`, for OPC Classic `Opc.UaFx.Advanced` ([Downloads](https://www.traeger.de/en/docs/development/opcua/downloads))
- **OPC UA server:** a reachable server, for first tests for example the server from the [complete example](https://www.traeger.de/en/docs/development/opcua/server/getting-started#complete-example) of server development
- **License:** not required for the evaluation. Without a license key, the SDK runs with its full feature set, limited to 30 minutes per application launch ([Set up the license](https://www.traeger.de/en/docs/development/opcua/license-setup#evaluation))

## Connect to an OPC UA server

**1.** Add a reference to the client namespace `Opc.UaFx.Client`:

```csharp
using Opc.UaFx.Client;
```

```vbnet
Imports Opc.UaFx.Client
```

**2.** Create an instance of the `OpcClient` class with the address of the server:

```csharp
var client = new OpcClient("opc.tcp://localhost:4840/");
```

```vbnet
Dim client = New OpcClient("opc.tcp://localhost:4840/")
```

**3.** Connect to the server and start the session:

```csharp
client.Connect();
```

```vbnet
client.Connect()
```

**4.** Work with the server (your code):

```csharp
// Your code to interact with the server.
```

```vbnet
'Your code to interact with the server.
```

**5.** Disconnect before the application exits:

```csharp
client.Disconnect();
```

```vbnet
client.Disconnect()
```

**6.** With a `using` block, it looks like this:

```csharp
using (var client = new OpcClient("opc.tcp://localhost:4840/")) {
    client.Connect();
    // Your code to interact with the server.
}
```

```vbnet
Using client As New OpcClient("opc.tcp://localhost:4840/")
    client.Connect()
    'Your code to interact with the server.
End Using
```

How you continue depends on whether you know the nodes and NodeIds of the server:

- **Unknown:** The section [Explore the address space](https://www.traeger.de/en/docs/development/opcua/client/browse#explore-the-address-space) shows which nodes the server provides.
- **Known:** [Read values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values#read-values) or [Write values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values#write-values)

## Find servers

Types used: `OpcDiscoveryClient`, `OpcApplicationDescription`

If you do not know the address of a server, a discovery server (for example the Local Discovery Server on port 4840) returns the servers registered with it, along with their discovery addresses. For each server, `DiscoverServers` returns its name, its type, and its addresses. An overload of `DiscoverServers` restricts the result to servers with specific application URIs, and an overload of `DiscoverEndpoints` restricts it to endpoints with specific transport profiles. To find out which endpoints a server offers, continue with the section [Choose a secure endpoint](https://www.traeger.de/en/docs/development/opcua/security/client#choose-a-secure-endpoint):

```csharp
using (var discovery = new OpcDiscoveryClient("opc.tcp://localhost:4840/")) {
    foreach (OpcApplicationDescription server in discovery.DiscoverServers()) {
        Console.WriteLine("{0} ({1})", server.Name, server.Type);
 
        foreach (Uri url in server.DiscoveryUrls)
            Console.WriteLine("  {0}", url);
    }
}

```

```vbnet
Using discovery = New OpcDiscoveryClient("opc.tcp://localhost:4840/")
    For Each server As OpcApplicationDescription In discovery.DiscoverServers()
        Console.WriteLine("{0} ({1})", server.Name, server.Type)

        For Each url As Uri In server.DiscoveryUrls
            Console.WriteLine("  {0}", url)
        Next
    Next
End Using
```

## Connect to an OPC Classic server

To connect to an *OPC Classic server*, the client must run on Windows, and the [OPC Classic runtime](https://www.traeger.de/en/docs/development/opcua/downloads#opc-classic-runtime) must be installed on the computer. Support for OPC Classic is only included in the `Opc.UaFx.Advanced` package.

The page [OPC Classic](https://www.traeger.de/en/docs/development/opcua/client/opc-classic) describes what you can do after connecting to a Classic server (DA, AE, and HDA with the same API).

**1.** Add references to the Classic and client namespaces:

```csharp
using Opc.UaFx.Client;
using Opc.UaFx.Client.Classic;
```

```vbnet
Imports Opc.UaFx.Client
Imports Opc.UaFx.Client.Classic
```

**2.** Create an instance of the `OpcClient` class with the address of the server:

```csharp
var client = new OpcClient("opc.com://localhost:48410/<progId>/<classId>");
```

```vbnet
Dim client As New OpcClient("opc.com://localhost:48410/<progId>/<classId>")
```

**3.** Connect to the server and start the session:

```csharp
client.Connect();
```

```vbnet
client.Connect()
```

**4.** Work with the server (your code):

```csharp
// Your code to interact with the server.
```

```vbnet
'Your code to interact with the server.
```

**5.** Disconnect before the application exits:

```csharp
client.Disconnect();
```

```vbnet
client.Disconnect()
```

**6.** With a `using` block, it looks like this:

```csharp
using (var client = new OpcClient("opc.com://localhost:48410/<progId>/<classId>")) {
    client.Connect();
    // Your code to interact with the server.
}
```

```vbnet
Using client As New OpcClient("opc.com://localhost:48410/<progId>/<classId>")
    client.Connect()
    'Your code to interact with the server.
End Using
```

How you continue depends on whether you know the nodes and NodeIds of the server:

- **Unknown:** The section [Explore the address space](https://www.traeger.de/en/docs/development/opcua/client/browse#explore-the-address-space) shows which nodes the server provides.
- **Known:** [Read values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values#read-values) or [Write values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values#write-values)

**The address of the server is structured like this**: `opc.com://localhost:48410/<progId>/<classId>`

- `opc.com` states that the client connects to an *OPC Classic server*.
- `localhost` stands for the name or IP address of the computer on which the *OPC Classic server* runs.
- `48410` is the optional port number that the *OPC UA wrapper server*[^wrapper-server] uses. If you omit it, the wrapper server uses a free port assigned by the system.
- `<progId>` is an optional placeholder. Replace it with the `ProgID` from the DCOM application information of the *OPC Classic server*, for example `OPCManager.DA.XML-DA.Server.DA`. The address `opc.com://localhost/<classId>` without `<progId>` works as well.
- `<classId>` is a placeholder. Replace it with the `ClassId` (also CLSID or `AppID`) from the DCOM application information of the *OPC Classic server*, for example `{E4EBF7FA-CCAC-4125-A611-EAC4981C00EA}`. You must specify the `ClassId` as a GUID.

**Determine the `<classId>` or `<progId>` of the server**:

**Method: `OpcClassicDiscoveryClient`**

```csharp
using (var discoveryClient = new OpcClassicDiscoveryClient("<host>")) {
    var servers = discoveryClient.DiscoverServers();

    foreach (var server in servers) {
        Console.WriteLine(
                "- {0}, ClassId={1}, ProgId={2}",
                server.Name,
                server.ClassId,
                server.ProgId);
    }
}
```

```vbnet
Using discoveryClient As New OpcClassicDiscoveryClient("<host>")
    Dim servers = discoveryClient.DiscoverServers()

    For Each server In servers
        Console.WriteLine( _
                "- {0}, ClassId={1}, ProgId={2}", _
                server.Name, _
                server.ClassId, _
                server.ProgId)
    Next
End Using
```

**Method: system information.** Perform the following steps on the computer of the *OPC Classic server*:

1. Determine the `AppID` in Component Services
   - Control Panel
   - Administrative Tools
   - Component Services
   - Expand "Component Services"
   - Expand "Computers"
   - Expand "My Computer"
   - Expand "DCOM Config"
   - Select `<OPC Classic Server>`
   - Open "Properties"
   - First tab "General"
   - Copy "Application ID:", which is the `AppID`
2. Determine the `ProgId` in the system registry
   - "Windows key" + "R"
   - Type `regedit`
   - Click "OK"
   - Expand the "Computer" key
   - Then the "HKEY_LOCAL_MACHINE" key
   - Expand "SOFTWARE"
   - Expand "WOW6432Node" (only on 64-bit systems, otherwise skip this step)
   - Expand "Classes"
   - Expand "CLSID"
   - Expand `<classId>`
   - Select `ProgID`
   - Copy the value "(Default)" in the "Data" column, which is the `ProgID`

[^wrapper-server]: The OPC UA client starts the *OPC UA wrapper server* automatically and stops it when it disconnects. Each client starts its own wrapper server. The *OPC UA wrapper server* wraps the requests of the OPC UA client and sends them to the *OPC Classic server*. The *OPC UA wrapper server* sends the responses of the OPC Classic server back to the *OPC UA client* as OPC UA responses.

## Complete example

Complete program: a client that connects to a server and
reads a temperature node once per second:

```csharp
namespace Client
{
    using System;
    using System.Threading;

    using Opc.UaFx.Client;

    /// <summary>
    /// This sample demonstrates how to connect to an OPC UA server and read the value of a node
    /// once per second.
    /// </summary>
    public class Program
    {
        public static void Main()
        {
            using (var client = new OpcClient("opc.tcp://localhost:4840")) {
                client.Connect();

                while (true) {
                    var temperature = client.ReadNode("ns=2;s=Temperature");
                    Console.WriteLine("Current Temperature is {0} °C", temperature);

                    Thread.Sleep(1000);
                }
            }
        }
    }
}

```

```vbnet
Imports System
Imports System.Threading

Imports Opc.UaFx.Client

Namespace Client
    ''' <summary>
    ''' This sample demonstrates how to connect to an OPC UA server and read the value of a node
    ''' once per second.
    ''' </summary>
    Public Class Program
        Public Shared Sub Main()
            Using client = New OpcClient("opc.tcp://localhost:4840")
                client.Connect()

                While True
                    Dim temperature = client.ReadNode("ns=2;s=Temperature")
                    Console.WriteLine("Current Temperature is {0} °C", temperature)

                    Thread.Sleep(1000)
                End While
            End Using
        End Sub
    End Class
End Namespace

```

If the server from the [complete example](https://www.traeger.de/en/docs/development/opcua/server/getting-started#complete-example) of server development runs on the same computer, the client prints a line `Current Temperature is … °C` once per second. The value rises from 100 to 110 and then starts again at 100.

## Next steps

- [Browse nodes](https://www.traeger.de/en/docs/development/opcua/client/browse): Explore the address space of a server: node by node from the ObjectsFolder, or several levels in one pass.

- [Read and write values](https://www.traeger.de/en/docs/development/opcua/client/read-write-values): Read and write the values of single and multiple nodes, access other attributes and parts of arrays, and evaluate the results with their status.

- [Subscriptions](https://www.traeger.de/en/docs/development/opcua/client/subscriptions): Subscribe to value changes and events of nodes, handle notifications, manage subscriptions, and narrow them down with filters.

- [Secure clients](https://www.traeger.de/en/docs/development/opcua/security/client): Secure the client: choose an endpoint, validate server certificates, protect your own certificate, authenticate users, and use a checklist for production.
