Connecting to a robot

Code that drives a robot runs in one of two places: on your own machine, reaching the robot over the network, or on the robot itself, as a program the robot executes. Both use the same Nate client and the same API. What differs is where the client gets its address and its credentials.

From a remote host

Address and credentials

The robot is reached by its IP address or by a name, such as the mDNS name it announces on the local network. The API is served over HTTPS on port 8443 and the event broker over MQTTS on port 8883.

Logging in takes the username and password of a user of the robot, both required. There is no API key to pass instead: the client logs in with the credentials and obtains a session token on its own.

1 from pyniryo_nate import Nate
2
3 with Nate(hostname="10.10.10.10", login=("user", "secret")) as nate:
4     print(nate.device.get_identity())

The same client is configured from the environment when the constructor is given nothing:

export NATE_HOSTNAME=10.10.10.10
export NATE_USERNAME=user
export NATE_PASSWORD=secret
1 from pyniryo_nate import Nate
2
3 with Nate() as nate:
4     print(nate.device.get_identity())

Warning

An environment variable takes precedence over the constructor argument. With NATE_HOSTNAME set, Nate(hostname="10.10.10.11") still connects to the robot named by the variable. A process that drives several robots must leave NATE_HOSTNAME unset and pass each address to the constructor.

What the constructor does

The constructor returns a client that is ready to use, or raises. Before it returns it:

  1. opens a TLS connection and checks that the robot is a Niryo robot, and the expected one when a device ID is given, see Trust and identity;

  2. logs in and obtains a session token;

  3. checks that the identity the API reports matches the certificate;

  4. connects to the event broker, which carries the robot state and the subscriptions.

The session token expires after NATE_TOKEN_VALIDITY, one day by default. The client renews it in the background for as long as it lives, so a long-running process never has to log in again.

Trust and identity

Every connection is encrypted. The robot presents a certificate signed by the Niryo certificate authority, whose root ships with the package, so trusting a Niryo robot needs no setup. A robot whose certificate is signed by anyone else is refused with TlsError. To trust another root as well, point NATE_CA_FILE at a PEM file holding it.

Optional: The robot is identified by the device ID written in its certificate. Pass the expected one and any other robot at that address is refused before a credential is sent:

1 nate = Nate(hostname="10.10.10.10", login=("user", "secret"), device_id="a1b2c3d")

Without an expected device ID, the first robot reached binds the client for its lifetime: every later connection, the event broker included, must come from that same robot. get_identity() reports the device ID of the robot in hand, to pin it the next time.

Errors

The constructor raises:

  • ValueError when the username or the password is missing, before anything is sent;

  • TlsError when the certificate is not trusted or names another robot than the expected one;

  • TransportError when the robot cannot be reached, after the retries configured by NATE_RETRY and NATE_RETRY_DELAY_FACTOR, or does not answer within NATE_HTTP_TIMEOUT;

  • ClientError with a status_code of 401 when the robot refuses the credentials.

 1 from pyniryo_nate import Nate
 2 from pyniryo_nate.exceptions import ClientError, TlsError, TransportError
 3
 4 try:
 5     nate = Nate(hostname="10.10.10.10", login=("user", "secret"))
 6 except TlsError as error:
 7     print(f"not the robot expected, or not a Niryo robot: {error}")
 8 except TransportError as error:
 9     print(f"robot unreachable: {error}")
10 except ClientError as error:
11     if error.status_code == 401:
12         print("wrong username or password")
13     else:
14         raise

Environment variables

Variable

Meaning

NATE_HOSTNAME

Address of the robot, default localhost.

NATE_USERNAME, NATE_PASSWORD

Credentials of a user of the robot.

NATE_DEVICE_ID

Device ID of the expected robot.

NATE_CA_FILE

PEM file holding extra roots to trust, on top of the Niryo root shipped with the package.

NATE_HTTP_PORT, NATE_MQTT_PORT

Ports of the API and of the event broker, default 8443 and 8883.

NATE_HTTP_TIMEOUT

Seconds to wait for an API answer, default 10.

NATE_RETRY, NATE_RETRY_DELAY_FACTOR

How many times a failed connection is retried, default 5, and the factor applied to the delay between two retries, default 0.5.

NATE_TOKEN_VALIDITY

Lifetime of the session token, default 1d. A number followed by d, h or s.

As a program run by the robot

A program is a Python file that the robot stores and runs. Programs are run from Niryo Studio, where the Programming panel of a project holds them and Run starts one on the robot. They can also be uploaded and started from the client, with create() and execute(). pyniryo-nate is installed in the runtime that executes them.

Connecting from the program

Inside the program, the hostname and login provided in the constructor are ignored:

1 from pyniryo_nate import Nate
2 from pyniryo_nate.models import Joints
3
4 with Nate() as nate:
5     for _ in range(3):
6         nate.robot.move(Joints(0, 0, 0, 0, 0, 0)).wait()
7         nate.robot.move(Joints(0.5, 0, 0, 0, 0, 0)).wait()

The robot provides everything the client needs: its own address and ports, the certificate to trust, and an execution token that identifies this run. The client sends that token as its bearer credential on both transports, with no login and no renewal. No username or password is involved, and the program must not carry any. The token is only valid for that run and only while it is running or paused, so a program cannot act on the robot after it has ended, and the file holds nothing worth protecting. With the token, the moves of the program go through in automatic mode, where a remote client is refused, see Direct control.

Warning

An execution started from the client with an environment overrides the variables the robot sets for the program, the NATE_* ones included. NATE_USERNAME and NATE_PASSWORD both set there are the one thing that takes precedence over the execution token: the program then logs in as that user, which is how it is redirected to another robot, and only on purpose.

Running the same file from your machine

A program built with Nate() runs unchanged on your machine once NATE_HOSTNAME, NATE_USERNAME and NATE_PASSWORD are set, which is how a program is developed before being uploaded. Run that way it is a remote client like any other: its moves need the key selector on manual, and it holds nothing.