This is a Kotlin implementation of a digital adapter that allows interaction to the digital twin as a Web of Things (WoT) Thing.
// Example of a Servient with HTTP and MQTT binding from library kotlin-wot
val mqttExposerConfig = MqttClientConfig("localhost", 61890, "exposer-0")
val port = 8080
val baseUrl = "http://localhost:${port}"
val exposingServient = Servient(
servers = listOf(
HttpProtocolServer(bindPort = port, baseUrls = listOf(baseUrl)),
MqttProtocolServer(mqttExposerConfig)
)
)
val config = WoTDigitalAdapterConfiguration(
servient = exposingServient,
thingId = "temperature-sensor-0",
thingTitle = "temperature sensor",
description = "A temperature sensor with humidity reading and reset/setTemperature actions",
observableProperties = setOf("temperature-property-key"),
//allPropertiesObservable = true,
)
val woTDigitalAdapter = WoTDigitalAdapter("digital-adapter-0", config) val thingId = woTDigitalAdapter.thingId
val thingDescription = woTDigitalAdapter.getThingDescription().toJson() // adapter need to be fully started
val thingUrl = "${baseUrl}/${thingId}"From
DigitalTwinStateProperty(
key = 'temperature-property-key',
value = TemperaturePropertyObject(23.5, 14, listOf(false, false, false)),
type='physical.TemperaturePropertyObject',
readable=true,
writable=true,
exposed=true
)To Thing Description
{
"properties": {
"temperature-property-key": {
"type": "object",
"forms": [
{
"href": "mqtt://localhost:61890/temperature-sensor-0/properties/temperature-property-key",
"contentType": "application/json",
"op": [
"readproperty",
"writeproperty"
]
},
{
"href": "mqtt://localhost:61890/temperature-sensor-0/properties/temperature-property-key/observable",
"contentType": "application/json",
"op": [
"observeproperty",
"unobserveproperty"
]
},
{
"href": "http://localhost:8080/temperature-sensor-0/properties/temperature-property-key",
"contentType": "application/json",
"op": [
"readproperty",
"writeproperty"
],
"optionalProperties": {
"htv:methodName": ""
}
},
{
"href": "http://localhost:8080/temperature-sensor-0/properties/temperature-property-key/observable",
"contentType": "application/json",
"subprotocol": "longpoll",
"op": [
"observeproperty",
"unobserveproperty"
]
}
],
"observable": true,
"properties": {
"temperature": {
"type": "number"
},
"hour": {
"type": "integer"
},
"alarms": {
"type": "array",
"items": {
"type": "boolean"
}
}
},
"default": {
"temperature": 0.0,
"hour": 0,
"alarms": [
false,
false,
false
]
}
}
}
}From
DigitalTwinStateAction(
key='set-temperature-action-key',
type='temperature.actuation',
contentType='text/plain', exposed=true
)To Thing Description
{
"actions": {
"set-temperature-action-key": {
"forms": [
{
"href": "mqtt://localhost:61890/temperature-sensor-0/actions/set-temperature-action-key",
"contentType": "application/json",
"op": [
"invokeaction"
]
},
{
"href": "http://localhost:8080/temperature-sensor-0/actions/set-temperature-action-key",
"contentType": "application/json",
"op": [
"invokeaction"
]
}
],
"@type": "temperature.actuation",
"input": {
"type": "string"
}
}
}
}NOTE: Serialization of collection or object type input is not supported, Use string instead.
From
DigitalTwinStateEvent(
key='overheating-event-key',
type='text/plain'
)To Thing Description
{
"events": {
"overheating-event-key": {
"@type": "text/plain",
"forms": [
{
"href": "mqtt://localhost:61890/temperature-sensor-0/events/overheating-event-key",
"contentType": "application/json",
"op": [
"subscribeevent",
"unsubscribeevent"
],
"optionalProperties": {
"mqtt:qos": 0,
"mqtt:retain": false
}
},
{
"href": "http://localhost:8080/temperature-sensor-0/events/overheating-event-key",
"contentType": "application/json",
"subprotocol": "longpoll",
"op": [
"subscribeevent"
]
}
]
}
}
}Web of Things Thing Description does not have a direct mapping for Digital Twin Relationships. So they are represented as read-only properties with complex object types. With this solution the name of the relation is the only information available in the TD, the remaining fields must be accessed by reading the property.
DigitalTwinStateRelationship(
name='insideIn',
type='insideIn',
instances={ physical.asset.relationship.insideIn.building-hq=DigitalTwinStateRelationshipInstance(
relationshipName='insideIn',
targetId='building-hq',
instanceKey='physical.asset.relationship.insideIn.building-hq',
metadata={}
)}
)To Thing Description
{
"properties": {
"insideIn": {
"type": "object",
"forms": [[ {}, {} ]],
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"instances": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"targetId": {
"type": "string"
},
"targetType": {
"type": "string"
},
"attributes": {
"type": "object"
}
}
}
}
},
"readOnly": true
}
}
}