Previous
Lifecycle of a module
If your physical or virtual hardware is not already supported by an existing module, you can create a new module to add support for it. You can keep the module private or share it with your organization or the public. You can use built-in tools to manage versioning and deployment to machines as you iterate on your module.
This page provides instructions for creating and uploading a module in Python or Go. For C++ module examples, see the C++ examples directory on GitHub. If you want to create a module for use with a microcontroller, see Modules for ESP32.
The easiest way to generate the files for your module is to use the Viam CLI:
Install the Viam CLI and authenticate to Viam, from the same machine that you intend to upload your module from.
Run the module generate
command in your terminal.
If you are writing your module using Python, you must have Python version 3.11 or newer installed on your computer for this command to work:
viam module generate
Follow the prompts.
The generator will create a folder containing stub files for your modular sensor component. In the next section, you’ll customize some of the generated files to support your sensor.
If you have multiple modular components that are related to or even dependent upon each other, you can opt to put them all into one module. Note that each model can implement only one API. For an example of how this is done, see Create a Hello World module.
Edit the generated files to add your logic:
Open
Edit the validate_config
function to do the following:
For more information, see Module dependencies.
Edit the reconfigure
function, which gets called when the user changes the configuration.
This function should do the following:
If you assigned any configuration attributes to global variables, get the values from the latest config
object and update the values of the global variables.
Assign default values as necessary to any optional attributes if the user hasn’t configured them.
If your module has dependencies, get the dependencies from the dependencies
map and cast each resource according to which API it implements, as described in Module dependencies.
Edit the methods you want to implement:
For each method you want to implement, replace the body of the method with your relevant logic. Make sure you return the correct type in accordance with the function’s return signature. You can find details about the return types at python.viam.dev.
You can find more examples by looking at the source code GitHub repos linked from each module in the registry.
Add logging messages as desired. The following log severity levels are available for resource logs:
# Within some method, log information:
self.logger.debug("debug info")
self.logger.info("info")
self.logger.warn("warning info")
self.logger.error("error info")
self.logger.exception("error info", exc_info=True)
self.logger.critical("critical info")
Resource-level logs are recommended instead of global logs for modular resources, because they make it easier to determine which component or service an error is coming from. Resource-level error logs appear in the ERROR LOGS section of each resource’s configuration card in the app.
In order to see resource-level debug logs when using your modular resource, you’ll either need to run viam-server
with the -debug
option or configure your machine or individual resource to display debug logs.
Edit the generated viam-sdk
which is auto-populated.
For most modules, you do not need to edit the
Open
Add any configurable attributes to the Config
struct.
Edit the Validate
function to do the following:
For more information, see Module dependencies.
(Optional) Create and edit a Reconfigure
function:
In most cases, you can omit this function and leave resource.AlwaysRebuild
in the Config
struct.
This will cause viam-server
to fully rebuild the resource each time the user changes the configuration.
If you need to maintain the state of the resource, for example if you are implementing a board and need to keep the software PWM loops running, you should implement this function so that viam-server
updates the configuration without rebuilding the resource from scratch.
In this case, your Reconfigure
function should do the following:
config
object and update the values of the global variables.For an example that implements the Reconfigure
method, see
Edit the constructor to do the following:
If you didn’t create a Reconfigure
function, use the constructor to assign default values as necessary to any optional attributes if the user hasn’t configured them.
If you created a Reconfigure
function, make your constructor call Reconfigure
.
Edit the methods you want to implement:
For each method you want to implement, replace the body of the method with your relevant logic. Make sure you return the correct type in accordance with the function’s return signature. You can find details about the return types at go.viam.com/rdk/components.
You can find more examples by looking at the source code GitHub repos linked from each module in the registry.
Add logging messages as desired.
You can add log messages with various levels of severity:
fn (c *component) someFunction(ctx context.Context, a int) {
// Log with severity info:
c.logger.CInfof(ctx, "performing some function with a=%v", a)
// Log with severity debug (using value wrapping):
c.logger.CDebugw(ctx, "performing some function", "a" ,a)
// Log with severity warn:
c.logger.CWarnw(ctx, "encountered warning for component", "name", c.Name())
// Log with severity error without a parameter:
c.logger.CError(ctx, "encountered an error")
}
In order to see debug logs when using your modular resource, you’ll need to run viam-server
with the -debug
option.
It’s a good idea to test your module locally before uploading it to the registry. You can configure it in the web UI using the local files on your machine.
Prepare to run your module
If you enabled cloud build, use these steps.
Create a
#!/usr/bin/env bash
# bash safe mode. look at `set --help` to see what these are doing
set -euxo pipefail
cd $(dirname $0)
MODULE_DIR=$(dirname $0)
VIRTUAL_ENV=$MODULE_DIR/venv
PYTHON=$VIRTUAL_ENV/bin/python
./setup.sh
# Be sure to use `exec` so that termination signals reach the python process,
# or handle forwarding termination signals manually
exec $PYTHON src/main.py $@
Make your reload script executable by running the following command in your module directory:
chmod 755 reload.sh
Create a virtual Python environment with the necessary packages by running the setup file from within the module directory:
sh setup.sh
Edit your "entrypoint"
, "build"
, and "path"
fields as follows:
"entrypoint": "reload.sh",
"first_run": "",
"build": {
"build": "rm -f module.tar.gz && tar czf module.tar.gz requirements.txt src/*.py src/models/*.py meta.json setup.sh reload.sh",
"setup": "./setup.sh",
"path": "module.tar.gz",
"arch": [
"linux/amd64",
"linux/arm64"
]
}
Create a virtual Python environment with the necessary packages by running the setup file from within the module directory:
sh setup.sh
This environment is where the local module will run.
viam-server
does not need to run inside this environment.
From within the module directory, compile your module into a single executable:
viam module build local
Configure your local module on a machine
Run the following command to build and start your module and push it to your machine:
viam module reload <insert relevant named args>
For more information, run the command with the -h
flag or see the CLI documentation.
When you run viam module reload
, the module will be added to your device automatically.
On your machine’s CONFIGURE tab, click the + (create) icon in the left-hand menu. Select Local module, then Local module.
Enter the absolute path to the /home/jessamy/my-module/run.sh
on Linux, or /Users/jessamy/my-python-sensor-module/run.sh
on macOS.
For modules configured this way, viam-server
uses this path instead of the entrypoint
field in your
Click Create.
On your machine’s CONFIGURE tab, click the + (create) icon in the left-hand menu. Select Local module, then Local module.
Enter the absolute path to the /home/jessamy/my-go-module/bin/mymodule
on Linux, or /Users/jessamy/my-go-module/bin/mymodule
on macOS.
For modules configured this way, viam-server
uses this path instead of the entrypoint
field in your
Click Create.
Configure the model provided by your module
Click the + button again, this time selecting Local module and then Local component.
Select or enter the model namespace triplet, for example jessamy:weather:meteo-PM
.
You can find the triplet in the model
field of your
Select the Type corresponding to the API you implemented.
Enter a Name such as my-cool-component
.
Click Create.
Configure any required attributes using proper JSON syntax.
Test the component
Click the TEST bar at the bottom of your modular component configuration, and check whether it works as expected. For example, if you created a sensor component, check whether readings are displayed.
Iterate
If your component works, you’re almost ready to share your module by uploading it to the registry. If not, you have some debugging to do.
Each time you make changes to your local module code, you need to update its instance on your machine:
Run the reload command again to rebuild and restart your module:
viam module reload <insert relevant named args>
Since you are using
Run the following command to rebuild your module:
viam module build local
Then restart it in your machine’s CONFIGURE tab. In upper right corner of the module’s card, click … menu, then click Restart.
See Using the build
subcommand for advanced build
options.
Once you have thoroughly tested your module, continue to package and deploy it.
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!