Using Extra Params with Viam's SDKs

How to utilize and define the extra parameters that many resource API methods offer in the Go and Python SDKs.

Utilize

You can use extra parameters with modular resource implementations that are models of built-in resource types.

For example, a new model of sensor, or a new model of SLAM service.

The extra parameters in that built-in resource type’s API allow users to pass information to a resource’s driver that isn’t specified as a parameter for all models of the resource type. This is necessary to keep the API of resource types consistent across, for example, all models of motor or all models of camera.

Send extra information in an API call in extra parameters as follows:

Optional[Dict[str, Any]] indicates you are required to pass in an object of either type Dict[str, Any] or None as a parameter when calling this method.

An object of type Dict[str, Any] is a dictionary with keys of type str and values of any type,

For example:

async def main():
    # ... Connect to the machine.

    # Get your sensor resource from the machine.
    your_sensor = YourSensor.from_robot(robot, "your-sensor")

    # Define a dictionary containing extra information.
    your_info = {"type": "temperature", "description": "more info", "id": 123}

    # Send this information in an call to the sensor resource's API.
    await your_sensor.get_readings(extra=your_info)

extra (map[string]interface{}) indicates you are required to pass in an object of either type map[string]interface{} or nil as a parameter when calling this method.

An object of type map[string]interface{} is an map with keys of type string and values of any type that you have cast to an interface.

For example:

func main() {
    ... // Connect to the machine

    // Get your sensor resource from the machine.
    yourSensor, err := YourSensor.FromRobot(robot, "your-sensor")

    // Define a map containing extra information.
    your_info := map[string]interface{}{"type": "temperature", "description": "more info", "id": 123}

    // Send this information in an call to the sensor resource's API.
    err := yourSensor.Readings(context.Background(), your_info)
}

Define

If extra information must be passed to a resource, it is handled within a new, modular resource model’s custom API wrapper.

Click for instructions on defining a custom model to utilize extra params

To do this, define a custom implementation of the resource’s API as a new model, and modify the resource’s API methods to handle the extra information you send. Follow the steps in the Modular Resources documentation to do so.

For an example of how to check the values of keys in an extra parameter of a built-in resource API method, reference this modification to the built-in sensor resource type’s Readings method in the code of a new sensor model:

# Readings depends on extra parameters.
@abc.abstractmethod
async def get_readings(self,
                       *,
                       extra: Optional[Dict[str, Any]] = None,
                       timeout: Optional[float] = None,
                       **kwargs):
# Define an empty dictionary for readings.
readings = {}

# If extra["type"] is temperature or humidity, get the temperature or
# humidity from helper functions and return these values as the readings
# the sensor has provided.
if extra["type"] == "temperature":
    readings["type"] = get_temp()
elif extra["type"] == "humidity":
    readings["type"] = get_humidity()
# If the type is not one of these two cases, raise an exception.
else:
    raise Exception(f"Invalid sensor reading request: type {type}")

return readings</code>

// Readings depends on extra parameters.
func (s *mySensor) Readings(ctx context.Context, extra map[string]interface{}) (map[string]interface{}, error) {
// Define an empty map for readings.
readings := map[string]interface{}{}

// If extra[&#34;type&#34;] is temperature or humidity, get the temperature or humidity from helper methods and return these values as the readings the sensor has provided.
if readingType, ok := extra[&#34;type&#34;]; ok {
    rType, ok := readingType.(string)
    if !ok {
        return nil, errors.New(&#34;invalid sensor reading request&#34;)
    }
    switch rType {
    case &#34;temperature&#34;:
        readings[rType] = getTemp()
    case &#34;humidity&#34;:
        readings[rType] = getHumidity()
    // If the type is not one of these two cases, return an error.
    default:
        return nil, errors.Errorf(&#34;Invalid sensor reading request: type %s&#34;, rType)
    }
}

// Return the readings and `nil`/no error.
return readings, nil

}

See Extend Viam with Modular Resources for more information and instructions on modifying built-in API specifications.

Have questions, or want to meet other people working on robots? Join our Community Discord.

If you notice any issues with the documentation, feel free to file an issue or edit this file.