Vorto Language for Digital Twins
October 30, 2020 ยท View on GitHub
Version 1.0
Contents
Information Model
Function Block
Properties
Event
Operation
Primitive Types
Enum
Dictionary
Entity
Model Property
Function Block Mapping
Introduction
This document specifies the Vorto Language (vortolang 1.0), a language for describing models and interfaces for IoT Digital Twins. Digital twins are models of entities in the physical world such as a (multi) sensor device, smart power plant, and other entities that participate in IoT solutions. Modeling enables IoT solutions and IoT platforms to provision, use, and configure IoT devices and logical entities from multiple sources in a single solution. Using the vortolang and describing the entities's capabilities, IoT platforms and IoT solutions can leverage the semantics of these IoT entities.
Digital Twin Vorto Language
Digital twins are described using the vortolang, which is domain-specific language (DSL). This DSL underlies a very simple grammar, making it very easy to describe digital twin models. In order to be used in IoT Platforms and solutions, the vortolang can easily be converted into well adopted languages, such as JSON-LD, where additional context-specific attributes can be added. Many (free) libraries are available to process these language files. At definition time, developers can use the vortolang without any knowledge about JSON-LD or others, and fully focus on describing the device capabilities in a very expressive way.
The vortolang is made up of a set of metamodel classes (described later in more detail) that define the capabilities of digital twins. There are two top-level classes, Information Model and Function Block, that describe a digital twin and the capabilities of digital twins, respectively. There are three metamodel classes that describe capabilities: Properties, Events, and Operations.
When writing a digital twin definition, it's necessary to specify the version of the vortolang being used (currently 1.0)
Information Models and Function Blocks
There are two top-level metamodel classes: Information Model and Function Block. Information Models describe a complete digital twin, such as a physical device. Often, Information Models are associated with a specific device product, such as a "Bosch Dinion IP Starlight 8000MP" security camera, while Function Blocks describe the related capabilities of an digital twin (its status- and configuration properties, events, and operations). Function Blocks can be reused across different Information Models. Information Models are often made up of multiple Function Blocks (interfaces).
Information Model
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.
Information Model properties
| Keyword | Required | Data type | Description |
|---|---|---|---|
| vortolang | required | string | Identifies which vortolang version used to define the Information Model. Currently '1.0' |
| namespace | required | string |
The name must match the regular expression:
name('.' name )*
|
| version | required | string |
The name must match the regular expression:
/^\d+\.\d+\.\d+(-\\w+)*$/
|
| displayname | optional | string | a name of the information model for human display |
| description | optional | string | A description for human display. |
| category | optional | string |
Custom tag to categorize the model, e.g. sensor, smarthome/kitchen etc. The name must match the regular expression: name('/' name )*
|
| using | required | A set of Model References |
Defines the imported models that are referenced by this Information Model under 'functionblocks' |
| infomodel | required | string |
The name must match the regular expression:
^[A-Z][a-zA-Z0-9]*$
|
| functionblocks | required | A set of Model Property of type Function Block |
A set of Function Block properties. |
BNF (Backus normal form)
InformationModel:
'vortolang' 1.0
'namespace' qualifiedName
'version' version
('displayname' string)?
('description' string)?
('category' ID('/' ID)*)?
(modelReference)*
'infomodel' ID '{'
'functionblocks' '{'
(functionblockProperty)*
'}'
;
functionblockProperty:
('mandatory' | 'optional')? ('multiple')? ID 'as' [FunctionBlock::ID | qualifiedName] (description)?
qualifiedName:
NamespaceID ('.' NamespaceID)*;
NamespaceID:
ID | REUSABLEKEYWORD;
KEYWORD:
NONREUSABLEKEYORD | REUSABLEKEYWORD;
NONREUSABLEKEYORD:
'dateTime' | 'functionblocks' | 'infomodel' | 'mandatory' | 'namespace' | 'optional' |
'version' | 'dictionary' | 'extension' | 'functionblock';
REUSABLEKEYWORD:
'fault' | 'status' | 'events' | 'operations' | 'breakable' | 'category' | 'configuration' |
'description';
version : int('.' int)*('-'ID)?;
ID:
'^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
;
description: STRING
modelReference:
'using' qualifiedName ';' version;
Example:
vortolang 1.0
namespace com.mycompany
version 1.0.0
description "Information model for FabLab.eu's IoT Octopus"
category multisensor
using com.ipso.smartobjects.Accelerometer ; 1.1.0
using com.ipso.smartobjects.Barometer ; 1.1.0
infomodel IoTOctopus {
functionblocks {
mandatory accelerometer as Accelerometer "some description"
optional barometer as Barometer
}
}
Function Block
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.
Function Block properties
| Keyword | Required | Data type | Description |
|---|---|---|---|
| vortolang | required | string | Identifies which vortolang version used to define the Function Block. Currently '1.0' |
| namespace | required | string |
The name must match the regular expression:
name('.' name )*
|
| version | required | string |
The name must match the regular expression:
/^\d+\.\d+\.\d+(-\\w+)*$/
|
| displayname | optional | string | a name of the information model for human display |
| description | optional | string | A description for human display. |
| category | optional | string |
Custom tag to categorize the model, e.g. sensor, smarthome/kitchen etc. The name must match the regular expression: name('/' name )*
|
| using | required | A set of Model References |
Defines the imported models that are referenced by this Information Model under 'functionblocks' |
| functionblock | required | string |
The name must match the regular expression:
^[A-Z][a-zA-Z0-9]*$
|
| extends | optional | ID of a Function Block |
Extends another Function Block by specializing it with extended properties
|
| configuration | optional | Configuration Properties |
An object describing configuration Properties. Configuration properties are read-writable by default.
|
| status | optional | Status Properties |
An object describing status Properties. Status properties are read-only by default.
|
| events | optional | a set of Events |
Describes data emitted by a device or other entity |
| operations | optional | a set of Operations |
Describes functions that can be performed on the device or entity. |
BNF (Backus normal form)
FunctionBlock:
'vortolang' 1.0
'namespace' qualifiedName
'version' version
('displayname' string)?
('description' string)?
('category' ID('/' ID)*)?
(modelReference)*
'functionblock' ID ('extends' [Functionblock::ID | qualifiedName])? '{'
('configuration' '{'
(Property)*
'}')?
('status' '{'
(Property)*
'}')?
('events' '{'
(ID '{'
(Property)*
'}')*
'}')?
('operations' '{'
(Operation)*
'}')?
'}'
;
qualifiedName:
NamespaceID ('.' NamespaceID)*;
NamespaceID:
ID | REUSABLEKEYWORD;
KEYWORD:
NONREUSABLEKEYORD | REUSABLEKEYWORD;
NONREUSABLEKEYORD:
'dateTime' | 'functionblocks' | 'infomodel' | 'mandatory' | 'namespace' | 'optional' |
'version' | 'dictionary' | 'extension' | 'functionblock';
REUSABLEKEYWORD:
'fault' | 'status' | 'events' | 'operations' | 'breakable' | 'category' | 'configuration' |
'description';
version : int('.' int)*('-'ID)?;
ID: '^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
modelReference: 'using' qualifiedName ';' version;
description: STRING
Property: Please refer to chapter Model Property for details
Operation:
('extension')? ('mandatory' | 'optional')? ('breakable')? ID '(' (OperationType (',' OperationType)*)?')' ('returns' OperationType)? (description)?;
OperationType: DictonaryOperationType | OperationPrimitiveType | OperationObjectType;
DictonaryOperationType:
('multiple')? ID 'as' DictionaryType ('<' ConstraintRule '>')? (description)?;
OperationPrimitiveType: ('multiple')? ID 'as' PrimitiveType ('<' ConstraintRule '>')? (description)?;
OperationObjectType: ('multiple')? ID 'as' ObjectType (description)?;
Example:
vortolang 1.0
namespace com.mycompany
version 1.0.0
functionblock Accelerometer {
configuration {
mandatory enable as boolean
}
status {
mandatory xValue as float "The measured value along the X axis."
optional yValue as float "The measured value along the Y axis."
optional zValue as float "The measured value along the Z axis."
}
operations {
reset() returns boolean "resets the accelerometer"
}
}
Properties
Properties describe both read-only and read-write state of a digital twin. Read-only properties are defined as status properties, whereas read-write properties as configuration properties. For example, a device serial number may be a status property and the temperature set point on a thermostat may be a configuration property.
Function Block property is defined as a Model Property
Status Property Example
functionblock Thermostat {
...
status {
mandatory serialNumber as string
}
}
Configuration Property Example
functionblock Thermostat {
...
configuration {
optional temperature as float <MIN 0, MAX 35> "writable temperature with a range constraint"
mandatory enable as boolean "enables the sensor to start sending data"
}
}
Event
Events define data that is emitted by the device or entity. This kind of data would need to be transmitted to an IoT business solution in a reliable way.
An Event property is defined as a Model Property
Event Example
functionblock Geolocation {
...
events {
enterFence {
entryPoint as Location3D
timestamp as dateTime
}
leaveFence {
exitPoint as Location3D
timestamp as dateTime
}
}
}
Operation
An operation represents a function that can be performed on a Digital Twin. Operations may have request params as well as a return type
| Keyword | Required | Description |
|---|---|---|
| breakable | Optional | Signals, that it could eventually cause an error when performing the operation on the device |
| operation name | required | Name of the operation |
| request params | optional | request params, separated by , |
| response type | optional | Specifies a response of the operation. Response type must comply to Data Type |
| description | optional | A description for human display |
Example
op() "A simple operation without request and response types"
breakable op() "An operation that could cause an error when performed"
op() returns int "Operation that returns a primitive type"
op() returns multiple int "Operation that returns an array of a primitive type"
op(msg as string) "Operation with a single primitive param"
op(multiple msg as string "msg description") "array param with description"
op(msg as int <MIN 0, MAX 100>) "Param with constraint"
Data Types
Primitive Types
A full set of primitive data types are provided and can be specified directly as a type value of a model property.
| Primitive Schema | Description |
|---|---|
| boolean | a boolean value |
| dateTime | A date and time in ISO 8601 format |
| double | An IEEE 8-byte floating point number |
| float | An IEEE 4-byte floating point number |
| int | A signed 4-byte integer |
| long | A signed 8-byte integer |
| string | A UTF8 string |
| base64Binary | Represents an arbitrary binary content |
| base64Binary | Represents an arbitrary binary content |
| short | A short 16-bit integer between -32768 and 32767 |
| byte | A 8-bit integer between -128 and 127 |
Enum
An enum is an enumeration of values of the same type similar to an enum in Java.
| Keyword | Required | Data type | Description |
|---|---|---|---|
| vortolang | required | string | Identifies which vortolang version used to define the Enumeration. Currently '1.0' |
| namespace | required | string |
The name must match the regular expression:
name('.' name )*
|
| version | required | string |
The name must match the regular expression:
/^\d+\.\d+\.\d+(-\\w+)*$/
|
| displayname | optional | string | a name of the enumeration model for human display |
| description | optional | string | A description for human display. |
| category | optional | string |
Custom tag to categorize the model, e.g. sensor, smarthome/kitchen etc. The name must match the regular expression: name('/' name )*
|
| literal | required | a set of literal values |
Multiple literal values are separated by ,
It must match the regular expression:
('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
| literal description | optional | string | A description for human display. |
BNF (Backus normal form)
Enumeration:
'vortolang' 1.0
'namespace' qualifiedName
'version' version
('displayname' string)?
('description' string)?
('category' ID('/' ID)*)?
'enum' ID '{'
(enumLiteral) (',' enumLiteral)*
'}'
;
qualifiedName:
NamespaceID ('.' NamespaceID)*;
NamespaceID:
ID | REUSABLEKEYWORD;
KEYWORD:
NONREUSABLEKEYORD | REUSABLEKEYWORD;
NONREUSABLEKEYORD:
'dateTime' | 'functionblocks' | 'infomodel' | 'mandatory' | 'namespace' | 'optional' |
'version' | 'dictionary' | 'extension' | 'functionblock';
REUSABLEKEYWORD:
'fault' | 'status' | 'events' | 'operations' | 'breakable' | 'category' | 'configuration' |
'description';
version : int('.' int)*('-'ID)?;
ID: '^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
description: STRING
enumLiteral: ID (description)?
Example
vortolang 1.0
namespace com.mycompany
version 1.0.0
enum Unit {
kg "Kilogram unit" ,
g "gram unit"
}
Entity
| Keyword | Required | Data type | Description |
|---|---|---|---|
| vortolang | required | string | Identifies which vortolang version used to define the Enumeration. Currently '1.0' |
| namespace | required | string |
The name must match the regular expression:
name('.' name )*
|
| version | required | string |
The name must match the regular expression:
/^\d+\.\d+\.\d+(-\\w+)*$/
|
| displayname | optional | string | a name of the enumeration model for human display |
| description | optional | string | A description for human display. |
| category | optional | string |
Custom tag to categorize the model, e.g. sensor, smarthome/kitchen etc. The name must match the regular expression: name('/' name )*
|
| using | required | A set of Model References |
Defines the imported models that are referenced by this Entity |
| extends | optional | Entity name |
Expresses inheritance of entities |
| properties | optional | A set of Model Property elements |
A set of Model Property elements
|
BNF (Backus normal form)
Entity:
'vortolang' 1.0
'namespace' qualifiedName
'version' version
('displayname' string)?
('description' string)?
('category' ID('/' ID)*)?
(modelReference)*
'entity' ID ('extends' [Entity::ID | qualifiedName])? '{'
(property)*
'}'
;
qualifiedName:
NamespaceID ('.' NamespaceID)*;
NamespaceID:
ID | REUSABLEKEYWORD;
KEYWORD:
NONREUSABLEKEYORD | REUSABLEKEYWORD;
NONREUSABLEKEYORD:
'dateTime' | 'functionblocks' | 'infomodel' | 'mandatory' | 'namespace' | 'optional' |
'version' | 'dictionary' | 'extension' | 'functionblock';
REUSABLEKEYWORD:
'fault' | 'status' | 'events' | 'operations' | 'breakable' | 'category' | 'configuration' |
'description';
version : int('.' int)*('-'ID)?;
ID: '^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
modelReference: 'using' qualifiedName ';' version;
description: STRING
Property: Please refer to chapter Model Property for details
Example
vortolang 1.0
namespace com.mycompany
version 1.0.0
entity Color {
mandatory red as int <MIN 0, MAX 255> "The red component of a color"
mandatory green as int <MIN 0, MAX 255> "The green component of a color"
mandatory blue as int <MIN 0, MAX 255> "The blue component of a color"
}
Dictionary
A dictionary describes values in a map.
Example
mandatory lookupTable as dictionary[string, Color] "Lookup table conversion for color"
mandatory lookupRGBTable as dictionary[Color, RGB] "Lookup table conversion for color from description to RGB"
mandatory temperatureLabelConversion as dictionary[int, string] "map of temperature to description"
mandatory simpleMap as dictionary "example of a map with no key and value types"
Model Property
A model property can be used by events, function block properties or entities.
| Keyword | Required | Description |
|---|---|---|
| extension | optional | Indicates that the property is extended from a supertype with additional meta data |
| mandatory or optional | optional | Whether the property is mandatory or optional. Default is optional. |
| multiple | optional | Indicates if the property is an array type |
| with | optional | additional meta - data about the property, such as measurementUnit or if the property is readable or writable |
BNF (Backus normal form)
Property:
('extension')? ('mandatory] | 'optional')? ('multiple')? ID 'as' PropertyType
('with' '{' PropertyAttribute (',' PropertyAttribute)* '}')?
('<' ConstraintRule '>')?
(description=STRING)?
;
PropertyType: ObjectType | PrimitiveType | DictionaryType;
ObjectType: [Type::ID | qualifiedName];
PrimitiveType:
'string' | 'int' | 'float' | 'boolean' | 'dateTime' | 'double' | 'long' | 'short' |'base64Binary' | 'byte';
DictionaryType: 'dictionary' ('['PropertyType ',' PropertyType ']')?
PropertyAttribute: BooleanPropertyAttribute | EnumLiteralPropertyAttribute;
BooleanPropertyAttribute: ('readable' | 'writable') ':' ('true' | 'false');
EnumLiteralPropertyAttribute: 'measurementUnit' ':' [Enum::ID | QualifiedName];
Constraint: ('MIN' | 'MAX' | 'STRLEN' | 'REGEX' | 'MIMETYPE' | 'SCALING' | 'DEFAULT' | 'NULLABLE') IntervalType;
IntervalType: INT | SIGNEDINT | FLOAT | DATETIME | STRING | BOOLEAN;
Example
Consider the following Enum which defines some Temperature Units
vortolang 1.0
namespace org.example
version 1.0.0
displayname "TemperatureUnits"
description "Datatype for TemperatureUnits"
enum TemperatureUnits {
Kelvin "Degree Kelvin" ,
Celsius "Degree Celsius",
Fahrenheit "Degree Fahrenheit"
}
Then we can reference the measurement unit in a property as follows:
vortolang 1.0
namespace org.example
version 1.0.0
displayname "Test FB"
description "Functionblock for Example"
using org.example.TemperatureUnits;1.0.0
functionblock TestMu {
status {
temperature as float with {
measurementUnit: org.example.TemperatureUnits.Kelvin
}
}
}
Note, in the example above we also say that the propery is readable.
Function Block Mapping
A Function Block Mapping describes a mapping of a Function Block and its properties for a specific platform.
BNF (Backus Normal Form)
'vortolang' 1.0
'namespace' qualifiedName
'version' version
('displayname' string)?
('description' string)?
('category' ID('/' ID)*)?
(modelReference)*
'functionblockmapping' ID '{'
'targetplatform' ID
(MappingInstruction)*
'}'
;
ID: '^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
version : int('.' int)*('-'ID)?;
qualifiedName:
NamespaceID ('.' NamespaceID)*;
NamespaceID:
ID | REUSABLEKEYWORD;
KEYWORD:
NONREUSABLEKEYORD | REUSABLEKEYWORD;
NONREUSABLEKEYORD:
'dateTime' | 'functionblocks' | 'infomodel' | 'mandatory' | 'namespace' | 'optional' |
'version' | 'dictionary' | 'extension' | 'functionblock';
REUSABLEKEYWORD:
'fault' | 'status' | 'events' | 'operations' | 'breakable' | 'category' | 'configuration' |
'description';
modelReference: 'using' qualifiedName ';' version;
MappingInstruction: 'from' ID to ID 'with '{' MappingProperty (',' MappingProperty)* '}'
MappingProperty: ID ':' '"'string'"'