The SDK talks to the robot controller over Robot Web Services (RWS), the HTTP interface that ABB controllers expose on the network. Nothing has to be installed on the robot.

Two classes can open a connection:

- `AbbController` : the main entry point. It holds the connection parameters and gives access to every protocol.
- `RwsClient` : a standalone RWS client, when you only need RWS and prefer a smaller object.

## Quick connection

Pass an IP address and you are connected. The default parameters match an OmniCore controller with its factory user account.

**C# : ConnectQuick**
```csharp
using UnderAutomation.ABB;

public class ConnectQuick
{
    static void Main()
    {
        /**/
        // Connect to an OmniCore controller with the default RWS parameters
        AbbController robot = new AbbController();
        robot.Connect("192.168.0.1");

        // Every RWS service is reachable from robot.Rws
        Console.WriteLine(robot.Rws.Controller.GetIdentity().Name);
        /**/

        robot.Disconnect();
    }
}
```

## Full connection parameters

`ConnectionParameters` gives access to every option. Use it when the controller is not on its default port, uses HTTPS, or runs RobotWare 6.

**C# : Connect**
```csharp
using UnderAutomation.ABB;
using UnderAutomation.ABB.Rws;

public class Connect
{
    static void Main()
    {
        /**/
        ConnectionParameters parameters = new ConnectionParameters("192.168.0.1");

        // Ping the controller first, so an unreachable robot fails immediately
        parameters.PingBeforeConnect = true;

        parameters.Rws.Enable = true;
        parameters.Rws.Username = "Default User";
        parameters.Rws.Password = "robotics";
        parameters.Rws.UseHttps = false;
        parameters.Rws.Port = 0; // 0 means 80 for HTTP and 443 for HTTPS
        parameters.Rws.Timeout = 10000;
        parameters.Rws.Version = RwsVersion.OmniCore_V2_0;

        AbbController robot = new AbbController();
        robot.Connect(parameters);
        /**/

        robot.Disconnect();
    }
}
```

When `PingBeforeConnect` is `true` (default), the SDK sends an ICMP ping before the first HTTP request. An unreachable robot then fails in a few milliseconds instead of waiting for the HTTP timeout. Set it to `false` when ICMP is blocked on your network.

The default user account of an ABB controller is `Default User` with the password `robotics`. Change it if your controller uses a dedicated account. The account must have the User Authorization System (UAS) grants for what you want to do: reading is always allowed, writing needs the matching grant.

## IRC5 or OmniCore

One API covers the two generations of controllers. Only the `Version` property changes.

| Controller | RobotWare     | RWS version | `RwsVersion` value |
| ---------- | ------------- | ----------- | ------------------ |
| IRC5       | 6 and earlier | RWS 1.0     | `Irc5_V1_0`         |
| OmniCore   | 7 and later   | RWS 2.0     | `OmniCore_V2_0`     |

**C# : ConnectVersion**
```csharp
using UnderAutomation.ABB;
using UnderAutomation.ABB.Rws;

public class ConnectVersion
{
    static void Main()
    {
        /**/
        // IRC5 controller, RobotWare 6 : RWS 1.0
        ConnectionParameters irc5 = new ConnectionParameters("192.168.0.1");
        irc5.Rws.Version = RwsVersion.Irc5_V1_0;

        // OmniCore controller, RobotWare 7 : RWS 2.0
        ConnectionParameters omniCore = new ConnectionParameters("192.168.0.2");
        omniCore.Rws.Version = RwsVersion.OmniCore_V2_0;

        // UseHttps is independent of the version. Set it to match how this
        // particular controller is configured on the network, not its generation.
        omniCore.Rws.UseHttps = true;

        AbbController robot = new AbbController();
        robot.Connect(omniCore);

        // The same code then works on both controllers
        Console.WriteLine(robot.Rws.System.GetInfo().Version);
        /**/
    }
}
```

`OmniCore_V2_0` is the default. If you connect to an IRC5 without setting the version, the first request fails with a 404 status code.

`UseHttps` is a separate setting from `Version`. Both generations can be configured for HTTP or for HTTPS, this depends on how the controller itself is set up, not on which RWS version it speaks. Check your controller's own network configuration and set `UseHttps` to match. When the controller answers on HTTPS with a self-signed certificate, the SDK accepts it, you do not have to install anything in the certificate store.

The details of both versions are described in [IRC5 or OmniCore: which RWS version](/abb/documentation/irc5-vs-omnicore).

## Standalone RWS client

`RwsClient` connects without `AbbController`. The services are then directly on the client, `client.Controller` instead of `robot.Rws.Controller`.

**C# : ConnectStandalone**
```csharp
using UnderAutomation.ABB.Rws;

public class ConnectStandalone
{
    static void Main()
    {
        /**/
        // RwsClient talks to the controller without going through AbbController
        RwsClient client = new RwsClient();
        client.Connect("192.168.0.1", "Default User", "robotics", 0, 10000, false, RwsVersion.OmniCore_V2_0);

        Console.WriteLine(client.Controller.GetIdentity().Name);

        client.Disconnect();
        /**/
    }
}
```

## Synchronous and asynchronous

Every service method exists twice: a synchronous version, and an asynchronous one with the same name followed by `Async` and an optional `CancellationToken`.

**C# : ConnectAsync**
```csharp
using UnderAutomation.ABB;

public class ConnectAsync
{
    static async Task Main()
    {
        AbbController robot = new AbbController();
        robot.Connect("192.168.0.1");

        /**/
        // Every service method has an asynchronous twin, with a cancellation token
        var identity = await robot.Rws.Controller.GetIdentityAsync();
        var tasks = await robot.Rws.Rapid.GetTasksAsync();

        using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
        {
            var state = await robot.Rws.Panel.GetControllerStateAsync(cts.Token);
            Console.WriteLine(state);
        }
        /**/

        Console.WriteLine($"{identity.Name} runs {tasks.Length} RAPID tasks");
    }
}
```

The asynchronous methods are not available on .NET Framework 3.5 and 4.0, which have no `async` / `await`. Everything else in the SDK works on those versions.

## Errors

Every RWS failure is reported as an `RwsException`. It carries the HTTP status code and, when the controller sends one, the ABB error code and message.

**C# : ConnectErrors**
```csharp
using UnderAutomation.ABB;
using UnderAutomation.ABB.Rws;

public class ConnectErrors
{
    static void Main()
    {
        AbbController robot = new AbbController();
        robot.Connect("192.168.0.1");

        /**/
        try
        {
            robot.Rws.Panel.SetSpeedRatio(50);
        }
        catch (RwsException ex)
        {
            // StatusCode is the HTTP status returned by the controller
            // 403 usually means that another client holds the mastership
            Console.WriteLine($"RWS error {ex.StatusCode} : {ex.RwsErrorMessage}");
            Console.WriteLine($"ABB error code : {ex.RwsErrorCode}");
            Console.WriteLine($"Raw response : {ex.ResponseBody}");
        }
        /**/
    }
}
```

Common status codes:

| Status | Meaning                                                                                                           |
| ------ | ----------------------------------------------------------------------------------------------------------------- |
| 400    | The controller refused the value, for example a speed ratio out of range                                          |
| 403    | Another client holds the [mastership](/abb/documentation/rws-mastership), or the user account lacks the UAS grant |
| 404    | The resource does not exist on this controller, often a wrong `RwsVersion`                                        |
| 500    | The controller could not run the operation in its current state                                                   |

## Disconnect

**C# : ConnectDisconnect**
```csharp
using UnderAutomation.ABB;

public class ConnectDisconnect
{
    static void Main()
    {
        AbbController robot = new AbbController();
        robot.Connect("192.168.0.1");

        /**/
        // Always disconnect : the controller keeps a limited number of sessions open
        robot.Disconnect();

        Console.WriteLine(robot.Enabled); // False
        /**/
    }
}
```

A controller accepts a limited number of simultaneous sessions, around 70 on OmniCore. An application that connects in a loop without disconnecting exhausts them, and every following request answers 503.

## API reference