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) |
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" : { ... } } |
|
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. Example: |
|
Function Block |
Feature definition of a single feature, referencing the Vorto Function Block. { "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 |
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 |
Additional restrictions and meta information on single digital twin facet model properties |
Function Block
property:
with
attributes |
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
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 |
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
|
constraints defined in with are mapped to JSON Schema validation keywords: "minimum" |
with (property metadata) readable |
- (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:
Function Block operation with > 1 parameters For operations with more than one parameter, the message payload must be a JSON object. 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:
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:
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
Function Block : ConnectionStatus
Function Block : SwitchableLamp extends Switchable
Function Block : DimmableLamp extends Dimmable extends Switchable
Function Block : ColorableLamp extends Colorable extends Switchable
Function Block : SmokeDetector
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( 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" } |