Advanced module patterns | Viam Documentation

Advanced module patterns

Some use cases require approaches beyond the standard module workflow. This page covers three advanced patterns: defining a new resource API, deploying custom components as remote parts, and packaging modules with Docker.

Define a new resource API

You can define a new, custom resource API if:

Tip

Defining a new resource API is significantly more complex than using an existing API. In most cases, use an existing API instead.

If you want to use most of an existing API but need a few additional functions, use the DoCommand endpoint with extra parameters to add custom functionality.

If your use case uses only DoCommand and no other API methods, define a new model of generic component or generic service.

Steps to define a new API

Viam uses protocol buffers for API definition. To define a new API:

  1. Decide whether your custom API is a component (interfaces with hardware) or a service (provides higher-level functionality).

  2. Choose a name for your API (called the subtype). Determine a valid API namespace triplet. For example, your-org-namespace:component:gizmo.

  3. Create a directory for your module with a src subdirectory.

Tip

If you are writing your module in Python, you can use this module generator tool to generate stub files for the new API and a module that implements it.

  1. Write the proto methods in a <API name>.proto file inside src/proto/. For reference:
  1. Define the proto methods in Python or Go in a file called api.py or api.go:
  1. Generate the required configuration files (buf.yaml, buf.gen.yaml, buf.lock). See the Buf documentation.

  2. Use the protobuf compiler to generate all other necessary protocol buffer code from your .proto file.

After defining your API

Once your API is defined, create a model that implements it.

Keep in mind:

Custom components as remote parts

Running modular resources on the computer directly connected to your components is the preferred approach. However, if you cannot use modular resources because you need to host viam-server on a non-Linux system or have a compilation issue, you can code a custom resource implementation, host it on a server, and add it as a remote part of your machine.

Once configured, you control the custom component with the Viam SDKs like any other component.

Steps

  1. Code a new model of a built-in resource type by creating a new interface that implements the required methods from its API definition.
  2. Register the custom component on a new gRPC server instance and start the server.
  3. Add the server as a remote part of your machine.
  4. (Optional) Ensure the remote server automatically starts when the machine boots.

Each remote server can host one or many custom components.

Tip

For detailed instructions, see the full example in the Python SDK documentation.

  1. Code a new model of a built-in resource type by subclassing it (for example, sensor or arm). Implement any required methods from its API definition.
  2. Register the custom component on a new gRPC server instance using the viam.rpc library.
  3. Add the server as a remote part of your machine.
  4. (Optional) Ensure the remote server automatically starts when the machine boots.

Each remote server can host one or many custom components.

Important

You must define all methods belonging to a built-in resource type when defining a new model. Otherwise, the class will not instantiate.

Deploy a module using Docker

In rare cases, you may need to package and deploy a module using Docker. Use cases include:

If you deploy using Docker, create a “first run” script to handle setup. This is not recommended for modules that do not use Docker.

Use a first_run script

  1. Create a tarball containing:

This example Makefile builds a module binary and bundles it with a meta.json and first-run script.

  1. Edit meta.json to include the first_run field:
{
     "first_run": "first_run.sh"
}
  1. Configure the module on your machine normally. The first-run script executes once when viam-server receives a new configuration, and once per version update.
  2. (Optional) To force the first-run script to run again without changing the module version, delete the marker file at .viam/packages/data/module/<id>/bin.first_run_succeeded.
  3. (Optional) The default first-run timeout is 1 hour. Adjust with "first_run_timeout": "5m" in the module configuration.