Tempus - Thingsboard
Tempus - Thingsboard
Release 1.3
Hashmap, Inc
Contents
1 About 1
2 Features 1
3 Contents 2
3.1 Quick Start . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3.2 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.3 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.4 API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.5 Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.6 Administration UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.7 Tempus Rule Engine Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
3.8 Data Model Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
3.9 Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
3.10 Gateway . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
3.11 Indices and tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1 About
Tempus Cloud is an open IIoT/IoT framework (Field/Edge to Cloud/DC) and rapid analytics application creator that
provides a spectrum of outcome-based experiences on an unmodified data stream and does not force customers into a
proprietary approach but focuses on a use-case driven approach for top-line/bottom-line benefits.
2 Features
• Business Unit Management: Tempus cloud allows for authorization by business unit to allow for segmentation
of users, while still allowing all the data to be viewed in context if requred.
• Asset Management: Tempus Cloud has a flexible asset management model that is based on a graph repre-
sentation. This allows for different users targeting different types of analysis to arrange the data as they
wish. For example, if User A would like to look at their data geographically, they might choose to create
relations on a Country/Region/City basis, while User B has the freedom to organize assets by workflows
and facilities.
• Device Management: Devices can be managed and controlled via Tempus Cloud. All of the communcation
is facilitated via standard MQTT. This can be secured via X.509 certificates or simple access token for
authentication and authorization, and TLS for encryption of the data in motion.
Additionally, there is a comprehensive attribute management system in place, that allows for attributes to
be provided by the client, the server, or shared between the two.
• Visualization: Tempus includes a flexible Visualization and dashboarding framework. These visualizations can
be created and modified on the fly allowing users to see what they need to see, when they need to see it.
• Rules Engine: There is a flexible rules engine that allows for the invocation of plugins to allow for multiple
outcomes based on a combination of rule sets. These outcomes can be (but not limited to):
Alarming Data Routing Emailing / Notifications RPC communication to the Edge Modification
of the data flow from the edge
Rapid Computation Deployment: Tempus Cloud also has the capability to orchestrate and manage Spark compu-
tataions on the data. This allows for a deeper analysis of the streaming data, in which the results can be visualized
in real time, or even sent back to the edge.
3 Contents
Linux Installation
This guide describes how to install Tempus Cloud on a Linux based server machine. Instructions below are provided
for Ubuntu 16.04 and CentOS 7. These instructions can be easily adapted to other similar operating systems.
Hardware requirements
To run Tempus Cloud and third-party components on a single machine you will need at least 1Gb of RAM.
Java
Tempus Cloud service is running on Java 8. Although you are able to start the service using OpenJDK, the solution is
actively tested on Oracle JDK.
Follow this instructions to install Oracle JDK 8:
• Ubuntu 16.04
• CentOS 7
Please don’t forget to configure your operating system to use Oracle JDK 8 by default. Corresponding instructions are
in the same articles listed above.
[Optional] External database installation
Tempus Cloud is able to use a SQL or Cassandra database. By default, Tempus Cloud uses embedded HSQLDB
instance which is convenient for evaluation or development purposes. If this is your first experience with Tempus
Cloud we recommend to skip this step and use the embedded database. Alternatively, you can configure your platform
to use either scalable Cassandra DB cluster or various SQL databases. If you prefer to use an SQL database, we
recommend PostgreSQL.
NOTE: This is an optional step. It is required only for production usage. You can use embedded HSQLDB for
platform evaluation or development Instructions listed below will help you to install PostgreSQL.
CentOS
Ubuntu
Once PostgreSQL is installed you may want to create a new user or set the password for the the main user. See the
following guides for more details:
• Using postgresql roles and databases
• Changing the postgres user password
When it’s done, connect to the database and create Tempus Cloud DB:
NOTE: This is an optional step. It is required only for production usage. You can use embedded HSQLDB for
platform evaluation or development instructions listed below will help you to install Cassandra.
CentOS
# Cassandra installation
sudo yum install dsc30
# Tools installation
sudo yum install cassandra30-tools
# Start Cassandra
sudo service cassandra start
# Configure the database to start automatically when OS starts.
sudo chkconfig cassandra on
Ubuntu
CentOS
Ubuntu
NOTE: This is an optional step. It is required only for production usage. You can use embedded HSQLDB for
platform evaluation or development
Edit Tempus Cloud configuration file
# username: "${SPRING_DATASOURCE_USERNAME:sa}"
# password: "${SPRING_DATASOURCE_PASSWORD:}"
For PostgreSQL:
Uncomment ‘# PostgreSQL DAO Configuration’ block. Be sure to update the postgres databases username and pass-
word in the bottom two lines of the block (here, as shown, they are both “postgres”).
For Cassandra DB: Locate and set database type configuration parameter to ‘cassandra’.
database:
type: "${DATABASE_TYPE:cassandra}" # cassandra OR sql
We recommend to use embedded HSQLDB or PostgreSQL DB in this setup. We don’t recommend to use Cassandra
on machines with less then 4GB of RAM.
For Tempus Cloud service:
Once Tempus Cloud service is installed, you can execute the following script:
# --loadDemo option will load demo data: users, devices, assets, rules, widgets.
sudo /usr/share/Tempus/bin/install/install.sh --loadDemo
Start Tempus Cloud service
Once started, you will be able to open Web UI using the following link:
http://localhost:8080/
Troubleshooting
/var/log/tempus
You can issue the following command in order to check if there are any errors on the backend side:
Create a Tenant
This will guide you though how to create a tenant in Tempus Cloud.
If you don’t have access to a running Tempus Cloud instance please follow this guide:
Create a Tenant
1. Navigate to the login page for Tempus Cloud (by default http://host_ip:8080, where host ip is the address running
Tempus)
2. Login with the following credentials:
• User: [email protected]
• Password: sysadmin
Please Note: This password MUST be changed prior to production
3. Click on Tenants under TENANT MANAGEMENT
4. Click on the “+” icon at the bottom right of the screen to add a tenant
1. After performing the steps to create a tenant, navigate to the Tenants page and click on the user button of the
tenant card that you want to create the administrator for.
2. Click on the “+” symbol at the bottom right to create an administrator
3. Enter in the Tenant admin info as required
The user can be activated in one of 2 ways:
• Display Activation Link: Useful for when the email server has not been configured, or it is not a real user
• Send Activation Mail: Will send an email to the user with the supplied email address to complete the activation
process
We will choose the Display Activation Link option.
4. Follow the activation link and create a password, and then click Create Password
5. You have now created the Tenant admin and should be logged in as the Tenant Administrator after activation
The goal of this guide is for you to collect and visualize some IoT device data using Tempus Cloud. This guide will
help you with:
• Provisioning a device
• Manage device credentials
• Push data from a device to the Tempus cloud instance using MQTT
• Create a dashboard to visualize the data
Setup and Requirements
If you don’t have access to a running Tempus Cloud instance please follow this guide:
Make sure you have created a tenant by following this guide:
The first step is to login into administration Web UI. If you are using local Tempus cloud installation you can login to
administration Web UI using the account you created in the quickstart guide for creating a tenant.
Provision your Device
1. Open the Devices panel and click on the “+” button at the bottom-right corner of the page.
2. Populate and save device name (for example, “SN-001”). It will be referred to later as $DEVICE_NAME.
Device names must be unique. Populating device name based on a unique serial number or other device identifier
is generally a good idea. Click “Add” button will add corresponding device card to the panel.
Manage device credentials
1. Click on the device card created in the previous step. This action will open “device details” panel. Click on the
“manage credentials” button on the top of the panel. This action will open a popup window with device credentials.
2. Device credentials window will show auto-generated device access token that you can change. Please save this
device token. It will be referred to later as $ACCESS_TOKEN
Pushing Data From the Device - Nifi
Attributes
3. Right-click on the PublishMQTT processor and click configure, then click on the Properties tab
4. Fill in the information as follows
• For the Broker URI put in tcp://host_ip:1883 (1883 is the default mqtt port)
• For the Client ID enter nifi
• For the User Name enter the $ACCESS_TOKEN that was created earlier
• For the password enter a space character
• For the Topic use v1/devices/me/attributes
• For the QoS enter 0
• For Retain Message enter false
5. Click on settings and tick the boxes to auto-terminate the failure and success relationships, as this is the last
processor in the flow, and click Apply
6. Add a GenerateFlowFile processor to the Canvas
7. Right-click on the GenerateFlowFile processor and click configure, then click on the Properties tab
8. Fill in the information as follows
• For Custom Text Enter: {“firmware_version”:”1.0.1”, “serial_number”:”SN-001”}
9. Click on the Scheduling tab
• Enter 1 sec for the Run Schedule
10. Click Apply
11. Start both Processors
12. Navigate to the Tempus Devices panel
13. Click on the device card that you published data to
14. Click on attributes
15. You should see the 2 attributes appear in the pane as below:
Telemetry
3. Right-click on the PublishMQTT processor and click configure, then click on the Properties tab
4. Fill in the information as follows
• For the Broker URI put in tcp://host_ip:1883 (1883 is the default mqtt port)
• For the Client ID enter nifi
• For the User Name enter the $ACCESS_TOKEN that was created earlier
• For the password enter a space character
• For the Topic use v1/devices/me/telemetry
• For the QoS enter 0
• For Retain Message enter false
5. Click on settings and tick the boxes to auto-terminate the failure and success relationships, as this is the last
processor in the flow, and click Apply
6. Add a GenerateFlowFile processor to the Canvas
7. Right-click on the GenerateFlowFile processor and click configure, then click on the Properties tab
8. Fill in the information as follows
• For Custom Text Enter: {“temperature”:21, “humidity”:55.0, “active”: false}
9. Click on the Scheduling tab
• Enter 1 sec for the Run Schedule
10. Click Apply
11. Start both Processors
12. Navigate to the Tempus Devices panel
13. Click on the device card that you published data to
14. Click on Latest Telemetry
15. You should see the 2 attributes appear in the pane as below:
Observe device data on the Web UI
Attributes
The easiest way to create new dashboard is to select device attributes and show them on widget.
Once you click on “Show on widget” button, you will see a “widget preview” panel where you can
• Select widget bundle
• Select preferred widget
• Add widget to new or existing dashboard
Select the Widget Bundle Cards and click the > until you get to the Attributes Card as shown below
Click Add to Dashboard
Select Create New Dashboard
Type in the title Demo Dashboard and click ADD
Next we will add some of the telemetry data as well.
Click on the Latest Telemetry tab
Select the Telemetry values that you would like to monitor on the dashboard and click Show on Widget
Under Cards choose Time Series Table
Click Add to Dashboard
This time select Select Existing Dashboard
Click in the box that says Select Dashboard and choose the Demo Dashboard that we created above.
Tick the Open Dashboard checkbox as well.
Click ADD
The 2 Widgets that were created in the steps above should now be shown.
3.2 Features
There are several Features to the Tempus Cloud Framework that are delivered out of the box.
Entities Overview
Tempus Cloud provides the user interface and REST APIs to provision and manage multiple entity types and their
relations in your IoT application. Supported entities are:
• Tenants - you can treat tenant as a separate business-entity: individual or organization who owns or produce
devices and assets; Tenant may have multiple tenant administrator users and millions of customers;
• Customers - customer is also a separate business-entity: individual or organization who purchase or uses tenant
devices and/or assets; Customer may have multiple users and millions of devices and/or assets;
• Users - users are able to browse dashboards and manage entities;
• Devices - basic IoT entities that may produce telemetry data and handle RPC commands. For example sensors,
actuators, switches;
• Assets - abstract IoT entities that may be related to other devices and assets. For example factory, field, vehicle;
• Alarms - events that identify issues with your assets, devices or other entities;
• Dashboards - visualization of your IoT data and ability to control particular devices through user interface;
• Rules - processing units for incoming messages, entity lifecycle events, etc;
• Plugins - extensions to the platform that process IoT data and help to integrate with other server applications
Each entity supports:
• Attributes - static and semi-static key-value pairs associated with entities. For example serial number, model,
firmware version;
• Telemetry data - time-series data points available for storage, querying and visualization. For example temper-
ature, humidity, battery level;
• Relations - directed connections to other entities. For example contains, manages, owns, produces.
Additionally, devices and assets also have a type. This allows distinguising them and process data from them in a
different way. This guide provides the overview of the features listed above, some useful links to get more details and
real-life examples of their usage.
Real-life application
The easiest way to understand the concepts of Tempus is to implement your first Tempus application. Let’s assume
we want to build an application that collects data from soil moisture and temperature sensors, visualize this data on
the dashboard, detect issues, raise alarms and control the irrigation. Let’s also assume we want to support multiple
fields with hundreds of sensors. Fields may be also grouped to the Geo regions. We believe there should be following
logical steps to build such an application:
For example:
create-asset.sh
curl -v -X POST -d @create-asset.json http://localhost:8080/api/asset \
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN
create-asset.json
{"name":"Field C","type":"field"}
Note: in order to execute this request, you will need to substitute $JWT_TOKEN with a valid JWT token. This token
should belong to a user with TENANT_ADMIN role. You can use following guide to get the token.
Also, you can provision new relation using POST request to the following URL
http(s)://host:port/api/asset
create-relation.sh
curl -v -X POST -d @create-asset.json http://localhost:8080/api/relation \
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
create-relation.json
{"from":{"id":"$FROM_ASSET_ID","entityType":"ASSET"},"type":"Contains","to":{
˓→"entityType":"ASSET","id":"$TO_ASSET_ID"}}
Note: Don’t forget to replace $FROM_ASSET_ID and $TO_ASSET_ID with valid asset ids. Note: One can relate
any entities. For example, assets to devices or assets to users. You can receive them as a result of previous REST API
call or use Web UI.
Attribute Management
Attribute types
All attributes may be used in Rule Engine components: filters, processors, and actions. This guide provides the
overview of the features listed above and some useful links to get more details.
Device specific attributes are separated into two main groups:
• client-side - attributes are reported and managed by the device application. For example current soft-
ware/firmware version, hardware specification, etc.
image
• shared - attributes are reported and managed by the server-side application. Visible to the device application.
For example customer subscription plan, target software/firmware version.
image
Getting Started
MQTT basics
MQTT is a lightweight publish-subscribe messaging protocol which probably makes it the most suitable for various
IoT devices. You can find more information about MQTT here. Tempus Cloud server nodes act as an MQTT Broker
that supports QoS levels 0 (at most once) and 1 (at least once) and a set of predefined topics.
You can find a large number of MQTT client libraries on the web. Examples in this article will be based on Mosquitto
and MQTT.js. In order to setup one of those tools, you can use instructions in our Hello World guide.
MQTT Connect
We will use access token device credentials in this article and they will be referred to later as $ACCESS_TOKEN.
The application needs to send MQTT CONNECT message with username that contains $ACCESS_TOKEN. Possible
return codes and their reasons during connect sequence:
• 0x00 Connected - Successfully connected to Tempus Cloud MQTT server.
• 0x04 Connection Refused, bad user name or password - Username is empty.
• 0x05 Connection Refused, not authorized - Username contains invalid $ACCESS_TOKEN.
Key-Value Format
By default, Tempus Cloud supports key-value content in JSON. Key is always a string, while value can be either string,
boolean, double or long. Using custom binary format or some serialization framework is also possible. See protocol
customization for more details. For example:
v1/devices/me/telemetry
{"key1":"value1", "key2":"value2"}
or
[{"key1":"value1"}, {"key2":"value2"}]
Please note that in this case, the server-side timestamp will be assigned to uploaded data!
In case your device is able to get the client-side timestamp, you can use following format:
{"ts":1451649600512, "values":{"key1":"value1", "key2":"value2"}}
In the example above, we assume that “1451649600512” is a unix timestamp with milliseconds precision. For exam-
ple, the value ‘1451649600512’ corresponds to ‘Fri, 01 Jan 2016 12:00:00.512 GMT’
Mosquitto
MQTT.js
telemetry-data-as-object.json
telemetry-data-as-array.json
[{"key1":"value1"}, {"key2":true}]
telemetry-data-with-ts.json
In order to support depth data, the administrator must first configure Tempus to handle depth data. This is done by
chaning the configuration in Tempus.yml and uner the heading UI Related configuration set depthSeries to true:
{"ds":5844.23,"values":{"viscosity":0.1, "humidity":22.0}}
Notice the use of DS. DS stands for depth stamp. This can either be in meters or feet, but must be consistant throughout
the publication of data to the device. Mixing of units will cause data integrity issues.
Attributes API
In order to publish client-side device attributes to Tempus Cloud server node, send PUBLISH message to the following
topic:
v1/devices/me/attributes
Mosquitto
MQTT.js
new-attributes-values.json
In order to request client-side or shared device attributes to Tempus Cloud server node, send PUBLISH message to the
following topic:
v1/devices/me/attributes/request/$request_id
where $request_id is your integer request identifier. Before sending PUBLISH message with the request, client need
to subscribe to:
v1/devices/me/attributes/response/+
The following example is written in javascript and is based on mqtt.js. Pure command-line examples are not available
because subscribe and publish need to happen in the same mqtt session.
MQTT.js
export TOKEN=$ACCESS_TOKEN
node mqtt-js-attributes-request.js
mqtt-js-attributes-request.js
client.on('connect', function () {
console.log('connected')
client.subscribe('v1/devices/me/attributes/response/+')
client.publish('v1/devices/me/attributes/request/1', '{"clientKeys":"attribute1,
˓→attribute2", "sharedKeys":"shared1,shared2"}')
})
Result
{"key1":"value1"}
Note: The intersection of client-side and shared device attribute keys is a bad practice! However, it is still possible to
have same keys for client, shared or even server-side attributes.
In order to subscribe to shared device attribute changes, send SUBSCRIBE message to the following topic:
v1/devices/me/attributes
Once shared attribute will be changed by one of the server-side components (REST API or custom plugins) the client
will receive the following update:
{"key1":"value1"}
Mosquitto
MQTT.js
Server-side RPC
In order to subscribe to RPC commands from the server, send SUBSCRIBE message to the following topic:
v1/devices/me/rpc/request/+
Once subscribed, the client will receive individual commands as a PUBLISH message to the corresponding topic:
v1/devices/me/rpc/request/$request_id
where $request_id is an integer request identifier. The client should publish the response to the following topic:
v1/devices/me/rpc/response/$request_id
The following example is written in javascript and is based on mqtt.js. Pure command-line examples are not available
because subscribe and publish need to happen in the same mqtt session.
MQTT.js
export TOKEN=$ACCESS_TOKEN
node mqtt-js-rpc-from-server.js
mqtt-js-rpc-from-server.js
client.on('connect', function () {
console.log('connected');
client.subscribe('v1/devices/me/rpc/request/+')
});
Client-side RPC
In order to send RPC commands to server, send PUBLISH message to the following topic:
v1/devices/me/rpc/request/$request_id
where $request_id is an integer request identifier. The response from server will be published to the following topic:
v1/devices/me/rpc/response/$request_id
The following example is written in javascript and is based on mqtt.js. Pure command-line examples are not available
because subscribe and publish need to happen in the same mqtt session.
MQTT.js
export TOKEN=$ACCESS_TOKEN
node mqtt-js-rpc-from-client.js
mqtt-js-rpc-from-client.js
client.on('connect', function () {
console.log('connected');
client.subscribe('v1/devices/me/rpc/response/+');
var requestId = 1;
var request = {
"method": "getTime",
"params": {}
};
client.publish('v1/devices/me/rpc/request/' + requestId, JSON.stringify(request));
});
Protocol Customization
MQTT transport can be fully customized for specific use-case by changing the corresponding module.
Getting started
CoAP basics
CoAP is a light-weight IoT protocol for constrained devices. You can find more information about CoAP here. CoAP
protocol is UDP based, but similar to HTTP it uses request-response model. CoAP observes option allows to subscribe
to resources and receive notifications on resource change.
Tempus Cloud nodes act as CoAP Servers that support both regular and observe requests.
You can find CoAP client libraries for different programming languages on the web. Examples in this article will be
based on CoAP cli. In order to setup this tool, you can use instructions in our Hello World guide.
CoAP Authentication and error codes
We will use access token device credentials in this article and they will be referred to later as $ACCESS_TOKEN. The
application needs to include $ACCESS_TOKEN as a path parameter into each CoAP request. Possible error codes
and their reasons:
• 4.00 Bad Request - Invalid URL, request parameters or body.
• 4.01 Unauthorized - Invalid $ACCESS_TOKEN.
• 4.04 Not Found - Resource not found.
Key-value format
By default, Tempus Cloud supports key-value content in JSON. Key is always a string, while value can be either string,
boolean, double or long. Using custom binary format or some serialization framework is also possible. See protocol
customization for more details. For example:
{"stringKey":"value1", "booleanKey":true, "doubleKey":42.0, "longKey":73}
In order to publish telemetry data to Tempus Cloud server node, send POST request to the following URL:
coap://host:port/api/v1/$ACCESS_TOKEN/telemetry
or
[{"key1":"value1"}, {"key2":"value2"}]
Please note that in this case, the server-side timestamp will be assigned to uploaded data!
In case your device is able to get the client-side timestamp, you can use following format:
{"ts":1451649600512, "values":{"key1":"value1", "key2":"value2"}}
In the example above, we assume that “1451649600512” is a unix timestamp with milliseconds precision. For exam-
ple, the value ‘1451649600512’ corresponds to ‘Fri, 01 Jan 2016 12:00:00.512 GMT’
Example
coap-telemetry.sh
# Publish data as an object without timestamp (server-side timestamp will be used)
cat telemetry-data-as-object.json | coap post coap://localhost/api/v1/$ACCESS_TOKEN/
˓→telemetry
telemetry-data-as-object.json
{"key1":"value1", "key2":true, "key3": 3.0, "key4": 4}
telemetry-data-as-array.json
[{"key1":"value1"}, {"key2":true}]
telemetry-data-with-ts.json
{"ts":1451649600512, "values":{"key1":"value1", "key2":"value2"}}
Attributes API
In order to publish client-side device attributes to Tempus Cloud server node, send POST request to the following
URL:
coap://host:port/api/v1/$ACCESS_TOKEN/attributes
coap-telemetry.sh
# Publish client-side attributes update
cat new-attributes-values.json | coap post coap://localhost/api/v1/$ACCESS_TOKEN/
˓→attributes
new-attributes-values.json
{"attribute1":"value1", "attribute2":true, "attribute3":42.0, "attribute4":73}
In order to request client-side or shared device attributes to Tempus Cloud server node, send GET request to the
following URL:
coap://host:port/api/v1/$ACCESS_TOKEN/attributes?clientKeys=attribute1,attribute2&
˓→sharedKeys=shared1,shared2
Example
# Send CoAP attributes request
coap get coap://localhost/api/v1/$ACCESS_TOKEN/attributes?clientKeys=attribute1,
˓→attribute2&sharedKeys=shared1,shared2
(continues on next page)
(continued from previous page)
Result
{"key1":"value1"}
Please note: the intersection of client-side and shared device attribute keys is a bad practice! However, it is still
possible to have same keys for client, shared or even server-side attributes.
In order to subscribe to shared device attribute changes, send GET request with Observe option to the following URL:
coap://host:port/api/v1/$ACCESS_TOKEN/attributes
Once shared attribute will be changed by one of the server-side components (REST API or custom plugins) the client
will receive the following update:
Example
Result
{"key1":"value1"}
RPC API
Server-side RPC
In order to subscribe to RPC commands from the server, send GET request with observe flag to the following URL:
coap://host:port/api/v1/$ACCESS_TOKEN/rpc
Once subscribed, a client may receive rpc requests. An example of RPC request body is shown below:
{
"id": "1",
"method": "setGpio",
"params": {
"pin": "23",
"value": 1
}
}
where
• id - request id, integer request identifier
• method - RPC method name, string
• params - RPC method params, custom json object
and can reply to them using POST request to the following URL:
coap://host:port/api/v1/$ACCESS_TOKEN/rpc/{$id}
Example Reply
Reply Body
{"result":"ok"}
Client-side RPC
In order to send RPC commands to the server, send POST request to the following URL:
coap://host:port/api/v1/$ACCESS_TOKEN/rpc
Both request and response body should be valid JSON documents. The content of the documents is specific to the
plugin that will handle your request.
Example Request
Request Body
Response Body
{"time":"2016 11 21 12:54:44.287"}
Protocol customization
CoAP transport can be fully customized for specific use-case by changing the corresponding module.
Getting Started
HTTP basics
HTTP is a general-purpose network protocol that can be used in IoT applications. You can find more information
about HTTP here. HTTP protocol is TCP based and uses request-response model.
Tempus Cloud server nodes act as an HTTP Server that supports both HTTP and HTTPS protocols.
You can find HTTP client libraries for different programming languages on the web. Examples in this article will be
based on curl. In order to setup this tool, you can use instructions in our Hello World guide.
We will use access token device credentials in this article and they will be referred to later as $ACCESS_TOKEN. The
application needs to include $ACCESS_TOKEN as a path parameter in each HTTP request. Possible error codes and
their reasons:
• 400 Bad Request - Invalid URL, request parameters or body.
• 401 Unauthorized - Invalid $ACCESS_TOKEN.
• 404 Not Found - Resource not found.
Key-value format
By default, Tempus Cloud supports key-value content in JSON. Key is always a string, while value can be either string,
boolean, double or long. Using custom binary format or some serialization framework is also possible. See protocol
customization for more details. For example:
In order to publish telemetry data to Tempus Cloud server node, send POST request to the following URL:
http(s)://host:port/api/v1/$ACCESS_TOKEN/telemetry
{"key1":"value1", "key2":"value2"}
or
[{"key1":"value1"}, {"key2":"value2"}]
Please note that in this case, the server-side timestamp will be assigned to uploaded data!
In case your device is able to get the client-side timestamp, you can use following format:
In the example above, we assume that “1451649600512” is a unix timestamp with milliseconds precision. For exam-
ple, the value ‘1451649600512’ corresponds to ‘Fri, 01 Jan 2016 12:00:00.512 GMT’
http-telemetry.sh
# Publish data as an object without timestamp (server-side timestamp will be used)
curl -v -X POST -d @telemetry-data-as-object.json http://localhost:8080/api/v1/
˓→$ACCESS_TOKEN/telemetry --header "Content-Type:application/json"
telemetry-data-as-object.json
{"key1":"value1", "key2":true, "key3": 3.0, "key4": 4}
telemetry-data-as-array.json
[{"key1":"value1"}, {"key2":true}]
telemetry-data-with-ts.json
{"ts":1451649600512, "values":{"key1":"value1", "key2":"value2"}}
Attributes API
In order to publish client-side device attributes to Tempus Cloud server node, send POST request to the following
URL:
http(s)://host:port/api/v1/$ACCESS_TOKEN/attributes
Example
# Publish client-side attributes update
curl -v -X POST -d @new-attributes-values.json http://localhost:8080/api/v1/$ACCESS_
˓→TOKEN/attributes --header "Content-Type:application/json"
new-attributes-values.json
{"attribute1":"value1", "attribute2":true, "attribute3":42.0, "attribute4":73}
In order to request client-side or shared device attributes to Tempus Cloud server node, send GET request to the
following URL:
http(s)://host:port/api/v1/$ACCESS_TOKEN/attributes?clientKeys=attribute1,attribute2&
˓→sharedKeys=shared1,shared2
Example
Result
{"key1":"value1"}
Please note: the intersection of client-side and shared device attribute keys is a bad practice! However, it is still
possible to have same keys for client, shared or even server-side attributes.
In order to subscribe to shared device attribute changes, send GET request with optional “timeout” request parameter
to the following URL:
http(s)://host:port/api/v1/$ACCESS_TOKEN/attributes/updates
Once shared attribute will be changed by one of the server-side components (REST API or custom plugins) the client
will receive the following update:
Example
Result
{"key1":"value1"}
RPC API
Server-side RPC
In order to subscribe to RPC commands from the server, send GET request with optional “timeout” request parameter
to the following URL:
http(s)://host:port/api/v1/$ACCESS_TOKEN/rpc
Once subscribed, a client may receive rpc request or a timeout message if there are no requests to a particular device.
An example of RPC request body is shown below:
{
"id": "1",
"method": "setGpio",
"params": {
"pin": "23",
(continues on next page)
(continued from previous page)
"value": 1
}
}
where
• id - request id, integer request identifier
• method - RPC method name, string
• params - RPC method params, custom json object
and can reply to them using POST request to the following URL:
http://host:port/api/v1/$ACCESS_TOKEN/rpc/{$id}
Example Reply
Reply Body
{"result":"ok"}
Client-side RPC
In order to send RPC commands to the server, send POST request to the following URL:
http://host:port/api/v1/$ACCESS_TOKEN/rpc
Both request and response body should be valid JSON documents. Theh content of the documents is specific to the
plugin that will handle your request.
Example Request
Request Body
Response Body
{"time":"2016 11 21 12:54:44.287"}
Protocol customization
HTTP transport can be fully customized for specific use-case by changing the corresponding module.
Device Time Series data can be downloaded in CSV format between two timestamp values. The API can be in-
voked as below except that values in brackets needs to be replaced with actual values(device id, start timestamp, end
timestamp).Authorization header values also need to be provided in headers.
http://host:port/api/download/deviceSeriesData?deviceId=<Device_Id>&type=ts&startValue
˓→<Start_Timestamp_Long_Value>&endValue<End_Timestamp_Long_Value>
Device Depth Series data can be downloaded in CSV format between two depth values. The API can be in-
voked as below except that values in brackets needs to be replaced with actual values(device id, start depth, end
depth).Authorization header values also need to be provided in headers.
http://host:port/api/download/deviceSeriesData?deviceId=<Device_Id>&type=ds&startValue
˓→<Start_Depth_Double_Value>&endValue<End_Depth_Double_Value>
Attributes Data
Device Attributes data can be downloaded in CSV format. The API can be invoked as below except that value in
bracket needs to be replaced with actual value(device id).Authorization header values also need to be provided in
headers.
http://host:port/api/download/deviceAttributesData?deviceId=<Device_Id>
Telemetry plugin
Tempus Cloud consists of core services and pluggable modules called plugins. Telemetry plugin is responsible for
persisting attributes data to internal data storage; provides server-side API to query and subscribe for attribute up-
dates. Since Telemetry plugin functionality is critical for data visualization purposes in dashboards, it is configured
on the system level by a system administrator. Advanced users or platform developers can customize telemetry plugin
functionality.
Tempus Cloud uses either Cassandra NoSQL database or SQL database to store all data.
Although you can query the database directly, Tempus Cloud provides a set of RESTful and Websocket API that
simplify this process and apply certain security policies:
Tenant Administrator user is able to manage attributes for all entities that belong to the corresponding tenant. Customer
user is able to manage attributes only for entities that are assigned to the corresponding customer.
Data Query API
You can fetch list of all attribute keys for particular entity type and entity id using GET request to the following URL
http(s)://host:port/api/plugins/telemetry/{entityType}/{entityId}/keys/attributes
get-attributes-keys.sh
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
get-attributes-keys-result.json
[“model”,”softwareVersion”]
Supported entity types are: TENANT, CUSTOMER, USER, RULE, PLUGIN, DASHBOARD, ASSET, DEVICE,
ALARM
You can fetch list of latest values for particular entity type and entity id using GET request to the following URL
http(s)://host:port/api/plugins/telemetry/{entityType}/{entityId}/values/attributes?
˓→keys=key1,key2,key3
get-attributes-values.sh
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
get-attributes-values-result.json
[
{
"lastUpdateTs": 1479735871836,
"key": "model",
"value": "Model 42"
},
{
"lastUpdateTs": 1479735871836,
"key": "softwareVersion",
"value": "1.0.0"
}
]
Supported entity types are: TENANT, CUSTOMER, USER, RULE, PLUGIN, DASHBOARD, ASSET, DEVICE,
ALARM
Working with Telemetry Data
Tempus Cloud provides an API to upload timeseries key-value data. Flexibility and simplicity of key-value format
allow easy and seamless integration with almost any IoT device on the market. Telemetry upload API is specific for
each supported network protocol. You can review API and examples in corresponding reference page:
Telemetry Plugin
Tempus Cloud consists of core services and pluggable modules called plugins. Telemetry plugin is responsible for per-
sisting timeseries data to internal data storage; provides server-side API to query and subscribe for data updates. Since
Telemetry plugin functionality is critical for data visualization purposes in dashboards, it is configured on the system
level by a system administrator. Advanced users or platform developers can customize telemetry plugin functionality.
Internal data storage
Tempus Cloud uses either Cassandra NoSQL database or SQL database to store all data. A device that is sending data
to the server will receive confirmation about data delivery as soon as data is stored in DB. Modern MQTT clients allow
temporary local storage of undelivered data. Thus, even if one of the Tempus Cloud nodes goes down, the device will
not lose the data and will be able to push it to other servers. Server side applications are also able to publish telemetry
valued for different entities and entity types. Although you can query the database directly, Tempus Cloud provides
set of RESTful and Websocket API that simplify this process and apply certain security policies:
• Tenant Administrator user is able to fetch data for all entities that belong to the corresponding tenant.
• Customer user is able to fetch data only for entities that are assigned to the corresponding customer.
You can fetch list of all data keys for particular entity type and entity id using GET request to the following URL
http(s)://host:port/api/plugins/telemetry/{entityType}/{entityId}/keys/timeseries
get-telemetry-keys.sh
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
get-telemetry-keys-result.json
["gas","temperature"]
Supported entity types are: TENANT, CUSTOMER, USER, RULE, PLUGIN, DASHBOARD, ASSET, DEVICE,
ALARM
You can fetch list of latest values for particular entity type and entity id using GET request to the following URL
http(s)://host:port/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?
˓→keys=key1,key2,key3
get-telemetry-keys.sh
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
get-telemetry-keys-result.json
{
"gas": [
{
"ts": 1479735870786,
"value": "1"
}
],
"temperature": [
{
"ts": 1479735870786,
"value": "3"
}
]
}
Supported entity types are: TENANT, CUSTOMER, USER, RULE, PLUGIN, DASHBOARD, ASSET, DEVICE,
ALARM
You can also fetch list of historical values for particular entity type and entity id using GET request to the following
URL
http(s)://host:port/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?
˓→keys=key1,key2,key3&startTs=1479735870785&endTs=1479735871858&interval=60000&
˓→limit=100&agg=AVG
˓→endTs=1479735871858&interval=60000&limit=100&agg=AVG" \
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
get-telemetry-values-result.json
{
"gas": [
{
"ts": 1479735870786,
"value": "1"
},
{
"ts": 1479735871857,
(continues on next page)
(continued from previous page)
"value": "2"
}
],
"temperature": [
{
"ts": 1479735870786,
"value": "3"
},
{
"ts": 1479735871857,
"value": "4"
}
]
}
Supported entity types are: TENANT, CUSTOMER, USER, RULE, PLUGIN, DASHBOARD, ASSET, DEVICE,
ALARM
Websocket API
Websockets are actively used by Thingsobard Web UI. Websocket API duplicates REST API functionality and pro-
vides the ability to subscribe to device data changes. You can open a websocket connection to a telemetry plugin using
the following URL
ws(s)://host:port/api/ws/plugins/telemetry?token=$JWT_TOKEN
Once opened, you can send subscription commands and receive subscription updates:
• cmdId - unique command id (within corresponding websocket connection)
• entityType - unique entity type. Supported entity types are: TENANT, CUSTOMER, USER, RULE, PLUGIN,
DASHBOARD, ASSET, DEVICE, ALARM
• entityId - unique entity identifier
• keys - comma separated list of data keys
• timeWindow - fetch interval for timeseries subscriptions, in milliseconds. Data will be fetch within following
interval [now()-timeWindow, now()]
• startTs - start time of fetch interval for historical data query, in milliseconds.
• endTs - end time of fetch interval for historical data query, in milliseconds.
Example
<script type="text/javascript">
function WebSocketAPIExample() {
var token = "YOUR_JWT_TOKEN";
var entityId = "YOUR_DEVICE_ID";
var webSocket = new WebSocket("ws(s)://host:port/api/ws/plugins/telemetry?
˓→token=" + token);
webSocket.onopen = function () {
var object = {
tsSubCmds: [
{
entityType: "DEVICE",
entityId: entityId,
scope: "LATEST_TELEMETRY",
cmdId: 10
}
],
historyCmds: [],
attrSubCmds: []
};
var data = JSON.stringify(object);
webSocket.send(data);
alert("Message is sent: " + data);
};
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketAPIExample()">Run WebSocket</a>
</div>
Tempus Cloud allows you to send remote procedure calls (RPC) from server side applications to devices and vice
versa. Basically, this feature allows you to send commands to devices and receive results of commands execution.
Similar, you can execute request from the device, apply some calculations or other server-side logic on the back-end
and push the response back to the device. This guide covers Tempus Cloud RPC capabilities. After reading this guide,
you will get familiar with following topics:
• RPC call types
• Basic RPC use-cases
• RPC client-side and server-side APIs
• RPC widgets
Thinsboard RPC feature can be divided into two types based on originator: device-originated and server-originated
RPC calls. In order to use more familiar names, we will name device-originated RPC calls as a client-side RPC calls
and server-originated RPC calls as server-side RPC calls.
Tempus Cloud provides convenient API to send and receive RPC commands from applications running on the device.
This API is specific for each supported network protocol. You can review API and examples in corresponding reference
page:
Tempus Cloud provides System RPC Plugin that allows you to send RPC calls from server-side applications to the
device. In order to send RPC request you need execute HTTP POST request to the following URL:
http(s)://host:port/api/plugins/rpc/{callType}/{deviceId}
where
• callTyp is either oneway or twoway
• deviceId is your target device id
The request body should be a valid json object with two elements:
• method - method name, json string
• params - method parameters, json object
For example:
set-gpio-request.sh
--header "Content-Type:application/json" \
--header "X-Authorization: $JWT_TOKEN"
set-gpio-request.json
{
"method": "setGpio",
"params": {
"pin": "23",
"value": 1
}
}
Please note that in order to execute this request, you will need to substitute $JWT_TOKEN with a valid JWT token.
This token should belong to either
• user with TENANT_ADMIN role
• user with CUSTOMER_USER role that owns the device identified by $DEVICE_ID
You can use following topic to get the token:
Swagger
http://YOUR_HOST:PORT/swagger-ui.html
Generate JWT Token
In order to get a JWT token, you need to execute the following request:
In case of local installation:
• replace $TEMPUS_URL with 127.0.0.1:8080
In case of remote installation:
• replace $TEMPUS_URL with <host>:<port> (replacing host and port with the respective host and port of the
machine running Tempus).
get-token.sh
˓→URL/api/auth/login'
response.json
{"token":"$YOUR_JWT_TOKEN", "refreshToken":"$YOUR_JWT_REFRESH_TOKEN"}
Now, in the Tempus REST API URL click ‘Authorize’ button located in the page header, then in the ‘Api key autho-
rization’ ‘value’ text field enter “Bearer $YOUR_JWT_TOKEN”
Rules Engine
Getting Started
The Rules engine allows you to process messages from devices with a configurable set of rules. With Rule Engine you
can:
• send an email when device attribute changes.
• create an alarm when telemetry value exceeds a certain threshold.
• forward telemetry data to Kafka, RabbitMQ or external RESTful server.
• and much more using other rules and plugins.
Please Note we recommend to get familiar with basic Tempus Cloud features below, before you proceed:
Rule engine operates with two main components: Rules and Plugins. The job of Rule Engine is to sequentially apply
configured rules to incoming messages. Although rules are applied sequentially, rule execution is asynchronous and
is based on actors. This allows processing of messages from the device in the same order in which they are received
without sacrificing performance. The results of processing may or may not be delivered back to device application.
This depends on rule configuration. For example, you may push incoming telemetry data to internal Cassandra DB,
and simultaneously send it to Kafka. You are able to configure to ignore Kafka errors or report an error back to the
device. In this case, the device may either retry the operation, re-send the data to a different server or simply ignore
the error.
Rule vs Plugin
We will review following example to explain the difference between Rule and Plugin. Let’s assume you want to
send an email to an engineer when the engine temperature is too high. In this case, Rule is responsible for analyzing
telemetry data and building email (body, to, cc, etc). However, the plugin is responsible for actual communication
with the email server and sending emails. So, multiple rules may use the same email plugin that is configured once.
Scopes
Lifecycle
Tempus Cloud Rules and Plugins components have same lifecycle events:
• Created - component is provisioned, but is not processing any messages yet.
• Activated - component is able to receive and process new device messages.
• Suspended - component is not able to receive new device messages.
• Deleted - component is stopped and deleted from the database.
Rules
Tempus Cloud Rule consists of three main components: Filters, Processor and Action. Depending on implementation,
each component may require certain configuration before it can be used. In order to configure Rule, you need to
specify at least one filter and one action. Rule Processors are optional. Let’s review role of each component.
Filters
Rule Filter is responsible for filtering incoming messages. You can treat it as a boolean function that has device
attributes and message as parameters:
Tempus Cloud provides the following Rule filters out of the box:
• Message Type Filter - allows to filter incoming messages by type.
• Device Attributes Filter - allows to filter incoming messages based on current device attributes. You can define
filter using javascript. See filter documentation for more details.
• Device Telemetry Filter - allows to filter incoming “Post Telemetry” message based on it’s values. You can
define filter using javascript. See filter documentation for more details.
• Method Name Filter - allows to filter incoming “RPC Request” message based on it’s method name.
Single Rule may contain multiple filters. Usually, one can filter based on message type and device attributes first and
then apply additional filtering based on content of the message.
Processors
Rule Processor is responsible for processing incoming message and adding metadata to it. You can treat it as a function
that has device attributes and message as parameters and returns certain metadata:
Tempus Cloud provides the following Rule processors out of the box:
• Alarm Deduplication Processor generates and persists unique alarms. Populates certain metadata tag to identify
new alarms. See filter documentation for more details.
Actions
Plugin Action is responsible for converting incoming message and metadata to new custom message that is forwarded
to certain plugin. Action may be oneway or twoway. In case of oneway action, rule is not expecting any reply from
plugin. In case of twoway action, rule is expecting a reply from plugin within a certain timeout. If there is no reply
within a configured timeout, Rule will report an error to the device. For example, storing data into the internal storage
is twoway action, however, pushing data into external system may be oneway (optional). Although particular Action
is a part of the corresponding Rule, you can also treat it as part of the corresponding Plugin. So, you can treat an action
as the following interface between Rule and Plugin:
boolean isOneWay()
Plugins
Tempus Cloud Plugins allow you to configure and customize system behavior. Although plugins are able to process
messages from Rules, they also provide APIs to integrate with your server-side applications. With Plugin you can: *
process messages from devices * process REST API calls from server side applications * communicate with server-
side applications using websockets. * communicate between instances of the same plugin in the Tempus Cloud cluster
using asynchronous RPC calls. * persist and query events, telemetry data, and device attributes.
As we already discussed, Rules may communicate with Plugins using Actions. Let’s review other Plugin APIs.
REST API
Plugins are able to process REST API calls from authorized users - customers and system or tenant administrators.
This may be useful for server-side integrations. For example, System RPC Plugin allows executing RPC calls to
devices using REST API.
Websocket API
Plugins are able to handle websocket messages from authorized users - customers and system or tenant administrators.
This may be useful for integrations with server-side applications that want to receive real-time updates. For example,
System Telemetry Plugin allows subscribing to device attributes and timeseries data changes using websockets.
Clustering API
When plugin is provisioned, Tempus Cloud creates an instance of the plugin actor on each Tempus Cloud server in
the cluster. In order to implement complex use-cases, plugin instances may require a way to communicate with each
other. For example, let’s assume that we have a three node cluster (nodes A, B and C). A device may be connected
via MQTT session to node A. Customer users may open a Web UI to observe telemetry data in real time and load
balancer will forward their browsers to different nodes (B and C in our case). Telemetry plugin needs to keep track of
websocket subscriptions for particular device in order to push update to customer’s browser.
Implementations
Tempus Cloud provides the following Plugins out of the box: * Telemetry Plugin - system plugin that is responsible for
processing various requests related to device attributes and telemetry. * RPC Plugin - allows to execute RPC calls to
devices using REST API. RPC call will be delivered to device using supported network protocols. * Device Messaging
Plugin - allows devices that are assigned to the same customer exchange events. * Send Mail Plugin - allows to send
emails. You can specify mail server properties. See plugin documentation for more details. * Kafka Plugin - allows to
push telemetry messages to Apache Kafka. See plugin documentation for more details. * RabbitMQ Plugin - allows to
push telemetry messages to RabbitMQ. See plugin documentation for more details. * REST API Call Plugin - allows
to push telemetry messages to external servers using REST API. See plugin documentation for more details. * Time
RPC Plugin - allows to send RPC requests from device to get current server-side timestamp.
Troubleshooting and statistics
Tempus Cloud keeps track of usage statistics, errors and lifecycle events for each rule and plugin.
Statistics
Tempus Cloud collects and periodically persists usage statistics to internal database. You can review this statistics via
Web UI or get it using REST API. Statistics contain an amount of successfully processed messages and amount of
errors during processing.
Errors
Whenever exception or error occurs, Tempus Cloud persists it to the internal database. You can review this errors
via Web UI or get it using REST API. In case of misconfiguration or critical issue with plugin, errors may happen
quite frequently. Persisting all errors may significantly reduce performance, so you can configure how often errors are
persisted.
Lifecycle events
Whenever plugin or rule lifecycle event happens, Tempus Cloud persists it to the internal database. You can observe
status of the lifecycle, stack trace in case of errors, event time and server address. In case of misconfiguration, you can
easily detect the root cause by browsing the error stack trace.
Data Visualization
Getting Started
Tempus Cloud allows you to configure customizable IoT dashboards. Each IoT Dashboard may contain multiple
dashboard widgets that visualize data from multiple IoT devices. Once IoT Dashboard is created, you may assign it to
one of the customers of you IoT project. IoT Dashboards are light-weight and you may have millions of dashboards.
For example, you may automatically create a dashboard for each new customer based on data from registered customer
IoT devices. Or you may modify dashboard via script when a new device is assigned to a customer. All these actions
may be done manually or automated via REST API. You can find useful links to get started below:
• Getting started guide - will cover basic steps to create a dashboard.
• IoT Dashboards - contains tutorials about basic IoT dashboard operations.
• Samples - contains several examples that include both client-side applications and corresponding data visualiza-
tion.
• Widget Library - contains an overview of dashboard widget bundles:
– Digital and analog gauges for latest real-time values visualization
– Highly customizable Bar and Line charts for visualization of historical and sliding-window data points
– Map widgets for tracking movement and latest positions of IoT devices on Google or OpenStreet
maps.
– GPIO control widgets that allow sending GPIO toggle commands to devices.
– Card widgets to enhance your dashboards with flexible HTML labels based on static content or latest
telemetry values from IoT devices.
3.3 Installation
Platforms
This guide describes how to install Tempus Cloud on AWS EC2 using community AWS AMIs.
AMI is based on the microservices version of Tempus Cloud. The microservices are deployed as docker containers
using docker-compose on the Amazon Linux 2 OS. This AMI to simplify the deployment and getting started process.
We recommend to use the AMI as a trial environment and move to Tempus Cloud on EKS once you plan a production
deployment. For Tempus Cloud AMI you can choose any instance type with at least 4GB of RAM. The AMI is
available only in the N. Virginia zone.
Use the following link to start the installation of AMIs:
• N. Virginia
Configure Instance
No specific configuration items here. You can choose a t2.medium instance or above.
Add Storage
Minimum 20 Gb of Storage is required. We recommend having at least 50 if you plan to upload some data.
Add Tags
No specific configuration items here. You can leave this tab without changes or apply a configuration that is specific
to your use-case.
We recommend to create new security group, for example “Tempus”. Configure following inbound rules:
Once the instance is launched, please wait some time for services to boot up and open Administration UI in the browser
using public DNS from instance details.
Accessing Tempus Cloud service
Once the instance from AMI is created, please access http://your_public_ip to access the application.
You can use the following credentials to login:
Troubleshooting
You can issue the following command in order to check if there are any errors on the backend side:
Issue Logging
Schema Upgrade
These commands need to be run manually to alter/update the database for the mentioned stories.
1. The key point here is now, there can be computations other than spark computation namely kubleless computa-
tions.
2. The schema of the computation tables which currently holds the configuration parameters like jar_name,
jar_path etc will not be present in kubeless computation.
3. This means kubeless computation have different configuration, hence a need for schema alteration of computa-
tions.
For SQL
For NOSQL
3.4 API
Depending on the use case there are several different API’s that can be leveraged in Tempus. The following is a high
level breakdown of the API’s available in Tempus.
Data Acqusition
Getting started
This will guide you through how to provision nifi flow to fetch data for selective mnemonics for logs using nifi-witsml-
bundle.
You will need nifi-tempus-bundle and nifi-witsml-bundle for creating provisioning flow. Clone nifi-tempus-bundle and
nifi-witsml-bundle and build the respective maven projects. Finally copy the nar files to nifi lib directory.
• nifi-tempus-bundle : https://github.com/hashmapinc/nifi-tempus-bundle
• nifi-witsml-bundle : https://github.com/hashmapinc/nifi-witsml-bundle
1. On your nifi canvas create a flow as shown in image. This flow will let you fetch mnemonics for log object.
2. Configure ListObjects(GetLogs) processor as shown. This processor will fetch log meta-data with mnemonic
list from Witsml server.
3. EvaluateJsonPath(PopulateAttributesFromJson) processor will add flowfile-attributes from logs json data. Con-
figuration is being shown in image, don’t forget to add the highlighted mnemonicList attribute.
4. To validate the process you will need to list-queue between EvaluateJsonPath and LogToTempus. On attribute
tab you can see mnemonicList as below.
5. To convert the logs mnemonic list to Tempus gateway device attribute json format you will use LogToTempus
Processor.
6. LogToTempus processor configuration are shown as follows.
1. Create a nifi flow as follows to subscribe to shared attributes of tempus device and store the list of mnemonics
in a file.
2. ConsumeMqtt processor will subscribe to Tempus Device Attribute topic for shared attributes :
3. TempusToNodeList is processor from nifi-tempus-bundle will process the different types shared attributes json
messages from tempus.
4. TempusToNodeList takes File path which will be used as storage for extracted node mnemonic list from Json
messages. You also need to select the Data type as “WITSML”.
5. Output of TempusToNodeList will be passed on to PutFile processor to write/replace the updated node list to
the storage file :
1. Create nifi flow to read witsml-storage file and pass the mnemonics list to WitsmlJsonToAttribute processor.
2. GetFile processor will read the storage file in which you have been putting mnemonics list in previous steps.
NOTE : make “Keep Source File” as true.
3. WitsmlJsonToAttribute will read the flowfile content and add wellId, wellboreId, logId, wellName and mnemon-
ics as flowfile attributes.
4. Data from WitsmlJsonToAttribute will be passed to GetData(GetLogData) processor. GetData processor will
fetch data for only the selected mnemonics.
5. LogData from processor can be passed to LogToTempus processor to process the data and convert it into Tempus
GatewayJson format. Finally this data can be published through PublishMqtt processor.
Introduction
Tempus supports the streaming data quality analysis, which means the meta data and quality information related to
tags(i.e. keys) in telemetry data can be processed and stored.
For quality timeseries and depthseires data is processed over a period of time and depth respectively and various
aggregation constants avg, mean, median etc are calculated and stored for timestamp and depthstamp for each tag.
Getting Started
Sparkplug basics
Sparkplug is a specification for MQTT enabled devices and applications to send and receive messages in a stateful
way. While MQTT is stateful by nature it doesn’t ensure that all data on a receiving MQTT application is current or
valid. Sparkplug provides a mechanism for ensuring that remote device data is current and valid.
Sparkplug B specification specifies how various MQTT devices must connect and disconnect from the MQTT server
i.e. Tempus in our case. This includes device lifecycle messages such as the required birth and last will & testament
messages that must be sent to ensure the device lifecycle state and data integrity.
Sparkplug specification doc can be found here : https://s3.amazonaws.com/cirrus-link-com/Sparkplug+Specification+
Version+1.0.pdf
Open source library used
• We use cirrus link java client library for encoding and decoding the sparkplug B format data.
• Link of repo https://github.com/Cirrus-Link/Sparkplug.git
• This library internally uses Google protobuf for encoding/ decoding purpose.
Implementation
In tempus the data gets published to devices through MQTT clients, so we primarily focus on the sparkplug message
types related to device only i.e DBIRTH, DDATA, DDEATH. The state management for devices will also include
usage of these message types.
The implementation is divided in the following stages:
• Persisting sparkplug b specification payload data to tempus devices(sparkplug devices).
• State management for sparkplug devices on tempus side.
• Subscription of sparkplug b spec data devices on tempus by some external app.
• Tempus uses a gateway device to act as a bridge between external devices connected to different systems and
Tempus. Gateway API provides the ability to exchange data between multiple devices and the platform using
single MQTT connection.
• Publishing to a device through a gateway device results in creation of that device if it does not exists.
• Similarly a sparkplug B supported message would be published through a gateway device resulting in creation
of new devices, if not already created, which are compliant with sparkplug B specification.
• The topic name for publish would be different for each of the sparkplug device compliant with topic name
format defined in sparkplug B specification. For example the format structure is:
namespace/group_id/msg_type/edge_node_id/device_id
– The namespace element of the Topic Namespace is the root element that will define both the structure of
the remaining namespace elements as well as the encoding used for the associated payload data.
– The group_id element of the Topic Namespace provides for a logical grouping of MQTT EoN and Devices
into the MQTT Server and back out to the consuming MQTT Clients.
– The message_type element of the Topic Namespace provides an indication as to what the MQTT Payload
of message will contain(DDEATH, DBIRTH, DDATA).
– The edge_node_id element of the Sparkplug Topic Namespace uniquely identifies the MQTT EoN Node
within the infrastructure.
– The device_id element of the Sparkplug Topic Namespace identifies an MQTT Device attached to the
MQTT EoN Node. In our case it would be the name of device.
• The device access token would be the gateway device token.
• Dbirth, Ddeath, and Ddata messages would be used to manage the state of devices.
• For example if the client publishing loses connection with tempus mqtt server, the subscriber client connected
to tempus mqtt server is sent a Ddeath msg.
• If the client comes up again to publish data, it should publish Dbirth again followed by Ddata otherwise the
publish message would be discarded.
• Refer to the below diagram:
Subscription of sparkplug b spec data on tempus devices(sparkplug devices) by some external app
• Telemetry data for each of sparkplug device on tempus can be subscribed on a separate topic, whose name is as
per the sparkplug specification.
• The subscriber would be able to see the telemetry data if the telemetry data is being published to that sparkplug
device at that point of time.
• To test the sparkplug B spec support on Tempus, we need to have something which publishes data to tempus in
sparkplug B format.
• For this purpose we can again use the open source cirrus link sparkplug repo.
• Standalone sparkplug example for java i.e. SparkplugExample.java can be slightly modified for publishing as
well as subscribing telemetry data to and from Tempus.
API Usage
3.5 Security
Tempus MQTT Server and clients can be secure with multiple options.
Security Options
Tempus provides the ability to run MQTT server over SSL. Both one-way and two-way SSL are supported. To enable
SSL, you will need to obtain a valid or generate a self-signed SSL certificate and add it to the keystore. Once added,
you will need to specify the keystore information in tempus.yml file. See the instructions on how to generate SSL
certificate and use it in your Tempus installation below. You can skip certificate generation step if you already have a
certificate.
DOMAIN_SUFFIX="$(hostname)"
ORGANIZATIONAL_UNIT=Tempus
ORGANIZATION=Tempus
CITY=Roswell
STATE_OR_PROVINCE=GA
TWO_LETTER_COUNTRY_CODE=US
SERVER_KEYSTORE_PASSWORD=server_ks_password
SERVER_KEY_PASSWORD=server_key_password
SERVER_KEY_ALIAS="serveralias"
SERVER_FILE_PREFIX="mqttserver"
SERVER_KEYSTORE_DIR="/etc/tempus/conf/"
CLIENT_KEYSTORE_PASSWORD=password
CLIENT_KEY_PASSWORD=password
CLIENT_TRUSTSTORE="client_truststore"
CLIENT_KEY_ALIAS="clientalias"
CLIENT_FILE_PREFIX="mqttclient"
where
• DOMAIN_SUFFIX - Corresponds to CN value of the certificate. Must correspond to the target server domain
(wildcards are allowed). Defaults to the current hostname
• ORGANIZATIONAL_UNIT - Corresponds to OU value of the certificate.
• ORGANIZATION - Corresponds to O value of the certificate.
• CITY - Corresponds to L value of the certificate.
• STATE_OR_PROVINCE - Corresponds to ST value of the certificate.
• TWO_LETTER_COUNTRY_CODE - Corresponds to C value of the certificate.
• SERVER_KEYSTORE_PASSWORD - Server Keystore password
• SERVER_KEY_PASSWORD - Server Key password. May or may not be the same as
SERVER_KEYSTORE_PASSWORD
• SERVER_KEY_ALIAS - Server key alias. Must be unique within the keystore
• SERVER_FILE_PREFIX - Prefix to all server keygen-related output files
• SERVER_KEYSTORE_DIR - The default location where the key would be optionally copied. Can be overri-
den by -d option in server.keygen.sh script or entered manually upon the scrip run
The rest of the values are not important for the server keystore generation To run the server keystore generation, use
following commands.
keytool -genkeypair -v \
-alias $SERVER_KEY_ALIAS \
-dname "CN=$DOMAIN_SUFFIX, OU=$ORGANIZATIONAL_UNIT, O=$ORGANIZATION, L=$CITY, ST=
˓→$STATE_OR_PROVINCE, C=$TWO_LETTER_COUNTRY_CODE" \
-keystore $SERVER_FILE_PREFIX.jks \
-keypass $SERVER_KEY_PASSWORD \
-storepass $SERVER_KEYSTORE_PASSWORD \
-keyalg RSA \
-keysize 2048 \
-validity 9999
keytool -export \
-alias $SERVER_KEY_ALIAS \
-keystore $SERVER_FILE_PREFIX.jks \
-file $SERVER_FILE_PREFIX.pub.pem -rfc \
-storepass $SERVER_KEYSTORE_PASSWORD
keytool -export \
-alias $SERVER_KEY_ALIAS \
-file $SERVER_FILE_PREFIX.cer \
-keystore $SERVER_FILE_PREFIX.jks \
-storepass $SERVER_KEYSTORE_PASSWORD \
-keypass $SERVER_KEY_PASSWORD
mkdir -p $SERVER_KEYSTORE_DIR
cp $SERVER_FILE_PREFIX.jks $SERVER_KEYSTORE_DIR
The keytool will used the configuration specified and will generate the following output files:
• SERVER_FILE_PREFIX.jks - Java keystore file. This is the file which will be used by Tempus MQTT Service
• SERVER_FILE_PREFIX.cer - Server public key file. It will be then imported to client’s .jks keystore file.
• SERVER_FILE_PREFIX.pub.pem - Server public key in PEM format, which can be then used as a keystore
or imported by non-Java clients.
To copy the keystore file, upload it manually to a directory which is in server’s classpath. You may want to modify
owner and permissions for the keystore file:
Server configuration
Locate your tempus.yml file and uncomment the lines after “# Uncomment the following lines to enable ssl for
MQTT”:
You may also want to change mqtt.bind_port to 8883 which is recommended for MQTT over SSL servers. The
key_store Property must point to the .jks file location. key_store_password and key_password must be the same as
were used in keystore generation.
NOTE: Tempus supports .p12 keystores as well. if this is the case, set key_store_type value to ‘PKCS12’ After these
values are set, launch or restart your tempus server.
Client Examples
Device credentials are used in order to connect to the Tempus server by applications that are running on the device.
Tempus is designed to support different device credentials. There are two supported credentials types at the moment:
• Access Tokens - general purpose credentials that are suitable for wide range of devices. Access Token based
authentication may be used in not encrypted or one-way SSL mode.
– Advantages: supported by resource constrained devices. Low network overhead. Easy to provision and
use.
– Disadvantages: may be easily intercepted while using un-encrypted network connection (HTTP instead
of HTTPS, MQTT without TLS/SSL, etc).
• X.509 Certificates - PKI and TLS standard. X.509 Certificate based authentication is used in two-way SSL
mode.
– Advantages: high level of security using the encrypted network connection and public key infrastructure.
– Disadvantages: not supported by some resource constrained devices. Affects battery and CPU usage.
Device credentials need to be provisioned to corresponding device entity on the server. There are multiple ways to do
this:
• Automatically, using Tempus Swagger. For example during manufacturing, QA or purchase order fulfilment.
• Manually, using Tempus Web UI. For example for development purposes, or by system administrator.
Access Token based authenication
Access Token Based Authentication is the default device authentication type. Once the device is created in Tempus,
the default access token is generated. It can be changed afterwards. In order to connect the device to a server using
Access Token based authentication, the client must specify the access token as part of request URL (for HTTP and
CoAP) or as a user name in MQTT connect message. See supported protocols API for more details.
One-way SSL authentication is a standard authentication mode, where your client device verifies the identity of a
server using server certificate. In order to run one-way MQTT SSL, the server certificate chain should be signed by
authorized CA or client must import the self-signed server certificate (.cer or .pem) to its trust store. Otherwise, a
connection will fail with the ‘Unknown CA’ error.
X.509 Certificate Based Authentication is used in Two-Way SSL connection. In this case, the certificate itself is the
client’s ID, thus, Access Token is no longer needed.
Instructions below will describe how to generate a client-side certificate and connect to the server that is running MQTT
over SSL. You will need to have the public key of the server certificate in PEM format. See following instructions for
more details on server-side configuration.
Export the following enviroment variable, and update the values if needed:
DOMAIN_SUFFIX="$(hostname)"
ORGANIZATIONAL_UNIT=Tempus
ORGANIZATION=Tempus
CITY=Roswell
STATE_OR_PROVINCE=GA
TWO_LETTER_COUNTRY_CODE=US
SERVER_KEYSTORE_PASSWORD=server_ks_password
SERVER_KEY_PASSWORD=server_key_password
SERVER_KEY_ALIAS="serveralias"
SERVER_FILE_PREFIX="mqttserver"
SERVER_KEYSTORE_DIR="/etc/tempus/conf/"
CLIENT_KEYSTORE_PASSWORD=password
CLIENT_KEY_PASSWORD=password
CLIENT_KEY_ALIAS="clientalias"
CLIENT_FILE_PREFIX="mqttclient"
-keystore $SERVER_FILE_PREFIX.jks \
-keypass $SERVER_KEY_PASSWORD \
-storepass $SERVER_KEYSTORE_PASSWORD \
-keyalg RSA \
-keysize 2048 \
-validity 9999
keytool -export \
-alias $SERVER_KEY_ALIAS \
-keystore $SERVER_FILE_PREFIX.jks \
-file $SERVER_FILE_PREFIX.pub.pem -rfc \
-storepass $SERVER_KEYSTORE_PASSWORD
keytool -export \
-alias $SERVER_KEY_ALIAS \
-file $SERVER_FILE_PREFIX.cer \
-keystore $SERVER_FILE_PREFIX.jks \
-storepass $SERVER_KEYSTORE_PASSWORD \
-keypass $SERVER_KEY_PASSWORD
mkdir -p $SERVER_KEYSTORE_DIR
cp $SERVER_FILE_PREFIX.jks $SERVER_KEYSTORE_DIR
Go to Tempus Web UI -> Devices -> Your Device -> Device Credentials. Select X.509 Certificate device credentials,
insert the contents of CLIENT_FILE_PREFIX.pub.pem file and click save. Alternatively, the same can be done
through the REST API.
3.6 Administration UI
Administration
Tenants
Tempus support Multitenancy out-of-the-box. You can treat Tempus tenant as a separate business-entity: individual or
organization who owns or produce devices.
System administrator is able to create tenant entities.
System administrator is also able to create multiple users with Tenant Administrator role for each tenant by pressing
“Manage Tenant Admins” button in Tenant details.
Business Units
Tenant administrator is able create new business unit or delete them from Tempus.
Manage business unit users
Activation link is provided for a user to activate an account and create a password.
Create user password
Tempus supports following asset management features using Web UI and Swagger.
Tenant administrator is able to register new assets or delete them from Tempus.
Get Asset Id
Tenant administrator and business unit users are able to copy asset id to clipboard using “Copy Asset Id” button.
Tenant administrator is able to assign assets to certain business unit. This will allow Customer users to fetch asset data
using REST APIs or Web UI.
Manage asset attributes
Tenant administrator and business unit users are able to manage asset server-side attributes.
Browse asset alarms
Tenant administrator and business unit users are able to browse asset alarms.
Browse asset events
Tenant administrator and business unit users are able to browse events related to particular asset using “Events” tab.
Lifecycle events and statistics are coming soon.
Tenant administrator and business unit users are able to manage asset relations.
Devices
Tempus supports following device management features using Web UI and Swagger.
Tenant administrator is able to register new devices or delete them from Tempus.
Manage device credentials
Tenant administrator is able to manage device credentials. Current release supports Access Token and X.509 Certifi-
cates based credentials.
Get Device Id
Tenant administrator and business unit users are able to copy device id to the clipboard using “Copy Device Id” button.
Assign devices to business units
Tenant administrator is able to assign devices to certain business unit. This will allow Customer users to fetch device
data using REST APIs or Web UI.
Tenant administrator and business unit users are able to browse device attributes.
Browse device telemetry
Tenant administrator and business unit users are able to browse device telemetry data.
Browse device alarms
Tenant administrator and business unit users are able to browse device alarms.
Browse device events
Tenant administrator and business unit users are able to browse events related to a particular device using “Events”
tab. Lifecycle events and statistics are coming soon.
Tenant administrator and business unit users are able to manage device relations.
Rules
Rules page
Rules Administration UI page displays a table of system and tenant specific rules. Each rule has a separate card. You
are able to do following operations:
• Import Or Create new Rule
• Export Rule to JSON
• Suspend and Activate particular Rule
• Delete the Rule
See Rule Engine documentation for more details.
Rules details
Each rule is a represented as a separate card. You are able to edit rule components and review the rule events in the
Rule details panel.
You are also able to review rule life-cycle events, rule stats, and errors during message processing. Please note that in
case of frequent errors the error messages are sampled.
Rules import/export
Rule export
You are able to export your rule to JSON format and import it to the same or another Tempus instance. In order to
export rule, you should navigate to the Rules page and click on the export button located on the particular rule card.
Rule import
Similar, to import the rule you should navigate to the Rules page and click on the big “+” button in the bottom-right
part of the screen and then click on the import button.
Note All imported rules are in the suspended state. Don’t forget to activate your rule after import.
Troubleshooting
Plugins
Plugins page
Plugins Administration UI page displays a table of system and tenant specific plugins. Each plugin has a separate card.
You are able to do following operations:
• Import Or Create new Plugin
• Export Plugin to JSON
• Suspend and Activate particular Plugin
• Delete the Plugin
See Rule Engine documentation for more details.
Plugin details
Each plugin is a represented as a separate card. You are able to edit plugin configuration and review the plugin events
in the Plugin details panel.
Kafka Plugins
You are also able to review plugin life-cycle events, stats, and errors during message processing. Please note that in
case of frequent errors the error messages are sampled.
Plugin import/export
Plugin export
You are able to export your plugin to JSON format and import it to the same or another Tempus instance. In order to
export plugin, you should navigate to the Plugins page and click on the export button located on the particular plugin
card.
Plugin import
Similar, to import the plugin you should navigate to the Plugins page and click on the big “+” button in the bottom-right
part of the screen and then click on the import button.
SQS Plugins
You are also able to review plugin life-cycle events, stats, and errors during message processing. Please note that in
case of frequent errors the error messages are sampled.
Plugin import/export
Plugin export
You are able to export your plugin to JSON format and import it to the same or another Tempus instance. In order to
export plugin, you should navigate to the Plugins page and click on the export button located on the particular plugin
card.
Plugin import
Similar, to import the plugin you should navigate to the Plugins page and click on the big “+” button in the bottom-right
part of the screen and then click on the import button.
Kinesis Plugins
Plugin import/export
Plugin export
You are able to export your plugin to JSON format and import it to the same or another Tempus instance. In order to
export plugin, you should navigate to the Plugins page and click on the export button located on the particular plugin
card.
Plugin import
Similar, to import the plugin you should navigate to the Plugins page and click on the big “+” button in the bottom-right
part of the screen and then click on the import button.
Note All imported plugins are in the suspended state. Don’t forget to activate your plugin after import.
Troubleshooting
Widget Library
Introduction
All IoT Dashboards are constructed using Tempus widgets that are defined in Widget Library. Each widget provides
end-user functions such as data visualization, remote device control, alarms management and displaying static custom
html content.
Widget Types
According to the provided features, each widget definition represents specific widget type. At the moment there are
five widget types:
• Latest values
• Time-series
• RPC (Control widget)
• Alarm Widget
• Static
Each widget type has own specific datasource configuration and corresponding widget API. Each widget requires
datasource for data visualization. Types of the available datasource depend on widget type of the widget:
• Target device - this datasource type is used in RPC. Basically, you need to specify target device for RPC widget
• Alarm source - this datasource type is used in Alarm widgets. This datasource requires source entity to display
related alarms and corresponding alarm fields.
• Entity - this datasource type is used in both time-series and latest values widgets. Basically, you need to specify
target entity and timeseries key or attribute name.
• Function - this datasource type is used in both time-series and latest values widgets for debug purposes. Basi-
cally, you are able to specify a javascript function that will emulate data from a device in order to tune visual-
ization.
Latest values
Displays latest values of particular entity attribute or timeseries data point (for ex. any Gauge Widget or Entities Table
widget). This kind of widgets uses values of entity attribute(s) or timeseries as datasource.
Below is an example of latest values widget - Digital Gauge displaying current power value.
Time-series
Displays historical values for the selected time period or latest values in the certain time window (for ex. “Timeseries
- Flot” or “Timeseries table”). This kind of widgets uses only values of entity timeseries as datasource. In order
to specify the time frame of displayed values, Timewindow settings are used. Timewindow can be specified on the
dashboard level or on the widget level. It can be either realtime - dynamically changed time frame for some latest
interval, or history - fixed historical time frame. All these settings are part of Time-series widget configuration.
Below is an example of time series widget - “Timeseries - Flot” displaying amperage values of three devices in real-
time.
RPC (Control widget)
Allows to send RPC commands to devices and handles/visualize reply from the device (for ex. “Raspberry Pi GPIO
Control”). RPC widgets are configured by specifying target device as target endpoint for RPC commands.
Below is an example of RPC widget - “Basic GPIO Control” - sending GPIO switch commands and detecting current
GPIOs switch status.
Alarm Widget
Display alarms related to the specified entity in the certain time window (for ex. “Alarms table”). Alarm widgets
are configured by specifying entity as alarms source and corresponding alarm fields. Like Time-series widgets alarm
widgets have the timewindow configuration in order to specify the time frame of displayed alarms. Additionally
configuration contains “Alarm status” and “Alarms polling interval” parameters. “Alarm status” parameter specifies
the status of alarms being fetched. “Alarms polling interval” controls alarms fetching frequency in seconds.
Below is an example of Alarm widget - “Alarms table” displaying latest alarms for the asset in real-time.
Static
Displays static customizable html content (for ex. “HTML card”). Static widgets don’t use any datasources and
usually configured by specifying static html content and optionally css styles.
Below is an example of a Static widget - “HTML card” displaying specified html content.
Widget definitions are grouped into widget bundles according to their purpose. There are System level and Tenant
level Widgets Bundles. Initial Tempus installation is shipped with the basic set of system level Widgets Bundles.
There are more than thirty widgets in seven widget bundles available out-of-the-box. System level bundles can be
managed by a System administrator and are available for use by any tenant in the system. Tenant level bundles can
be managed by a Tenant administrator and are available for use only by this tenant and its business units. You can
always implement and add your widgets by following this guide.
Digital Gauges
Useful for visualization of temperature, humidity, speed and other integer or float values.
Analog Gauges
Charts
Useful for visualization and control of GPIO state for target devices.
Control widgets
Useful for visualize current state and send RPC commands to target devices.
Maps widgets
Useful for visualization of devices geo locations and track devices routes both in real-time and history mode.
Cards
Alarm widgets
Useful for visualization of alarms for specific entities both in real-time and history mode.
You are able to export widgets bundle to JSON format and import it to the same or another Tempus instance. In order
to export widgets bundle, you should navigate to the Widgets Library page and click on the export button located on
the particular widgets bundle card.
Widgets Bundle import
Similar, to import the widgets bundle you should navigate to the Widgets Library page and click on the big “+” button
in the bottom-right part of the screen and then click on the import button.
The widgets bundle import window should a popup and you will be prompted to upload the json file.
You are able to export particular widget type from widgets bundle to JSON format and import it to the same or another
Tempus instance. In order to export widget type, you should navigate to the Widgets Library page, then open desired
widgets bundle and finally click on the export button located on the particular widget type card.
Similar, to import the widget type you should navigate to the Widgets Library page, then open your widgets bundle
and click on the big “+” button in the bottom-right part of the screen and then click on the import button.
The widget type import window will show a popup and you will be prompted to upload the json file.
Dashboards
Tempus allow you to define default IoT dashboard for your business unit users in 2 simple steps:
Navigate to “Business Unit -> Your business unit -> Buinsess Unit Users” and toggle edit mode using ‘pencil’ button
in the top-right corner of the screen.
Select the IoT dashboard from the list and apply changes. Please note that you can also check the “Always Fullscreen”
mode to prevent a user from navigating to different dashboards/screens.
IoT Dashboard import/export
Dashboard export
You are able to export your dashboard to JSON format and import it to the same or another Tempus instance. In
order to export dashboard, you should navigate to the Dashboards page and click on the export button located on the
particular dashboard card.
Dashboard import
Similar, to import the dashboard you should navigate to the Dashboards page and click on the big “+” button in the
bottom-right part of the screen and then click on the import button.
The dashboard import window should popup and you will be prompted to upload the json file.
Once you click on the “import” button you will need to specify the device aliases. This basically allows you to set
what device(s) correspond to dashboard alias.
Cluster Information
Mail Settings
Tempus System Administrator is able to configure a connection to a SMTP server that will be used to distribute
activation and password reset emails to users. This configuration step is required in production environments. If you
are evaluating the platform, pre-provisioned demo accounts are sufficient in most of the use cases. NOTE System Mail
settings are used only during user creation and password reset process and are controlled by a system administrator.
Tenant administrator is able to setup email plugin to distribute alarms produced by rule engine.
• Step 1. Login as system administrator
• Step 2. Change administrator email address
• Step 3. Open ‘Outgoing Mail’ and populate SMTP server settings
– Step 3.1. Sendgrid configuration example
– Step 3.2. Gmail configuration example
• Step 4. Save configuration
Following steps are required to configure system mail settings.
Login to your Tempus instance WEB UI as a system administrator using default account.
Right click on the burger in the top-right corner of the WEB UI and select ‘Profile’. Change ‘sysad-
[email protected]’ to your email address. Now re-login as administrator again.
Navigate to System Settings -> Outgoing Mail and populate the form. Click on ‘Send Test Email’ button. A test email
will be sent to the email address that you have specified in ‘Step 2’. In case of error in configuration, you should
receive a popup with the error log.
SendGrid configuration is fairly simple and straightforward. First, you need to create SendGrid account. You can try
it for free and the free plan is most likely enough for platform evaluation. Once you create your account, you will be
forwarded to the welcome page. Now you can provision your SMTP Relay credentials. See the screen-shot below.
Once you populate the API key name and generate it, you will be able to copy-paste settings from the screen to Tempus
mail settings form.
Copy-paste the settings, update ‘Mail From’ field and click on ‘Send Test Mail’ button.
Once you receive the notification about a successfull test, save populated data. You can also complete verification on
the SendGrid website.
Step 3.2. Gmail configuration example
In order to use G-mail, you will need to do two extra steps. First, you need to allow less secure apps. Second, you
need to enable two-step verification and generate an app password. Although the second step is not mandatory, it is
highly recommended.
Once this is ready, you should be able to setup Gmail account using the information below
Similar settings are available for G-suite accounts, however, you may need to contact your system administrator to
enable less secure apps, etc. Note that you can also enable/disable TLS using checkbox.
Step 4. Save configuration
Once you will receive test email you can save SMTP server configuration.
WhiteLabeling
Tempus System Administrator is able to configure a Theme depending on there branding, also System Administrator
can change the default Logo for the application.
Change Theme
System Administrator can change the Theme on the system which will be applicable to all the Users,Tenant admin
and Customers.
Change Logo
System Administrator can change the Logo on the system which will be applicable to all the Users,Tenant admin and
Customers.
Agent
Tempus support configuring and deploying agent. Agent is nothing but tempus-gateway that allows you to integrate
IoT devices connected to legacy and third-party systems with Tempus Cloud.
Agent Configuration
Once the agent configuration has been saved. It can deploy by clicking on deploy button. Here is the screenshot
representing how the status will look after clicking on deploy:
The rule engine consists of 4 distinct parts. They are discussed in the sections below.
Rule Engine Components
Processors
There are 5 filter types that allow a tenant administrator to perform a number of data driven actions.
Filter Types
Overview
This component allows filtering incoming messages by attributes of the device. This filter is very useful if you want
to apply the rule only to the certain sub-set of your device. Filter expression is a javascript expression and basically
defines this sub-set. You are able to use any attribute types.
Configuration
You are able to write boolean javascript expression using following bindings:
• cs - client-side attributes map.
• ss - server-side attributes map.
• shared - shared attributes map.
If you are not sure that certain attribute is present, you can add check it’s type for undefined. For example, filter below
will match if client-side attribute ‘firmware_version’ is set and equal to ‘1.0.0’
Example
If you are not sure that all attributes are present for your device, you should use the following syntax that adds all
necessary “null” checks
typeof cs.firmware_version !== 'undefined' &&
typeof cs.country !== 'undefined' &&
typeof shared.subscription_plan !== 'undefined' &&
typeof ss.balance !== 'undefined' &&
cs.firmware_version=='1.1.0' && cs.country=='USA' && shared.subscription_plan==
˓→'premium' && ss.balance > 0
Overview
This component allows filtering incoming messages by type. This filter is very efficient. We recommend using this
filter in almost every rule to quickly ignore irrelevant messages.
Configuration
You are able to select multiple types: “Get Attributes”, “Post Attributes”, “Post Telemetry” and “RPC Request”.
Example
As a system administrator, you are able to review filter example inside Rules->System Telemetry Rule->Filters-
>Message Telemetry Filter.
Device Telemetry Filter
Overview
This component allows filtering incoming telemetry messages by their values. This filter is very useful if you want
to apply rule based on certain values of telemetry. For example, an engine controller may periodically report its
temperature. When engine temperature is higher than 100 degrees you may raise an alert. The filter expression is
written in javascript.
Configuration
You are able to write boolean javascript expression using bindings that match keys of your telemetry message. If you
are not sure that certain key is present in your message, you can add check it’s type for undefined. For example, filter
below will match if temperature is higher then 100 degrees.
The following filter will match if device is enabled, operating in mode ‘A’ and temperature is greater than 1000 degrees
temperature > 1000 && enabled == true && mode == 'A'
If you are not sure that all telemetry data points are present in the message, you should use the following syntax that
adds all necessary “null” checks
typeof temperature!== 'undefined' && typeof enabled !== 'undefined' && typeof mode !
˓→== 'undefined' &&
Example
This component allows filtering incoming RPC request messages by method name. This filter is very efficient and
useful to forward RPC request to particular plugins that handle them.
Configuration
You are able to select multiple method names in one filter. For example, if you want to have two plugins (their
functionality is just for the demo purposes):
• plugin A allows getting current time
• plugin B allows getting the weather forecast You may implement plugin A to handle getTime method and plugin
B to handle getWeather method. In this case you will need to configure two rules:
• rule A that points to plugin A based on “getTime” method filter
• rule B that points to plugin B based on “getWeather” method filter
Overview
This component allows for filtering data based on the Device Type of the device that the data originated from.
Configuration
You are able to add one or more device types to the filter. Simply click the + NEW button and add the device type to
filter on.
Example
Actions
Actions are executions via plugins that allow Tempus to perform a task based on the result of one or more filters within
a rule.
Action Types
Overview
This component allows creating a kafka message by substitution of device attributes and message data into configurable
templates.
Configuration
Overview
This component allows creating RabbitMQ message by substitution of device attributes and message data into config-
urable templates.
Configuration
During action configuration you are able to specify following: * set flag to confirm delivery * rabbitmq
exchange name * rabbitmq queue name * rabbitmq message properties (BASIC, MINIMAL_BASIC, MINI-
MAL_PERSISTENT_BASIC, PERSISTENT_BASIC, PERSISTENT_TEXT_PLAIN, TEXT_PLAIN) * rabbitmq
message body template The Body Template syntax is based on Velocity
Overview
This component allows creating a POST/PUT request body by substitution of device attributes and message data into
configurable templates.
Configuration
Overview
This component allows building email message by substitution of device attributes and message data into configurable
templates.
Configuration
During action configuration you are able to specify following templates: from, to, cc, bcc, subject and body. The
template syntax is based on Velocity and is already described in alarm processor documentation. Additionally, you
can specify Send Flag property. This is an optional property that may be used in combination with isNewAlarm or left
blank.
Overview
This component allows forwarding incoming attributes and timeseries requests to telemetry plugin.
Configuration
Example
As a system administrator, you are able to review action example inside Rules->System Telemetry Rule->Actions-
>Telemetry Plugin Action.
Plugins
Plugins allow Tempus to interact with other systems through various means. The currently supported plugins are
below.
Platforms
Overview
This RPC plugin enables communication between various IoT devices through the Tempus cluster. The plugin intro-
duces basic security features: devices are able to exchange messages only if they belong to the same customer. The
plugin implementation can be customized to cover more complex security features. Configuration
You can specify following configuration parameters:
• Maximum amount of devices per customer
• Default request timeout
• Maximum request timeout
The plugin handles two rpc methods: getDevices and sendMsg. The examples listed below will be based on demo
account and MQTT protocol. Please note that you are able to use other protocols - CoAP and HTTP.
In order to send a message to other devices, you will need to know their identifiers. A device can request a list of other
devices that belong to the same customer using getDevices RPC call.
mqtt-get-device-list.sh
export TOKEN=A1_TEST_TOKEN
node mqtt-get-device-list.js
mqtt-get-device-list.js
client.on('connect', function () {
console.log('connected');
client.subscribe('v1/devices/me/rpc/response/+');
var requestId = 1;
var request = {
"method": "getDevices",
"params": {}
};
client.publish('v1/devices/me/rpc/request/' + requestId, JSON.stringify(request));
});
[
{
"id": "aa435e80-9fce-11e6-8080-808080808080",
"name": "Test Device A2"
},
{
"id": "86801880-9fce-11e6-8080-808080808080",
"name": "Test Device A3"
}
]
A device can send a message to other device that belongs to the same customer using sendMsg RPC call. The example
below will attempt to send a message from device “Test Device A1” to device “Test Device A2”.
mqtt-send-msg.sh
export TOKEN=A1_TEST_TOKEN
node 'mqtt-send-msg.js'
mqtt-send-msg.js
client.on('connect', function () {
console.log('connected');
client.subscribe('v1/devices/me/rpc/response/+');
var requestId = 1;
var request = {
method: "sendMsg",
params: {
deviceId: "aa435e80-9fce-11e6-8080-808080808080",
timeout: 2000,
oneway: false,
body: {
param1: "value1"
}
}
};
client.publish('v1/devices/me/rpc/request/' + requestId, JSON.stringify(request));
});
export TOKEN=A2_TEST_TOKEN
node mqtt-receive-msg.js
mqtt-recieve-msg.sh
client.on('connect', function () {
console.log('connected');
client.subscribe('v1/devices/me/rpc/request/+');
});
{"status":"ok"}
Note that target device id, access tokens, request and response bodies are hardcoded into scripts and correspond to
devices that must be created beforehand.
Telemetry Plugin
Overview
Telemetry plugin is responsible for: * persisting attribute updates to internal data storage; * persisting timeseries data
to internal data storage; * provides server-side API to query and subscribe for data updates. Since Telemetry plugin
functionality is critical for data visualization purposes in dashboards, it is configured on the system level by a system
administrator. Advanced users or platform developers can customize telemetry plugin functionality.
Configuration
Server-side API
Telemetry plugin API description is available in corresponding attributes and telemetry guides.
Example
As a system administrator, you are able to review plugin example inside Plugins->System Telemetry Plugin.
RPC Plugin
Overview
RPC plugin is responsible for: * providing REST API to send RPC request from server-side applications to devices; *
pushing RPC request to devices via one of available protocols: MQTT, CoAP or HTTP;
By default, this plugin is configured on the system level by a system administrator. You are able to configure your own
instance of the plugin on tenant level. Advanced users or platform developers can customize rpc plugin functionality.
Configuration
You can specify default RPC timeout for plugin instance in the plugin configuration.
Server-side API
Mail Plugin
Overview
Mail plugin is responsible for sending email messages that are triggered by corresponding rule actions.
Configuration
Server-side API
Kafka Plugin
Overview
Kafka plugin is responsible for sending messages to Kafka brokers triggered by specific rules
Configuration
Example
In this example, we are going to demonstrate how you can configure this extension to be able to send a message to
Kafka topic every time new telemetry message for the device arrives.
Prerequisites before contining Kafka extension configuration:
• Kafka broker is up and running
• Appropriate Kafka Topic created
• Tempus is up and running
Let’s configure Kafka plugin first. Go to Plugins menu and create new plugin:
Please set correctly Kafka Bootstrap Servers URL and any other parameters located in plugin configuration section
that is suitable for your case so Kafka extension is able to connect to Kafka broker.
Click on Activate plugin button:
{"temp":73.4}
You should see 73.4 message in appropriate Kafka topic once you’ll post this message. Here is an example of a
command that publish single telemetry message to locally installed Tempus:
Overview
Simple RPC plugin that is responsible for handling “getTime” RPC request from devices. This plugin is a part of
default Tempus installation for demo purposes. It demonstrates that devices can send RPC request via various connec-
tivity protocols to execute server-side logic and get the result.
Configuration
You can specify time format configuration parameter. See DateTimeFormatter API for more details.
Server-side API
This reference document explains different actions and operation related to Data Model. The document includes
creation, updation, deletion and assignment of Data Model to different Business Units and creating Asset Landing
Pages for DataModel Objects.
Data Model Information
The page displays the overall created Data Model for login tenant admin.
Click on orange button to Add a Data Model, a pop-up will open, fill in the details related to Data Model. On clicking
on Add button, you will be redirected to canvas for Adding DataModel Objects.
For adding DataModel Object refer DataModel Object Reference documentation.
This reference explains the different parts and operation related DataModel Object like creation, updation and deletion.
Object Information
The first page of the DataModel Object creation stepper is for entering general object information. This includes:
• Object Name - the name of the object. This must be unique within a datamodel.
• Object Description - the optional description of the object.
• Object Type - the type of object this is. This can be either Device or Asset.
• Object Icon - the icon of object. This can only be provided for Asset.
For our example, let’s create a Developer object.
Object Attributes
The Object Attributes section is where the attribute fields of this object are defined. For our Developer example
object, we have created attributes for:
• Name - the name of the developer. This could be manually entered for each developer.
• Age - the age of the developer. This could be updated based on an external birthday metadata source.
• Heart Rate - the developer’s heart rate. This could come from a fitness Device associated with the devel-
oper.
• Location - the location of the developer. This could come from a mobile Device associated with the
developer.
These attributes are of course just examples to illustrate how to use object attributes. We don’t actually monitor the
developers this closely (yet).
Object Relationships
The Relationships section is where the DataModel Object can define how it relates to other objects in the DataModel.
At this point, only a Parent relationship is supported, but more general relationships will be supported in the future.
For our example, let’s assume we have already created a Manager datamodel object that we would like to assign as
the Parent of our Developer object.
Object Review
The Review section allows us to review the DataModel Object we have defined.
For our example, this looks right for our Developer object. We will accept by clicking Submit to save our object
to the datamodel.
NOTE : After adding DataModel Objects click on the orange tick button on buttom right corner, otherwise your changes
will not be saved.
Object Saved Review
The final DataObject Model view for Developer Object after submitting and saving changes of DataModel.
Results
With that, we have created our first small DataModel Object. This can be expanded to account for the devices associ-
ated with a Developer (macbook, fitness tracker, phone, etc. . . ).
To assign a Data Model to a Business Unit, move to Business Unit tab and click on particular Business Unit card. This
will open a side navigation for Business Unit, now click on edit and select the Data Model from DataModel drop-down
and finally apply changes.
For creating Asset Landing Pages refer to Asset Landing Page document.
Results
3.9 Development
Source Code
The Tempus source code is version controlled using Git version control at GitHub
The Tempus documentation source code is available at GitHub
Issue Tracking
Building
We recommend running the following git config commands in order to ensure that git checks out the repository in a
consistent manner. These changes are particularly important if running on Windows, as the git client has trouble with
long filenames otherwise. Additionally, in Windows, the default behavior of the git client, when installed, is to set the
core.autocrlf configuration option to true, which can cause some of the unit tests to fail.
git config --global core.longpaths true
git config --global core.autocrlf false
The master branch currently represents the last release of Tempus. If you would like to work on the active / stable
branch you need to check out the ‘dev’ branch.
Pre-requisites
• Docker
• Docker Compose
• Make
• Maven > 3.1
• JDK 8
Source Code
The Tempus source code is version controlled using Git version control at GitHub
The Tempus documentation source code is available at GitHub
Issue Tracking
Introduction
The TempusDevEnvironment orchestrates the setup of a developer environment suitable for demos or development
work. This setup requires 3 repositories to be pulled:
1. TempusDevEnvironment (this one)
2. Tempus (described above)
3. Nifi-simulator-bundle (described below)
Checking out the TempusDevEnvironment from Git
Once you have cloned both repositories edit the Makefile in the root of the TempusDevEnvironment project.
Modify the top 2 lines that specify PROJECT_DIR (this is the root of the Tempus project) and the
SIM_PROJECT_DIR (this is the simulator bundle that was cloned with the command above).
There are 6 options in this make file:
1. Install
• This will only build Tempus and the Simulator bundle following the steps in the first section
2. Copy
• This will copy the files to the appropriate place so the docker images can be built
3. Build
• This will build and start the docker compose
4. Build-ldap
• This will build the environment with openLdap and ldapAdmin
To get started run
make all
Introduction
Tempus Cloud widgets are additional UI modules that can be easily integrated into any Dashboard and provide end-
user functions such as data visualization, remote device control, alarms management and displaying static custom html
content. According to the provided features each widget definition represents specific Widget Type.
In order to create a new widget definition, navigate to the “Widget Library”, then open existing “Widgets Bundle” or
create a new one. In the “Widgets Bundle” view, click on the big “+” button in the bottom-right part of the screen and
then click on the “Create new widget type” button.
Select widget type window should popup and you will be prompted to select corresponding widget type that you are
going to develop.
After that the “Widget Editor” page will be opened pre-populated with the starter widget template according to the
previously selected widget type.
Widget Editor overview
Widget Editor view represents mini IDE designed to develop custom widget definitions. It consists of top toolbar and
four main sections:
• Resources/HTML/CSS
• JavaScript
• Settings schema
• Widget preview
Resources/HTML/CSS section
This section consists of three tabs. The first Resources tab is used to specify external JavaScript/CSS resources used
by the widget.
Second HTML tab contains widget html code (Note: some widgets create html content dynamically and initial html
content can be empty).
Third CSS tab contains widget specific CSS style definitions.
JavaScript section
This section contains all widget related JavaScript code according to the Widget API.
This section consists of two tabs. The first Settings schema tab is used to specify json schema of widget settings in
order to auto-generate UI form using react-schema-form builder. This generated UI form is displayed in the Advanced
tab of widget settings. Settings Object serialized by this schema is used to store specific widget settings and accessible
from widget JavaScript code.
Second Data key settings schema tab is used to specify json schema of particular data key settings in order to auto-
generate UI form using react-schema-form builder. This generated UI form is displayed in Advanced tab of the Data
key configuration dialog. Settings Object serialized by this schema is used to store specific settings for each data key
of the datasource defined in the widget. These settings are accessible from widget JavaScript code.
Widget preview section
This section is used to preview and test widget definition. It is presented as mini dashboard containing one widget
instantiated from the current widget definition. It has mostly all functionality provided by usual Tempus dashboard but
has some limitations. For example, only “Function” can be selected as datasource type in widget datasources section
for debug purposes.
All widget related code is located in the JavaScript section. The built-in variable self that is a reference to the widget
instance is also available. Each widget function should be defined as a property of the self variable. self variable has
property ctx - reference to widget context that has all necessary API and data used by widget instance. Below is brief
description of widget context properties:
In order to implement new widget the following JavaScript functions should be defined (Note: each function is optional
and can be implemented according to the widget specific/behaviour):
Function Description
onInit() The first function which is called when widget is ready for initialization. Should be used to
prepare widget DOM, process widget settings and initial subscription information.
onDataUp- Called when the new data is available from the widget subscription. Latest data can be ac-
dated() cessed from the defaultSubscription object of widget context (ctx).
onResize() Called when widget container is resized. Latest width and height can be obtained from widget
context (ctx).
onEditMod- Called when dashboard editing mode is changed. Latest mode is handled by isEdit property
eChanged() of ctx.
onMobileMod- Called when dashboard view width crosses mobile breakpoint. Latest state is handled by
eChanged() isMobile property of ctx.
onDestroy() Called when widget element is destroyed. Should be used to cleanup all resources if necessary.
getSettingsS- Optional function returning widget settings schema json as alternative to Settings tab of Set-
chema() tings schema section.
getDataKeySet- Optional function returning particular data key settings schema json as alternative to Data key
tingsSchema() settings schema tab of Settings schema section.
typeParame- Returns object describing widget datasource parameters. See Type parameters object.
ters()
actionSources() Returns object describing available widget action sources used to define user actions. See
Action sources object.
Widget subscription object contains all subscription information including current data according to the widget type.
Depending on widget type subscription object provides different data structures. For Latest values and Time-series
widget types it provides the following properties:
• datasources - array of datasources used by this subscription and has the following structure:
datasources = [
{ // datasource
type: 'entity',// type of the datasource. Can be "function" or "entity"
name: 'name', // name of the datasource (in case of "entity" usually Entity
˓→name)
{ // dataKey
name: 'name', // the name of the particular entity attribute/
˓→timeseries
label: 'Sin', // label of the dataKey. Used as display value (for ex.
˓→in the widget legend section)
},
(continues on next page)
(continued from previous page)
//...
]
},
//...
]
• data - array of latest data received in scope of this subscription and has the following structure:
data = [
{
datasource: {}, // datasource object of this data. See datasource structure
˓→ above.
dataKey: {}, // dataKey for which the data is held. See dataKey structure
˓→above.
For Alarm widget type it provides the following properties: * alarmSource - information about entity for which
alarms are fetched and has the following structure:
alarmSource = {
type: 'entity',// type of the alarm source. Can be "function" or "entity"
name: 'name', // name of the alarm source (in case of "entity" usually Entity
˓→name)
dataKeys: [ // array of keys indicating alarm fields used to display alarms data
{ // dataKey
name: 'name', // the name of the particular alarm field
type: 'alarm', // type of the dataKey. Only "alarm" in this case.
label: 'Severity', // label of the dataKey. Used as display value (for
˓→ex. as a column title in the Alarms table)
},
//...
]
}
• alarms - array of alarms received in scope of this subscription and has the following structure:
alarms = [
{ // alarm
id: { // alarm id
entityType: "ALARM",
id: "943b8cd0-576a-11e7-824c-0b1cb331ec92"
},
createdTime: 1498150092317, // Alarm created time (unix timestamp)
startTs: 1498150092316, // Alarm started time (unix timestamp)
endTs: 1498563899065, // Alarm end time (unix timestamp)
ackTs: 0, // Time of alarm aknowledgment (unix timestamp)
clearTs: 0, // Time of alarm clear (unix timestamp)
originator: { // Originator - id of entity produced this alarm
entityType: "ASSET",
id: "ceb16a30-4142-11e7-8b30-d5d66714ea5a"
},
originatorName: "Originator Name", // Name of originator entity
type: "Temperature", // Type of the alarm
severity: "CRITICAL", // Severity of the alarm ("CRITICAL", "MAJOR", "MINOR",
˓→"WARNING", "INDETERMINATE")
For other widget types like RPC or Static subscription object is optional and does not contain necessary information.
Timewindow functions
Object with timewindow functions used to manage widget data time frame. Can by used by Time-series or Alarm
widgets.
Function Description
onUpdateTimewin- This function can be used to update current subscription time frame to historical
dow(startTimeMs, end- one identified by startTimeMs and endTimeMs arguments.
TimeMs)
onResetTimewindow() Resets subscription time frame to default defined by widget timewindow compo-
nent or dashboard timewindow depending on widget settings.
Control API
Actions API
Function Description
getActionDescrip- Returns the list of action descriptors for provided actionSourceId
tors(actionSourceId)
handleWidgetAc- Handles action produced by particular action source. $event - event object associated
tion($event, descriptor, with action, descriptor - action descriptor, entityId and entityName - current entity id
entityId, entityName) and name provided by action source if available.
State Controller
Reference to Dashboard state controller providing API to manage current dashboard state.
Function Description
openState(id, Navigates to new dashboard state. id - id of the target dashboard state, params - object with state
params, open- parameters to use by the new state, openRightLayout - optional boolean argument to force open
RightLayout) right dashboard layout if present in mobile view mode.
updateS- Updates current dashboard state. id - optional id of the target dashboard state to replace current
tate(id, state id, params - object with state parameters to update current state parameters, openRightLayout
params, open- - optional boolean argument to force open right dashboard layout if present in mobile view mode.
RightLayout)
getStateId() Returns current dashboard state id.
get- Returns current dashboard state parameters.
StateParams()
get- Returns state parameters for particular dashboard state identified by id.
StateParams-
ByStateId(id)
return {
maxDatasources: -1, // Maximum allowed datasources for this widget, -1 - unlimited
maxDataKeys: -1 //Maximum allowed data keys for this widget, -1 - unlimited
}
Action sources object
Map describing available widget action sources to which user actions can be assigned. It has the following structure:
return {
'headerButton': { // Action source Id (unique action source identificator)
name: 'Header button', // Display name of action source, used in widget
˓→settings ('Actions' tab).
}
};
Below is the set of simple tutorials how to create minimal widgets of each type. In order to minimize the amount of
code, the Angular framework will be used, on which Tempus UI is actually based. By the way, you can always use
pure JavaScript or jQuery API in your widget code.
In the Widgets Bundle view click on the big “+” button in the bottom-right part of the screen and then click on the
“Create new widget type” button. Click on the Latest Values button in the Select widget type popup. The Widget
Editor will be opened pre-populated with the content of the default Latest Values template widget.
• Clear content of the CSS tab of “Resources” section.
• Put the following HTML code inside the HTML tab of “Resources” section:
<div>{{dataKeyData.dataKey.label}}:</div>
<div>{{dataKeyData.data[0][0] | date : 'yyyy-MM-dd HH:mm:ss'}}</div>
<div>{{dataKeyData.data[0][1]}}</div>
</div>
</div>
self.onInit = function() {
self.ctx.$scope.data = self.ctx.defaultSubscription.data;
• Click on the Run button in the Widget Editor Toolbar in order to see the result in Widget preview section.
In this example the data property of subscription is assigned to the $scope and become accessible within HTML
template. Inside the HTML a special ng-repeat angular directive is used in order to iterate over available dataKeys
datapoints and render corresponding latest values with their timestamps.
Time-Series widget
In the Widgets Bundle view click on the big “+” button in the bottom-right part of the screen and then click on the
“Create new widget type” button. Click on the Time-Series button in the Select widget type popup. The Widget Editor
will be opened pre-populated with the content of default Time-Series template widget.
• Clear content of the CSS tab of “Resources” section.
• Put the following HTML code inside the HTML tab of “Resources” section:
<tr>
</thead>
<tbody>
<tr ng-repeat="data in datasourceData[$index][0].data track by
˓→$index">
</tr>
</tbody>
</table>
</md-tab>
</md-tabs>
</div>
self.onInit = function() {
self.ctx.$scope.datasources = self.ctx.defaultSubscription.datasources;
self.ctx.$scope.data = self.ctx.defaultSubscription.data;
self.ctx.$scope.datasourceData = [];
}
self.ctx.$scope.datasourceData[currentDatasourceIndex].push(dataKeyData);
}
self.onDataUpdated = function() {
self.ctx.$scope.$digest();
}
• Click on the Run button in the Widget Editor Toolbar in order to see the result in Widget preview section.
In this example the datasources and data property of subscription is assigned to the $scope and become accessible
within HTML template. The datasourceData scope property is introduced to map datasource specific dataKeys data by
datasource index for flexible access within HTML template. Inside the HTML a special ng-repeat angular directive is
used in order to iterate over available datasources and render corresponding tabs. Inside each tab the table is rendered
using dataKeys data obtained from datasourceData scope property accessed by datasource index. Each table renders
columns by iterating over all dataKeyData objects and renders all available datapoints by iterating over data array of
each dataKeyData to render timestamps and values. Note that in this code onDataUpdated function is implemented
with a call to angular $digest function necessary to perform new rendering cycle when new data is received.
Alarm widget
In the Widgets Bundle view click on the big “+” button in the bottom-right part of the screen and then click on the
“Create new widget type” button. Click on the Alarm Widget button in the Select widget type popup. The Widget
Editor will be opened pre-populated with the content of the default Alarm template widget.
• Put the following HTML code inside the HTML tab of “Resources” section:
<div flex layout="column" style="height: 100%;">
<div>My first Alarm widget.</div>
<table style="width: 100%;">
<thead>
<tr>
<th ng-repeat="dataKey in alarmSource.dataKeys">{{dataKey.label}}</th>
<tr>
</thead>
<tbody>
<tr ng-repeat="alarm in alarms">
<td ng-repeat="dataKey in alarmSource.dataKeys"
ng-style="getAlarmCellStyle(alarm, dataKey)">
{{getAlarmValue(alarm, dataKey)}}
</td>
</tr>
</tbody>
</table>
</div>
• Put the following JSON content inside the “Settings schema” tab of Settings schema section:
{
"schema": {
"type": "object",
"title": "AlarmTableSettings",
"properties": {
"alarmSeverityColorFunction": {
"title": "Alarm severity color function: f(severity)",
"type": "string",
"default": "if(severity == 'CRITICAL') {return 'red';} else if
˓→(severity == 'MAJOR') {return 'orange';} else return 'green'; "
(continues on next page)
(continued from previous page)
}
},
"required": []
},
"form": [
{
"key": "alarmSeverityColorFunction",
"type": "javascript"
}
]
}
} catch (e) {
alarmSeverityColorFunction = null;
}
self.onDataUpdated = function() {
self.ctx.$scope.alarms = self.ctx.defaultSubscription.alarms;
}
• Click on the Run button in the Widget Editor Toolbar in order to see the result in Widget preview section.
In this example the alarmSource and alarms properties of subscription is assigned to the $scope and become accessible
within HTML template. Inside the HTML a special ng-repeat angular directive is used in order to iterate over avail-
able alarm dataKeys of alarmSource and render corresponding columns. The table rows are rendered by iterating over
alarms array and corresponding cells rendered by iterating over dataKeys. The function getAlarmValue is fetching
alarm value using special alarmFields constants obtained from types which is part of Tempus UI and accessed via
Angular $injector. The function getAlarmCellStyle is used to assign custom cell style for each alarm cell. In this
example, we introduced new settings property called alarmSeverityColorFunction that contains function body return-
ing color depending on alarm severity. Inside the getAlarmCellStyle function there is corresponding invocation of
alarmSeverityColorFunction with severity value in order to get color for alarm severity cell. Note that in this code
onDataUpdated function is implemented in order to update alarms property with latest alarms from subscription.
Static widget
In the Widgets Bundle view click on the big “+” button in the bottom-right part of the screen and then click on the
“Create new widget type” button. Click on the Static Widget button in the Select widget type popup. The Widget
Editor will be opened pre-populated with the content of default Static template widget.
• Put the following HTML code inside the HTML tab of “Resources” section:
</div>
• Put the following JSON content inside the “Settings schema” tab of Settings schema section:
{
"schema": {
"type": "object",
"title": "Settings",
"properties": {
"alertContent": {
"title": "Alert content",
"type": "string",
"default": "Content derived from alertContent property of widget
˓→settings."
}
}
},
"form": [
"alertContent"
(continues on next page)
(continued from previous page)
]
}
self.onInit = function() {
self.ctx.$scope.showAlert = function() {
var alertContent = self.ctx.settings.alertContent;
if (!alertContent) {
alertContent = "Content derived from alertContent property of widget
˓→settings.";
}
window.alert(alertContent);
};
• Click on the Run button in the Widget Editor Toolbar in order to see the result in Widget preview section.
This is just a static HTML widget so there is no subscription data or special widget API was used. Only custom
showAlert function was implemented showing an alert with the content of alertContent property of widget settings.
You can switch to dashboard edit mode in Widget preview section and change value of alertContent by changing
widget settings in the “Advanced” tab of widget details. Then you can see that the new alert content is displayed.
Below are some examples demonstrating how external JavaScript libraries or existing code can be reused/integrated
to create new widgets.
In this example Latest Values gauge widget will be created using external gauge.js library.
In the Widgets Bundle view click on the big “+” button in the bottom-right part of the screen and then click on the
“Create new widget type” button. Click on the Latest Values button in the Select widget type popup. The Widget
Editor will be opened pre-populated with the content of default Latest Values template widget.
• Open Resources tab and click “Add” then insert the following link:
http://bernii.github.io/gauge.js/dist/gauge.min.js
<canvas id="my-gauge"></canvas>
var canvasElement;
var gauge;
self.onInit = function() {
(continues on next page)
(continued from previous page)
canvasElement = $('#my-gauge', self.ctx.$container)[0];
gauge = new Gauge(canvasElement);
gauge.minValue = -1000;
gauge.maxValue = 1000;
gauge.animationSpeed = 16;
self.onResize();
}
self.onResize = function() {
canvasElement.width = self.ctx.width;
canvasElement.height = self.ctx.height;
gauge.update(true);
gauge.render();
}
self.onDataUpdated = function() {
var value = self.ctx.defaultSubscription.data[0].data[0][1];
gauge.set(value);
}
• Click on the Run button in the Widget Editor Toolbar in order to see the result in Widget preview section.
In this example API of the external JS library was used that become available after injecting the corresponding URL
in Resources section. The value displayed was obtained from subscription data property for the first dataKey.
Another approach of creating widgets is to use existing bundled JavaScript code. In this case, you can create own
JavaScript class or Angular directive and bundle it into the Tempus UI code. In order to make this code accessible
within the widget, you need to register corresponding Angular module or inject JavaScript class to a global variable
(for ex. window object). Some of the Tempus widgets already use this approach. Take a look at the widget.service.js.
Here you can find how some bundled classes or modules are registered for later use in Tempus widgets. For example
“Timeseries - Flot” widget (from “Charts” Widgets Bundle) uses TbFlot JavaScript class which is injected as window
property inside widget.service.js:
...
$window.TbFlot = TbFlot;
...
Another example is “Timeseries table” widget (from “Cards” Widgets Bundle) that uses Angular directive tb-
timeseries-table-widget which is registered as dependency of tempus.api.widget’ Angular module inside wid-
get.service.js. Thereby this directive becomes available for use inside the widget template HTML.
...
...
...
The most simple method of debugging is Web console output. Just place console.log(. . . ) function inside any part
of widget JavaScript code. Then click Run button to restart widget code and observe debug information in the Web
console.
Another and most effective method of debugging is to invoke browser debugger. Put debugger; statement into the place
of widget code you are interested in and then click Run button to restart widget code. Browser debugger (if enabled)
will automatically pause code execution at the debugger statement and you will be able to analyze script execution
using browser debugging tools.
While developing client-side js, if you need to access the document or window objects, add this comment at the
end of the line in your code referencing the object:
//eslint-disable-line
This will tell the linter to ignore the line. Only do this if you have to. In most cases, use the angular $window object
instead.
Custom Widgets
3D Trajectory Viewer
Usage
This widget expects data to exist in the first data source of the widget.
It will look for trajectory data objects with the following fields:
azi - azimuth in degrees incl - incline in degrees md - measured depth in any units. The metric of this measure will
be used in the chart.
Help
UI Development Guide
By default, the Tempus Cloud UI is served on port 8080. However, when developing the UI, developing in hot redeploy
mode is significantly more efficent.
To start the UI container in hot redeploy mode you will need to install node.js first. Once node.js is installed you can
start container by executing next command:
cd ${TEMPUS_WORK_DIR}/ui
mvn clean install -P npm-start
This will launch a server that will listen on 3000 port. All REST API and websocket requests will be forwarded to
8080 port.
cd ${TB_WORK_DIR}
java -jar application/target/tempus-${VERSION}-boot.jar
Dry run
Navigate to http://localhost:3000/ or http://localhost:8080/ and login into Tempus Cloud using demo data credentials:
login [email protected] password tenant
Make sure that you are able to login and everything has started correctly.
Introduction
Kubeless is a serverless framework on top of Kubernetes, which provides a way to deploy & run “functions” on K8s
cluster.
Function can be any source code written in PHP, Java 1.8, Node.js, Golang, .Net, Ruby or Python, having a method
which takes event and context as parameters. Check this link for more details on function.
Triggers are associated with functions to invoke them on specific event, examples are HttpTrigger, KafkaTrigger and
CronTrigger where Http call will trigger execution of function having HttpTrigger, KafkaTrigger will invoke function
once data is published to specified topic and CronTrigger will be invoked on specific schedule.
Kubeless java-client provides APIs to deploy and perform other operations on functions & triggers over k8s cluster.
Below is detailed usage examples.
Usage
API Client
Kubeless java-client provides ApiClient from Kubernetes Java client to communicate with K8s API server.
ApiClient can be used depending upon, from where you are going to deploy your function.
• If you will be deploying functions from code running in Pod from same cluster use below code
import io.kubernetes.client.util.Config;
ApiClient client = Config.fromCluster()
import io.kubernetes.client.util.Config;
String filename = "/path/to/kubeconfig";
ApiClient client = Config.fromConfig(filename)
If you use Config.defaultClient() it attempts to auto detect where the code is being used and creates a client object
accordingly. It first looks for a kubeconfig file in environment variable $KUBECONFIG, then falls back to path
$HOME/.kube/config. If that doesn’t work, it falls back to an in-cluster mode by detecting a default service account.
Lastly, if none of this works, it attempts to connect to the server at http://localhost:8080
Once ApiClient is built set it as Default client to use for further requests as
Configuration.setDefaultApiClient(client);
Function API
KubelessV1beta1FunctionApi contains APIs for communicating with k8s cluster with Kubeless. It contains APIs to
• list all functions
• fetch specific function by name
• delete specific function by name
• create new function
• update existing function
To create a new instance of FunctionApi client you need to pass “namespace” within which functions will be created
This will pick up ApiClient created in earlier step from Configuration object.
Below is complete code that will be used to list all functions from default namespace
import com.hashmapinc.kubeless.apis.KubelessV1beta1FunctionApi;
import com.hashmapinc.kubeless.models.V1beta1Function;
import com.hashmapinc.kubeless.models.V1beta1FunctionList;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Response;
import io.kubernetes.client.ApiClient;
import io.kubernetes.client.ApiException;
import io.kubernetes.client.Configuration;
import io.kubernetes.client.JSON;
import io.kubernetes.client.util.Config;
import java.io.IOException;
As you can see JSON object is used here to deserialize a response from K8s API server, which internally uses Gson
registered with few Data converters like Date time.
All the models which are used as Request and Response needs to be Serialized and Deserialized, respectively, using
JSON instance only.
Similarly API client can be used to create a function, which requires a target V1beta1Function instance
Trigger API
Once function is created next step is to add a trigger which will trigger an execution of function. Let’s look at an
example of adding Kafka trigger
To create a Kafka trigger we need to provide few labels to match with a function to which we want to add a trigger
like below:
Then using Kubeless Trigger API client we can send a request to deploy this trigger on K8s cluster as below,
3.10 Gateway
This guide describes how to configure device of type gateway to connect to Tempus-gateway. Tempus-gateway is a
solution that allows you to integrate IoT devices connected to legacy and third-party systems with Tempus Cloud.
Gateway Extension
Click on device of type gateway. Go to extension tab at top-right corner by clicking on ‘>’. Then, Click on the “+”
button at the top-right corner of the page.
WITSML Extension
After clicking on add extension, add name and type of extension as shown below:
• genindex
• modindex
• search