ABB Warmstorage
Introduction
ABB Warmstorage refers to the Edgenius application that consists of ABB Ability™ database and interfacing software components. TSAPI (or TSModule) is the non-persistent edge module built for ABB Ability Platform, with the purpose of serving as an abstraction layer on top of ABB Ability™ History database. The component's main responsibility is collecting timeseries data through MQTT protocol, and writing the data to the database. In addition, the component exposes a web endpoint for the purpose of data retrieval, which is built as close as possible to the pre-existing Data Access Service on the ABB Ability Cloud. The combination of this module and database, can serve as a local storage on Edge.
This component is designed in a way that it does not store any data on its own, and it does not hold any state; In other words, after the initial deployment, it can be restarted if needed, and unlikely crashes would not cause any issues to the system as a whole. Incoming data is passed on to the database after the verification process, and retried in case of issues. The only exception of discarding data is when the data does not make sense to be retried(i.e. invalid data).
For the component to function properly, a setup is required. This setup involves passing in the appropriate configuration, and launching the component in conjunction with an MQTT broker, and ABB Ability™ History at the minimum. In a generic use case, TsModule is run inside of a docker container, and its configuration is automatically generated by Type Definition Registry and passed on to the module by Ability Edge Proxy; However, it is possible to setup TSAPI manually outside of the Ability Edge. This guide will go through both methods as thoroughly as possible, and provide samples to get you started.
Installation
Edgenius
The ABB Warmstorage application should be available in your Edgenius directory. You can install it to an edge through Edgenius Management Portal.
There are only couple of configuration options.
- History length - determines how long data is stored in days
- Toggle for variables, events and alarms. You can disable storing of any of these.
The software implements the data access api for edgenius. All information for accessing the api is found in Edgenius documentation and here: https://clientsuccess.ability.abb/api/instance/data.html
Edgenius SNO
To change Helm chart values before installing the "ABB Warmstorage application" chart on Edgenius SNO, you will need to update the following file: ansible_scripts/config/chart_values/warm_storage_app.j2.
To change persistent volume size for the persistent volume claim "pvc04" (mount path /var/lib/rtdbdata) of CpmPlus database, add following values for the abb-warmstorage-cpmmodule:
persistence:
pvc04:
size: 200Gi
To add or change environment values for containers, add them with the env list:
abb-warmstorage-tsmodule:
image:
repository: {{ project }}/cpmplustsmodule
env:
- name: VtrinConfiguration__RTDB__Histories__DefaultHistory__HistoryLengthInDays
value: "60"
Full example:
global:
moduleCategory: App
storageClassName: {{ cluster_storage_class }}
registry: "{{ cluster_registry_svc_url }}"
imagePullSecrets: []
serviceAccount:
name: {{ cluster_service_account }}
abb-warmstorage-cpmmodule:
image:
repository: {{ project }}/cpmplushistory
persistence:
pvc04:
size: 200Gi
abb-warmstorage-tsmodule:
image:
repository: {{ project }}/cpmplustsmodule
env:
- name: VtrinConfiguration__RTDB__Histories__DefaultHistory__HistoryLengthInDays
value: "60"
- name: Some_Other_Env_Variable_Name
value: "true"
Usage
TsModule's core functionality is writing time series data into the database and allowing the readback of the said data. The current implementation uses the MQTT protocol to read the incoming data, and accepts data only in JSON format. The readback feature is done through an HTTP endpoint, and also only accepts queries in JSON format. Each section will be described separately.
Writing Data
ABB Ability specifications declare three types of timeseries data: Variable data, Event data, and Alarm data
The module subsribes to the warm/# topic and identifies the type of timeseries data based on it's subtopics. This will be explained in detail in upcoming sections.
Writing Variable Data
As a user, if you intend to write variable data to the storage, warm/variables is the topic you must write to. The payload must be in JSON format, and it can be a single element, or an array of elements(enclosed with brackets). Please note that there is no need to create variables on the database, as the component will create them for you if they do not exist; however, each variable may only contain one type of data; meaning that it can either be single values or arrays. This is determined by the first data point that the modules receives for each variable(if it has singular value or an array of values). You can find a sample below:
{
"objectId": "0c055b6c-004d-493d-8caa-96c952c0e207",
"model": "abb.ability.device",
"timestamp": "2020-01-01T00:00:00Z",
"variable": "sampleVariable",
"quality": 0,
"value": 15
}| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| objectId | Yes | Unique ObjectId for the variable in the format of GUID | String |
| model | Yes | Abb Ability Information Model format of model for variable | String |
| timestamp | Yes | Datetime offset in the ISO 8601 format | String |
| variable | Yes | Name of the variable | String |
| value | Yes | Value of the data point. Can be a single or array of primitive data types: integer, floating point, boolean OR can be single string. Every other type will be treated as a string in the database. | Object |
| quality | No | Quality value of the data point. Follows the format of "IEC 62361-2 Data Value Quality" | Unsigned Integer |
Writing Event Data
As a user, if you intend to write event data to the storage, warm/events is the topic you must write to. The payload must be in json format, and it can be a single element, or an array of elements(enclosed with brackets). You can find a sample below:
{
"event": "ArbitraryEventName",
"model": "abb.ability.device",
"timestamp": "2020-01-01T00:00:00Z",
"objectId": "0c055b6c-004d-493d-8caa-96c952c0e207",
"value":{
"sampleIntegerProperty": 15
}
}| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| objectId | Yes | Unique ObjectId for the variable in the format of GUID | String |
| model | Yes | Abb Ability Information Model format of model for variable | String |
| timestamp | Yes | Datetime offset in the ISO 8601 format | String |
| event | Yes | Name of the event | String |
| value | Yes | Dictionary of key/value pair. What you put inside is arbitrary. | Dictionary |
Writing Alarm Data
As a user, if you intend to write alarm data to the storage, warm/alarms is the topic you must write to. The payload must be in json format, and it can be a single element, or an array of elements(enclosed with brackets). You can find a sample below:
{
"alarm": "ArbitraryEventName",
"alarmKey":"ArbitraryAlarmKey",
"model": "abb.ability.device",
"timestamp": "2020-01-01T00:00:00Z",
"objectId": "0c055b6c-004d-493d-8caa-96c952c0e207",
"value":{
"sampleIntegerProperty": 15
}
}| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| objectId | Yes | Unique ObjectId for the variable in the format of GUID | String |
| model | Yes | Abb Ability Information Model format of model for variable | String |
| timestamp | Yes | Datetime offset in the ISO 8601 format | String |
| alarm | Yes | Name of the alarm | String |
| alarmKey | No | Arbitrary Key for the alarm | String |
| value | Yes | Dictionary of key/value pair. What you put inside is arbitrary. | Dictionary |
Reading Data
The reading of data is performed through an HTTP endpoint, exposed on port 8001 by default. You need to send an HTTP POST to the address specified for each type. This will be explained below.
Reading Single Variable Data
Send an http post to ~/edge/variables in order to read variable data. The request body must contain a json in the following format:
{
"date": {
"from": "<string>",
"to": "<string>"
},
"filter": "<string>",
"select": {
"properties": "<string>"
},
"orderBy": {
"property": "<string>",
"order": "<string>"
},
"limit": "<int>"
}You can find info about each property in the table below:
| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| date | Yes | Date object | Object |
| date.from | Yes | Starting date range for query | string (ISO 8601 format) |
| date.to | No | Ending date range for query. If not provided, will default to api's server current UTC time. | string (ISO 8601 format) |
| filter | No | A predicate string adhering to ABB's Query Expression Language format | string |
| select | No | Select object | Object |
| select.properties | No | A comma separated list of properties that will return in the response. If this field is set, then the items in this property's value will be the only properties in the response. Example: "properties": "objectId,model". | string |
| orderBy | No | Object used to order the data. | Object |
| orderBy.property | Yes | Property in which to order. | string |
| orderBy.order | Yes | Order by property. Available options are asc or desc | string |
| limit | No | Post processing limit. Example: If the warm data storage returns 10,000 records but this property is set to 100, then the top 100 records of that 10,000 will be returned. | int |
Reading Aggregated Variable Data
Send an http post to ~/edge/variables in order to read variable data. The request body must contain a json in the following format:
{
"date": {
"from": "<string>",
"to": "<string>"
},
"filter": "<string>",
"select": {
"count": "",
"min": "<string>",
"max": "<string>",
"first": "<string>",
"last": "<string>",
"sum": "<string>",
"avg": "<string>",
},
"groupBy": {
"time": "<string>",
"properties": "<string>"
},
"orderBy": {
"property": "<string>",
"order": "<string>"
},
"limit": "<int>"
}You can find info about each property in the table below:
| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| date | Yes | Date object | Object |
| date.from | Yes | Starting date range for query | string (ISO 8601 format) |
| date.to | No | Ending date range for query. If not provided, will default to api's server current UTC time. | string (ISO 8601 format) |
| filter | No | A predicate string adhering to ABB's Query Expression Language format | string |
| select | Yes | Select object. At least one of the below select objects is required. | Object |
| select.count | No | Count of results based upon the current filter. Requires an empty string value (ie: "count": ""). | int |
| select.min | No | Minimum value, only applicable to numeric and date time properties. Supports multiple comma-separated list of property names. Example: value,timestamp. | string |
| select.max | No | Maximum value, only applicable to numeric and date time properties. Supports multiple comma-separated list of property names. Example: value,timestamp. | string |
| select.first | No | First value. Supports multiple comma-separated list of property names. Example: value,timestamp. | string |
| select.last | No | Last value. Supports multiple comma-separated list of property names. Example: value,timestamp. Using timestamp will provide the exact timestamp of the value's occurrence. Therefore, using timestamp with last provides a true last known value searching capability. | string |
| select.sum | No | Sum value, only applicable to numeric properties. Supports multiple comma-separated list of property names. | string |
| select.avg | No | Average value, only applicable to numeric. Supports multiple comma-separated list of property names. | string |
| groupBy | No | Object used to group the data. | Object |
| groupBy.time | No | Used to group by a user-specified time interval. Supported time intervals are m, h, d. Example: 1m, 10h, 5d. By specifying this property, timestamp will automatically be returned in the response. The timestamp value will be the histogram timestamp nearest the specified time interval, not the precise timestamp of the occurring value. | Object |
| groupBy.properties | No | Group by values of specified properties, supports comma-separated list of property names. All properties for a given event type are supported. | Object |
| orderBy | No | Object used to order the data. | Object |
| orderBy.property | Yes | Property in which to order. | string |
| orderBy.order | Yes | Order by property. Available options are asc or desc | string |
| limit | No | Post processing limit. Example: If the warm data storage returns 10,000 records but this property is set to 100, then the top 100 records of that 10,000 will be returned. | int |
Please note that the main difference between a single read query and an aggregated query is determined from the Select property in the query. If Select does not exist in your query, or it exists and Select.Properties is defined, the query will be treated as a single query; Otherwise, the query will be treated as an aggregate query. Setting aggregate properties such as Select.Max or Select.Count in a query which has also has its Select.Properties set will result in a single query and the aggregates will be ignored.
Reading Single Event Data
Send an http post to ~/edge/events in order to read single event data. The request body must contain a json in the following format:
{
"date": {
"from": "<string>",
"to": "<string>"
},
"filter": "<string>",
"select": {
"properties": "<string>"
},
"orderBy": {
"property": "<string>",
"order": "<string>"
},
"limit": "<int>"
}You can find info about each property in the table below:
| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| date | Yes | Date object | Object |
| date.from | Yes | Starting date range for query | string (ISO 8601 format) |
| date.to | No | Ending date range for query. If not provided, will default to api's server current UTC time. | string (ISO 8601 format) |
| filter | No | A predicate string adhering to ABB's Query Expression Language format | string |
| select | No | Select object | Object |
| select.properties | No | A comma separated list of properties that will return in the response. If this field is set, then the items in this property's value will be the only properties in the response. Example: "properties": "objectId,model". | string |
| orderBy | No | Object used to order the data. | Object |
| orderBy.property | Yes | Property in which to order. | string |
| orderBy.order | Yes | Order by property. Available options are asc or desc | string |
| limit | No | Post processing limit. Example: If the warm data storage returns 10,000 records but this property is set to 100, then the top 100 records of that 10,000 will be returned. | int |
Reading Aggregated Event Data
This features is currently unimplemented and will be added at a future date.
Reading Single Alarm Data
Send an http post to ~/edge/alarms in order to read single alarm data. The request body must contain a json in the following format:
{
"date": {
"from": "<string>",
"to": "<string>"
},
"filter": "<string>",
"select": {
"properties": "<string>"
},
"orderBy": {
"property": "<string>",
"order": "<string>"
},
"limit": "<int>"
}You can find info about each property in the table below:
| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| date | Yes | Date object | Object |
| date.from | Yes | Starting date range for query | string (ISO 8601 format) |
| date.to | No | Ending date range for query. If not provided, will default to api's server current UTC time. | string (ISO 8601 format) |
| filter | No | A predicate string adhering to ABB's Query Expression Language format | string |
| select | No | Select object | Object |
| select.properties | No | A comma separated list of properties that will return in the response. If this field is set, then the items in this property's value will be the only properties in the response. Example: "properties": "objectId,model". | string |
| orderBy | No | Object used to order the data. | Object |
| orderBy.property | Yes | Property in which to order. | string |
| orderBy.order | Yes | Order by property. Available options are asc or desc | string |
| limit | No | Post processing limit. Example: If the warm data storage returns 10,000 records but this property is set to 100, then the top 100 records of that 10,000 will be returned. | int |
Reading Aggregated Alarm Data
This features is currently unimplemented and will be added at a future date.
Response Format
There are a total of 4 different response codes to your query:
HTTP Status Code 200 OK
HTTP Status Code 400 BadRequest
HTTP Status Code 500 InternalServerError
HTTP Status Code 503 ServiceUnavailable
BadRequest is responded when your query is malformed and cannot be parsed into the correct structure. InternalSeverError happens when an error happens on querying process and must be reported to the development team with the response body, as it containts the error.
ServiceUnavailable happens when the connectivity to CpmPlus database is not present. This usually is resolved after a few seconds.
Configuration
Configuring TsAPI can be done with three methods: Platform, file, and environment values. Each method will be documented here, but please not that you should only choose one and not combine two different methods as the results will be unpredictable.
In case you are deploying TsAPI as a part of the "Warm Storage Component" from the "Edge Management Portal", you can ignore the configuration methods, and only review the Structure section"
Structure
The configuration of TsModule, can be declared as the JSON below. Please note that the behavior of the component can significantly change based on these values and therefore, it is strongly adviced to to customize the values based on your requirements, or consult with the development team in case of ambiguity:
{
"mqttConfiguration": {
"clientId": "ModuleNameHere",
"username": "Mqttusername",
"password": "mqttpassword",
"brokerUri": "tcp://localhost:2883",
"Throttling": 0
},
"VtrinConfiguration": {
"TSDBConnectionString": "wss://cpmplushistory:9443/history",
"username": "root",
"password": "root",
"RTDB": {
"histories": {
"defaultHistory": {
"Name": "StreamHistory"
},
"unimportantKey": {
"Name": "firstHistory",
"HistoryLengthInDays": 1000
},
"anotherUnimportantKey": {
"Name": "secondHistory",
"HistoryLengthInDays": 10
}
},
"defaultArrayLengths": 15,
"enableNonChronologicalWrite": true,
"PropertyToHistoryMappings": {
"ArbitraryKeyOne": {
"variable": "variableNameOne",
"objectId": "b560357f-7612-4cba-9b1f-84b78b7179ae",
"model": "abb.ability.device",
"historyName": "secondHistory"
},
"ArbitraryKeyTwo": {
"variable": "variableNameTwo",
"objectId": "b560357f-7612-4cba-9b1f-84b78b7179ae",
"model": "abb.ability.device",
"historyName": "firstHistory"
}
}
}
}
}The explanation for each key and value are listed in the table below:
| Parameter | Mandatory | Description | Data Type |
|---|---|---|---|
| mqttConfiguration | Yes | Configuration for the mqtt client of the program | Object |
| mqttConfiguration.clientId | Yes | ClientId that the mqtt client will use to connect to the broker | String |
| mqttConfiguration.username | No | Username for mqtt client for broker connection | String |
| mqttConfiguration.password | No | Password for mqtt client for broker connection | String |
| mqttConfiguration.brokerUri | Yes | Uri that the mqtt client will connect to | Uri |
| mqttConfiguration.throttling | No | Maximum allowed number of incoming mqtt messages per second | Unsigned Integer |
| vtrinConfiguration | Yes | Configuration for the storage database | Object |
| vtrinConfiguration.TSDBConnectionString | Yes | The URI for the cpmPlusHistory database | Uri |
| vtrinConfiguration.username | Yes | Username for connecting to cpmPlusHistory database | String |
| vtrinConfiguration.password | Yes | Password for connecting to cpmPlusHistory database | String |
| vtrinConfiguration.rtdb | Yes | Internal configuration for cpmPlusHistory | Object |
| vtrinConfiguration.rtdb.histories | Yes | Dictionary of histories in use. They will be created at the started if not existing | Object |
| vtrinConfiguration.rtdb.histories.defaultHistory | Yes | The default history which any variable unmapped to a certain history will be written to | Object |
| vtrinConfiguration.rtdb.histories.defaultHistory .name | Yes | Name of the default history | String |
| vtrinConfiguration.rtdb.histories.defaultHistory .historyLengthInDays | No | Number of days that the data will be stored in the default history | Integer |
| vtrinConfiguration.rtdb.histories.arbitraryKeyOne | No | Custom history to be created. There can be many of these. Key is unimportant. | Object |
| vtrinConfiguration.rtdb.histories.arbitraryKeyOne .name | Yes | Custom History name. | String |
| vtrinConfiguration.rtdb.histories.arbitraryKeyOne .historyLengthInDays | No | Number of days that the data will be stored in this custom history | Integer |
| vtrinConfiguration.rtdb.defaultArrayLengths | Yes | Arrays are stored on RTDB with a fixed length. Set this to the max length of your arrays. | Integer |
| vtrinConfiguration.rtdb.enableNonChronologicalWrite | No | RTDB discards values with out of order timestamp by default. This Changes the behavior. | Boolean |
| vtrinConfiguration.rtdb.PropertyToHistoryMappings | No | Mapping each variable to go to be written to specific history | Object |
| vtrinConfiguration.rtdb.PropertyToHistoryMappings .KeyOne | No | One Mapping Object. Key is unimportant and unused. | Object |
| vtrinConfiguration.rtdb.PropertyToHistoryMappings .KeyOne.variable | Yes | Variable Name | String |
| VtrinConfiguration.rtdb.PropertyToHistoryMappings .KeyOne.objectId | Yes | ObjectId for the variable | String |
| VtrinConfiguration.rtdb.PropertyToHistoryMappings .KeyOne.model | Yes | Model for the variable | String |
| VtrinConfiguration.rtdb.PropertyToHistoryMappings .KeyOne.historyName | Yes | The name of the history which the variable should be written to | String |
Configuration Through Normal Edge Deployement
From the Abb Ability IoT Platform version 19.0.9 and beyond, TsModule has to be declared as a system module. This is due to the specific MQTT access control granted to different types of modules on a normal edge deployement, and TsApi requiring elevated permissions. Configuring TsModule on platform versions prior to 19.0.9 is not possible from the typedefinitions, as the configuration will not be passed on to the module by the Ability Edge Proxy.
Inside the abb.ability.edge.configuration type definition of your edge model, you can find a key named systemModules. Under that key, add the following json and customize it to your liking. This sample is the same as what was provided in the previous section, modified to be compatible with the platform. Please remember that the other MQTT values are determined and set by the Ability Edge Proxy and are not configurable from TsApi's configuration.
"TsModule": {
"image": {
"isMandatory": true,
"dataType": "string",
"value": "TsModuleImageNameHere:latest"
},
"configuration": {
"mqttConfiguration": {
"Throttling": {
"dataType": "integer",
"value": 0
}
},
"VtrinConfiguration": {
"TSDBConnectionString": {
"dataType": "string",
"value": "wss://cpmplushistory:9443/history"
},
"username": {
"dataType": "string",
"value": "root"
},
"password": {
"dataType": "string",
"value": "root"
},
"RTDB": {
"histories": {
"defaultHistory": {
"Name": {
"dataType": "string",
"value": "StreamHistory"
}
},
"unimportantKey": {
"Name": {
"dataType": "string",
"value": "firstHistory"
},
"HistoryLengthInDays": {
"dataType": "integer",
"value": 1000
}
},
"anotherUnimportantKey": {
"Name": {
"dataType": "string",
"value": "secondHistory"
},
"HistoryLengthInDays": {
"dataType": "integer",
"value": 10
}
}
},
"defaultArrayLengths": {
"dataType": "integer",
"value": 15
},
"enableNonChronologicalWrite": {
"dataType": "boolean",
"value": true
},
"PropertyToHistoryMappings": {
"ArbitraryKeyOne": {
"variable": {
"dataType": "string",
"value": "variableNameOne"
},
"objectId": {
"dataType": "string",
"value": "b560357f-7612-4cba-9b1f-84b78b7179ae"
},
"model": {
"dataType": "string",
"value": "abb.ability.device"
},
"historyName": {
"dataType": "string",
"value": "secondHistory"
}
},
"ArbitraryKeyTwo": {
"variable": {
"dataType": "string",
"value": "variableNameTwo"
},
"objectId": {
"dataType": "string",
"value": "b560357f-7612-4cba-9b1f-84b78b7179ae"
},
"model": {
"dataType": "string",
"value": "abb.ability.device"
},
"historyName": {
"dataType": "string",
"value": "firstHistory"
}
}
}
}
}
}
}Configuration Through File
It is also possible to configure the module through a configuration file. This method is platform independant; as the component always checks the existance of this file first for its configuration. It is worth noting that this file is automatically created by the Ability Edge Proxy from version 19.0.9 onwards.
The file must be located at /app/config/configuration.json Please note that in case you are running the component on a Windows system outside of a container, this file may have to be located at your main drive(usually C drive).
The content of the file is the exact same as what was provided in the Structure section.
Configuration Through Environment Values
Lastly, you are also able to configure the module through environment values. This is the most unconvential way and should only be used when the other two options are not available.
The following table presents the key/value pairs that you need to declare on the environment for this method:
| Key | Sample Value |
|---|---|
| mqtt_client_id | ModuleNameHere |
| module_id | Mqttusername |
| mqtt_password_file | Mqttpassword |
| mqtt_url | tcp://localhost:2883 |
| VtrinConfiguration__TSDBConnectionString | wss://cpmplushistory:9443/history |
| VtrinConfiguration__username | root |
| VtrinConfiguration__password | root |
| VtrinConfiguration__RTDB__EnableNonChronologicalWrite | true |
| VtrinConfiguration__RTDB__defaultArrayLengths | 15 |
| VtrinConfiguration__RTDB__Histories__DefaultHistory__Name | StreamHistory |
| VtrinConfiguration__RTDB__Histories__ArbitraryKeyOne__Name | FirstHistory |
| VtrinConfiguration__RTDB__Histories__ArbitraryKeyOne__HistoryLengthInDays | 1000 |
| VtrinConfiguration__RTDB__Histories__ArbitraryKeyTwo__Name | secondHistory |
| VtrinConfiguration__RTDB__Histories__ArbitraryKeyTwo__HistoryLengthInDays | 10 |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyOne__Variable | variableNameOne |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyOne__ObjectId | b560357f-7612-4cba-9b1f-84b78b7179ae |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyOne__Model | abb.ability.device |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyOne__HistoryName | secondHistory |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyTwo__Variable | variableNameTwo |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyTwo__ObjectId | b560357f-7612-4cba-9b1f-84b78b7179ae |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyTwo__Model | abb.ability.device |
| VtrinConfiguration__RTDB__PropertyToHistoryMappings__ArbitraryKeyTwo__HistoryName | FirstHistory |
Features
Variable links
Variables can be links to other variables. This is an extension to informaion model object definition. Regularly object model does not store information about variables but only properties. In the link case the variable is stored in the object model along with a link field which points to another variable.
If an object has variables where some of them are links to other variables these can be supported to some extent. For example the following object has a regular variable and a linked variable. The regular variable is not expressed in the object model but only the variable that is a link. To get the link resolved, TsApi module has to receive the regular variable data of this object to trigger the link resolving.
{
"type": "abb.processAutomation.sensors.tempSensor",
"name": "bestsensor",
"model": "abb.ability.device",
"objectid": "944bdd85-644f-47f7-bac5-2c8c76a120b0",
"version": 54,
"properties": {
"serialNumber": {
"value": "string"
}
},
"variables": {
"temperature": {
"link": "2e3dbd5c-2012-48ed-aba4-c62f2887ec31/abb.robotics.ioModel#/variables/gripperOpen"
}
}
}The link format listed above must be followed exactly and is currently the only supported format. This allows to link to a specific variable.
If this object has for example another variable called "Power", TsApi needs to receive for example following data. This will trigger TSApi to investigate this object and populate its links.
{
"objectId": "944bdd85-644f-47f7-bac5-2c8c76a120b0",
"model": "abb.ability.device",
"timestamp": "2020-01-01T00:00:02Z",
"variable": "Power",
"quality": 0,
"value": 4
}To give better example of creating such objects, a type definition for this type would be:
{
"typeid": "abb.processAutomation.sensors.tempSensor",
"model": "abb.ability.device",
"version": "1.0.0",
"isExtensible": true,
"properties": {
"serialNumber": {
"datatype": "string"
}
},
"variables": {
"power": {
"datatype": "integer"
}
},
"attributes": {
"link": {
"dataType": "string",
"appliesTo": [
"string",
"number",
"integer",
"boolean",
"array"
]
}
}
}The power variable could directly have the link attribute or we can extend the type by adding this temperature variable. An object of this type should then be extended for exapmle with this extension:
{
"variables": {
"temperature": {
"link": "2e3dbd5c-2012-48ed-aba4-c62f2887ec31/abb.robotics.ioModel#/variables/gripperOpen",
}
}
}Then query can be made to query the temperature variable but the query will return values from another object which data should be sent as:
{
"objectId": "2e3dbd5c-2012-48ed-aba4-c62f2887ec31",
"model": "abb.robotics.ioModel",
"timestamp": "2020-01-01T00:00:02Z",
"variable": "gripperOpen",
"quality": 0,
"value": 33
}This could be then queried with
{
"date":{
"from" : "2000-01-01T00:00:00Z"
},
"filter": "variable='temperature' and objectid='944bdd85-644f-47f7-bac5-2c8c76a120b0'
}This returns the values of gipperOpen as temperature values of the object 9444.
Same data can be queried through the link destination:
{
"date":{
"from" : "2000-01-01T00:00:00Z"
},
"filter": "variable='gripperOpen' and objectid='2e3dbd5c-2012-48ed-aba4-c62f2887ec31'
}Which would return the values of io.gripperOpen but expressed as values of temperature.
The version where variable links is available is:
application version 5.1.0
abbiapcpdev.azurecr.io/cpmplustsmodule:2.7.0
abbiapcpdev.azurecr.io/cpmplushistory:530.2204.1r
Updated 5 months ago
