ClickHouse Integration
How to integrate ClickHouse with Connectware, including streaming shop floor data into a MergeTree table over the ClickHouse HTTP interface and polling aggregated results back into an MQTT topic.
This guide describes how to integrate ClickHouse with Connectware. You configure a service commissioning file that streams shop floor data into a ClickHouse table over the ClickHouse HTTP interface and polls an aggregation query back into an MQTT topic. A complete example file is available at the end of this guide.
Objectives
Establishing a connection between Connectware and the ClickHouse HTTP interface.
Streaming shop floor data from an ISA-95-style topic hierarchy into a production events table.
Polling an aggregation query into an MQTT topic on a fixed interval.
Prerequisites
To follow this guide, you will need the following:
A running instance of Cybus Connectware.
A ClickHouse instance that is reachable from Connectware. This can be a self-hosted ClickHouse server or a ClickHouse Cloud service.
A ClickHouse user with
INSERTandSELECTprivileges on the target database.Access to the Admin UI with sufficient user permissions.
Basic knowledge of MQTT and the Connectware services concept (for example, service commissioning files, connections, and endpoints).
Connectware and ClickHouse Integration
ClickHouse exposes an HTTP interface on port 8123 (HTTP) or 8443 (HTTPS, the standard port for ClickHouse Cloud). Every request carries a SQL statement in the query URL parameter. For an INSERT, the rows travel in the request body. Connectware communicates with this interface through the HTTP/REST connector:
Write endpoints send a POST request per MQTT message. The
queryproperty of the endpoint holds theINSERTstatement with the JSONEachRow format clause, and the message body becomes the request body, which is exactly one JSON row.Subscribe endpoints send a GET request on a fixed interval. The
queryproperty holds aSELECTstatement, and the connector publishes the JSON result to the MQTT broker. ClickHouse treats GET requests as read-only, so the polling endpoint cannot modify data.
ClickHouse supports HTTP Basic Authentication and the X-ClickHouse-User and X-ClickHouse-Key headers. This guide uses Basic Authentication through the auth property of the connection. If you prefer the header variant, set the two headers in the headers property instead (see HTTP Connection Properties).
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 database.
Production Events Table
The integration writes into a single table that stores one row per shop floor event. Create it in your ClickHouse instance, for example with clickhouse-client or the ClickHouse Cloud SQL console:
The table uses the MergeTree engine, the standard choice for high-volume time series data in ClickHouse. The ORDER BY clause sorts the data by location and time, which makes queries that filter on the equipment hierarchy fast. LowCardinality(String) compresses the location columns, which contain few distinct values. The event_time column defaults to the insert time, so the messages do not need to carry a timestamp. If you want to store machine timestamps instead, send an event_time key in the row.
ClickHouse 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.
clickhouseScheme:httporhttps. Usehttpsfor ClickHouse Cloud.clickhouseHostandclickhousePort: The hostname and port of the ClickHouse HTTP interface. The default port is8123for HTTP and8443for HTTPS.clickhouseUsernameandclickhousePassword: The ClickHouse user that Connectware uses to connect.clickhouseDatabase: The database that contains theproduction_eventstable.pollingInterval: The interval in milliseconds between polling queries.topicRoot: The root of the MQTT topic hierarchy. Defaults toenterprise.
ClickHouse Connection
To connect to ClickHouse, we set up a Cybus::Connection resource that uses the HTTP/REST connector with Basic Authentication. All endpoints in this guide share this connection.
The connection also configures the health probing. ClickHouse answers GET /ping with Ok. without touching any data, which makes it the ideal probe target. The default probing method of the connector is a HEAD request on /, so we override both properties.
Streaming Production Events into ClickHouse
The write endpoint sends one POST request per MQTT message. Its query property adds the static URL parameters to every request:
query: TheINSERTstatement. TheFORMAT JSONEachRowclause tells ClickHouse to parse the request body as one JSON object per row, matching keys to column names. Columns that the row omits, such asevent_time, take their default values.database: The default database for the statement, so the table name stays unqualified.async_insert: Enables asynchronous inserts. Every MQTT message becomes its ownINSERTrequest, and many small direct inserts degrade MergeTree performance. With asynchronous inserts, ClickHouse buffers incoming rows server-side and flushes them in batches. The companion settingwait_for_async_insertdefaults to1, so ClickHouse acknowledges a request only after the buffer is flushed and flush errors still reach Connectware.
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 HTTP/REST connector expects the request body in the body property of the message (see Publishing Data to REST Servers). The rule builds this object, combining the topic levels with the event_type and value fields of the machine payload. Because body is a JSON object, the connector serializes it into the request body as a single JSON object, which is exactly one valid JSONEachRow row.
Any message published to a matching topic, for example enterprise/hamburg/assembly/line-1/press-01/production-events, now inserts one row into the table. The machine payload only needs the event fields, the topic provides the rest:
ClickHouse rejects rows whose values do not match the column types, for example a string in the event_value column. The rejected request appears as an error property on the /res topic of the endpoint, and the row is lost. The senders of the MQTT messages must ensure that the values match the table schema.
Polling an Aggregate Back to MQTT
For the opposite direction, a subscribe endpoint polls a SELECT statement on a fixed interval and publishes the result to the MQTT broker. This example aggregates the production events of the last five minutes per line and event type, so downstream consumers such as dashboards or MES systems receive a regularly updated snapshot.
The FORMAT JSON clause makes ClickHouse return a JSON document with the result rows in its data property. The output_format_json_quote_64bit_integers parameter stops ClickHouse from quoting 64-bit integers as strings, so the count() result arrives as a number.
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 HTTP Endpoint Properties).
Every poll publishes a message with a timestamp property and a value property that contains the ClickHouse response, including the result rows in value.data and query statistics:
If downstream consumers only need the rows, add a transform rule with the expression value.data to the mapping, which publishes the plain array instead.
Verifying the Integration
Install the service and set the parameters with the values of your ClickHouse instance.
Check that the connection is in the Connected state on the service details page in the Admin UI. The probing calls
GET /ping, which does not require authentication, so wrong credentials surface on the endpoints, not on the connection state.Publish a test message with the machine payload shown in this guide to
enterprise/hamburg/assembly/line-1/press-01/production-events, for example with an MQTT client or the Admin UI.Check that the row arrived in the database, for example with
SELECT * FROM factory.production_events ORDER BY event_time DESC LIMIT 10in clickhouse-client or the SQL console. The result of every insert is also published to the/restopic of the write endpoint. If ClickHouse rejects a request, the message on the/restopic contains anerrorproperty with the HTTP status and the ClickHouse error text.Use the Data Explorer to inspect the polled aggregation on the
enterprise/production-events/throughputtopic.
Service Commissioning File Example
Last updated
Was this helpful?

