Cumulocity Mapper
The Cumulocity mapper, referred to as c8y-mapper
in the rest of this document,
maps data in Thin Edge format into their equivalent Cumulocity format.
Registration​
Cumulocity keeps the record of all the registered devices and their associated metadata in its inventory.
The c8y-mapper
creates and maintains inventory entries for all the devices and services registered with thin-edge.
The mapper subscribes to the following topics to get a list of all registered devices and services:
mosquitto_sub -t 'te/+' -t 'te/+/+' -t 'te/+/+/+' -t 'te/+/+/+/+'
The registration messages received for child devices and services are mapped as follows:
Child device​
Thin Edge (input)
te/device/child01
{
"@type": "child-device",
"name": "child01",
"type": "SmartHomeHub"
}
Cumulocity IoT (output)
c8y/s/us
101,<main-device-id>:device:child01,SmartHomeHub
Where the <main-device-id>
is added as the prefix to the external id to avoid id clashes
with devices using the same name in other tedge deployments connected to the same tenant.
Child device with explicit id​
Thin Edge (input)
te/device/child01
{
"@type": "child-device",
"@id": "child01",
"name": "child01",
"type": "SmartHomeHub"
}
Cumulocity IoT (output)
c8y/s/us
101,child01,SmartHomeHub
Where the provided @id
is directly used as the external id.
Nested child device​
Thin Edge (input)
te/device/nested_child01
{
"@type": "child-device",
"@parent": "device/child01//",
"name": "nested_child01",
"type": "BatterySensor"
}
Cumulocity IoT (output)
c8y/s/us/<main-device-id>:device:child01
101,<main-device-id>:device:nested_child01,nested_child01,BatterySensor
Main device service​
Thin Edge (input)
te/device/main/service/nodered
{
"@type": "service",
"name": "Node-Red",
"type": "systemd"
}
Cumulocity IoT (output)
c8y/s/us
102,<main-device-id>:device:main:service:nodered,systemd,Node-Red,up
Child device service​
Thin Edge (input)
te/device/child01/service/nodered
{
"@type": "service",
"name": "Node-Red",
"type": "systemd"
}
Cumulocity IoT (output)
c8y/s/us/<main-device-id>:device:child01
102,<main-device-id>:device:child01:service:nodered,systemd,Node-Red,up
Where the unique external IDs to be used in the cloud are derived from the entity identifier subtopics,
replacing the /
characters with :
.
The main device is registered with the cloud via the tedge connect c8y
command execution
and hence there is no mapping done for main device registration messages.
Inventory data updates for the main device are handled differently.
Telemetry​
Telemetry data types like measurements, events and alarms are mapped to their respective equivalents in Cumulocity as follows:
Measurement​
Thin Edge (input)
te/device/main///m/environment
{
"temperature": 23.4
}
Cumulocity IoT (output)
c8y/measurement/measurements/create
{
"type": "environment",
"time": "2021-04-22T17:05:26.958340390+00:00",
"temperature": {
"temperature": {
"value": 23
}
}
}
Measurement without type​
Thin Edge (input)
te/device/main///m/
{
"temperature": 23.4
}
Cumulocity IoT (output)
c8y/measurement/measurements/create
{
"type": "ThinEdgeMeasurement",
"time": "2021-04-22T17:05:26.958340390+00:00",
"temperature": {
"temperature": {
"value": 23
}
}
}
Measurement of child device​
Thin Edge (input)
te/device/child01///m/
{
"temperature": 23.4
}
Cumulocity IoT (output)
c8y/measurement/measurements/create
{
"externalSource":{
"externalId":"<main-device-id>:device:child01",
"type":"c8y_Serial"
},
"type":"ThinEdgeMeasurement",
"time":"2013-06-22T17:03:14+02:00",
"temperature":{
"temperature":{
"value":23
}
}
}
Measurement with unit​
The unit is a metadata associated with measurements which can be registered as a metadata message for a given measurement type.
If the following metadata message is registered for the environment
measurement type:
- tedge
- mosquitto
- mqtt
tedge mqtt pub -r 'te/device/main///m/environment/meta' '{
"units": {
"temperature": "°C"
}
}'
mosquitto_pub -r -t 'te/device/main///m/environment/meta' -m '{
"units": {
"temperature": "°C"
}
}'
te/device/main///m/environment/meta
{
"units": {
"temperature": "°C"
}
}
Then subsequent messages will be mapped with the registered unit value as follows.
Thin Edge (input)
te/device/main///m/environment
{
"temperature": 23.4
}
Cumulocity IoT (output)
c8y/measurement/measurements/create
{
"type": "environment",
"time": "2021-04-22T17:05:26.958340390+00:00",
"temperature": {
"temperature": {
"value": 23,
"unit": "°C"
}
}
}
Events​
Thin Edge (input)
te/device/main///e/login_event
{
"text": "A user just logged in",
"time": "2021-01-01T05:30:45+00:00"
}
Cumulocity IoT (output)
c8y/s/us
400,login_event,"A user just logged in",2021-01-01T05:30:45+00:00
Event - Complex​
Thin Edge (input)
te/device/main///e/login_event
{
"text": "A user just logged in",
"time": "2021-01-01T05:30:45+00:00",
"customFragment": {
"nested": {
"value": "extra info"
}
}
}
Cumulocity IoT (output)
c8y/event/events/create
{
"externalSource":{
"externalId":"<main-device-id>",
"type":"c8y_Serial"
},
"type":"login_event",
"text":"A user just logged in",
"time":"2021-01-01T05:30:45+00:00",
"customFragment": {
"nested": {
"value": "extra info"
}
}
}
Alarms​
Thin Edge (input)
te/device/main///a/temperature_high
{
"severity": "critical",
"text": "Temperature is very high",
"time": "2021-01-01T05:30:45+00:00"
}
Cumulocity IoT (output)
c8y/s/us
301,temperature_high,"Temperature is very high",2021-01-01T05:30:45+00:00
Alarm - Complex​
Thin Edge (input)
te/device/main///a/pressure_alarm
{
"severity": "major",
"time": "2023-01-25T18:41:14.776170774Z",
"text": "Pressure alarm",
"customFragment": {
"nested": {
"value": "extra info"
}
}
}
Cumulocity IoT (output)
c8y/alarm/alarms/create
{
"externalSource": {
"externalId": "<main-device-id>",
"type": "c8y_Serial"
},
"type": "pressure_alarm",
"severity": "MAJOR",
"time": "2023-01-25T18:41:14.776170774Z",
"text": "Pressure alarm",
"customFragment": {
"nested": {
"value": "extra info"
}
},
}
Health status​
Thin Edge (input)
te/device/main/service/my-service/status/health
{
"status": "up",
"pid": "21037"
}
Cumulocity IoT (output)
c8y/s/us/<service-external-id>
104,up
Twin​
The twin
metadata is mapped to inventory data in Cumulocity.
Twin - Main device​
A device's digital twin model can be updated by publishing to a specific topic.
The type part of the topic is used to group the data so it is easier for components to subscribe to relevant parts.
Thin Edge (input)
te/device/main///twin/device_OS
{
"family": "Debian",
"version": "11"
}
Cumulocity IoT (output)
c8y/inventory/managedObjects/update/<main-device-id>
{
"device_OS": {
"family": "Debian",
"version": "11"
}
}
Twin - Child Device​
Thin Edge (input)
te/device/child01///twin/device_OS
{
"family": "Debian",
"version": "11"
}
Cumulocity IoT (output)
c8y/inventory/managedObjects/update/<main-device-id>:device:child01
{
"device_OS": {
"family": "Debian",
"version": "11"
}
}
Twin - Service on Main Device​
Thin Edge (input)
te/device/main/service/tedge-agent/twin/runtime_stats
{
"memory": 3024,
"uptime": 86400
}
Cumulocity IoT (output)
c8y/inventory/managedObjects/update/<main-device-id>:device:main:service:tedge-agent
{
"runtime_stats": {
"memory": 3.3,
"uptime": 86400
}
}
Twin - Service on Child Device​
Thin Edge (input)
te/device/child01/service/tedge-agent/twin/runtime_stats
{
"memory": 3.3,
"uptime": 86400
}
Cumulocity IoT (output)
c8y/inventory/managedObjects/update/<main-device-id>:device:child01:service:tedge-agent
{
"runtime_stats": {
"memory": 3.3,
"uptime": 86400
}
}
Twin data - Root fragments​
Data can be added on the root level of the twin by publishing the values directly to the topic with the key used as type. The payload can be any valid JSON value other than a JSON object. JSON objects must be published to their typed topics directly.
Thin Edge (input)
te/device/main///twin/subtype
"my-custom-type"
Cumulocity IoT (output)
c8y/inventory/managedObjects/update/<main-device-id>
{
"subtype": "my-custom-type"
}
Updating the following properties via the twin
channel is not supported
name
type
as they are included in the entity registration message and can only be updated with another registration message.
Twin - Deleting a fragment​
Thin Edge (input)
te/device/child01/service/tedge-agent/twin/runtime_stats
<<empty>>
Cumulocity IoT (output)
c8y/inventory/managedObjects/update/<main-device-id>:device:child01:service:tedge-agent
{
"runtime_stats": null
}
Base inventory model​
The contents of {tedge_config_dir}/device/inventory.json
are used to populate the initial inventory fragments
of the the main thin-edge device in Cumulocity.
For example, if the inventory.json
contains the following fragments:
{
"c8y_Firmware": {
"name": "raspberrypi-bootloader",
"version": "1.20140107-1",
"url": "31aab9856861b1a587e2094690c2f6e272712cb1"
},
"c8y_Hardware": {
"model": "BCM2708",
"revision": "000e",
"serialNumber": "00000000e2f5ad4d"
}
}
It is mapped to the following Cumulocity message:
c8y/inventory/managedObjects/update
{
"c8y_Agent": {
"name": "thin-edge.io",
"url": "https://thin-edge.io",
"version": "x.x.x"
},
"c8y_Firmware": {
"name": "raspberrypi-bootloader",
"version": "1.20140107-1",
"url": "31aab9856861b1a587e2094690c2f6e272712cb1"
},
"c8y_Hardware": {
"model": "BCM2708",
"revision": "000e",
"serialNumber": "00000000e2f5ad4d"
}
}
Where the c8y_Agent
fragment is auto-generated by thin-edge and appended to the contents of the file before it is published.
The fragments in this file are also published to the te/device/main///twin/<fragment-key>
topics so that
the local twin metadata on the broker is also up-to-date and other components can also consume it.
For example, the above inventory.json
would result in the following twin
messages:
te/device/main///twin/c8y_Agent
{
"name": "thin-edge.io",
"url": "https://thin-edge.io",
"version": "x.x.x"
}
te/device/main///twin/c8y_Firmware
{
"name": "raspberrypi-bootloader",
"version": "1.20140107-1",
"url": "31aab9856861b1a587e2094690c2f6e272712cb1"
}
te/device/main///twin/c8y_Hardware
{
"model": "BCM2708",
"revision": "000e",
"serialNumber": "00000000e2f5ad4d"
}
The following keys in the inventory.json
file are also ignored:
name
type
as they are included in the entity registration message and can only be updated with another registration message.
Updating entity type in inventory​
After updating the inventory with inventory.json
file contents,
the device type
of the main device, set using the device.type
tedge config key,
is also updated in the inventory with the following message:
c8y/inventory/managedObjects/update
{
"type": "configured-device-type"
}
Operations/Commands​
Operations from Cumulocity are mapped to their equivalent commands in Thin Edge format.
Supported Operations/Capabilities​
All the supported operations of all registered devices can be derived from the metadata messages
linked to their respective cmd
topics with a simple subscription as follows:
mosquitto_sub -v -t 'te/+/+/+/+/cmd/+'
If that subscription returns the following messages:
[te/device/main///cmd/restart] {}
[te/device/main///cmd/log_upload] { "types": ["tedge-agent", "mosquitto"] }
[te/device/child01///cmd/config_snapshot] { "types": ["mosquitto", "tedge", "collectd"] }
[te/device/child01///cmd/config_update] { "types": ["mosquitto", "tedge", "collectd"] }
The cmd
metadata registered for both the main
device and the child device child01
are mapped to the following supported operations messages:
[c8y/s/us] 114,c8y_Restart,c8y_LogfileRequest
[c8y/s/us/<main-device-id>:device:child01] 114,c8y_UploadConfigFile,c8y_DownloadConfigFile
The operation specific metadata like types
for log_upload
, config_snapshot
and config_update
are also mapped to their corresponding supported logs and supported configs messages as follows:
[c8y/s/us] 118,"tedge-agent", "mosquitto"
[c8y/s/us/<main-device-id>:device:child01] 119,"mosquitto", "tedge", "collectd"
Device Restart​
Request​
Cumulocity IoT (input)
c8y/s/ds
510,<main-device-id>
Thin Edge (output)
te/device/main///cmd/restart/<cmd-id>
{
"status": "init"
}
Response​
Even though operations on tedge can have different kinds of status
for each operation type,
the mapper recognizes and maps only the following status
values as follows:
Thin Edge (input) | Cumulocity (output) |
---|---|
Topic
Payload
| Topic
Payload
|
Topic
Payload
| Topic
Payload
|
Topic
Payload
| Topic
Payload
|
All other status
values are just ignored.
Restart: Child device​
Cumulocity IoT (input)
c8y/s/ds
510,<main-device-id>:device:child01
Thin Edge (output)
te/device/child01///cmd/restart
{}
Software Update​
Cumulocity IoT (input)
c8y/s/ds
528,<main-device-id>,nodered::debian,1.0.0,<c8y-url>,install,collectd,5.7,,install,rolldice,1.16,,delete
Thin Edge (output)
te/device/main///cmd/software_update/<cmd_id>
{
"status": "init",
"updateList": [
{
"type": "debian",
"modules": [
{
"name": "nodered",
"version": "1.0.0",
"url": "<tedge-url>",
"action": "install"
},
{
"name": "collectd",
"version": "5.7",
"action": "install"
},
{
"name": "rolldice",
"version": "1.16",
"action": "remove"
}
]
}
]
}
Where the collectd
binary from the <c8y-url>
is downloaded to the tedge file transfer repository by the mapper,
and the local <tedge-url>
of that binary is included in the mapped request.
Configuration Snapshot​
Cumulocity IoT (input)
c8y/s/ds
526,<main-device-id>,collectd
Thin Edge (output)
te/device/main///cmd/config_snapshot/<cmd_id>
{
"status": "init",
"type": "collectd",
"url": "<tedge-url>"
}
Where the url
is the target URL in the tedge file transfer repository to which the config snapshot must be uploaded.
Configuration Update​
Cumulocity IoT (input)
c8y/s/ds
524,<main-device-id>,<c8y-url>,collectd
Thin Edge (output)
te/device/main///cmd/config_update/<cmd_id>
{
"status": "init",
"type": "collectd",
"url": "<tedge-url>"
}
Where the collectd
configuration binary from the <c8y-url>
is downloaded to the tedge file transfer repository by the mapper,
and the local <tedge-url>
of that binary is included in the mapped request.
Log Upload​
Cumulocity IoT (input)
c8y/s/ds
522,<main-device-id>,tedge-agent,2013-06-22T17:03:14.000+02:00,2013-06-22T18:03:14.000+02:00,ERROR,1000
Thin Edge (output)
te/device/main///cmd/log_upload/<cmd_id>
{
"status": "init",
"type": "tedge-agent",
"tedgeUrl": "<tedge-url>",
"dateFrom": "2013-06-22T17:03:14.000+02:00",
"dateTo": "2013-06-23T18:03:14.000+02:00",
"searchText": "ERROR",
"lines": 1000
}
Where the url
is the target URL in the tedge file transfer repository to which the config snapshot must be uploaded.