Version 1.0
Information Model
Function Block
Properties
Event
Operation
Primitive Types
Enum
Dictionary
Entity
Model Property
Function Block Mapping
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 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
)
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).
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.
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 Reference s |
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. |
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;
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
}
}
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.
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 Reference s |
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 Event s |
Describes data emitted by a device or other entity |
operations | optional | a set of Operation s |
Describes functions that can be performed on the device or entity. |
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)?;
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 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
functionblock Thermostat {
...
status {
mandatory serialNumber as string
}
}
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"
}
}
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
functionblock Geolocation {
...
events {
enterFence {
entryPoint as Location3D
timestamp as dateTime
}
leaveFence {
exitPoint as Location3D
timestamp as dateTime
}
}
}
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 |
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"
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 |
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. |
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)?
vortolang 1.0
namespace com.mycompany
version 1.0.0
enum Unit {
kg "Kilogram unit" ,
g "gram unit"
}
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 Reference s |
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
|
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
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"
}
A dictionary describes values in a map.
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"
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 |
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;
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.
A Function Block Mapping describes a mapping of a Function Block and its properties for a specific platform.
'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'"'