diff --git a/src/assets/images/user-guide/integrations/http-integration.svg b/src/assets/images/user-guide/integrations/http-integration.svg index aaf8b1f374..82416219d1 100644 --- a/src/assets/images/user-guide/integrations/http-integration.svg +++ b/src/assets/images/user-guide/integrations/http-integration.svg @@ -349,7 +349,7 @@ opacity: 1; - + diff --git a/src/assets/images/user-guide/integrations/http/http-enable-security-1.png b/src/assets/images/user-guide/integrations/http/http-enable-security-1.png index dbd8513d02..85477da61a 100644 Binary files a/src/assets/images/user-guide/integrations/http/http-enable-security-1.png and b/src/assets/images/user-guide/integrations/http/http-enable-security-1.png differ diff --git a/src/assets/images/user-guide/integrations/http/http-enable-security-2.png b/src/assets/images/user-guide/integrations/http/http-enable-security-2.png index 5e7eb8bbac..1e50c8a788 100644 Binary files a/src/assets/images/user-guide/integrations/http/http-enable-security-2.png and b/src/assets/images/user-guide/integrations/http/http-enable-security-2.png differ diff --git a/src/assets/images/user-guide/integrations/http/http-enable-security-3.png b/src/assets/images/user-guide/integrations/http/http-enable-security-3.png index bfe2a60cca..2fbfdb6590 100644 Binary files a/src/assets/images/user-guide/integrations/http/http-enable-security-3.png and b/src/assets/images/user-guide/integrations/http/http-enable-security-3.png differ diff --git a/src/assets/images/user-guide/integrations/http/http-enable-security-4.png b/src/assets/images/user-guide/integrations/http/http-enable-security-4.png index 24cd1c7ada..0d0771ec0a 100644 Binary files a/src/assets/images/user-guide/integrations/http/http-enable-security-4.png and b/src/assets/images/user-guide/integrations/http/http-enable-security-4.png differ diff --git a/src/content/_includes/docs/user-guide/integrations/http.mdx b/src/content/_includes/docs/user-guide/integrations/http.mdx index 0eb0b75df6..e39d373230 100644 --- a/src/content/_includes/docs/user-guide/integrations/http.mdx +++ b/src/content/_includes/docs/user-guide/integrations/http.mdx @@ -8,30 +8,58 @@ import TabItem from '@components/TabItem.astro'; -HTTP Integration converts existing protocols and payload formats to ThingsBoard message format. Common deployment scenarios: +HTTP Integration enables external applications, cloud services, scripts, and HTTP-enabled devices to push data into ThingsBoard using standard HTTP `POST` requests. Incoming requests are passed to an uplink converter that decodes the payload and maps it to ThingsBoard telemetry and attributes. -- Stream device or asset data from an external system, IoT platform, or connectivity provider back-end. -- Stream data from a custom cloud application. -- Connect an existing device with a custom HTTP-based protocol to ThingsBoard. +Use this integration when: + +- Devices support HTTP but not MQTT or CoAP. +- Third-party platforms or services deliver data via webhooks. +- Custom backends need a simple REST interface to push data into ThingsBoard. -## ThingsBoard integration setup +## Prerequisites + +Before creating the integration, ensure: + +- You have access to ThingsBoard PE or ThingsBoard Cloud with integration functionality enabled for your tenant. +- You have permissions to create integrations and data converters. +- You know the structure of the incoming HTTP payload. + +## Uplink Data Converter for HTTP Integration + +The uplink converter decodes the HTTP request payload and maps it to ThingsBoard's data model: it resolves the target device and extracts fields into telemetry and attributes. + +For the full decoder function reference — all input parameters and output fields — see Uplink data converter. + + + +### Example: Mapping JSON Payload + +Suppose your device or service sends this HTTP POST body: -### Create an uplink converter +```json +{ + "deviceName": "Thermometer A", + "deviceType": "thermostat", + "model": "N001", + "param2": "SN-12345", + "temperature": 25.0 +} +``` -The uplink converter decodes the incoming HTTP request body and maps it to the ThingsBoard data model. The decoder receives: -- `payload` — raw bytes of the HTTP request body -- `metadata` — HTTP request headers (as `Header:{name}` keys, e.g. `Header:content-type`) and `integrationName` +The converter below parses it and maps each field to ThingsBoard: -It must return `deviceName`, `deviceType`, `attributes`, and `telemetry`. Both are flat key-value maps — nested objects are not supported. For the full decoder API, see Uplink data converter. + -**The decoder function used in this tutorial:** - ```js maxLines=15 collapsible @@ -100,17 +128,17 @@ return result; -The decoder expects a flat JSON body and maps its fields to ThingsBoard: +**Field mapping:** -| JSON field | Output field | Type | Notes | -|------------|--------------|------|-------| -| `deviceName` | `deviceName` | — | Device identifier; auto-creates the device on first uplink | -| `deviceType` | `deviceType` | — | Device profile name | -| `model` | `model` | attribute | | -| `param2` | `serialNumber` | attribute | Field is renamed in the output | -| `temperature` | `temperature` | telemetry | | +| Payload field | ThingsBoard field | Output type | Notes | +|---------------|-------------------|-------------|-------| +| `data.deviceName` | `deviceName` | — | Device identifier; auto-creates the device on first uplink | +| `data.deviceType` | `deviceType` | — | Device profile name | +| `data.model` | `model` | attribute | | +| `data.param2` | `serialNumber` | attribute | Field is renamed in the output | +| `data.temperature` | `temperature` | telemetry | | -For request body `{"deviceName":"Thermometer A","deviceType":"thermostat","model":"N001","param2":"SN-12345","temperature":25.0}` the decoder produces: +**Converter output:** ```json { @@ -121,15 +149,11 @@ For request body `{"deviceName":"Thermometer A","deviceType":"thermostat","model } ``` -**To adapt this converter to your device:** +For common scripting patterns — renaming fields, extracting nested values, normalizing data, and handling non-JSON payloads — see Uplink data converter: Common scripting patterns. -- **Device name from a different field** — replace `data.deviceName` with the field that carries the device identifier in your payload. -- **Hardcoded device type** — replace `data.deviceType` with a string literal (e.g. `'thermostat'`) if all devices share the same profile. -- **Rename a field** — use `outputName: data.sourceField` to store the value under a different key in ThingsBoard (as shown with `serialNumber: data.param2`). -- **Different telemetry or attribute fields** — add, remove, or rename entries in the `telemetry` and `attributes` blocks. -- **Non-JSON payload** — replace `decodeToJson(payload)` with `decodeToString(payload)` and parse the string manually. +### Create Uplink Data Converter -**Import the uplink converter:** +Create an uplink converter to decode incoming HTTP payloads, then configure the integration to expose the HTTP endpoint.
    @@ -155,7 +179,7 @@ For request body `{"deviceName":"Thermometer A","deviceType":"thermostat","model
-### Create the integration +## Create HTTP Integration
    @@ -163,29 +187,33 @@ For request body `{"deviceName":"Thermometer A","deviceType":"thermostat","model
  1. Basic settings:
      -
    • Set Integration type to HTTP.
    • -
    • Enable integration and Allow create devices or assets are on by default.
    • +
    • Select HTTP as integration type.
    • +
    • Enter a Name for the integration, or keep the default HTTP integration.
    • +
    • Enable integration — controls whether the integration is active and processes incoming requests. Leave on to start immediately. Disable to pause the integration without deleting it (useful during maintenance or while updating the converter).
    • +
    • Allow create devices or assets — when enabled, ThingsBoard automatically creates a new device the first time an uplink arrives for an unknown device name. Disable if you want to accept data only from devices already registered in ThingsBoard.
    • Click Next.
  2. Uplink data converter: +
  3. Downlink data converter:
      -
    • Click Skip — the downlink converter is only required for RPC and can be added later.
    • +
    • Click Skip — a downlink converter is only needed when ThingsBoard must send data back to the device (e.g., RPC commands or shared attribute updates). It can be configured later.
  4. Connection:
    • Copy the HTTP endpoint URL — you will use it to send uplink messages.
    • -
    • In Advanced settings enable Replace response status from 'No-Content' to 'OK'.
    • +
    • In Advanced settings, enable Replace response status from "No-Content" to "OK" if your device or client requires a 200 OK response — by default the integration returns 204 No Content.
    Read more about each parameter in connection settings.
  5. @@ -194,13 +222,13 @@ For request body `{"deviceName":"Thermometer A","deviceType":"thermostat","model -#### Connection settings +### Connection Settings

    Base URL

    @@ -223,7 +251,7 @@ When enabled, ThingsBoard validates each incoming request against a list of requ | Field | Description | |-------|-------------| | **Header** | Name of the required HTTP header (e.g. `Authorization`, `X-API-Key`) | -| **Secret** | Required value for that header (e.g. `Bearer my-token`) | +| **Value** | Required value for that header (e.g. `Bearer my-token`) | Multiple header filters can be added. All configured headers must be present in every request. @@ -241,7 +269,7 @@ When enabled, ThingsBoard generates an **Integration key** and **Integration sec Optional key–value pairs attached to the integration. These values are injected into every message processed by the integration and are accessible in converter scripts as `integrationMetadata`. -## Send an uplink message +## Send Test Uplink Send a test message by running the command below, replacing `$YOUR_HTTP_ENDPOINT_URL` with the HTTP endpoint URL copied during setup. @@ -259,11 +287,10 @@ Go to **Entities ⇾ Devices** — device *Thermometer A* is provisioned aut { src: '/src/assets/images/user-guide/integrations/http/http-integration-go-to-devices-1.png', alt: 'Entities → Devices (1): Thermometer A auto-created by the integration (2); Latest telemetry tab (3) shows temperature = 33', caption: 'Go to Entities → Devices (1) — Thermometer A is auto-created on the first uplink (2). Open Latest telemetry (3) to confirm temperature = 33' }, ]} /> - +## Validation and Debugging -Go to **Integrations center ⇾ Integrations**, click **HTTP integration**, and open the **Events** tab. You should see one event with status "OK": +Go to **Integrations center ⇾ Integrations**, click **HTTP integration**, and open the **Events** tab. +You should see one event with status **OK**: -Use Dashboards to visualize the received data. ThingsBoard provides **Solution Templates** with pre-built dashboards for common use cases. +Use Dashboards to visualize the received data. ThingsBoard provides **Solution Templates** with pre-built dashboards for common use cases. + +## Secure HTTP Integration with Header Filters -## Restrict access with a header filter +A header filter protects the integration endpoint by requiring every incoming HTTP request to include one or more specific headers with exact values. Requests missing a required header or sending the wrong value are rejected with `401 Unauthorized` before reaching the converter. -Require a specific HTTP header on every incoming request — requests without it are rejected. +Use this to prevent unauthorized systems from pushing arbitrary data to your ThingsBoard endpoint. -1. Open the HTTP integration, click **Toggle edit mode** (pencil icon, top right). -2. Enable the **Enable security (Headers filter)** toggle, enter a header name (e.g. `test-header`) and value (e.g. `secret`), click **Add**, then click **Apply changes**. +1. Open the HTTP integration and click **Toggle edit mode** (pencil icon, top right). +2. Enable **Enable security (Headers filter)**. +3. Click **Add** and enter the **Header** name and its expected **Value**, then click **Add**. +4. Repeat to add more headers if needed — all configured headers must be present in every request. +5. Click **Apply changes**. -Once configured, add the required header to every uplink request with `-H "$HEADER:$VALUE"`. +**Header filter fields:** -Run the command below, replacing `$YOUR_HTTP_ENDPOINT_URL`, `$HEADER`, and `$VALUE` with your values: +| Field | Description | +|-------|-------------| +| **Header** | HTTP header name ThingsBoard checks on each incoming request | +| **Value** | Exact value required in that header | + +**Example: Authorization header** + +A common pattern is to protect the endpoint with a bearer token. Set **Header** to `Authorization` and **Value** to `Bearer my-secret-token`, then include the header in every uplink request. Replace `$YOUR_HTTP_ENDPOINT_URL` with the HTTP endpoint URL copied during setup: ```bash -curl -v -X POST -d '{"deviceName":"Thermometer A","deviceType":"thermostat","temperature":33,"model":"N001"}' $YOUR_HTTP_ENDPOINT_URL -H "Content-Type:application/json" -H "$HEADER:$VALUE" +curl -v -X POST \ + -d '{"deviceName":"Thermometer A","deviceType":"thermostat","temperature":33,"model":"N001"}' \ + $YOUR_HTTP_ENDPOINT_URL \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer my-secret-token" ``` -## Configure downlink - -The downlink converter (encoder) transforms a Rule Engine message into the HTTP response body returned to the device. For the full encoder function reference, see Downlink data converter. +Any request without the correct `Authorization` header is rejected. -HTTP downlinks are not pushed — they are delivered as the response body to the device's **next uplink request**. When a downlink is queued, the integration returns `200 OK` with the encoded payload instead of `204 No Content`. +## Configure Downlink -The encoder function receives `msg`, `metadata`, and `msgType`, and must return an object with: -- `contentType` — `JSON`, `TEXT`, or `BINARY` (`BINARY` expects a Base64-encoded string) -- `data` — the response body string -- `metadata` — optional key-value pairs +HTTP downlinks are not pushed to the device — they are delivered as the response body to the device's **next uplink request**. When a downlink is queued, the integration returns `200 OK` with the encoded payload instead of `204 No Content`. - +The downlink converter transforms a Rule Engine message into the HTTP response body. For the full encoder function reference, see Downlink data converter. -### Add a downlink converter +### Add Downlink Converter - 1. Go to **Integrations center ⇾ Integrations** and open the HTTP Integration. + 1. Go to **Integrations center ⇾ Integrations** and open the HTTP integration. 2. Click **Toggle edit mode**. 3. In the **Downlink data converter** field, click **Create new**. - 4. In the **Add data converter** dialog, enter a name, and write or paste the encoder script. + 4. Enter a name and paste the encoder script below, then click **Add**. - - -```js maxLines=15 collapsible -/** Encoder **/ - -var result = { - contentType: "JSON", // JSON, TEXT, or BINARY (base64) - data: JSON.stringify(msg), // encode the full message as the response body - metadata: {} -}; - -return result; -``` - - -```js maxLines=15 collapsible +```js /** Encoder **/ var result = { @@ -360,11 +381,11 @@ var result = { return result; ``` - - - 5. Click **Add**, then click **Apply changes**. +
      +
    1. Click Apply changes.
    2. +
    -### Configure the Root Rule Chain +### Configure Root Rule Chain @@ -386,7 +407,7 @@ import ConfigureDownlinkRuleChain from '@includes/docs/user-guide/integrations/_ { src: '/src/assets/images/user-guide/integrations/http/http-integration-configure-rule-chain-3.png', alt: 'Rule chain with integration downlink node connected to Attributes Updated output', caption: 'Connect the node to the Attributes Updated / Post attributes output and click Apply changes' }, ]} /> -### Test the downlink +### Test Downlink When a shared attribute is created or updated, the Rule Engine routes the event to the integration, which queues the encoded payload as the response to the device's next uplink. @@ -408,7 +429,7 @@ Send the uplink message again. ThingsBoard returns the downlink payload in the H { src: '/src/assets/images/user-guide/integrations/http/http-send-downlink-message-3.png', alt: 'Terminal — HTTP/2 200 response with {"powerState":"on"} body', caption: 'Response body contains the downlink payload: {"powerState":"on"}' }, ]} /> -The sent and received data can be viewed in the downlink converter's **Events** tab — the **In** block shows the input data, the **Out** block shows the encoded message sent to the device, and **Metadata** shows the request headers: +To inspect the exchange, open the downlink converter's **Events** tab — **In** shows the Rule Engine message, **Out** shows the encoded response, **Metadata** shows the request headers. -## See also +## Troubleshooting + +**No telemetry or device after sending a request** + +Open the converter's **Events** tab: go to **Integrations center → Data converters**, click your converter, and open **Events**. If **Out** is empty or shows an error, the script failed. Check the **In** column first to confirm the payload you expected was received. + +**Common issues:** + +| Symptom | Likely cause | Fix | +|---------|-------------|-----| +| Telemetry missing in ThingsBoard | Wrong field path in the script | Check **Out** in converter events; verify `data.yourField` matches the actual JSON key | +| Device not created, `deviceName` is null | Field doesn't exist or has a different name | Add a fallback: `var deviceName = data.id \|\| 'Unknown';` | +| Script error in converter events | Accessing a field on a `null` parent | Add a null-check: `data.sensor ? data.sensor.temp : null` | +| Device not auto-created despite correct converter output | **Allow create devices or assets** is disabled | Enable it in the integration settings | +| Unexpected key names in ThingsBoard | Output key name differs from expected | Field names in `attributes`/`telemetry` blocks become the ThingsBoard keys exactly as written | + +**Converter not triggered at all** + +- Check the integration **Events** tab — `ERROR` status means the request was rejected (e.g., failed header filter, malformed body). +- No events at all: verify the `POST` is going to the exact endpoint URL copied from the integration **Connection** step. +- Confirm the integration is enabled — the toggle must be on in integration settings. + +## See Also - Integration overview - Uplink data converter diff --git a/src/content/_includes/docs/user-guide/integrations/uplink-data-converter.mdx b/src/content/_includes/docs/user-guide/integrations/uplink-data-converter.mdx index 88de00cc4c..929276edc3 100644 --- a/src/content/_includes/docs/user-guide/integrations/uplink-data-converter.mdx +++ b/src/content/_includes/docs/user-guide/integrations/uplink-data-converter.mdx @@ -12,6 +12,30 @@ import TabItem from '@components/TabItem.astro'; The **Uplink data converter** is the decoding stage of every **ThingsBoard integration**, where raw payloads from an external device or network server are mapped to the ThingsBoard data model: device or asset name, profile, customer, group, telemetry values, and attributes. +Without an uplink converter, ThingsBoard cannot understand how external HTTP payloads should be interpreted and processed internally. + +Example: + +Incoming HTTP payload: + +```json +{ + "device": "Boiler-01", + "temperature": 42 +} +``` + +Converter output: + +```json +{ + "deviceName": "Boiler-01", + "telemetry": { + "temperature": 42 + } +} +``` + ThingsBoard provides three ways to define the decoder: - **Typed:** Configure entity type, name patterns, and field mappings in the UI — ThingsBoard pre-fills a decoder script tailored to each integration type. No scripting needed for structured JSON payloads; for binary or custom-encoded payloads, edit the pre-filled decoder to match your device's payload format. Supported integrations: ChirpStack, Loriot, The Things Stack Community, The Things Stack Industries, ThingPark, and ThingPark Enterprise. @@ -117,6 +141,98 @@ Keys added to the **Update only keys list** in **Advanced decoding parameters** In a cluster deployment, keys in the Update only keys list may still be written more than once when uplink messages arrive at different executor nodes, or immediately after a converter configuration change. +### Common Scripting Patterns + +The patterns below apply to any generic uplink converter, regardless of integration type. + +**Device name from a different field** + +Replace the field reference to match whatever field carries the device identifier in your payload: + +```js +var deviceName = data.serial; // if your field is "serial" +var deviceName = data.id; // if your field is "id" +var deviceName = 'Gateway-01'; // hardcoded — all data goes to one device +``` + +**Hardcoded device type** + +If all devices share the same profile, use a string literal instead of reading it from the payload: + +```js +var deviceType = 'thermostat'; +``` + +**Rename a field** + +Map a source field to a different ThingsBoard key using `newName: data.originalField`: + +```js +attributes: { + serialNumber: data.param2, // renames param2 → serialNumber + firmwareVersion: data.fw, // renames fw → firmwareVersion +} +``` + +**Extract nested values** + +If your payload contains nested objects, access them with dot notation: + +```json +{ "sensor": { "temperature": 22.5, "humidity": 60 } } +``` + +```js +telemetry: { + temperature: data.sensor.temperature, + humidity: data.sensor.humidity +} +``` + +**Separate telemetry from attributes** + +Put values that change over time in `telemetry`, and device metadata in `attributes`: + +```js +attributes: { + firmware: data.fw, // rarely changes — store as attribute + model: data.model +}, +telemetry: { + temperature: data.temp, // changes over time — store as telemetry + battery: data.bat, + rssi: data.signal +} +``` + +**Normalize or transform values** + +Transform values inside the decoder before mapping them: + +```js +telemetry: { + temperature: data.tempC * 9/5 + 32, // Celsius → Fahrenheit + batteryPercent: Math.round(data.bat * 100) // 0–1 float → 0–100 integer +} +``` + +**Non-JSON payload** + +If the device sends plain text or CSV, decode the payload as a string and parse manually: + +```js +// Example: "Sensor-01,22.5,60" +var str = decodeToString(payload); +var parts = str.split(','); +var result = { + deviceName: parts[0], + telemetry: { + temperature: parseFloat(parts[1]), + humidity: parseFloat(parts[2]) + } +}; +``` + ## Typed Uplink Converter Available from **ThingsBoard 4.0**. Configure the entity type, name pattern, and key mappings in the UI — ThingsBoard pre-fills a decoder script for the selected integration type. For structured JSON payloads, no script changes are needed. For binary payloads, modify the pre-filled decoder to match your device's payload format.