For the complete documentation index, see llms.txt. This page is also available as Markdown.

TimescaleDB Integration

How to integrate TimescaleDB with Connectware, including writing time-series sensor data into a hypertable and polling time_bucket aggregates back into MQTT topics.

This guide describes how to integrate TimescaleDB with Connectware. You configure a service commissioning file that streams time-series sensor data from the shop floor into a TimescaleDB hypertable and polls aggregated query results back into an MQTT topic. A complete example file is available at the end of this guide.

Objectives

  • Establishing a connection between Connectware and TimescaleDB.

  • Writing sensor values from an ISA-95-style topic hierarchy into a hypertable, including the machine timestamps.

  • Polling time-bucketed aggregates from the hypertable into an MQTT topic on a fixed interval.

Prerequisites

To follow this guide, you will need the following:

Connectware and TimescaleDB Integration

TimescaleDB extends PostgreSQL with hypertables: tables that are automatically partitioned by time and optimized for high ingest rates and time-based queries. That makes it a natural sink for shop floor sensor data, which arrives as a continuous stream of timestamped values.

Because TimescaleDB is a PostgreSQL extension, Connectware communicates with it through the SQL connector using the postgres:// URL scheme. No TimescaleDB-specific driver is required. The connector works by defining SQL queries or query templates on endpoints:

  • Write endpoints define a query template, typically an INSERT statement. The template contains placeholders in the form $identifier, which the connector replaces with the values from the JSON payload of each incoming MQTT message (see Placeholder Syntax).

  • Subscribe endpoints define a query and a polling interval. The connector executes the query on a regular basis and publishes the result rows as a JSON array to the MQTT broker. This is where TimescaleDB functions such as time_bucket come in, because they run inside the query.

The MQTT topics in this guide follow an ISA-95-style equipment hierarchy (<enterprise>/<site>/<area>/<line>/<cell>). The mapping subscribes with named wildcards across all levels, so any machine in the hierarchy is picked up without changing the integration, and the topic levels become column values in the hypertable.

Sensor Measurements Hypertable

The integration writes into a single hypertable that stores one row per sensor reading. Create the table in your target database and convert it into a hypertable partitioned by the time column:

TimescaleDB partitions the hypertable into time-based chunks behind the scenes. You keep querying measurements like a regular PostgreSQL table. For all options, such as custom chunk intervals, see the create_hypertable reference.

Unlike a plain event table, the time column has no default. The machines provide their own timestamps, so a reading is stored at the time it was measured, not at the time it arrived in the database.

TimescaleDB Connection Properties

We add the connection values as parameters to the service commissioning file, so you can set them when you install the service.

Do not worry about copying the service commissioning file snippets together into one, the complete example file is available at the end of this guide.

  • timescaleHost and timescalePort: The hostname and port of your TimescaleDB server. The default port is 5432.

  • timescaleUsername and timescalePassword: The database role that Connectware uses to connect.

  • timescaleDatabase: The database that contains the measurements hypertable.

  • pollingInterval: The interval in milliseconds between polling queries.

  • topicRoot: The root of the MQTT topic hierarchy. Defaults to enterprise.

TimescaleDB Connection

To connect to the database, we set up a Cybus::Connection resource that uses the SQL connector. The connector expects a single connection URL of the form postgres://<user>:<password>@<host>:<port>/<database>, which the !sub substitution assembles from the parameters. Both endpoints in this guide share this connection.

For all available connection properties, including certificate handling and the reconnection strategy, see SQL Connection Properties.

Writing Sensor Measurements

The write endpoint defines the INSERT statement as a query template. Each placeholder, for example $sensor, is replaced with the value of the matching key in the JSON payload of the incoming message.

The mapping feeds the endpoint from the topic hierarchy. It uses named wildcards, so the topic levels are available in the $context.vars object of the transform rule. The rule builds one flat object whose keys match the query placeholders, combining the topic levels with the timestamp, sensor, and value fields of the machine payload.

Any message published to a matching topic, for example enterprise/hamburg/assembly/line-1/press-01/measurements, now inserts one row into the hypertable. The machine payload carries the timestamp of the reading as an ISO 8601 string, which PostgreSQL casts to the timestamptz column:

If your machines publish Unix timestamps in milliseconds instead, convert them in the query template with to_timestamp($time / 1000.0).

All placeholders defined in the query must exist in the resulting message payload. If one is missing, the connector logs an error and ignores the message (see Writing Data).

Polling Aggregated Measurements

Publishing every raw reading back to MQTT rarely makes sense at shop floor data rates. Instead, a subscribe endpoint uses the TimescaleDB time_bucket function to downsample the data in the database: the query groups the readings of the last 15 minutes into one-minute buckets per sensor and returns the average, minimum, and maximum for each bucket. Downstream consumers such as dashboards receive a compact, regularly updated summary.

Choose the polling interval carefully. A low value can overload the database. Instead of a fixed interval, you can also poll on a schedule with the cronExpression property (see SQL Endpoint Properties).

Every query execution publishes a message with a timestamp property and a value property that contains the result rows. If the query returns no rows, value is an empty array ([]).

If the aggregation query becomes expensive on large hypertables, TimescaleDB continuous aggregates precompute the same time_bucket results incrementally in the background, so the polling endpoint can select from the materialized view instead.

Verifying the Integration

  1. Install the service and set the parameters with the values of your TimescaleDB server.

  2. Check that the connection is in the Connected state on the service details page in the Admin UI. If the credentials or the database name are wrong, the connection does not reach the connected state.

  3. Publish a test message with the machine payload shown in this guide to enterprise/hamburg/assembly/line-1/press-01/measurements, for example with an MQTT client or the Admin UI.

  4. Check that the row arrived in the hypertable, for example with SELECT * FROM measurements ORDER BY time DESC LIMIT 10 in psql. The result of every write is also published to the /res topic of the write endpoint, with value set to true on success.

  5. Use the Data Explorer to inspect the aggregated buckets on the enterprise/measurements/aggregated topic. The first bucket appears after the polling interval has elapsed.

Service Commissioning File Example

Last updated

Was this helpful?