Skip to main content
Version: Next

SmartREST Templates

Custom SmartREST 2.0 Templates can be used to extend the functionality of a device to support more operations than what the static SmartREST templates offer. supports subscription to custom templates as documented here.

For every template that the device uses, it must publish all data to s/uc/<template-name> topic and subscribe to s/dc/<template-name> to receive data from the cloud, based on that template. When these templates are configured with, subscriptions to all these relevant topics on Cumulocity cloud will be done by internally. Local processes on the device can access these templates on the local MQTT broker by simply publishing to c8y/s/uc/<template-name> and subscribing to c8y/s/dc/<template-name> topics (note the c8y/ prefix in topics).

A template named $TEMPLATE_NAME requires the following subscriptions to be added when connecting to Cumulocity:


This is not done automatically and the custom templates have to be declared using the tedge command.

Checking existing templates

tedge config get c8y.smartrest.templates

Add new template to thin-edge configuration

To add new template to the tedge config cli tool can be used as following:

sudo tedge config set c8y.smartrest.templates template-1,template-2

After adding or removing a template, you will need to run the following command before will use the new settings:

sudo tedge reconnect c8y

To add/append a new template to a device that's already configured with some, all the existing templates should also be declared along with the new one in the tedge config set command. For example, if template-1 is already configured on the device, as following:

tedge config get c8y.smartrest.templates

To add new template to the set it is required to include current template, so the command would look like this:

tedge config set c8y.smartrest.templates template-1,template-2

Now when we get the configuration the both templates will be there:

tedge config get c8y.smartrest.templates
["template-1", "template-2"]

Removing templates from configuration

To remove all the templates, the unset subcommand can used as follows:

sudo tedge config unset c8y.smartrest.templates

To remove one of existing templates you can overwrite the existing c8y.smartrest.templates with the new set which doesn't contain the unwanted template.

tedge config get c8y.smartrest.templates
["template-1", "template-2"]
sudo tedge config set c8y.smartrest.templates template-1

You can verify that the template has changed by reading the value again.

tedge config get c8y.smartrest.templates

After adding or removing a template, you will need to run the following command before will use the new settings:

sudo tedge reconnect c8y

Example: Creating a custom operation

The following example shows how to create a new SmartREST template with a single custom operation which will be activated when an operation is created with the set_wifi fragment. The operation includes 3 parameters where the wifi name, ssid and type are included in the message which is sent to the device via MQTT.

In this example, the operation handler on the side only prints out the received message on the console, but it can be extended to execute any command that is required for your task.

The operation response defined in the SmartREST template will convert the Cumulocity IoT Operation from json to an MQTT message in a Comma Separated Variables (CSV) format. The MQTT message is then received by and a script is called passing the message as the message to it. The script is used to perform the desired actions using the parameters provided in the message.

The snippets below are used to illustrate the message translation of the Cumulocity IoT operation to the message received by the device.

Cumulocity IoT Operation

"description": "Configure wifi",
"deviceId": "664853968",
"set_wifi": {
"name": "Factory Wifi",
"ssid": "factory-onboarding-wifi",
"type": "WPA3-Personal"

SmartREST (CSV) format received by

The above Cumulocity IoT operation is transformed into CSV (using the formatting/rules defined in the SmartREST template) and sent to the device via MQTT. The example below shows the format of the message as received by the device:

topic: c8y/s/dc/custom_devmgmt

The following procedure details the step-by-step instructions on how to implement the above example.

Step 1: Creating a SmartREST template

  1. Open the Cumulocity IoT Device Management Application in your web browser

  2. Navigate to Device Types → SmartREST Templates


  3. Click Add SmartREST template


  4. Add a new Response message, and enter the details as detailed in the screenshot.


    The properties used in the example can be also described as follows:

    Response IDdm101Unique id of the message
    Nameset_wifiHuman readable name of the message
    Base patternset_wifiThe common prefix added to each pattern (see Pattern.x rows)
    Conditionset_wifiThe fragment which will "activate" the SmartREST message translation
    Patterns.0nameWifi Connection Name (Custom parameter to be included in the body)
    Patterns.1ssidWifi SSID (Custom parameter to be included in the body)
    Patterns.2typeWifi Type (Custom parameter to be included in the body)
  5. Click Save


Alternative: Import SmartREST template from file

Alternatively, you can import a SmartREST template from an existing file. This approach is less error prone as you don't need to enter any of the values manually, but it obviously requires you to have already exported an existing SmartREST template.

  1. Save the following SmartREST template to a local file (on your machine) called custom_devmgmt.json

    file: custom_devmgmt.json
    "name": "custom_devmgmt",
    "type": "c8y_SmartRest2Template",
    "com_cumulocity_model_smartrest_csv_CsvSmartRestTemplate": {
    "requestTemplates": [],
    "responseTemplates": [
    "msgId": "dm101",
    "condition": "set_wifi",
    "base": "set_wifi",
    "name": "set_wifi",
    "pattern": [
    "__externalId": "custom_devmgmt"
  2. Open the Cumulocity IoT Device Management Application

  3. Navigate to Device Types → SmartREST templates


  4. Click Import template


  5. Select the Load from file and select the json file you saved in the first step and click Open


  6. Double check the information and select Import


    If the import was successful, then you should see the SmartREST template, custom_devmgmt, in the list:


Step 2: Configure

On the device, perform the following steps:

  1. Set the custom SmartREST template to be used by

    tedge config set c8y.smartrest.templates "custom_devmgmt"

    The custom_devmgmt is the id of the SmartREST template that was created in the previous step.

  2. Reconnect to Cumulocity IoT (assuming you have already connected to Cumulocity IoT once)

    tedge reconnect c8y

    This step ensures that the new SmartREST template id is also added in the list of MQTT topics to subscribe to. Without this step, will not be able to receive the custom operation.


You don't need to re-run this step when you add a new message definition to an existing template id.

Step 3: Creating the operation handler

On your device, run the following steps:

  1. Create the following custom operation handler file

    file: /etc/tedge/operations/c8y/set_wifi
    command = "/usr/bin/set_wifi"
    topic = "c8y/s/dc/custom_devmgmt"
    on_message = "dm101"

    The operation definition tells what to do when receiving a specific message (with the message id) on the given topic. Specifically, the definition will execute the /usr/bin/set_wifi script when a dm101 message is received on the c8y/s/dc/custom_devmgmt topic.

  2. Create the script which is called when receiving the dm101 message

    file: /usr/bin/set_wifi
    set -e

    # Constants

    # Input arguments
    NAME=$(echo "$COMMAND" | cut -d, -f 3)
    SSID=$(echo "$COMMAND" | cut -d, -f 4)
    TYPE=$(echo "$COMMAND" | cut -d, -f 5)

    echo "Processing message: $MESSAGE"
    echo "NAME: $NAME"
    echo "SSID: $SSID"
    echo "TYPE: $TYPE"
    exit "$OK"

    You can change the path where this file is located, but it MUST match the path given in the custom operation definition file under the exec.command property.

  3. Make the script executable

    sudo chmod 755 /usr/bin/set_wifi

Step 4: Sending a custom operation

  1. On your local machine, create a custom operation instance in Cumulocity IoT

    Below shows an example of creating the operation using the go-c8y-cli) cli tool. It assumes you have already activated your go-c8y-cli session which points to your intended Cumulocity IoT tenant.

    c8y operations create \
    --device 12345 \
    --template "{set_wifi:{name:'Factory Wifi',ssid:'factory-onboarding-wifi',type:'WPA3-Personal'}}" \
    --description "Configure wifi"

    Where 12345 should be replaced with the Cumulocity IoT device id of your device.

    If you're not familiar with go-c8y-cli, then you can send the Cumulocity REST API request using other tools such as Postman, curl etc., though you will have use the appropriate Authorization Header as defined by the official Cumulocity API Guide.

    Cumulocity IoT REST Request

    The custom operation can be created via the Cumulocity IoT REST API using the following details:

    POST /devicecontrol/operations


    "description": "Configure wifi",
    "deviceId": "664853968",
    "set_wifi": {
    "name": "Factory Wifi",
    "ssid": "factory-onboarding-wifi",
    "type": "WPA3-Personal"
  2. In the Cumulocity IoT Device Management application, check the Control page where you should see the "Configure Wifi" operation.


  3. On the device, open a console, and check the log file which when processing the custom operation

    The following command uses a simple bash one-liner to print the contents of the most recent file created matching the set_wifi* pattern under the /var/log/tedge/agent/ folder.

    cat "$(ls -t /var/log/tedge/agent/set_wifi* | head -1)"
    ----- $ /usr/bin/set-wifi "dm101,rpi5-d83add9f145a,Factory Wifi,factory-onboarding-wifi,WPA3-Personal"
    exit status: 0

    stdout <<EOF
    Processing message: dm101,rpi5-d83add9f145a,Factory Wifi,factory-onboarding-wifi,WPA3-Personal
    NAME: Factory Wifi"
    SSID: factory-onboarding-wifi"
    TYPE: WPA3-Personal"

    stderr <<EOF


If you encounter any problems whilst trying to create or use a custom operation then please check some of the following debugging tips. This will help you locate more precisely what is going wrong.

Check the incoming MQTT message

You can observe the MQTT message which is received by the local MQTT broker by subscribing to the following topic on your device:

tedge mqtt sub 'c8y/#'

When a new operation is received, the above mqtt sub command should print the following message (though the rpi5-d83add9f145a will be replaced with the external id of your device):

[c8y/s/dc/custom_devmgmt] dm101,rpi5-d83add9f145a,Factory Wifi,factory-onboarding-wifi,WPA3-Personal

If you don't receive a message, then check the following:

  • Check your SmartREST definition in Cumulocity IoT. The definition must be defined per Cumulocity IoT Tenant!

  • Check that the config has been updated to subscribe to the related SmartREST topic. Maybe you forgot to run:

    sudo tedge reconnect c8y

Debugging your script

If you know the expected format of the SmartREST message, then you can debug any potential scripting problems by manually calling your script with a simulated message.

For instance, if the operation definition has exec.command set to call the /usr/bin/set_wifi script, then you can simulate how would call the script by using the following command:

sudo -u tedge /usr/bin/set_wifi "dm101,$(tedge config get,Factory Wifi,factory-onboarding-wifi,WPA3-Personal"

The script is called with the MQTT message passed as the first argument (hence the double quotes). If the message payload has double quotes in it, then you will have to make sure you escape them using a backslash, e.g. \". Below shows an example with escaped double quotes:

sudo -u tedge /usr/bin/set_wifi "dm101,$(tedge config get,Factory using \"quotes\",factory-onboarding-wifi,WPA3-Personal"

The exec.command is called as the tedge user, so if you need root permissions (e.g. you want to use sudo within your script), then you need to make sure that you add whatever command you want to call to the sudoers definition. For example if you want to allow the tedge user to call the Network Manager cli tool, /usr/bin/nmcli, then you need to create a new sudoers definition:

file: /etc/sudoers.d/tedge-wifi
tedge  ALL = (ALL) NOPASSWD: /usr/bin/nmcli