Previous
Update and manage modules
To use the platform or machine APIs, you must authenticate using API keys.
The following steps show you how to use the following APIs from a module:
app_client)data_client)ml_training_client)billing_client)Add the following imports:
import os
from viam.app.viam_client import ViamClient
from viam.app.app_client import AppClient
from viam.app.data_client import DataClient
from viam.app.ml_training_client import MLTrainingClient
from viam.app.billing_client import BillingClient
Add the viam_client and other clients to the resource class:
class TestSensor(Sensor, EasyResource):
viam_client: Optional[ViamClient] = None
app_client: Optional[AppClient] = None
data_client: Optional[DataClient] = None
ml_training_client: Optional[MLTrainingClient] = None
billing_client: Optional[BillingClient] = None
# ...
Initialize the clients and use them:
async def some_module_function(self):
# Ensure there is only one viam_client connection
if not self.viam_client:
self.viam_client = await ViamClient.create_from_env_vars()
self.app_client = self.viam_client.app_client
self.data_client = self.viam_client.data_client
self.ml_training_client = self.viam_client.ml_training_client
self.billing_client = self.viam_client.billing_client
# Use the clients in your module
locations = await self.app_client.list_locations(os.environ.get("VIAM_PRIMARY_ORG_ID"))
Add the following imports:
"os"
"go.viam.com/rdk/app"
Add the viam_client and other clients to the resource class:
type testPlatformApisGoModuleTestDataClient struct {
resource.AlwaysRebuild
name resource.Name
logger logging.Logger
cfg *Config
cancelCtx context.Context
cancelFunc func()
viamClient *app.ViamClient
appClient *app.AppClient
dataClient *app.DataClient
mlTrainingClient *app.MLTrainingClient
billingClient *app.BillingClient
}
Initialize the clients and use them:
func (s *exampleModuleResource) SomeModuleFunction(ctx context.Context, extra map[string]interface{}) (map[string]interface{}, error) {
if s.viamClient == nil {
var err error
s.viamClient, err = app.CreateViamClientFromEnvVars(ctx, &app.Options{}, s.logger)
if err != nil {
return nil, err
}
s.appClient = s.viamClient.AppClient()
s.dataClient = s.viamClient.DataClient()
s.mlTrainingClient = s.viamClient.MLTrainingClient()
s.billingClient = s.viamClient.BillingClient()
}
locations, err := s.appClient.ListLocations(ctx, os.Getenv("VIAM_PRIMARY_ORG_ID"))
if err != nil {
return nil, err
}
// Use locations...
return map[string]interface{}{"location_count": len(locations)}, nil
}
The module environment variables VIAM_API_KEY and VIAM_API_KEY_ID provide machine owner access for the machine the module is running on.
If you need a higher level of access, you can pass API keys as part of the module configuration:
Create an API key with the appropriate permissions from your organization settings page.
Add the API key and API key ID values to the module configuration:
{
"modules": [
{
"type": "registry",
"name": "example-module",
"module_id": "naomi:example-module",
"version": "latest",
"env": {
"VIAM_API_KEY": "abcdefg987654321abcdefghi",
"VIAM_API_KEY_ID": "1234abcd-123a-987b-1234567890abc"
}
}
]
}
This changes the environment variables VIAM_API_KEY and VIAM_API_KEY_ID from the default to the provided ones.
To use the machine management (robot_client) API, you must get the machine’s FQDN and API keys from the module environment variables.
Add the following imports and the create_robot_client_from_module method:
# Add imports
import os
from viam.robot.client import RobotClient
# For robot client, you can also use the machine's FQDN:
async def create_robot_client_from_module():
# Get API credentials from module environment variables
api_key = os.environ.get("VIAM_API_KEY")
api_key_id = os.environ.get("VIAM_API_KEY_ID")
machine_fqdn = os.environ.get("VIAM_MACHINE_FQDN")
if not api_key or not api_key_id or not machine_fqdn:
raise Exception("VIAM_API_KEY, VIAM_API_KEY_ID, and " +
"VIAM_MACHINE_FQDN " +
"environment variables are required")
# Create robot client options with API key authentication
opts = RobotClient.Options.with_api_key(
api_key=api_key,
api_key_id=api_key_id
)
# Create RobotClient using the machine's FQDN
robot_client = await RobotClient.at_address(machine_fqdn, opts)
return robot_client
Add the robot_client or other clients to the resource class:
class TestSensor(Sensor, EasyResource):
robot_client: Optional[RobotClient] = None
# ...
Initialize the client and use it:
async def some_module_function(self):
# Ensure there is only one robot client
if not self.robot_client:
self.robot_client = await create_robot_client_from_module()
# Use the robot client
resources = [str(name) for name in self.robot_client.resource_names]
Add the following imports and the createRobotClientFromModule function:
"os"
"go.viam.com/rdk/robot/client"
"go.viam.com/utils/rpc"
func createRobotClientFromModule(ctx context.Context, logger logging.Logger) (*client.RobotClient, error) {
robotClient, err := client.New(
ctx,
os.Getenv("VIAM_MACHINE_FQDN"),
logger,
client.WithDialOptions(rpc.WithEntityCredentials(
os.Getenv("VIAM_API_KEY_ID"),
rpc.Credentials{
Type: rpc.CredentialsTypeAPIKey,
Payload: os.Getenv("VIAM_API_KEY"),
})),
)
if err != nil {
return nil, err
}
return robotClient, nil
}
Add the viam_client and other clients to the resource class:
type testPlatformApisGoModuleTestDataClient struct {
resource.AlwaysRebuild
name resource.Name
logger logging.Logger
cfg *Config
cancelCtx context.Context
cancelFunc func()
machine *client.RobotClient
}
Initialize the clients and use them:
func (s *exampleModuleResource) SomeModuleFunction(ctx context.Context, extra map[string]interface{}) (map[string]interface{}, error) {
if s.machine == nil {
var err error
s.machine, err = createRobotClientFromModule(ctx, s.logger)
if err != nil {
return nil, err
}
}
resources := s.machine.ResourceNames()
// Use resources...
return map[string]interface{}{"resource_count": len(resources)}, nil
}
To elevate access for the machine management API, follow the same steps described in Elevate access above.
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!