Write control code with Viam SDKs

Viam’s SDK libraries wrap Viam’s gRPC APIs for interacting with a machine’s components and services, as well as for cloud capabilities, such as data management and fleet management. You can run control code from anywhere; it does not necessarily have to be run on the same machine that runs viam-server.

Diagram showing how a client connects to a machine with Viam. Diagram shows a client as a computer sending commands to a machine. Robot 1 then communicates with other robotic parts over gRPC and WebRTC and communicating that information back to the client.

Backend SDKs

Use the backend SDK to build business logic to control components and services, as well as manage your fleet and data, and billing information, or provision machines. With the backend SDKs you can also create custom modular resources.

Frontend SDKs

Use the frontend SDK to control your machine’s components, as well as manage your data or provision machines.

Mobile SDK

Use the mobile SDK to build iOS and Android apps to control your machine’s components, as well as manage your fleet and data, or provision machines.


Installation

To install your preferred Viam SDK on your Linux or macOS development machine or single-board computer, run one of the following commands in your terminal:

If you are using the Python SDK, set up a virtual environment to package the SDK inside before running your code, avoiding conflicts with other projects or your system.

For macOS (both Intel x86_64 and Apple Silicon) or Linux (x86, aarch64, armv6l), run the following commands:

python3 -m venv .venv
source .venv/bin/activate
pip install viam-sdk

Windows is not supported. If you are using Windows, use the Windows Subsystem for Linux (WSL) and install the Python SDK using the preceding instructions for Linux. For other unsupported systems, see Installing from source.

If you intend to use the ML (machine learning) model service, use the following command instead, which installs additional required dependencies along with the Python SDK:

pip install 'viam-sdk[mlmodel]'
go get go.viam.com/rdk/robot/client
npm install @viamrobotics/sdk
flutter pub add viam_sdk

Code samples

Navigate to the CONNECT tab on your machine’s page on the Viam app and select one of the programming languages.

The sample code will show you how to authenticate and connect to a machine’s viam-server instance, as well as some of the methods you can use on your configured components and services.

For a full list of available API methods, see Component APIs and Service APIs:

Click this to see example connection code
import asyncio

from viam.robot.client import RobotClient


async def connect():
    opts = RobotClient.Options.with_api_key(
      # Replace "<API-KEY>" (including brackets) with your machine's API key
      api_key='<API-KEY>',
      # Replace "<API-KEY-ID>" (including brackets) with your API key ID
      api_key_id='<API-KEY-ID>'
    )
    return await RobotClient.at_address('ADDRESS FROM THE VIAM APP', opts)


async def main():
    robot = await connect()

    print('Resources:')
    print(robot.resource_names)

    await robot.close()

if __name__ == '__main__':
    asyncio.run(main())
package main

import (
  "context"

  "go.viam.com/rdk/logging"
  "go.viam.com/rdk/robot/client"
  "go.viam.com/rdk/utils"
)

func main() {
  logger := logging.NewLogger("client")
  robot, err := client.New(
      context.Background(),
      "ADDRESS FROM THE VIAM APP",
      logger,
      client.WithDialOptions(utils.WithEntityCredentials(
      // Replace "<API-KEY-ID>" (including brackets) with your machine's API key ID
      "<API-KEY-ID>",
      utils.Credentials{
          Type:    utils.CredentialsTypeAPIKey,
          // Replace "<API-KEY>" (including brackets) with your API key
          Payload: "<API-KEY>",
      })),
  )
  if err != nil {
      logger.Fatal(err)
  }
  defer robot.Close(context.Background())
  logger.Info("Resources:")
  logger.Info(robot.ResourceNames())
}
// This code must be run in a browser environment.

import * as VIAM from "@viamrobotics/sdk";

async function main() {
  // Replace with the host of your actual machine running Viam.
  const host = "ADDRESS FROM THE VIAM APP";

  const robot = await VIAM.createRobotClient({
    host,
    credential: {
      type: "api-key",
      // Replace "<API-KEY>" (including brackets) with your machine's API key
      payload: "<API-KEY>",
    },
    // Replace "<API-KEY-ID>" (including brackets) with your API key ID
    authEntity: "<API-KEY-ID>",
    signalingAddress: "https://app.viam.com:443",
  });

  console.log("Resources:");
  console.log(await robot.resourceNames());
}

main().catch((error) => {
  console.error("encountered an error:", error);
});
#include <string>
#include <vector>

#include <boost/optional.hpp>

#include <viam/sdk/robot/client.hpp>

using namespace viam::sdk;

int main() {
    std::string host("ADDRESS FROM THE VIAM APP");
    DialOptions dial_opts;
    // Replace "<API-KEY-ID>" with your machine's api key ID
    dial_opts.set_entity(std::string("<API-KEY-ID>"));
    // Replace "<API-KEY>" with your machine's api key
    Credentials credentials("api-key", "<API-KEY>");
    dial_opts.set_credentials(credentials);
    boost::optional<DialOptions> opts(dial_opts);
    Options options(0, opts);

    auto robot = RobotClient::at_address(host, options);

    std::cout << "Resources:\n";
    for (const Name& resource: robot->resource_names()) {
      std::cout << "\t" << resource << "\n" << std::endl;
    }

    return EXIT_SUCCESS;
}
// This must be run from inside an existing app,
// e.g. the default Flutter app created by `flutter create APP_NAME`

// Step 1: Import the viam_sdk
import 'package:viam_sdk/viam_sdk.dart';

// Step 2: Call this function from within your widget
Future<void> connectToViam() async {
  const host = 'ADDRESS FROM THE VIAM APP';
  // Replace '<API-KEY-ID>' (including brackets) with your API key ID
  const apiKeyID = '<API-KEY-ID>';
  // Replace '<API-KEY>' (including brackets) with your API key
  const apiKey = '<API-KEY>';

  final robot = await RobotClient.atAddress(
    host,
    RobotClientOptions.withApiKey(apiKeyId, apiKey),
  );
  print(robot.resourceNames);
}

Copy this code into a file on your development machine and run it.

You can run your program on any computer which:

  1. has the appropriate SDK installed
  2. can establish a connection to your machine through the cloud, on a local or wide area network (LAN or WAN), or locally

Authentication

To authenticate yourself to your machine, you need

  1. The machine part’s API key:

    To authenticate, use a machine part API key or an API key with access to the machine. Copy and paste the API key ID and the API key into your environment variables or directly into the code:

    async def connect():
        opts = RobotClient.Options.with_api_key(
            # Replace "<API-KEY>" (including brackets) with your machine's API key
            api_key='<API-KEY>',
            # Replace "<API-KEY-ID>" (including brackets) with your machine's API key
            # ID
            api_key_id='<API-KEY-ID>'
        )
        return await RobotClient.at_address('ADDRESS FROM THE VIAM APP', opts)
    
    robot, err := client.New(
        context.Background(),
        "ADDRESS FROM THE VIAM APP",
        logger,
        client.WithDialOptions(rpc.WithEntityCredentials(
        // Replace "<API-KEY-ID>" (including brackets) with your machine's API key ID
        "<API-KEY-ID>",
        rpc.Credentials{
            Type:    rpc.CredentialsTypeAPIKey,
            // Replace "<API-KEY>" (including brackets) with your machine's API key
            Payload: "<API-KEY>",
        })),
    )
    
    // Replace with the host of your actual machine running Viam.
    const host = "ADDRESS FROM THE VIAM APP";
    
    const robot = await VIAM.createRobotClient({
      host,
      credential: {
        type: "api-key",
        // Replace "<API-KEY>" (including brackets) with your machine's API key
        payload: "<API-KEY>",
      },
      // Replace "<API-KEY-ID>" (including brackets) with your machine's API key ID
      authEntity: "<API-KEY-ID>",
      signalingAddress: "https://app.viam.com:443",
    });
    
    std::string host("ADDRESS FROM THE VIAM APP");
    DialOptions dial_opts;
    dial_opts.set_type("api-key");
    // Replace "<API-KEY-ID>" with your machine's API key ID
    dial_opts.set_entity("<API-KEY-ID>");
    // Replace "<API-KEY>" with your machine's API key
    Credentials credentials("<API-KEY>");
    dial_opts.set_credentials(credentials);
    boost::optional<DialOptions> opts(dial_opts);
    Options options(0, opts);
    
    auto robot = RobotClient::at_address(host, options);
    
    Future<void> connectToViam() async {
      const host = 'ADDRESS FROM THE VIAM APP';
      // Replace '<API-KEY-ID>' (including brackets) with your API key ID
      const apiKeyID = '<API-KEY-ID>';
      // Replace '<API-KEY>' (including brackets) with your API key
      const apiKey = '<API-KEY>';
    
      final robot = await RobotClient.atAddress(
        host,
        RobotClientOptions.withApiKey(apiKeyId, apiKey),
      );
      print(robot.resourceNames);
    }
    
  1. The machine’s remote address:

    Include the address, which resembles 12345.somemachine-main.viam.cloud. The machine address is a public address to connect to your machine. You can find this address at the top of the machine’s CONNECT tab.

Apps with authentication

If you need to build apps with custom login flows, contact us.

Run code

After saving your code sample and adding control logic with Viam’s SDKs, run your program to control your Viam-connected machine.

You can remotely control your machine from anywhere in the world. If your machine and your personal computer are both connected to the Internet, you can run code to control your machine remotely from your personal computer.

A client connecting remotely to a machine

This method is convenient for most use cases because your machine and your personal computer do not have to be connected to the same WAN/LAN to issue control commands. When you run code on one computer, creating a client session, the code running on that computer sends instructions to your machine’s viam-server instance over the Internet.

After editing your code to include your machine’s authentication credentials, run a command to execute the program in the terminal of a computer with the appropriate programming language and Viam SDK installed:

python3 ~/myCode/myViamFile.py
go run ~/myCode/myViamFile.go

For an example, see this execution demo.

For information on running C++ code see the instructions on GitHub.

flutter run <DART_FILE>

As long as that computer is able to establish a network connection with the machine’s computer, your control logic will be executed on the machine.

If the internet becomes unavailable to the machine or to your computer but a local network is available, your code will continue to run as described in the next section:

You can wrap control code by creating a module. In wrapping your code into a module, you will be able to:

  • deploy it across one or more machines
  • use it in fragments
  • version it

You can package any files, code, or executable into a module. When you add a module to your machine’s configuration, the entrypoint defined for the module is run which can start your code.

If your control code augments what a component does, such as, for example, adding an overlay to a camera stream, you can create your own camera model inside your module and amend the API methods to have your custom functionality. For an example of this, see the facial-detection module which wraps its logic into a custom vision service.

If your functionality does not conform to existing API types such as the motor or camera API, you can use a generic API to wrap your code.

For more information, see How to create and deploy a new module.

Your machines do not need to be connected to the Internet for you to be able to run code. As long as your machine is connected to the same LAN or WAN network as the device running the code, you can connect to it and run code.

When you use the connection code sample from the CONNECT tab, that code establishes a client session that automatically uses the most efficient route to send commands to your machine. That means that when the device your code runs on is on the same network as your machine, even if internet is available, the connection will choose the most efficient route and connect over LAN or WAN. If you subsequently lose internet connectivity, but stay connected to LAN or WAN, the connection will thus remain.

You can run control code directly on your machine. If you run PID control loops or your machines have intermittent or no network connectivity, you can ensure lags in communication do not interfere with the machine’s performance by running the control code on the same board that is running viam-server. Running everything on one machine is also convenient if you have a machine (for example, an air quality sensor) that runs all the time, and you don’t want to have to connect to it from a separate computer constantly.

A client running on a machine

The script you run on-machine is the same as the script you run remotely or on a local network. When the connection code from the CONNECT tab’s Code sample page executes, it creates a client session connected to your machine using the most efficient route. Because the code is running on the same machine as viam-server, the favored route for commands is automatically over localhost.

Install the appropriate programming language and Viam SDK on your machine and run a command to execute the program in the terminal of that machine instead of from a separate computer:

python3 ~/myCode/myViamFile.py
go run ~/myCode/myViamFile.go

For an example, see this execution demo.

For information on running C++ code see the instructions on GitHub.

flutter run <DART_FILE>

If you want to run your code on-machine automatically when your machine boots, you can configure your machine to run your code as a process. You can configure the process to run once on boot, or continuously.

Find information on how to configure a process in Processes.

Debug

Read and filter a machine’s logs to view updates from your machine’s viam-server instance and troubleshoot issues with your program.

Navigate to the LOGS tab of your machine’s page in the Viam app.

Use the Filter input to filter the logs by key terms, and select from the Levels dropdown menu to filter the logs by warning level:

Filtering by log level of info in the logs tab of the Viam app.

sudo journalctl --unit=viam-server
cat $(brew --prefix)/var/log/viam.log

Next Steps

For examples projects, see: