|
| 1 | +--- |
| 2 | +title: "Define a New Resource Subtype" |
| 3 | +linkTitle: "New API Subtype" |
| 4 | +weight: 30 |
| 5 | +type: "docs" |
| 6 | +tags: ["rdk", "extending viam", "modular resources", "API"] |
| 7 | +description: "Define a custom API for a resource that does not fit into existing component or service subtypes." |
| 8 | +no_list: true |
| 9 | +aliases: |
| 10 | + - /extend/modular-resources/create/create-subtype/ |
| 11 | + - /modular-resources/advanced/create-subtype/ |
| 12 | + - /registry/advanced/create-subtype/ |
| 13 | +date: "2022-01-01" |
| 14 | +# updated: "" # When the content was last entirely checked |
| 15 | +--- |
| 16 | + |
| 17 | +You can define a new, custom {{< glossary_tooltip term_id="resource" text="resource" >}} _{{< glossary_tooltip term_id="subtype" text="subtype" >}}_ API if: |
| 18 | + |
| 19 | +- You have a {{% glossary_tooltip term_id="resource" text="resource" %}} that does not fit into any of the existing {{< glossary_tooltip term_id="component" text="component" >}} or {{< glossary_tooltip term_id="service" text="service" >}} subtypes. |
| 20 | +- You have a resource that could fit into an existing subtype, but you want to define an API with different methods and messages than the ones in the existing [APIs](/dev/reference/apis/) for that subtype. |
| 21 | + |
| 22 | +{{% alert title="Tip" color="tip" %}} |
| 23 | + |
| 24 | +If you want to use most of an existing API but need just a few other functions, try using the `DoCommand` endpoint and [extra parameters](/dev/reference/sdks/use-extra-params/) to add custom functionality to an existing subtype. |
| 25 | +For example, if you have a [sensor](/operate/reference/components/sensor/) and you want to define a `Calibrate` method, you can use `DoCommand`. |
| 26 | + |
| 27 | +If your use case uses only `DoCommand` and no other API methods, you can define a new model of [generic component](/operate/reference/components/generic/) or [generic service](/operate/reference/services/generic/). |
| 28 | + |
| 29 | +{{% /alert %}} |
| 30 | + |
| 31 | +## Define your new resource API |
| 32 | + |
| 33 | +Viam uses [protocol buffers](https://protobuf.dev/) for API definition. |
| 34 | + |
| 35 | +To define a new subtype, you need to define the methods and messages of the new API in [protobuf](https://github.com/protocolbuffers/protobuf), write code in Python or Go to implement the higher level server and client functions required, and generate all necessary [protobuf module files](https://buf.build/docs/generate/usage/). |
| 36 | +The following steps guide you through this process in more detail: |
| 37 | + |
| 38 | +1. Decide whether your custom subtype is a {{< glossary_tooltip term_id="component" text="component" >}} or a {{< glossary_tooltip term_id="service" text="service" >}}. |
| 39 | + If it provides an interface to control hardware, it is a component. |
| 40 | + If it provides higher-level functionality, it is a service. |
| 41 | +1. Choose a name for your subtype. |
| 42 | + For example, `gizmo`. |
| 43 | + |
| 44 | + Determine a valid {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet" >}} based on your subtype name. |
| 45 | + You can figure out the {{< glossary_tooltip term_id="model-namespace-triplet" text="model namespace triplet" >}} later when you [create a model that implements your custom API](/operate/get-started/other-hardware/). |
| 46 | + |
| 47 | + {{< expand "API namespace triplet and model namespace triplet example" >}} |
| 48 | + |
| 49 | + The `viam-labs:audioout:pygame` model uses the repository name [audioout](https://github.com/viam-labs/audioout). |
| 50 | + It implements the custom API `viam-labs:service:audioout`: |
| 51 | + |
| 52 | + ```json |
| 53 | + { |
| 54 | + "api": "viam-labs:service:audioout", |
| 55 | + "model": "viam-labs:audioout:pygame" |
| 56 | + } |
| 57 | + ``` |
| 58 | + |
| 59 | + For your custom API, your API namespace triplet might be `your-org-namespace:component:gizmo` where `your-org-namespace` is your organization namespace, found in your org settings page in the Viam app. |
| 60 | + |
| 61 | + {{< /expand >}} |
| 62 | + |
| 63 | +1. Create a directory for your module. |
| 64 | + Within that, create a directory called <file>src</file>. |
| 65 | + |
| 66 | + {{% alert title="Tip" color="tip" %}} |
| 67 | + |
| 68 | + If you are writing your module using Python, you can use this [module generator tool](https://github.com/viam-labs/generator-viam-module) to generate stub files for the new API as well as a new {{< glossary_tooltip term_id="module" text="module" >}} that implements the new API. |
| 69 | + |
| 70 | + {{% /alert %}} |
| 71 | + |
| 72 | +1. Define your new API: |
| 73 | + |
| 74 | + - [Write the proto](https://protobuf.dev/programming-guides/proto3/) methods in a `<subtype name>.proto` file inside your <file>src/proto</file> directory. |
| 75 | + For reference: |
| 76 | + - [Example modular component proto file](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/proto/gizmo.proto) |
| 77 | + - [Example modular service proto file](https://github.com/viam-labs/speech-service-api/blob/main/src/proto/speech.proto) |
| 78 | + - [Built-in Viam resource proto files](https://github.com/viamrobotics/api/tree/main/proto/viam) |
| 79 | + - And define the proto methods in a protobuf-supported language such as Python or Go in a file called `api.py` or `api.go`, respectively. |
| 80 | + - [Example component in Python](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/gizmo/api.py) |
| 81 | + - [Example service in Python](https://github.com/viam-labs/speech-service-api/blob/main/src/speech_service_api/api.py) |
| 82 | + |
| 83 | +1. In the root directory of your module, you need to generate some configuration files. |
| 84 | + You will typically need the following three files for most modules, though different files are required for some advanced use cases. |
| 85 | + See the [Buf documentation](https://buf.build/docs/generate/usage/) for instructions. |
| 86 | + |
| 87 | + - [<file>buf.yaml</file>](https://buf.build/docs/configuration/v1/buf-gen-yaml/) |
| 88 | + - [<file>buf.gen.yaml</file>](https://buf.build/docs/configuration/v1/buf-gen-yaml/) |
| 89 | + - [<file>buf.lock</file>](https://buf.build/docs/configuration/v1/buf-lock/) |
| 90 | + |
| 91 | +1. In the <file>/src/</file> directory of your module, use the protobuf compiler to [generate](https://buf.build/docs/tutorials/getting-started-with-buf-cli/#generate-code) all other necessary protocol buffer code, based on the `<subtype name>.proto` file you wrote. |
| 92 | + |
| 93 | + - [Example generated files for a Python-based service](https://github.com/viam-labs/speech-service-api/tree/main/src/proto). |
| 94 | + The `buf.` files were generated. |
| 95 | + The <file>speech.proto</file> was manually written. |
| 96 | + |
| 97 | +## Next steps |
| 98 | + |
| 99 | +{{< cards >}} |
| 100 | +{{% manualcard link="/operate/get-started/other-hardware/" %}} |
| 101 | + |
| 102 | +<h4>Implement your API</h4> |
| 103 | + |
| 104 | +Now that your resource API is defined, create a new model that implements your new API. |
| 105 | + |
| 106 | +{{% /manualcard %}} |
| 107 | +{{< /cards >}} |
0 commit comments