Introduction

This section walks you through the SmartREST protocol, the data format used, as well as the anatomy and registration of SmartREST templates. Built-in messages as well as errors are also discussed. For a step-by-step description, see Using the REST interface in the Microservice SDK guide.

The Cumulocity IoT REST APIs provide you with a generic IoT protocol that is simple to use from most environments. It can be ad-hoc adapted to any IoT use case and it uses standard Internet communication and security mechanisms. While this is a great leap forward over tailored IoT protocols with proprietary technologies, it poses some challenges to very constrained environments such as low-end microcontrollers or low-bandwidth communication channels.

For these environments, Cumulocity IoT offers the so-called SmartREST protocol. SmartREST combines the benefits of standard technology and tailored protocols:

In the next section, we will discuss the concepts behind SmartREST and the basic protocol that is used. SmartREST is based on separating metadata from payload data by using templates, which are described below. Finally, we show how to send and receive data using SmartREST.

How does SmartREST work?

The image below illustrates how SmartREST works. Devices and other clients connect to a dedicated SmartREST endpoint on Cumulocity IoT and send their data in rows of comma-separated values. These rows are expanded by Cumulocity IoT’s SmartREST proxy into standard Cumulocity IoT REST API requests. In the same way, responses from Cumulocity IoT are compressed by the proxy from their original JSON format into comma-separated values before sending them back to the device.

SmartREST architecture

How can Cumulocity IoT interpret comma-separated values into meaningful REST requests?

For that purpose, devices register templates with Cumulocity IoT. The templates contain the expanded REST requests together with placeholders into which the Cumulocity IoT SmartREST proxy consecutively inserts the comma-separate values. For responses, the templates describe which values to pick from the structured REST response to construct comma-separated values.

Templates are associated with software or firmware versions of a device. Usually, a particular implementation of a device or application can only issue a particular set of well-defined types of requests. All devices with the same implementation share the same set of request types. Hence, the templates can be defined at implementation time. To make the templates available to Cumulocity IoT, the first device with a particular implementation will send its templates and makes them available for usage by all similar devices.

This process is illustrated in the image below. Assume that a device with an implementation version “Device_1.0” starts communicating through SmartREST. After retrieving its credentials, the device will ask the SmartREST proxy if its template is already known. If the template is not found on the server, the device will send its template in a single static text request to Cumulocity IoT. Once this procedure has been carried out, all similar devices using that template can start communicating using SmartREST without re-sending the template to the server.

SmartREST templates

The example also roughly illustrates the translation process. In “Template 1”, "%%" is a placeholder to be filled by the SmartREST proxy. "time" is filled with a server-side timestamp (see below). The remaining placeholders are filled with request data. The line 1,200,20.5 in the example request is interpreted as follows:

The basic SmartREST protocol

The basic structure of all SmartREST requests is as follows:

Using the above example, a SmartREST request would be as follows:

POST /s HTTP/1.1
Authorization: <AUTHORIZATION>
X-Id: Device_1.0

1,200,20.5

And the corresponding response would be:

HTTP/1.1 200 OK
Transfer-Encoding: chunked

20,0

To match the requests and responses, a response line contains – next to the error code – the line of the request that the response answers. In this example, 20 indicates “OK” and 0 refers to the first line of the request.

How are templates registered?

As described above, a client using SmartREST will first ask if its SmartREST templates are already known to the server. This is done with an empty SmartREST request:

POST /s HTTP/1.1
Authorization: <AUTHORIZATION>
X-Id: Device_1.0

If the device implementation is known, the response will return an ID that can be used as “shorthand” in the “X-Id” header of later requests.

HTTP/1.1 200 OK

20,<id>

If the device implementation is unknown, the response will be:

HTTP/1.1 200 OK

40,"No template for this X-ID"

In this case, create all templates used in your device implementation.

POST /s HTTP/1.1
Authorization: <AUTHORIZATION>
X-Id: Device_1.0

10,1,POST,/measurement/measurements,application/vnd.com.nsn.cumulocity.measurement+json,,%%,NOW UNSIGNED NUMBER,{ "time": "%%", "type": ... }

In this example, 10 refers to a request template (whereas “11” would refer to a response template). The template is number 1, so SmartREST requests using this template have a “1” in their first column. The template refers to a POST request to the endpoint /measurement/measurements with a content type of application/vnd.com.nsn.cumulocity.measurement+json. The placeholder used in the template is %%. The placeholders are a time stamp (NOW), an unsigned number and a general number. Finally, the last column contains the body of the template to be filled in a POST request.

How are responses handled?

The above example illustrated the handling of requests and request templates. For responses, JSONPath expressions translate Cumulocity IoT REST responses into CSV. Assume, for example, that a device has a display and can show a message on it. An operation to update the message would look like:

{
	"c8y_Message": {
		"text": "Hello, world!"
	},
	"creationTime": "2019-02-25T08:32:45.435+01:00",
	"deviceId": "8789602",
	"status": "PENDING"
}

On the client side, the device mainly needs to know the text to be shown. In JSONPath, the "text" property is extracted using the following syntax:

$.c8y_Message.text

In this syntax, $ refers to the root of the data structure and the dot (.) selects an element from the data structure. For more details, refer to the JSONPath reference.

A device usually queries for all operations that are associated with it and that have a status of PENDING. The standard Cumulocity IoT response to such queries looks like:

{
	"operations": [{
		"c8y_Message": {
				"text": "Hello, world!"
		},
		"creationTime": "2014-02-25T08:32:45.435+01:00",
		"deviceId": "8789602",
		"status": "PENDING"
	}, {
		"c8y_Relay": {
			"status": "OPEN"
		}
	}]
}

The response contains a list of operations which can have different types. To work with such a structure, use the following response template:

11,2,$.operations,$.c8y_Message,$.c8y_Message.text

This means, value by value:

The SmartREST client will thus get the following response:

HTTP/1.1 200 OK

2,0,"Hello, world!"

That is, the response was created using template 2, the template to translate display message operations. The response refer to the first request sent. The actual message to set is “Hello, world!”.

MQTT quick reference

Quick reference

Connection

Topics

Publish

Subscribe

Topic format

<protocol>/<direction><type>[/<template>][/<child_id>]

where:

Device registration

Template registration

Templates

See the templates quick reference for an overview of the available MQTT static templates.

SmartREST 2.0

This section describes the SmartREST 2.0 payload format that can be used with the Cumulocity IoT MQTT implementation.

SmartREST 2.0 was designed to make use of the MQTT protocol, so it may reduce the payload even more than the SmartREST 1.0 via HTTP.

SmartREST 2.0 is only available via MQTT and it offers the following MQTT topics for the main communication:

To publish messages:

s/uc/<X-ID>

To publish messages in transient mode:

t/uc/<X-ID>

To publish messages in quiescent mode:

q/uc/<X-ID>

To publish messages in CEP mode:

c/uc/<X-ID>

Refer to SmartREST 1.0 > The protocol > Processing mode in the Reference guide for more information about transient, quiescent & CEP data processing.

To subscribe for responses:

s/dc/<X-ID>

The topics for creating templates are described in Creating templates via MQTT.

Changes from SmartREST 1.0

In its base, SmartREST 2.0 is like the previous version: a CSV-like payload format that is backed by previously created templates to finally create the targeted JSON structure.

Several changes in the functionality have been made:

Supported templates

SmartREST 2.0 lets you create templates for the following matching HTTP methods:

API GET POST PUT
Inventory x x x
Alarm   x x
Event   x  
Measurement   x  
Operation     x

Additionally, you can create templates to return certain values from responses and operations.

Template collections

A template collection is a set of request and response templates that specifies a device communication protocol. Each collection is referenced by a unique ID (called X-ID).

Creating templates via MQTT

Like in SmartREST 1.0, you must pass all templates in a collection in one message. After the creation of a template collection, it can no longer be modified through MQTT.

When creating templates, the client needs to publish to the following topic:

s/ut/<X-ID>

To verify if a template collection exists, the client can subscribe to the topic:

s/dt

When subscribed, the client can send an empty message to the creation topic which will trigger a new message about the creation status of this X-ID.

Examples

Empty publish to s/ut/myExistingTemplateCollection

20,myExistingTemplateCollection,<ID of collection>

Empty publish to s/ut/myNotExistingTemplateCollection

41,myNotExistingTemplateCollection

Request templates

A request template contains the following basic fields:

Field Data type Possible values Mandatory Description
messageId String   Y Unique ID to reference the template within the collection
method String GET
PUT
POST
Y Whether to get, update or create data
api String INVENTORY
MEASUREMENT
ALARM
EVENT
OPERATION
Y Cumulocity IoT API to be used
response Boolean true
false
N Whether the request should trigger response templates. For GET templates by default true otherwise by default false
mandatoryValues List<String>   Y Values for the mandatory fields on the API. The values depend on the API and method the template uses
customValues List<CustomValue>   N Custom values that should be added to the object

A request template lists all the fragments in the object structure (mandatory and custom) that should be added when creating or updating the data. It can set fixed values in the template that will then be replaced by the server. If it does not set the value in the template, the value needs to be included in the publish message (this includes mandatoryValues).

Info
If the message rate limit per second is exceeded, the requests are delayed and kept in queue. If the queue limit number is exceeded, the client messages are rejected and the client is disconnected.

Example

We create a template to create a measurement like this (measurements have two mandatory values: type and time)

# 10,msgId,method,api,response,type,time,custom1.path,custom1.type,custom1.value
10,999,POST,MEASUREMENT,,c8y_MyMeasurement,,c8y_MyMeasurement.M.value,NUMBER,

This template defines one additional custom property for the measurement. It leaves two fields empty in the template declaration (time and the custom property), so to use the template the client needs to send these two values:

999,2016-06-22T17:03:14.000+02:00,25
# We can also use server time by leaving the time empty
999,,25

The following sections will get into more detail of how to create and use different templates.

GET templates

GET templates for the inventory do not need any mandatory or custom values. Instead, they use two different fields.

With SmartREST 2.0 you have the option to either get an object from inventory by its ID or by an external ID directly. Therefore, instead of the fields mandatoryValues and customValues, the following two fields are used:

Field Data type Possible values Mandatory Description
byId Boolean true
false
Y Whether the GET should be executed by Cumulocity IoT ID (=true) or externalId (=false)
externalIdType String   N Sets a fixed externalIdType if the template calls by externalId

This enables you to query inventory in three different ways:

By Cumulocity IoT ID

# Creation:
10,999,GET,INVENTORY,,true
# Usage:
999,123456

By external ID with a fixed type in the template

# Creation:
10,999,GET,INVENTORY,,false,c8y_Serial
# Usage:
999,myDeviceImei

By external ID without fixed type in the template

# Creation:
10,999,GET,INVENTORY,,false
# Usage:
999,c8y_Serial,myDeviceImei
POST templates

POST templates require a different set of mandatory values based on the API:

API mandatory values
MEASUREMENT type, time
EVENT type, text, time
ALARM type, text, status, severity, time
INVENTORY externalIdType

This results in the following minimal template creations:

# Creation:
10,100,POST,MEASUREMENT,false,c8y_MyMeasurement,,c8y_MyMeasurement.M.value,NUMBER,
10,101,POST,EVENT,,c8y_CustomEvent,mytext,,
10,102,POST,ALARM,,c8y_CustomAlarm,mytext,ACTIVE,MAJOR,

# Usage:
100
101
102

Creating data on the inventory optionally includes the creation of an externalId for that object. This is controlled by the mandatory value externalIdType.

Important
POST Inventory templates start with the value of the externalId after the msgId. Leaving this column empty will result in not creating an external ID.
# Creation:
10,100,POST,INVENTORY,,c8y_MySerial
# Usage:
# Create object with externalId c8y_MySerial/myImei
100,myImei
# Create object with externalId c8y_MySerial/myImei
101,myImei,c8y_MySerial
# This message will result in not creating an external ID
101,,c8y_MySerial
PUT templates

PUT templates for inventory follow the same logic as the GET templates, and with the addition that you can also use custom values for PUT.

# Creation:
# 10,msgId,method,api,response,byId,externalIdTyoe,custom1.path,custom1.type,custom1.value
10,999,PUT,INVENTORY,,false,c8y_Serial,c8y_MyCustomValue,STRING,
# Usage:
999,myDeviceImei,myValue

The PUT template for alarms uses the type of the alarm to find the alarm to update. It will first check the ACTIVE alarms and, if there is no ACTIVE alarm, it will check the ACKNOWLEDGED alarms.

# Creation:
# 10,msgId,method,api,response,type,custom1.path,custom1.type,custom1.value
10,999,PUT,ALARM,,c8y_MyCustomAlarm,status,ALARMSTATUS
# Usage:
999,CLEARED

PUT templates for operations use the fragment of the operation to find the operation. It will first check the EXECUTING operations and, if there is no EXECUTING operation, it will check the PENDING operations.

# Creation:
# 10,msgId,method,api,response,fragment,custom1.path,custom1.type,custom1.value
10,999,PUT,OPERATION,,c8y_MyOperation,status,OPERATIONSTATUS,SUCCESSFUL,c8y_Fragment.val,NUMBER,
# Usage:
999,24
Adding custom properties

All POST and PUT values enable you to add custom properties to the results of the templates.

A single custom property requires you to add the following three values to your template creation:

Field Description
path A JsonPath for the value that should be set
type An optional data type of the value. Default: STRING
value The value to be set. Leaving this field empty requires the client to send the value when using the template
Type Description
STRING The default type. No additional verification of the value
DATE A time stamp in the ISO 8601 format. Using date and not sending a time stamp results in the use of server time
NUMBER An integer or number with decimal places
INTEGER An integer
UNSIGNED An integer (only positive)
FLAG An empty map (for example c8y_IsDevice: {}). The client does not need to send anything for this value
SEVERITY A severity of an alarm. Used to update the severity field of alarms
ALARMSTATUS A status of an alarm. Used to update the status field of alarms
OPERATIONSTATUS A status of an operation. Used to update the status field of operations
Examples

Template for clearing an alarm with an additional custom property

# Creation:
10,999,PUT,ALARM,,c8y_MyCustomALarm,status,ALARMSTATUS,CLEARED,c8y_CustomFragment.reason,STRING,
# Usage:
999,Device resolved alarm on its own

Template for creating a custom measurement

# Creation:
10,999,POST,MEASUREMENT,,c8y_CustomMeasurement,,c8y_CustomMeasurement.custom.value,NUMBER,,c8y_CustomMeasurement.custom.unit,STRING,X
# Usage:
999,30.6

Template for updating a property in the device

# Creation:
10,999,PUT,INVENTORY,,false,c8y_Serial,c8y_MyCustomValue,STRING,
# Usage:
999,myDeviceImei,updatedValue

Response templates

The SmartREST 2.0 response templates use the same structure as in SmartREST 1.0.

Field Data type Mandatory Description
messageId String Y Unique ID to reference the template within the collection
base String N A JsonPath prefix that all patterns will use
condition String N A JsonPath that needs to exist in the object to use the pattern
pattern List<String> Y A list of JsonPath that will be extracted from the object and returned to the device

Response templates will be used for every operation and for any request template that defines the response field with true. In each case, the server will try every registered response template, so there might be multiple response lines for a single operation or request.

SmartREST 2.0 will always return a response template if the condition is true (or no condition was defined). Patterns that did not resolve will be returned as empty string.

You should make use of the condition field to control when response templates should be returned.

In the examples below, you can see how to query data and parse custom operations.

Querying data from the device object

Device object:

{
  "id": "12345",
  "type": "myMqttDevice",
  "c8y_IsDevice": {},
  "c8y_Configuration": "val1=1\nval2=2"
}

Template creation:

10,999,GET,INVENTORY,,true
11,888,,c8y_IsDevice,type,c8y_Test,c8y_Configuration

Client publishes:

999,12345

Client receives:

888,myMqttDevice,,"val1=1\nval2=2"
Parsing custom operations

Operation object:

{
  "id": "12345",
  "deviceId": "67890",
  "agentId": "67890",
  "status": "PENDING",
  "c8y_CustomConfiguration": {
    "val1": "1",
    "val2": "2",
    "customValues": ["a", "b", "c"]
  },
  "description": "Send custom configuration"
}

Template creation:

11,111,c8y_CustomConfiguration,deviceId,val1,val2,customValues[*]
11,222,,deviceId,c8y_CustomConfiguration.val1,c8y_CustomConfiguration.val2
11,333,,deviceId,val1,val2,customValues[*]
11,444,c8y_CustomConfiguration,c8y_CustomConfiguration.val3,val1,val2,customValues[*]

Client receives (assuming the ClientId is “myMqttTestDevice”):

111,myMqttTestDevice,1,2,a,b,c
222,myMqttTestDevice,1,2
333,myMqttTestDevice,,,

The template 444 is not returned as the condition does not match the operation.

Querying data from the device object containing key with multiple objects

Device object:

{
  "id": "12345",
  "name": "test",
  "type": "c8y_MQTTdevice",
  "c8y_IsDevice": {},
  "myList": [
      {
          "pid": 12345,
          "type": "test"
      },
      {
          "pid": 123456,
          "type": "test2"
      }
  ]
}

Template creation:

10,999,GET,INVENTORY,,true
11,888,,,"$.myList[*].type"

Client publishes:

999,12345

Client receives:

888,test,test2

Using a default collection

Having the X-ID as part of the topic gives you the freedom to easily use multiple template collections, but adds additional bytes for every message. If anyway the device uses mostly (or completely) a single collection, it makes sense to specify this collection as your default collection.

With a default collection specified, the client can use special topics which do not require the X-ID, and instead the server will use the X-ID previously specified. The topics are s/ud for publishing and s/dd for subscribing.

You can specify one X-ID within your MQTT ClientId (see MQTT implementation).

Your MQTT ClientId could look like this:

d:myDeviceSerial:myDefaultTemplateXID
Info
If you use a default X-ID, you must include in the ClientId the d: at the beginning to specify that the client is a device.

It is not required that the default template exists at the time of establishing the MQTT connection (it will be verified once the client uses it).

Handling of IDs

Concept of ID-less communication

The MQTT implementation of Cumulocity IoT is specifically designed for device communication. Therefore, it tries to remove as much unnecessary logic from the client side as possible.

Using the REST (or SmartREST) protocol requires to know the ID of every object, alarm and operation you want to update. Hence, a client needs to keep a state of these IDs. For example, if it creates an alarm, it needs to know the ID of the alarm so it can clear it afterwards.

With the MQTT implementation we want to reduce the logic required on the device to do such actions and move the logic to the server.

Example 1: ID of the device

You must know the ID of the device object to update data in it via REST. Also, this ID is required for every other data that needs to be associated with the device, for example, the source in a measurement, alarm or event.

To remove the necessity of persisting the ID on the device, Cumulocity IoT offers the identity API where you can link external IDs (for example a serial number) to the object, so you can query the ID any time.

A typical device start looks like this:

REST Receiving Device ID

With MQTT, we automatically use the identity API with the MQTT clientId. This removes the necessity to tell the ID to the device, and because the client sends also the other data on this connection, we can associate every measurement, alarm, event, and so on with the correct device.

MQTT Automatically Resolve ID

Example 2: ID of alarms

When a client creates an alarm using the REST API, it needs to ensure that it gets the ID of the alarm that was generated by Cumulocity IoT in return.

The client will need this ID to later update the alarm, for example, to status CLEARED, if the alarm is not active anymore.

REST Handling Alarms

In Cumulocity IoT, a device can only have a single alarm per type in status ACTIVE. If it creates another alarm with the same type, it will get de-duplicated. Therefore, the MQTT implementation uses the type of an alarm as identifier. The client only needs to send which type of alarm has been resolved, and the server will find the correct alarm object.

MQTT Handling Alarms

MQTT Static templates

Overview

To ease device integration Cumulocity IoT already supports a number of static templates that can be used by any client without the need to create your own templates. These templates focus on the most commonly used messages for device management purposes.

To use the templates listed below, you must publish the messages to the topic s/us (t/us for transient processing of published content, q/us for quiescent processing of published content or c/us for CEP processing of published content. Refer to SmartREST 1.0 > The protocol > Processing mode in the Reference guide for further information.

You must subscribe to the topic s/ds to receive operations with the static templates.

Templates quick reference

Click the commands below to see more information on the respective template. If a parameter is in square brackets, it is optional.

Inventory templates

Measurement templates

Alarm templates

Event templates

Operation templates

The client can receive the following templates when subscribing to s/ds.

Inventory templates

Operation templates

Automatic device creation

The topic for static templates supports an automatic creation of devices. Whenever there is no child associated with your MQTT ClientID and you send data, Cumulocity IoT will automatically create a device for the MQTT ClientID. If you want to create the device on your own, your first message must be the device creation. In this case Cumulocity IoT will create the device from the template.

The automatic creation of devices is also supported for 1st level child devices. For child devices on a deeper level, you must use the template for creating a child device by sending it to the topic of the child device under the one you want to place the new child.

Handling non-mandatory parameters

If a parameter is not declared as mandatory, the client can send an empty string in that place.

100,,myType

Tailing commas is not required. The two lines below result in the same message.

100,,
100

Publish templates

The following templates can be used to publish data on the topics s/us as well as t/us. Refer to SmartREST 1.0 > The protocol > Processing mode in the Reference guide for more information about the t/ topic for transient data processing.

Inventory templates (1xx)

Device creation (100)

Create a new device for the serial number in the inventory if not yet existing. An externalId for the device with type c8y_Serial and the device identifier of the MQTT clientId as value will be created.

Position Parameter Mandatory Type Default value
1 device name NO String MQTT Device <serialNumber>
2 device type NO String c8y_MQTTDevice

Example

100,myDevice,myType

Child device creation (101)

Create a new child device for the current device. The newly created object will be added as child device. Additionally, an externaId for the child will be created with type c8y_Serial and the value a combination of the serial of the root device and the unique child ID.

Position Parameter Mandatory Type Default value
1 unique child ID YES String  
2 device name NO String MQTT Device <serialNumber>
3 device type NO String c8y_MQTTChildDevice

Example

101,uniqueChildId,myChildDevice,myChildType

Service creation (102)

Create a new software service for given device.

Position Parameter Mandatory Type
1 service unique external id YES String
2 service type YES String
3 service name YES String
4 service status YES String

Example

102,myDatabaseDevice,systemd,DatabaseService,up

Service status update (104)

Set a status for given software service.

Position Parameter Mandatory Type
1 service status YES String

Example

104,up

Get child devices (105)

Trigger the sending of child devices of the device.

Example

105

Clear device’s fragment (107)

Remove one or more fragments from a device.

Position Parameter Mandatory Type
1… fragmentName YES String

Example

107,c8y_Position,c8y_Configuration

Configure Hardware (110)

Update the hardware properties of the device.

Position Parameter Mandatory Type
1 serialNumber NO String
2 model NO String
3 revision NO String

Example

110,1234567890,myModel,1.2.3

Configure Mobile (111)

Update the mobile properties of the device.

Position Parameter Mandatory Type
1 imei NO String
2 iccid NO String
3 imsi NO String
4 mcc NO String
5 mnc NO String
6 lac NO String
7 cellId NO String

Example

111,1234567890,,54353

Configure Position (112)

Update the position properties of the device.

Position Parameter Mandatory Type
1 latitude NO Number
2 longitude NO Number
3 altitude NO Number
4 accuracy NO Integer

Example

112,50.323423,6.423423

Set Configuration (113)

Update the configuration properties of the device.

Position Parameter Mandatory Type
1 configuration NO String

Example

113,"val1=1\nval2=2"

Set supported operations (114)

Set the supported operations of the device.

Position Parameter Mandatory Type
1… List of supported operations NO String

Example

114,c8y_Restart,c8y_Configuration,c8y_SoftwareList
Info
If you want to remove an item from the supported operations list, send a new 114 request with the updated list, for example, 114, c8y_Restart,c8y_Configuration in order to remove c8y_SoftwareList after the request from the example above.

Set firmware (115)

Set the firmware installed on the device.

Position Parameter Mandatory Type
1 name NO String
2 version NO String
3 url NO String

Example

115,firmwareName,firmwareVersion,firmwareUrl

Set software list (116)

Set the list of software installed on the device.

Position Parameter Mandatory Type
1… List of 3 values per software NO (n/a)
1.1 name NO String
1.2 version NO String
1.3 url NO String

Example

116,software1,version1,url1,software2,,url2,software3,version3

Set required availability (117)

Set the required interval for availability monitoring as an integer value representing minutes. For more information, see c8y_RequiredAvailability in Device management library > Device availability. This will only set the value if it does not exist. Values entered, for example, through the UI, are not overwritten.

Position Parameter Mandatory Type
1 Required interval NO Integer

Example

117,60

Set supported logs (118)

Set the supported logs of the device.

Position Parameter Mandatory Type
1… List of supported logs NO String

Example

118,ntcagent,dmesg,logread

Set supported configurations (119)

Set the supported configurations of the device.

Position Parameter Mandatory Type
1… List of supported configurations NO String

Example

119,modbus,system

Set currently installed configuration (120)

Set currently installed configuration of the device.

Position Parameter Mandatory Type Default value
1 Configuration type YES String  
2 Configuration file download URL YES String  
3 File name NO String Configuration type
4 Date and time when the configuration was applied NO Date Current date and time

Example

120,myType,http://www.my.url,config.bin,2020-07-22T17:03:14.000+02:00

Set device profile that is being applied (121)

Set device profile that is being applied to the device.

Position Parameter Mandatory Type Default value
1 Profile executed YES String  
2 Profile ID NO String Profile ID from the oldest EXECUTING device profile operation

Example

121,true,8473

Set device agent information (122)

Allows a device to provide information about the agent running on it.

Position Parameter Mandatory Type Default value
1 Name of the agent YES String
2 Version of the agent YES String
3 The agent URL NO String
4 Maintainer of the agent YES String

Example

122,thin-edge.io,0.6,https://thin-edge.io,Software AG

Set advanced software list (140)

Sets the list of advanced software installed on the device. Any existing list will be overwritten.

Position Parameter Mandatory Type Default value
1 Name of the software YES String
2 Version of the software YES String
3 Type of the software NO String
4 URL of the software NO String

Example

140,docker,3.2.1,systemd,https://www.docker.com/,nginx,1.6,container,https://www.nginx.com/

Get the device managed object ID (123)

Retrieve the ID of the device managed object.

Example

123

Append advanced software items (141)

Appends advanced software items to the list that exists for the device.

Position Parameter Mandatory Type Default value
1 Name of the software YES String
2 Version of the software YES String
3 Type of the software NO String
4 URL of the software NO String

Example

141,docker,3.2.1,systemd,https://www.docker.com/,nginx,1.6,container,https://www.nginx.com/

Remove advanced software items (142)

Removes advanced software items from the list that exists for the device.

Position Parameter Mandatory Type Default value
1 Name of the software YES String
2 Version of the software YES String

Example

142,docker,3.2.1,nginx,1.6

Set supported software types (143)

Set the supported software types of the device. Ignores empty elements. An empty list removes the c8y_SupportedSoftwareTypes fragment entirely.

Position Parameter Mandatory Type
1… List of supported software types NO String

Example

143,yum,docker

Measurement templates (2xx)

Create custom measurement (200)

Create a measurement with a given fragment and series.

Position Parameter Mandatory Type Default value
1 fragment YES String  
2 series YES String  
3 value YES Number  
4 unit NO String  
5 time NO Date Current server time

Example

200,c8y_Temperature,T,25

Create a custom measurement with multiple fragments and series (201)

Create a measurement with multiple fragments and series.

Position Parameter Mandatory Type Default value
1 type YES String  
2 time NO Date  
3 List of 4 values per fragment-series combination YES (n/a)  
3.1 fragment YES String  
3.2 series YES String  
3.3 value YES Number  
3.4 unit NO String  

Example

201,KamstrupA220Reading,2022-03-19T12:03:27.845Z,c8y_SinglePhaseEnergyMeasurement,A+:1,1234,kWh,c8y_SinglePhaseEnergyMeasurement,A-:1,2345,kWh,c8y_ThreePhaseEnergyMeasurement,A+:1,123,kWh,c8y_ThreePhaseEnergyMeasurement,A+:2,234,kWh,c8y_ThreePhaseEnergyMeasurement,A+:3,345,kWh

Create signal strength measurement (210)

Create a measurement of type c8y_SignalStrength.

Position Parameter Mandatory Type Default value
1 rssi value YES, if 2 not set Number  
2 ber value YES, if 1 not set Number  
3 time NO Date Current server time

Example

210,-90,23,2016-06-22T17:03:14.000+02:00

Create temperature measurement (211)

Create a measurement of type c8y_TemperatureMeasurement.

Position Parameter Mandatory Type Default value
1 temperature value YES Number  
2 time NO Date Current server time

Example

211,25,2016-06-22T17:03:14.000+02:00

Create battery measurement (212)

Create a measurement of type c8y_Battery.

Position Parameter Mandatory Type Default value
1 battery value YES Number  
2 time NO Date Current server time

Example

212,95,2016-06-22T17:03:14.000+02:00

Alarm templates (3xx)

Create CRITICAL alarm (301)

Create a CRITICAL alarm.

Position Parameter Mandatory Type Default value
1 type YES String  
2 text NO String Alarm of type alarmType raised
3 time NO Date Current server time

Example

301,c8y_TemperatureAlarm

Create MAJOR alarm (302)

Create a MAJOR alarm.

Position Parameter Mandatory Type Default value
1 type YES String  
2 text NO String Alarm of type alarmType raised
3 time NO Date Current server time

Example

302,c8y_TemperatureAlarm,"This is an alarm"

Create MINOR alarm (303)

Create a MINOR alarm.

Position Parameter Mandatory Type Default value
1 type YES String  
2 text NO String Alarm of type alarmType raised
3 time NO Date Current server time

Example

303,c8y_TemperatureAlarm

Create WARNING alarm (304)

Create a WARNING alarm.

Position Parameter Mandatory Type Default value
1 type YES String  
2 text NO String Alarm of type alarmType raised
3 time NO Date Current server time

Example

304,c8y_TemperatureAlarm,,2013-06-22T17:03:14.000+02:00

Update severity of existing alarm (305)

Change the severity of an existing alarm.

Position Parameter Mandatory Type
1 type YES String
2 severity YES String

Example

305,c8y_TemperatureAlarm,CRITICAL

Clear existing alarm (306)

Clear an existing alarm.

Position Parameter Mandatory Type
1 type YES String

Example

306,c8y_TemperatureAlarm

Clear alarm’s fragment (307)

Remove one or more fragments from an alarm of a specific type.

Position Parameter Mandatory Type
1 alarmType YES String
2… fragmentName YES String

Example

307,c8y_TemperatureAlarm,c8y_Position,c8y_Configuration

Event templates (4xx)

Create basic event (400)

Create an event of given type and text.

Position Parameter Mandatory Type Default value
1 type YES String  
2 text YES String  
3 time NO Date Current server time

Example

400,c8y_MyEvent,"Something was triggered"

Create location update event (401)

Create typical location update event containing c8y_Position.

Position Parameter Mandatory Type Default value
1 latitude NO Number  
2 longitude NO Number  
3 altitude NO Number  
4 accuracy NO Number  
5 time NO Date Current server time

Example

401,51.151977,6.95173,67

Create location update event with device update (402)

Create typical location update event containing c8y_Position. Additionally the device will be updated with the same c8y_Position fragment.

Position Parameter Mandatory Type Default value
1 latitude NO Number  
2 longitude NO Number  
3 altitude NO Number  
4 accuracy NO Number  
5 time NO Date Current server time

Example

402,51.151977,6.95173,67

Clear event’s fragment (407)

Remove one or more fragments from an event of a specific type.

Position Parameter Mandatory Type
1 eventType YES String
2… fragmentName NO String

Example

407,c8y_MyEvent,c8y_Position,c8y_Configuration

Operation templates (5xx)

Get PENDING operations (500)

Trigger the sending of all PENDING operations for the agent.

Example

500

Set operation to EXECUTING (501)

Set the oldest PENDING operation with given fragment to EXECUTING.

Position Parameter Mandatory Type
1 fragment YES String

Example

501,c8y_Restart

Set operation to FAILED (502)

Set the oldest EXECUTING operation with given fragment to FAILED.

Position Parameter Mandatory Type
1 fragment YES String
2 failureReason NO String

Example

502,c8y_Restart,"Could not restart"

Set operation to SUCCESSFUL (503)

Set the oldest EXECUTING operation with given fragment to SUCCESSFUL.

It enables the device to send additional parameters that trigger additional steps based on the type of operation sent as fragment (see Section Updating operations).

Position Parameter Mandatory Type
1 fragment YES String
2… parameters NO String

Example

503,c8y_Restart

Set operation to EXECUTING (504)

Set the operation with the given ID to EXECUTING. The operation must exist and must have the requesting device as the source.

Position Parameter Mandatory Type
1 operationId YES String

Example

504,123

Set operation to FAILED (505)

Set the operation with the given ID to FAILED. The operation must exist and must have the requesting device as the source.

Position Parameter Mandatory Type
1 operationId YES String
2 failureReason NO String

Example

505,123,"Could not restart"

Set operation to SUCCESSFUL (506)

Set the operation with given ID to SUCCESSFUL. The operation must exist and must have the requesting device as the source.

This may let the device send additional parameters that trigger further steps based on the type of the operation, also see Updating operations.

Position Parameter Mandatory Type
1 operationId YES String
2… parameters NO String

Example

506,c8y_Restart

Subscribe templates

Inventory templates (1xx)

Get children of device (106)

List all children of the device.

Position Parameter Type
1… child String

Example

106,child1,child2,child3

Get the device managed object ID (124)

Retrieve the ID of the device managed object.

Position Parameter Type
1 id String

Example

124,12345

Operation templates (5xx)

All operation responses have the same base structure, leading with the message ID and followed by the ID of either the root device or a child which should handle the operation.

Restart (510)

Restart a device.

Example

510,DeviceSerial

Command (511)

Run the command being sent in the operation.

Position Parameter Type
1 Command text String

Example

511,DeviceSerial,execute this

Configuration (513)

Set the configuration being sent in the operation.

Position Parameter Type
1 configuration String

Example

513,DeviceSerial,"val1=1\nval2=2"

Firmware (515)

Install the firmware from the url.

Position Parameter Type
1 firmware name String
2 firmware version String
3 url String

Example

515,DeviceSerial,myFirmware,1.0,http://www.my.url

Software list (516)

Install the software sent in the operation.

Position Parameter Type
1… List of 3 values per software (n/a)
1.1 name String
1.2 version String
1.3 url String

Example

516,DeviceSerial,softwareA,1.0,url1,softwareB,2.0,url2

Measurement request operation (517)

Send the measurements specified by the request name.

Position Parameter Type
1 request name String

Example

517,DeviceSerial,LOGA

Relay (518)

Open or close the relay.

Position Parameter Type
1 Relay state String

Example

518,DeviceSerial,OPEN

RelayArray (519)

Open or close the relays in the array.

Position Parameter Type
1… List of relay state String

Example

519,DeviceSerial,OPEN,CLOSE,CLOSE,OPEN

Upload configuration file (520)

The current configuration is uploaded from Cumulocity IoT to the device.

Example

520,DeviceSerial

Download configuration file (521)

Download a configuration file from the URL.

Position Parameter Type
1 url String

Example

521,DeviceSerial,http://www.my.url

Logfile request (522)

Upload a log file for the given parameters.

Position Parameter Type
1 Log file name String
2 Start date Date
3 End date Date
4 Search text String
5 Maximum lines Integer

Example

522,DeviceSerial,logfileA,2013-06-22T17:03:14.000+02:00,2013-06-22T18:03:14.000+02:00,ERROR,1000

Communication mode (523)

Change the communication mode.

Position Parameter Type
1 mode String

Example

523,DeviceSerial,SMS

Download configuration file with type (524)

Download a configuration file from the URL with type.

Position Parameter Type
1 URL String
2 configuration type String

Example

524,DeviceSerial,http://www.my.url,type

Firmware from patch (525)

Install the firmware from the patch.

Position Parameter Type
1 firmware name String
2 firmware version String
3 URL String
4 dependency String

Example

525,DeviceSerial,firmwareName,1.0,http://www.my.url,dependency

Upload configuration file with type (526)

Configuration is uploaded from Cumulocity IoT to the device with type.

Position Parameter Type
1 configuration type String

Example

526,DeviceSerial,type

Set device profiles (527)

Set the device profiles

Position Parameter Type
1 firmware marker (n/a)
1… 5 values of firmware (n/a)
1.1 firmware name String
1.2 firmware version String
1.3 firmware URL String
1.4 firmware isPatch String
1.5 firmware dependency String
2 software marker (n/a)
2… List of 4 values per software (n/a)
2.1 software name String
2.2 software version String
2.3 software URL String
2.4 software action String
3 configuration marker (n/a)
3… List of 2 values per configuration (n/a)
3.1 configuration URL String
3.2 configuration type String

Example

527,DeviceSerial,$FW,firmwareName,1.0,http://www.my.url,true,dependency,$SW,softwareA,1.0,http://www.my.url1,action1,softwareB,2.0,http://www.my.url2,action2,$CONF,http://www.my.url1,type1,http://www.my.url2,type2

Update software (528)

Update the software installed on the device.

Position Parameter Type
1… List of 4 values per software (n/a)
1.1 name String
1.2 version String
1.3 URL String
1.4 action String

Example

528,DeviceSerial,softwareA,1.0,url1,install,softwareB,2.0,url2,install
Info

The action can either be install or delete.

When the install action is received, the device agent ensures that the software will appear in the c8y_SoftwareList fragment of the device after it has completed the installation. The agent will also determine if there is a previous version of the software and replace it with the new version, resulting in an update.

When the delete action is received, the device agent ensures that the software will no longer appear in the c8y_SoftwareList fragment of the device after the software update operation has completed.

Update advanced software (529)

Update the software installed on the device.

Position Parameter Type
1… List of 5 values per software (n/a)
1.1 name String
1.2 version String
1.2 type String
1.3 URL String
1.4 action to be performed String

Example

529,DeviceSerial,softwareA,1.0,url1,install,softwareB,2.0,url2,install

Cloud Remote Access connect (530)

Establish tunneling by Remote Access device agent.

Position Parameter Type
1 hostname String
2 port Integer
3 connection key String

Example

530,DeviceSerial,10.0.0.67,22,eb5e9d13-1caa-486b-bdda-130ca0d87df8

Updating operations

When using the template to set an operation to status SUCCESSFUL, it supports sending additional parameters to trigger additional calls on the server. The table below shows the operations supporting this feature and what will be done with the parameters.

Fragment Parameters Action triggered
c8y_Command result Result will be added to operation
c8y_RelayArray relay states Device object will be updated with the states
c8y_CommunicationMode no parameter needed Device object will be updated with the mode
c8y_LogfileRequest file url File url will be added to operation
c8y_DownloadConfigFile (optional) timestamp Device object will be updated with the ID of the configuration dump and the timestamp (or server time)

JSON via MQTT

Info
JSON via MQTT is meant as an addition to a device that is connected via SmartREST. This is not a standalone interface.

This section describes the JSON payload format that can be used with the Cumulocity IoT MQTT implementation.

Compared to SmartREST 2.0 – which only works with fixed templates – JSON’s support for MQTT was designed to combine the payload flexibility of our REST API with the low protocol overhead of MQTT.

The SmartREST way should still be the preferred way if it is important to reduce your payload to the minimum (mobile traffic, low capability device).

Topic structure

The topic structure in JSON MQTT is quite similar to the REST endpoints. The main difference is in the additional action part which is included in the topic.

To publish messages:

 <api>/<resource>/<action>/<resource_id>

To publish messages in transient mode:

t/<api>/<resource>/<action>/<resource_id>

To publish messages in quiescent mode:

q/<api>/<resource>/<action>/<resource_id>

To publish messages in CEP mode:

c/<api>/<resource>/<action>/<resource_id>
Info
<resource_id> is not required for every <action>. See the examples below.

Refer to Processing mode for more information about transient, quiescent and CEP data processing.

Topic actions

The action in the topic corresponds to the HTTP methods combined with the content-type header.

The following actions are available:

Supported endpoint

The current JSON MQTT implementation does not cover all SmartREST 2.0 operations, so for example the whole device bootstrap process must be done using SmartREST 2.0.

The following endpoints and actions are supported:

Endpoint create createBulk update delete
event/events x x x x
alarm/alarms x x x  
measurement/measurements x x   x
inventory/managedObjects x   x  
inventory/managedObjects/{id}/childDevices x      

If the operation is not supported, a proper error message will be sent to the error topic.

For all of the above endpoints, you can use the same payload like in the REST API. The only difference is in the “source” field - in REST this field is mandatory while for JSON MQTT there is no need to set the device ID here. The source device ID will automatically be resolved based on the MQTT client ID. This value will always be used no matter if something is already defined there.

Examples

Create new event

Publish a message on topic /event/events/create with payload:

{
  "type": "TestEvent",
  "text": "sensor was triggered",
  "time": "2014-03-03T12:03:27.845Z"
}

Create many events

Publish a message on topic /event/events/createBulk with payload:

{
  "events": [
    {
      "type": "TestEvent1",
      "text": "sensor was triggered",
      "time": "2014-03-03T12:03:27.845Z"
    },
    {
      "type": "TestEvent2",
      "text": "sensor was triggered",
      "time": "2014-03-04T12:03:27.845Z"
    }
  ]
}

Update event

Publish a message on topic /event/events/update/<event_id> with payload:

{
  "text": "new text"
}

Delete event

Publish a message on topic /event/events/delete/<event_id> with empty payload.

Create a measurement data point

Publish a message on topic measurement/measurements/create with payload:

{
  "type": "c8y_TemperatureMeasurement",
  "time": "2021-09-06T17:35:14.000+02:00",
  "c8y_TemperatureMeasurement": {
  	"T": {
      	"value": 20,
          "unit": "C"
    }
  }
}

Error handling

Use the error topic to subscribe for errors related to the JSON MQTT implementation. In case of invalid payload, wrong topic or any other exception, a notification will be published on this topic. The payload is in JSON format. Besides a standard error message, it also contains a message ID which helps the client in finding out which exact message was failing.

Example payload:

{
  "error": "undefined/validationError",
  "message": "Following mandatory fields should be included: severity,text,time",
  "messageId": 3
}

Receiving operations

A notification client can subscribe to the devicecontrol/notifications topic to receive notifications of newly created operations. Initially upon subscription, all operations which are not yet forwarded will be published.

Additionally, it contains an External ID, so the client can identify for which child the operation is executed.

Example notification:

{
  "agentId": "1",
  "creationTime": "2018-05-17T07:33:15.555Z",
  "delivery": {
    "log": [

    ],
    "status": "PENDING",
    "time": "2018-05-17T07:33:15.575Z"
  },
  "deviceId": "2",
  "id": "123",
  "status": "PENDING",
  "c8y_Command": {
    "text": "Do something"
  },
  "description": "Execute shell command",
  "externalSource": {
    "externalId": "3",
    "type": "c8y_Serial"
  }
}