> For the complete documentation index, see [llms.txt](https://docs.cybus.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cybus.io/2-4-2/guides/system-connectivity/cloud-iot-platforms/thingsboard-integration.md).

# ThingsBoard Integration

This guide describes how to integrate ThingsBoard with Connectware. You configure a service commissioning file that sends telemetry and attributes for your shop floor equipment to ThingsBoard through its MQTT gateway API and receives remote procedure call (RPC) commands in return. A complete example file is available at the end of this guide.

## Objectives

* Establishing an MQTT connection between Connectware and ThingsBoard, authenticated with a device access token.
* Sending telemetry for multiple shop floor devices over a single connection using the ThingsBoard gateway API.
* Sending client-side attributes for those devices.
* Receiving RPC commands from ThingsBoard in Connectware and publishing the responses.

## Prerequisites

To follow this guide, you will need the following:

* A running instance of Cybus Connectware.
* Access to a ThingsBoard instance (Community Edition, Professional Edition, or ThingsBoard Cloud) with permission to create devices.
* A gateway device in ThingsBoard and its access token. To create one, open the **Devices** page in ThingsBoard, add a new device, and select the **Is gateway** checkbox. The access token is available in the device details.
* Access to the [Admin UI](/2-4-2/access/admin-ui.md) with sufficient [user permissions](/2-4-2/access/user-management.md).
* Basic knowledge of MQTT and the Connectware [services](/2-4-2/data-flows/services.md) concept (for example, [service commissioning files](/2-4-2/data-flows/service-commissioning-files.md), [connections](/2-4-2/data-flows/service-commissioning-files/resources/cybus-connection.md), and [endpoints](/2-4-2/data-flows/service-commissioning-files/resources/cybus-endpoint.md)).

## Connectware and ThingsBoard Integration

ThingsBoard exposes an MQTT device API for telemetry, attributes, and RPC. A client authenticates with a device access token as the MQTT username and no password, on port 1883 for plain MQTT or port 8883 for MQTT over TLS. Each MQTT connection authenticates as exactly one device: everything published on the `v1/devices/me/...` topics is recorded against the device that owns the token. Connecting many machines this way would require one Connectware connection per ThingsBoard device.

Connectware usually represents many machines at once, so this guide uses the ThingsBoard gateway API instead. The gateway API works over a single MQTT connection, authenticated with the access token of one gateway device, and carries data for any number of devices. ThingsBoard creates a device automatically the first time the gateway publishes data for it and shows it as connected through the gateway.

The integration uses the following topics on the ThingsBoard broker:

* `v1/gateway/telemetry`: Publishes time series data for one or more devices.
* `v1/gateway/attributes`: Publishes client-side attributes for one or more devices.
* `v1/gateway/connect`: Announces a device to ThingsBoard so that it can receive RPC commands through the gateway.
* `v1/gateway/rpc`: Delivers RPC requests to the gateway and accepts the responses.

{% hint style="info" %}
To connect a single device only, use the device API topics `v1/devices/me/telemetry` and `v1/devices/me/attributes` with the access token of that device instead. The connection setup in this guide stays the same.
{% endhint %}

The MQTT topics on the Connectware side follow an ISA-95-style equipment hierarchy (`<enterprise>/<site>/<area>/<line>/<cell>`). The mappings subscribe with wildcards across all levels, so any machine in the hierarchy is picked up without changing the integration. The last topic level becomes the device name in ThingsBoard.

### ThingsBoard Connection Properties

The connection to ThingsBoard requires the hostname of your instance and the access token of the gateway device. We add them 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.

* `thingsboardHost`: The hostname of your ThingsBoard instance, without the scheme. For example, `thingsboard.example.com`.
* `accessToken`: The access token of the gateway device in ThingsBoard.
* `topicRoot`: The root of the MQTT topic hierarchy. Defaults to `enterprise`.

{% code lineNumbers="true" %}

```yaml
parameters:
  thingsboardHost:
    description: Hostname of your ThingsBoard instance
    type: string
    default: thingsboard.example.com

  accessToken:
    description: Access token of the gateway device in ThingsBoard
    type: string

  topicRoot:
    description: Root of the MQTT topic hierarchy
    type: string
    default: enterprise
```

{% endcode %}

### ThingsBoard Connection

To connect to the ThingsBoard broker, we set up a `Cybus::Connection` resource that uses the [MQTT connector](/2-4-2/connectors/enterprise-connectors/mqtt.md). ThingsBoard identifies the client by the access token in the `username` property, a password is not required. For all available connection properties, see [MQTT Connection Properties](/2-4-2/connectors/enterprise-connectors/mqtt/mqttconnection.md).

{% code lineNumbers="true" %}

```yaml
resources:
  thingsboardConnection:
    type: Cybus::Connection
    properties:
      protocol: Mqtt
      connection:
        host: !ref thingsboardHost
        port: 8883
        scheme: mqtts
        username: !ref accessToken
        clientId: connectware-gateway
        keepalive: 60
```

{% endcode %}

The example connects with TLS on port 8883. For plain MQTT, set the `port` to `1883` and the `scheme` to `mqtt`. If your ThingsBoard instance uses a certificate that the Connectware host system cannot validate, add the issuing CA certificate with the [caCert property](/2-4-2/connectors/enterprise-connectors/mqtt/mqttconnection.md#cacert-string).

### Sending Telemetry

The gateway API expects telemetry as a JSON object with one key per device name. Each key holds an array of entries with a `ts` timestamp in milliseconds and a `values` object containing the readings.

We define a write endpoint for the `v1/gateway/telemetry` topic and a mapping that feeds it from the MQTT topic hierarchy. The `transform` rule builds the gateway envelope: the named wildcard `+cell` is available as `$context.vars.cell` and becomes the device name, and `$millis()` sets the current time as the timestamp. Machines publish their readings as plain JSON without knowing about this convention.

{% code lineNumbers="true" %}

```yaml
telemetryEndpoint:
  type: Cybus::Endpoint
  properties:
    protocol: Mqtt
    connection: !ref thingsboardConnection
    write:
      topic: v1/gateway/telemetry

telemetryMapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          topic: !sub '${topicRoot}/+site/+area/+line/+cell/telemetry'
        publish:
          endpoint: !ref telemetryEndpoint
        rules:
          - transform:
              expression: |
                {
                  $context.vars.cell: [
                    {
                      "ts": $millis(),
                      "values": $
                    }
                  ]
                }
```

{% endcode %}

A machine that publishes the following payload to `enterprise/hamburg/assembly/line-1/press-01/telemetry` now appears in ThingsBoard as the device `press-01`, with `temperature` and `pressure` as telemetry keys:

{% code lineNumbers="true" %}

```json
{
  "temperature": 42.1,
  "pressure": 5.2
}
```

{% endcode %}

If your machines deliver their own timestamps, map them into the `ts` field instead of calling `$millis()`.

{% hint style="info" %}
Device names must be unique within your ThingsBoard tenant. If the same cell name occurs in more than one line, build a qualified device name in the transform expression, for example `$join([$context.vars.line, $context.vars.cell], '-')`.
{% endhint %}

### Sending Device Attributes

Attributes hold slowly changing metadata, such as a firmware version or a serial number, while telemetry holds time series data. The gateway API expects attributes as a JSON object with one key per device name and the attribute key-value pairs as the value. The endpoint uses the same connection and the `v1/gateway/attributes` topic.

{% code lineNumbers="true" %}

```yaml
attributesEndpoint:
  type: Cybus::Endpoint
  properties:
    protocol: Mqtt
    connection: !ref thingsboardConnection
    write:
      topic: v1/gateway/attributes

attributesMapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          topic: !sub '${topicRoot}/+site/+area/+line/+cell/attributes'
        publish:
          endpoint: !ref attributesEndpoint
        rules:
          - transform:
              expression: '{ $context.vars.cell: $ }'
```

{% endcode %}

A message published to `enterprise/hamburg/assembly/line-1/press-01/attributes` with the payload `{ "firmwareVersion": "1.0.3", "serialNumber": "SN-0001" }` sets these values as client-side attributes of the device `press-01`.

### Receiving and Answering RPC Commands

ThingsBoard dashboards and rule chains send RPC commands to devices, for example to change a setpoint or to trigger an action. For devices behind a gateway, ThingsBoard delivers these commands on the `v1/gateway/rpc` topic. ThingsBoard only routes RPC commands for devices that the gateway has announced on the `v1/gateway/connect` topic.

We define a write endpoint for the connect topic and a mapping that feeds it from Connectware. To announce a device, publish its name to the internal topic, for example with an MQTT client or the Admin UI:

{% code lineNumbers="true" %}

```yaml
deviceConnectEndpoint:
  type: Cybus::Endpoint
  properties:
    protocol: Mqtt
    connection: !ref thingsboardConnection
    write:
      topic: v1/gateway/connect

deviceConnectMapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          topic: !sub '${topicRoot}/thingsboard/connect'
        publish:
          endpoint: !ref deviceConnectEndpoint
```

{% endcode %}

Publishing `{ "device": "press-01" }` to `enterprise/thingsboard/connect` marks the device `press-01` as connected through the gateway.

For the commands themselves, a subscribe endpoint receives every RPC request from ThingsBoard, and a mapping forwards it to an internal topic where any other Connectware service can pick it up, for example to write the command to a PLC:

{% code lineNumbers="true" %}

```yaml
rpcRequestEndpoint:
  type: Cybus::Endpoint
  properties:
    protocol: Mqtt
    connection: !ref thingsboardConnection
    subscribe:
      topic: v1/gateway/rpc

rpcRequestMapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          endpoint: !ref rpcRequestEndpoint
        publish:
          topic: !sub '${topicRoot}/thingsboard/rpc/request'
```

{% endcode %}

Each request contains the target device, a request ID, the method name, and the parameters:

{% code lineNumbers="true" %}

```json
{
  "device": "press-01",
  "data": {
    "id": 1,
    "method": "setFanSpeed",
    "params": { "speed": 80 }
  }
}
```

{% endcode %}

For two-way RPC commands, ThingsBoard waits for a response with the same request ID. The service that handles the command publishes the response to the internal response topic, and a mapping sends it back to ThingsBoard on the same `v1/gateway/rpc` topic. One-way RPC commands do not require a response. ThingsBoard delivers responses to the caller of the RPC command, it does not echo them back to the gateway subscription.

{% code lineNumbers="true" %}

```yaml
rpcResponseEndpoint:
  type: Cybus::Endpoint
  properties:
    protocol: Mqtt
    connection: !ref thingsboardConnection
    write:
      topic: v1/gateway/rpc

rpcResponseMapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          topic: !sub '${topicRoot}/thingsboard/rpc/response'
        publish:
          endpoint: !ref rpcResponseEndpoint
```

{% endcode %}

The response must echo the device name and the request ID:

{% code lineNumbers="true" %}

```json
{
  "device": "press-01",
  "id": 1,
  "data": { "success": true }
}
```

{% endcode %}

## Verifying the Integration

1. Install the service and set the parameters with the hostname of your ThingsBoard instance and the access token of the gateway device.
2. Check that the connection is in the **Connected** state on the service details page in the Admin UI. If the access token is wrong, ThingsBoard rejects the connection and it does not reach the connected state.
3. Publish a test message, for example `{ "temperature": 42.1 }`, to `enterprise/hamburg/assembly/line-1/press-01/telemetry` with an MQTT client or the Admin UI.
4. Open the **Devices** page in ThingsBoard and check that the device `press-01` has been created. The **Latest telemetry** tab of the device shows the published values.
5. To test RPC, publish `{ "device": "press-01" }` to `enterprise/thingsboard/connect`, then send an RPC command from ThingsBoard, for example with an RPC widget on a dashboard. Use the [Data Explorer](/2-4-2/monitoring/data-explorer.md) to check that the request arrives on `enterprise/thingsboard/rpc/request`.

## Service Commissioning File Example

{% file src="/files/ASXHsmNdvEfXjHAHD6Dv" %}

{% code title="thingsboard-example.yml" lineNumbers="true" expandable="true" %}

```yaml
---
# ----------------------------------------------------------------------------
# Service Commissioning File
# ----------------------------------------------------------------------------
# Copyright: Cybus GmbH
# Contact: support@cybus.io
# ----------------------------------------------------------------------------
# ThingsBoard Integration (Example)
# ----------------------------------------------------------------------------

description: >
  Service commissioning file for the integration between Connectware and
  ThingsBoard using the MQTT gateway API (Example)

metadata:
  name: ThingsBoard Integration
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0

parameters:
  thingsboardHost:
    description: Hostname of your ThingsBoard instance
    type: string
    default: thingsboard.example.com

  accessToken:
    description: Access token of the gateway device in ThingsBoard
    type: string

  topicRoot:
    description: Root of the MQTT topic hierarchy
    type: string
    default: enterprise

resources:
  # Connection to the ThingsBoard broker, authenticated as the gateway device
  thingsboardConnection:
    type: Cybus::Connection
    properties:
      protocol: Mqtt
      connection:
        host: !ref thingsboardHost
        port: 8883
        scheme: mqtts
        username: !ref accessToken
        clientId: connectware-gateway
        keepalive: 60

  # Sends telemetry for any device in the topic hierarchy
  telemetryEndpoint:
    type: Cybus::Endpoint
    properties:
      protocol: Mqtt
      connection: !ref thingsboardConnection
      write:
        topic: v1/gateway/telemetry

  telemetryMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            topic: !sub '${topicRoot}/+site/+area/+line/+cell/telemetry'
          publish:
            endpoint: !ref telemetryEndpoint
          rules:
            - transform:
                expression: |
                  {
                    $context.vars.cell: [
                      {
                        "ts": $millis(),
                        "values": $
                      }
                    ]
                  }

  # Sends client-side attributes for any device in the topic hierarchy
  attributesEndpoint:
    type: Cybus::Endpoint
    properties:
      protocol: Mqtt
      connection: !ref thingsboardConnection
      write:
        topic: v1/gateway/attributes

  attributesMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            topic: !sub '${topicRoot}/+site/+area/+line/+cell/attributes'
          publish:
            endpoint: !ref attributesEndpoint
          rules:
            - transform:
                expression: '{ $context.vars.cell: $ }'

  # Announces a device to ThingsBoard so that it can receive RPC commands
  deviceConnectEndpoint:
    type: Cybus::Endpoint
    properties:
      protocol: Mqtt
      connection: !ref thingsboardConnection
      write:
        topic: v1/gateway/connect

  deviceConnectMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            topic: !sub '${topicRoot}/thingsboard/connect'
          publish:
            endpoint: !ref deviceConnectEndpoint

  # Receives RPC requests from ThingsBoard
  rpcRequestEndpoint:
    type: Cybus::Endpoint
    properties:
      protocol: Mqtt
      connection: !ref thingsboardConnection
      subscribe:
        topic: v1/gateway/rpc

  rpcRequestMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref rpcRequestEndpoint
          publish:
            topic: !sub '${topicRoot}/thingsboard/rpc/request'

  # Sends RPC responses back to ThingsBoard
  rpcResponseEndpoint:
    type: Cybus::Endpoint
    properties:
      protocol: Mqtt
      connection: !ref thingsboardConnection
      write:
        topic: v1/gateway/rpc

  rpcResponseMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            topic: !sub '${topicRoot}/thingsboard/rpc/response'
          publish:
            endpoint: !ref rpcResponseEndpoint
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.cybus.io/2-4-2/guides/system-connectivity/cloud-iot-platforms/thingsboard-integration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
