Bosch IoT Device Management - will be discontinued by mid 2024

Specification digital twin model mapping

When working with digital twins in the Bosch IoT Suite, it can be desirable to declare models which the digital twin instances must comply to.

Eclipse Vorto is an IoT language for digital twins that brings a common understanding to device data.
Eclipse Ditto and its commercial offering, the the digital twin layer service, holds and manages digital twin (runtime) instances which may follow a defined Vorto model.

By combining both, IoT language with model repository (Vorto), and digital twin instance management (Ditto), strongly typed communication with devices via their digital twins can be ensured.

This specification describes how the concepts of digital twins and their facets map to Eclipse Vorto modeling elements and to Eclipse Ditto digital twin runtime concepts.
Terms defined by Eclipse Vorto are highlighted in green in order to more clearly map them to Ditto concepts and terms.

Mapping overview

Concept

Model mapping (Eclipse Vorto)

Runtime mapping (Eclipse Ditto)

Digital twin model

Information Model

Thing definition, referencing the Vorto Information Model.

{
"thingId": "<namespace>:<thing-name>",
"policyId": "<namespace>:<policy-name>",
"definition": "<namespace>:<im-model-name>:<im-model-version>",
"features": {
...
}
}

Declaration which facets a digital twin model contains

Information Model functionblocks names

Separate features of the thing using the declared names from the Information Model functionblocks section as feature IDs.

The optional Function Blocks are also optional features in the thing.
The feature ID for Function Blocks with multiple parameter are prefixed with the name and can be suffixed with a custom part. This custom part has to be separated from the prefix using a ":" (colon) as separator. A best practice for the custom part of sequenced features is to use an index counter starting at 0.

Example:
multiple Temperature as Temperature
would result in feature IDs: Temperature:0, Temperature:1, Temperature:2, ... for sequenced features or Temperature:Top, Temperature:Bottom, ... for other features.

Digital twin facet model

Function Block

Feature definition of a single feature, referencing the Vorto Function Block.
Inheritance of Function Blocks causes multiple definition entries in the feature definition.

{
"definition": [
"<namespace>:<fb-model-name>:<fb-model-version>",
"<namespace>:<fb-model-name>:<fb-model-version>"
],
"properties": {
...
},
"desiredProperties": {
...
}
}

Digital twin facet model properties used for configuring the actual device

Function Block configuration section

The defined configuration properties are contained in the feature properties or desired properties under the "configuration" JSON object:

{
"definition": [ "..." ],
"properties": {
"configuration": {
...
}
},
"desiredProperties": {
"configuration": {
...
}
}
}

Digital twin facet model properties which are updated by the actual device (e.g. sensor readings)

Function Block status section

The defined status properties are contained in the feature properties or desired properties under the "status" JSON object. Desired properties for status do not make much sense, as data in status is always reported data coming from devices.

{
"definition": [ "..." ],
"properties": {
"status": {
...
}
}
}

Digital twin facet model operations which can be invoked on the actual device

Function Block operations section

The defined operations are interpreted as feature messages which are put into the feature's inbox
(message direction is TO the device).

Digital twin facet model events which are emitted by the actual device

Function Block events section

The defined events are interpreted as feature messages which are put into the feature's outbox
(message direction is FROM the device).

Additional restrictions and meta information on single digital twin facet model properties

Function Block property: with attributes
measurementUnit readable writable eventable

The with attributes of a defined Function Block property do not have any meaning to Ditto.

Model datatype mapping

Eclipse Vorto defines built in data types. As Eclipse Ditto uses a JSON based representation of its digital twins, the Vorto data types are mapped to JSON Schema data types.

The used JSON Schema version is: "draft-04".

Vorto type

JSON Schema type

Additional constraints / comments

base64Binary

string

base64 encoded string, has to be decodable with a base64 decoder

boolean

boolean


byte

integer


datetime

string

has to be an ISO 8601 formatted string

double

number


float

number


int

integer


long

number


short

integer


string

string


Custom datatypes which can optionally be defined in Vorto:

Vorto type

JSON Schema type

Additional constraints / comments

entity

object

there is no limit how "deep" entities are nested

enum

string

with defined JSON Schema "enum" values

dictionary

object

does only make sense when the keys of the dictionary can be represented by a string

→ constraint: only primitive types and "enums" may be used as dictionary keys

Digital twin

A digital twin (or thing) is represented by a JSON following a minimal structure/schema to conform to.

The latest JSON Schema of a thing itself is documented here:

A digital twin can contain (all optionally):

  • a definition: defining that the complete thing follows a certain digital twin model

  • attributes: being an arbitrary JSON object of un-modeled state

  • features: each feature consisting of

    • a feature ID

    • an optional feature definition

    • properties: containing either

      • an arbitrary JSON object of untyped JSON fields (if the feature contains no definition)

      • a defined set of JSON fields following the defined definition

Concluding, attributes of a digital twin contain JSON fields which won't follow a defined schema whereas features may optionally follow a defined schema.

Digital twin model

When a digital twin contains a definition, this definition refers to a Vorto Information Model coordinate in the following form:

"<namespace>:<im-model-name>:<im-model-version>"


The Information Model can be looked up at the Vorto repository by using the following URL:

https://github.com/eclipse/vorto/tree/development/models/<namespace>-<im-model-name>-<im-model-version>


"An Information Model describes a complete digital twin, such as a physical device and defines the set of interfaces as Function Blocks, implemented by the digital twin." (source)

By referencing a thing's definition, it is stated that the thing's features follow at least all of the declared Function Blocks from the functionblocks section of the Vorto Information Model.
Additional features, not declared in the thing's definition and the referenced Information Model, may be added to the thing as well.

The definition states that the thing contains at least the defined mandatory Function Blocks declared in the Information Model.

For each included Function Block in the functionblocks section, a digital twin facet (feature in the thing) is expected to be present.

Digital twin facet identifier

The feature ID is derived from the Information Model's functionblocks section.

The ID part (before the keyword as) becomes the feature ID, the case of the identifier as defined in the Information Model is preserved.

It is recommended to use UpperCamelCase notation for the identifiers when creating Vorto Information Models.
As the case is preserved, the resulting feature IDs will also be in UpperCamelCase.


Then the optional keyword is defined, the feature is not required to be present at all.

When the multiple keyword is defined, the feature ID is prefixed with the given ID part (before the keyword as) and optionally suffixed with a a custom part. This custom part has to be separated from the prefix using a ":" (colon) as separator. A best practice for the custom part of sequenced features is to use an index counter starting at 0.

Example:
multiple Temperature as Temperature
would result in feature IDs: Temperature:0, Temperature:1, Temperature:2, ... for a sequenced features or Temperature:Top, Temperature:Bottom, ... for other features.

Digital twin un-modeled state

A Digital twin (thing) may contain state or "metadata" (stored in the thing's attributes) which doesn't follow a schema.
The attributes contain an arbitrary JSON object which's content is completely up to the application making use of the digital twin.

Digital twin "Info" section in un-modeled state

By convention, a JSON object with the key "Info" may be present in the un-modeled (attributes) section of the twin.

The following information is included in this section:

Optional

JSON key

JSON Schema type

Description

X

displayName

string

Short general purpose descriptive name.

X

tags

object

keys: string
values: boolean

Assigned tags of this entity as dictionary of name of the tag to a boolean that expresses if this tag applies.

X

groupPath

string

Path indicating on which nested grouping structure this entity is located in.

Path should start with slash '/' and nested groups are also separated with slash '/'.

X

gateway

boolean

Indication if this device/thing is representing a gateway.

X

gatewayId

string

If this device/thing is not a gateway, then optionally the reference to a gateway device/thing is represented with this property.

Digital twin un-modeled behavior

Operations and events sent to the digital twin or emitted by the digital twin itself (and not to one of its facets / features) - like the attributes - don't follow a schema.
They are not even required to be of "Content-Type" application/json - their Content-Type and payload is completely up to the application making use of the digital twin.

Digital twin facets

A digital twin facet can declare a Function Block model and is represented at runtime by a feature in the thing.
It can consist of:

  • of state (the feature's properties)

  • and behavior in form of

    • operations to send to devices (messages TO a feature)

    • and events which can be emitted by devices (messages FROM a feature)

When a model was specified for a digital twin facet, the feature's properties and its message's payloads follow the defined schema of the model.

Digital twin facet model

When a digital twin facet defines a model (the feature contains a definition), the definition entries refer to Vorto Function Block coordinates in the following form:

<namespace>:<fb-model-name>:<fb-model-version>


The Function Block can be looked up at the Vorto repository by using the following URL:

https://github.com/eclipse/vorto/tree/development/models/<namespace>-<fb-model-name>-<fb-model-version>


"A Function Block describes related capabilities that are implemented by a digital twin. Function Blocks are reusable and can be reused across different Information Models." (source)

The feature definition holds a JSON array of references to Function Blocks with a special semantic regarding the order of the entries:

  • the included Function Block coordinate referenced in the Information Model's functionblocks section as first entry

  • if this Function Block extends another Function Block:

    • all other Function Blocks coordinates up the inheritance hierarchy are added as additional entries in the array

The schema applied to the feature properties is defined by all included Function Block models in the feature's definition array.

Digital twin facet state

When a feature contains a definition (referencing Vorto Function Blocks), the feature's properties and the feature's desiredProperties follow the schema defined in the Function Blocks that they refer to.

A reference implementation, generating the JSON Schema to apply, is provided as part of the Vorto project's Ditto Generator, generating a JSON Schema file in "draft-04" for validating the content of the feature's properties or desiredProperties.

The configuration and status categories of a Function Block are interpreted as 2 JSON objects below the properties or desiredProperties.
If either of the categories are missing from the Function Block, the JSON object must not be present as well in the properties or desiredProperties section:

{
"definition": [ "..." ],
"properties": {
"configuration": {
...
},
"status": {
...
}
},
"desiredProperties": {
"configuration": {
...
}
}
}


The mapping of Function Block Property characteristics to JSON Schema are:

Model ( Function Block Property characteristic)

JSON Schema equivalent

extension

- (not mapped)

mandatory / optional

mandatory properties are added to "required" array

multiple

JSON property is of "type" "array" with its "items" being of the defined Function Block Property type

constraints

MIN
MAX
STRLEN
REGEX
MIMETYPE
SCALING
DEFAULT
NULLABLE

constraints defined in with are mapped to JSON Schema validation keywords:

"minimum"
"maximum"
"maxLength"
"pattern"
- (not mapped)
"multipleOf"
"default"
- (not mapped)

with (property metadata)

readable
writable
measurementUnit

- (not mapped, pure model-metadata)

Digital twin facet behavior

Please have a look at the example thing JSON for details how the mapping is performed.

Digital twin facet behavior

When a digital twin facet follows a model (the feature contains a definition referencing one or multiple Function Blocks ), the messages to send to a feature's inbox and outbox follow the schema defined in the referenced Function Blocks.

When a definition is given, the payloads in the messages is required to be of "Content-Type" application/json as the Function Blocks are translated to a JSON Schema which can be used in order to validate whether the payloads of the inbox / outbox messages and their responses comply to the schema created for the Function Blocks's operations / events.

Digital twin facet operations

Operations are messages which are sent to digital twin facets (e.g. forwarding them to an actual device) and may be responded to with a response.

Function Block operations are mapped to messages with direction to a device (sending a message into the message inbox of a feature).
They can contain parameters (but don't need to) and they can describe a response (but don't need to).

Model ( Function Block operation )

Runtime (Ditto inbox message)

breakable

- (not mapped)

name

message subject

request parameters

Depending on the amount of operation request parameters, the message's payload differs:

Function Block operation with 0 parameters

When 0 parameters are defined, the "payload" of the message must be completely omitted.

Function Block operation with 1 single parameter

When exactly 1 parameter is defined, the parameter's type (either primitive type, entity type or enum type) becomes the complete payload of the message.

The value is the JSON encoded value. Examples:

  • a JSON string has to be quoted: "example-string"

  • a JSON boolean has no to be quoted: true

Function Block operation with > 1 parameters

For operations with more than one parameter, the message payload must be a JSON object.
The parameter names become named JSON keys inside this JSON object, their value being either the parameter's type (either primitive type, entity type or enum type).

With more than one parameter, the order of the parameters will be reflected in a header.

response type

When an operation response is defined, it is handled the same way as the "Operation with 1 single parameter":

When the response type is a primitive type, this primitive value is the expected payload as JSON encoded value. Examples:

  • a JSON string has to be quoted: "example-string"

  • a JSON boolean has no to be quoted: true

When the response type is a entity type, the response value is a JSON object of the JSON structured entity value.

Please have a look at the feature inbox messages examples for details how the mapping is performed.

Digital twin facet events

Events are messages which are emitted by a digital twin facet (e.g. from an actual device) whenever a special situation occurred.

Function Block events are mapped to messages with direction from a device (emitting a message into the messages outbox of a feature).
They can contain properties (but don't need to).

Model ( Function Block event )

Runtime (Ditto outbox message)

name

message subject

properties

The event properties follow the same capabilities as the operations/status properties.

The event name is not part of the payload.

Function Block event with 0 properties

When 0 properties are defined, the payload of the message must be completely omitted.

Function Block event with 1 property

When exactly 1 property is defined, the property's type (either primitive type, entity type or enum type) becomes the complete payload of the message.

The value is the JSON encoded value. Examples:

  • a JSON string has to be quoted: "example-string"

  • a JSON boolean has no to be quoted: true

Function Block event with >1 properties

For events with more than one property, the JSON mapping is the same as for configuration/status.

With more than one property, the order of the properties will be reflected in a header.

Please have a look at the feature outbox messages examples for details how the mapping is performed.

Facet operation and event parameter order

When processing messages in the digital twin layer, the header x-things-parameter-order is set to the order of the parameters in a received message JSON payload.

Alternatively, the application/device sending the operation or event may also specify this header in order to clearly indicate in which order the parameters were set.

This is done because JSON itself does not specify that the order of JSON fields has to be preserved, however implementations may rely on the order e.g. to determine expected type of the first parameter.

Please have a look here for more details: FAQ > Message payload need to follow a specific order.

Facet operation and event errors

Errors as a result to messages are not modeled in Eclipse Vorto Function Block operations or events.

If sending a message to a digital twin facet leads to an error, the Ditto error JSON format must be sent back as payload of the response message.

Ditto itself uses defined prefixes for its error codes, it is suggested to define another custom prefix for own error codes.

Example

This section contains an example:

  • a Vorto Information Model including several Function Blocks

  • a Ditto thing JSON representation to the payload of messages, all derived from the underlying Vorto model

Example Vorto Information Model

An example Information Model and Function Blocks were created in the org.eclipse.ditto.examples namespace in the Vorto repository in order to show how all supported Vorto concepts are mapped to Ditto things and messages.

The example Information Model is a quite mighty lamp which contains several status lamp indicators, a dimmable lamp and a lamp capable of changing its colors. In addition it is capable of detecting smoke.

Information Model : MightyLamp

Example digital twin model instance

Example thing JSON

The following JSON is an example for a digital twin instance following the Information Model for MightyLamp (listed above).

{
"thingId": "org.eclipse.ditto:my-mighty-lamp",
"policyId": "org.eclipse.ditto:my-policy",
"definition": "org.eclipse.ditto.examples:MightyLamp:2.0.0",
"attributes": {
"Info": {
"displayName": "My mighty lamp in living room",
"tags": {
"searchable": true
},
"groupPath": "/myhouse/basefloor/livingroom",
"gateway": false,
"gatewayId": "org.eclipse.ditto:my-mighty-gateway"
}
},
"features": {
"ConnectionStatus": {
"definition": [
"org.eclipse.ditto:ConnectionStatus:1.0.0"
],
"properties": {
"status": {
"readySince": "2020-07-21T08:39:00Z",
"readyUntil": "2020-07-21T08:50:00Z"
}
}
},
"StatusLamp0": {
"definition": [
"org.eclipse.ditto.examples:SwitchableLamp:1.0.0",
"org.eclipse.ditto.examples:Switchable:1.0.0"
],
"properties": {
"configuration": {
"on": true,
"bulbChangeDate": "2020-04-01T16:42:23Z",
"reportCurrentPowerConsumption": true,
"currentPowerConsumptionInterval": 30
},
"status": {
"currentPowerConsumption": 0.032
}
}
},
"StatusLamp1": {
"definition": [
"org.eclipse.ditto.examples:SwitchableLamp:1.0.0",
"org.eclipse.ditto.examples:Switchable:1.0.0"
],
"properties": {
"configuration": {
"on": false,
"bulbChangeDate": "2020-04-01T16:42:23Z",
"reportCurrentPowerConsumption": true,
"currentPowerConsumptionInterval": 30
},
"status": {
"currentPowerConsumption": 0.038
}
}
},
"StatusLamp2": {
"definition": [
"org.eclipse.ditto.examples:SwitchableLamp:1.0.0",
"org.eclipse.ditto.examples:Switchable:1.0.0"
],
"properties": {
"configuration": {
"on": false,
"bulbChangeDate": "2020-01-01T10:05:55Z",
"reportCurrentPowerConsumption": true,
"currentPowerConsumptionInterval": 30
},
"status": {
"currentPowerConsumption": 0.03
}
}
},
"Dimmed": {
"definition": [
"org.eclipse.ditto.examples:DimmableLamp:1.0.0",
"org.eclipse.ditto.examples:Dimmable:1.0.0",
"org.eclipse.ditto.examples:Switchable:1.0.0"
],
"properties": {
"configuration": {
"on": true,
"dimmerLevel": 0.88,
"bulbChangeDate": "2020-02-11T18:39:04Z",
"reportCurrentPowerConsumption": true,
"currentPowerConsumptionInterval": 30
},
"status": {
"currentPowerConsumption": 0.0489
}
}
},
"Colored": {
"definition": [
"org.eclipse.ditto.examples:ColorableLamp:1.0.0",
"org.eclipse.ditto.examples:Colorable:1.0.0",
"org.eclipse.ditto.examples:Switchable:1.0.0"
],
"properties": {
"configuration": {
"on": true,
"color": {
"r": 200,
"g": 0,
"b": 120
},
"bulbChangeDate": "2020-02-11T18:39:04Z",
"reportCurrentPowerConsumption": true,
"currentPowerConsumptionInterval": 30
},
"status": {
"currentPowerConsumption": 0.0489
}
}
},
"SmokeDetection": {
"definition": [
"org.eclipse.ditto.examples:SmokeDetector:1.0.0"
],
"properties": {
}
}
}
}

Example digital twin facet model operations

Feature inbox messages follow the defined Function Block operations.

The Colorable Function Block defines operations in all possible variants.
This section shows valid example payloads for the defined operations.

Function Block operation signature

Example Ditto HTTP API call

Example Ditto Protocol message

red(
r as int <MIN 0, MAX 255>
) returns Color


Request params: 1 primitive parameter

Response type: entity/object parameter

Path:

POST /api/2/things/org.eclipse.ditto:my-mighty-lamp
/features/Colored/inbox/messages/red

Request payload:

123

Response payload:

{
"r": 123,
"g": 255,
"b": 100
}

Request message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/red",
"headers": {
"content-type": "application/json",
"correlation-id": "0815"
},
"path": "/features/Colored/inbox/messages/red",
"value": 123
}

Response message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/red",
"headers": {
"content-type": "application/json",
"correlation-id": "0815"
},
"path": "/features/Colored/inbox/messages/red",
"value": {
"r": 123,
"g": 255,
"b": 100
},
"status": 200
}

Error message (this is an example where the device sends back an error with error code "device:value.out.of.range"):

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/red",
"headers": {
"content-type": "application/json",
"correlation-id": "0815"
},
"path": "/features/Colored/inbox/messages/red",
"value": {
"status": 400,
"error": "device:value.out.of.range",
"message": "The value <123> of the invoked 'red' operation was out of the range this device supports.",
"description": "Please keep the value inside the bounds of 0-100"
},
"status": 400
}

rgb( r as int <MIN 0, MAX 255>, g as int <MIN 0, MAX 255>, b as int <MIN 0, MAX 255>) returns Color


Request params: 3 primitive parameters

Response type: entity/object parameter

Path:

POST /api/2/things/org.eclipse.ditto:my-mighty-lamp
/features/Colored/inbox/messages/rgb

Request payload:

{
"r": 33,
"g": 44,
"b": 55
}

Response payload:

{
"r": 33,
"g": 44,
"b": 55
}

Request message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/rgb",
"headers": {
"content-type": "application/json",
"correlation-id": "0816"
},
"path": "/features/Colored/inbox/messages/rgb",
"value": {
"r": 33,
"g": 44,
"b": 55
}
}

Response message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/rgb",
"headers": {
"content-type": "application/json",
"correlation-id": "0816"
},
"path": "/features/Colored/inbox/messages/rgb",
"value": {
"r": 33,
"g": 44,
"b": 55
},
"status": 200
}

retrieveRed() returns int <MIN 0, MAX 255>


Request params: -

Response type: primitive parameter

Path:

POST /api/2/things/org.eclipse.ditto:my-mighty-lamp
/features/Colored/inbox/messages/retrieveRed

Request payload: -

Response payload:

33

Request message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/retrieveRed",
"headers": {
"content-type": "application/json",
"correlation-id": "0817"
},
"path": "/features/Colored/inbox/messages/retrieveRed"
}

Response message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/retrieveRed",
"headers": {
"content-type": "application/json",
"correlation-id": "0817"
},
"path": "/features/Colored/inbox/messages/retrieveRed",
"value": 33,
"status": 200
}

gradientFadeToColor( targetColor as Color)


Request params: 1 entity/object parameter

Response type: -

Path:

POST /api/2/things/org.eclipse.ditto:my-mighty-lamp
/features/Colored/inbox/messages/gradientFadeToColor

Request payload:

{
"r": 255,
"g": 255,
"b": 255
}

Response payload: -

Request message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/gradientFadeToColor",
"headers": {
"content-type": "application/json",
"correlation-id": "0818"
},
"path": "/features/Colored/inbox/messages/gradientFadeToColor",
"value": {
"r": 255,
"g": 255,
"b": 255
}
}

Response message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/gradientFadeToColor",
"headers": {
"content-type": "application/json",
"correlation-id": "0818"
},
"path": "/features/Colored/inbox/messages/gradientFadeToColor",
"status": 204
}

gradientColorChangeDuringInterval( startingColor as Color, targetColor as Color, interval as Duration)


Request params: 3 entity/object parameters

Response type: -

Path:

POST /api/2/things/org.eclipse.ditto:my-mighty-lamp
/features/Colored/inbox/messages/gradientColorChangeDuringInterval

Request payload:

{
"startingColor": {
"r": 0,
"g": 0,
"b": 0
},
"targetColor": {
"r": 255,
"g": 255,
"b": 255
},
"duration": {
"amount": 20,
"unit": "s"
}
}

Response payload: -

Request message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/gradientColorChangeDuringInterval",
"headers": {
"content-type": "application/json",
"correlation-id": "0819"
},
"path": "/features/Colored/inbox/messages/gradientColorChangeDuringInterval",
"value": {
"startingColor": {
"r": 0,
"g": 0,
"b": 0
},
"targetColor": {
"r": 255,
"g": 255,
"b": 255
},
"duration": {
"amount": 20,
"unit": "s"
}
}
}

Response message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/gradientColorChangeDuringInterval",
"headers": {
"content-type": "application/json",
"correlation-id": "0819"
},
"path": "/features/Colored/inbox/messages/gradientColorChangeDuringInterval",
"status": 204
}

Example digital twin facet model events

Feature outbox messages follow the Function Block events that are already defined.

The SmokeDetector Function Block defines events in different variants.
This section shows valid example payloads for the defined events.

Function Block event signature

Example Ditto HTTP API call

Example Ditto Protocol message

smokeDetected { mandatory priority as Priority mandatory density as float mandatory timestamp as dateTime }

Path:

POST /api/2/things/org.eclipse.ditto:my-mighty-lamp
/features/SmokeDetection/outbox/messages/smokeDetected

Request payload:

{
"priority": "high",
"density": 0.8,
"timestamp": "2020-07-21T16:42:00Z"
}

Message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/red",
"headers": {
"content-type": "application/json"
},
"path": "/features/SmokeDetection/outbox/messages/smokeDetected",
"value": {
"priority": "high",
"density": 0.8,
"timestamp": "2020-07-21T16:42:00Z"
}
}

smokeCleared { mandatory timestamp as dateTime }

Path:

POST /api/2/things/org.eclipse.ditto:my-mighty-lamp
/features/SmokeDetection/outbox/messages/smokeCleared

Request payload:

"2020-07-21T16:42:00Z"

Message:

{
"topic": "org.eclipse.ditto/my-mighty-lamp/things/live/messages/smokeCleared",
"headers": {
"content-type": "application/json"
},
"path": "/features/SmokeDetection/outbox/messages/smokeCleared",
"value": "2020-07-21T16:42:00Z"
}