LORIOT Integration
The LORIOT integration connects ThingsBoard to a LORIOT LoRaWAN Network Server: it receives uplink messages from LoRaWAN devices, decodes them via an uplink converter, and pushes telemetry and attributes to the platform. In the reverse direction, it encodes Rule Engine messages via a downlink converter and delivers them to devices through the LORIOT API.
Register a LORIOT account
Section titled “Register a LORIOT account”- Go to the LORIOT website and choose a service package (e.g. Community Public Network Server).
- Pick your preferred region and country, then complete the registration and log in.
ThingsBoard integration setup
Section titled “ThingsBoard integration setup”Create an uplink converter
Section titled “Create an uplink converter”The uplink converter decodes the incoming LORIOT message and maps it to the ThingsBoard data model. For the full decoder function reference, see Uplink data converter.
From ThingsBoard 4.0, you can map message fields to attributes or telemetry directly in the UI — no scripting needed for structured JSON payloads. For binary payloads, add a decoder script in the same wizard, as this tutorial demonstrates.
If your device is in the built-in catalog, use the Library tab — see Library — a built-in catalog of ready-to-use decoder functions for over 100 devices.
- Go to Integrations center ⇾ Data converters.
- Click + Add data converter ⇾ Create new converter.
- Set Converter type to Uplink (default).
- Select Integration type: Loriot.
- Enter a converter name:
Loriot Uplink Converter. - The Main decoding configuration section specifies:
- A naming template for automatic device creation —
Device $eui— change this if you prefer a different naming scheme. - Paste the decoder function below, or leave the default for unmodified LORIOT fields.
- A naming template for automatic device creation —
Review Advanced decoding parameters — pre-populated for LORIOT. Adjust the telemetry and attribute key lists if needed; see Advanced decoding parameters for details.
- Click Add.
/** * Decodes the incoming payload and returns a structured object containing telemetry data and attributes. * * @param {byte[]} input - The raw payload received as an array of bytes. * @returns {Object} output - The structured output with decoded telemetry and attributes. */
function decodePayload(input) { // Initialize the output object with empty attributes and telemetry for clarity. var result = { attributes: {}, telemetry: {}};
// Decode serial number (SN) from the first 4 bytes of the payload. // Press '?' icon in the top right corner to learn more about built in helper functions and capabilities. result.attributes.sn = parseBytesToInt(input, 0, 4);
// Extract the timestamp from metadata (represented in milliseconds). var timestamp = metadata.ts; // ts from the incoming message.
// Initialize an object to store decoded key/value telemetry data. var values = {};
// Decode battery level from the 5th byte of the payload. values.battery = parseBytesToInt(input, 4, 1);
// Decode temperature from the 6th and 7th bytes of the payload (divided by 100). values.temperature = parseBytesToInt(input, 5, 2) / 100.0;
// Decode saturation from the 8th byte of the payload. values.saturation = parseBytesToInt(input, 7, 1);
// Combine the timestamp with values and add it to the telemetry. result.telemetry = { ts: timestamp, values: values };
// Return the fully constructed output object. return result; // Same logic, less code: // return { // attributes: { // sn: parseBytesToInt(input, 0, 4) // }, // telemetry: { // ts: metadata.ts, // values: { // battery: parseBytesToInt(input, 4, 1), // temperature: parseBytesToInt(input, 5, 2) / 100.0, // saturation: parseBytesToInt(input, 7, 1) // } // } // };}
var result = decodePayload(payload);// Uncomment this code block to overwrite values set in the main configuration window. Useful if you extract device/asset/customer/group names from the payload;// result.type = 'DEVICE'; // Entity type allows you to choose type of created entity. Can be 'DEVICE' or 'ASSET'.// result.name = 'Temperature Sensor'; // Device or asset name (the value must be unique)// result.profile = 'IndustrialSensorProfile'; // Device or asset profile name.// result.customer = 'MyCustomer'; // If customer is not null - created entity will be assigned to customer with such name.// result.group = 'SensorsGroup'; // If group is not null - created entity will be added to the entity group with such name.
// Return the final result object.return result;/** * Decodes the incoming payload and returns a structured object containing telemetry data and attributes. * * @param {number[]} input - The raw payload received as an array of bytes. * @returns {Object} output - The structured output with decoded telemetry and attributes. */
function decodePayload(input) { // Initialize the output object with empty attributes and telemetry for clarity. var result = { attributes: {}, telemetry: {}};
// Decode serial number (SN) from the first 4 bytes of the payload. result.attributes.sn = parseBytesToInt(input, 0, 4);
// Extract the timestamp from metadata (represented in milliseconds). var timestamp = metadata.ts; // ts from the incoming message.
// Initialize an object to store decoded key/value telemetry data. var values = {};
// Decode battery level from the 5th byte of the payload. values.battery = parseBytesToInt(input, 4, 1);
// Decode temperature from the 6th and 7th bytes of the payload (divided by 100). values.temperature = parseBytesToInt(input, 5, 2) / 100.0;
// Decode saturation from the 8th byte of the payload. values.saturation = parseBytesToInt(input, 7, 1);
// Combine the timestamp with values and add it to the telemetry. result.telemetry = { ts: timestamp, values: values };
// Return the fully constructed output object. return result;}
var result = decodePayload(payload);// Uncomment this code block to overwrite values set in the main configuration window. Useful if you extract device/asset/customer/group names from the payload;// result.type = 'DEVICE'; // Entity type allows you to choose type of created entity. Can be 'DEVICE' or 'ASSET'.// result.name = 'Temperature Sensor'; // Device or asset name (the value must be unique)// result.profile = 'IndustrialSensorProfile'; // Device or asset profile name.// result.customer = 'MyCustomer'; // If customer is not null - created entity will be assigned to customer with such name.// result.group = 'SensorsGroup'; // If group is not null - created entity will be added to the entity group with such name.
// Return the final result object.return result;
/** * Converts a slice of bytes from an array into an integer (big-endian). * * @param {number[]} input - The array of bytes. * @param {number} offset - The starting index. * @param {number} length - The number of bytes to convert. * @returns {number} - The resulting integer. */function parseBytesToInt(input, offset, length) { var result = 0; for (var i = offset; i < offset + length; i++) { result = (result << 8) | (input[i] & 0xFF); } return result;}Understanding the decoder:
payload is the raw LoRaWAN payload bytes — ThingsBoard decodes the base64 data field from the LORIOT message automatically. parseBytesToInt(input, offset, length) reads length bytes starting at offset and returns a big-endian integer — a TBEL built-in; manually defined at the bottom of the JS tab. metadata.ts is the message timestamp in ms, falling back to current server time if unavailable.
The example decoder expects an 8-byte payload with this layout:
| Bytes | Length | Expression | Output field | Notes |
|---|---|---|---|---|
| 0–3 | 4 | parseBytesToInt(input, 0, 4) | attributes.sn | Serial number |
| 4 | 1 | parseBytesToInt(input, 4, 1) | telemetry.battery | Battery level (0–255) |
| 5–6 | 2 | parseBytesToInt(input, 5, 2) / 100.0 | telemetry.temperature | Temperature, scaled ÷ 100 |
| 7 | 1 | parseBytesToInt(input, 7, 1) | telemetry.saturation | Saturation (0–255) |
Device name and profile come from the Main decoding configuration section. Uncomment result.name, result.profile, etc. to override them from payload content instead.
To adapt this converter to your device:
- Match your payload structure — update the byte offsets, lengths, and field names in
decodePayloadto match your device’s binary protocol. Refer to your device’s payload specification. - Add or remove fields — add more
parseBytesToIntcalls (orparseBytesToFloat, string extraction, etc.) for additional sensors; remove entries your device doesn’t transmit. - Override device metadata from the payload — uncomment and populate
result.name,result.profile,result.group, orresult.customerto derive device identity from payload content rather than the converter UI configuration.
Create the integration
Section titled “Create the integration”- Go to Integrations center ⇾ Integrations and click + Add integration.
- Basic settings:
- Set Integration type to Loriot.
- Optionally enable Debug mode to track events and errors during development.
- Click Next.
- Uplink data converter:
- Click Select existing and choose the previously created Loriot Uplink Converter from the list.
- Click Next.
- Downlink data converter:
- Click Skip — the downlink converter is only needed for sending commands to devices and can be added later.
- Connection:
- Copy the HTTP endpoint URL — you will need it when configuring LORIOT.
- Click Add to complete the integration.
Connection settings
Section titled “Connection settings”Base URL
The base address of the ThingsBoard server, used to construct the HTTP endpoint URL. For ThingsBoard Cloud, this is https://thingsboard.cloud.
HTTP endpoint URL
Auto-generated endpoint for this integration. Paste this URL into the LORIOT HTTP Push output configuration so that LORIOT forwards device uplink messages to ThingsBoard.
Create Loriot Application output
When enabled, ThingsBoard uses the LORIOT API to register itself as an HTTP Push output in your LORIOT application automatically — no manual configuration in the LORIOT UI is required. Enabling this toggle reveals:
- Server — the LORIOT server subdomain (e.g.
eu1); see Finding server and application ID - Domain — the LORIOT domain (default:
loriot.io) - Application ID — the LORIOT application ID
- Credentials type — authentication method for the LORIOT API;
Basicreveals Email and Password fields for your LORIOT account
Send downlink
When enabled, ThingsBoard can send downlink commands to LORIOT devices via the LORIOT API. Enabling this toggle reveals additional fields:
- Downlink URL — auto-populated from Server and Domain (e.g.
https://eu1.loriot.io/1/rest); override only if your setup uses a custom endpoint - Application Access Token — LORIOT API token used to authenticate downlink requests; generate this in the Access Tokens section of your LORIOT application
Enable security (Headers filter)
Enable to restrict incoming requests to those carrying a specific HTTP header with a matching value. Click Add to define one or more Header / Value pairs. Requests missing any listed header or carrying an incorrect value are rejected. See Enable security for setup steps including the matching LORIOT HTTP Push configuration.
Execute remotely
When enabled, ThingsBoard generates an Integration key and Integration secret that allow the integration to run as a separate process outside the ThingsBoard cluster — useful when the integration must reach services not accessible from the ThingsBoard server.
Advanced settings
- Replace response status from ‘No Content’ to ‘OK’ — when checked, ThingsBoard responds with HTTP 200 instead of 204; use this if LORIOT treats a 204 response as an error
- Description — optional text description for this integration
- Metadata — key-value pairs injected into every uplink message as
integrationMetadatain converter scripts
Configure LORIOT to forward uplinks
Section titled “Configure LORIOT to forward uplinks”To receive uplinks, ThingsBoard must be registered as an HTTP output in your LORIOT application. Choose one of the two methods below — both result in the same data flow.
Manually create an HTTP Push output in the LORIOT UI. No LORIOT credentials are stored in ThingsBoard.
- In the LORIOT UI, go to Applications and open your application.
- In the left sidebar, click Output.
- Click + Add new output.
- Select HTTP Push as the output type.
- Paste the HTTP endpoint URL copied from the integration Connection step into the Target URL for POSTs field.
- Click Add Output.
ThingsBoard connects to the LORIOT API with your credentials and registers itself as an HTTP Push output automatically.
- Go to Integrations center ⇾ Integrations, open the Loriot integration, and click the edit (pencil) icon.
- Enable Create Loriot Application output.
- Enter the Server and Application ID — see Finding server and application ID below.
- Set Credentials type to Basic and enter your LORIOT account email and password.
- Click Apply changes.
Finding server and application ID
Section titled “Finding server and application ID”- Server: The subdomain in your LORIOT dashboard URL — e.g.
eu1fromeu1.loriot.io. - Application ID: Listed in the Applications page next to your application name.
Enable security (optional)
Section titled “Enable security (optional)”To reject requests that don’t include specific HTTP headers, enable Enable security (Headers filter) in the integration settings.
- Open the Loriot integration, click the edit (pencil) icon, and enable Enable security (Headers filter).
- Click Add and enter a Header name and Value (e.g.
authorization/secret). - Click Apply changes.
- In the LORIOT HTTP Push output configuration, enter the same values in Custom header name and Custom header value, then click Accept.
Test uplink
Section titled “Test uplink”When a device sends an uplink message via LORIOT, ThingsBoard automatically creates the device and stores its telemetry. If you do not have a physical device sending data, you can emulate a device message by sending an HTTP request directly to the ThingsBoard endpoint using curl — bypassing LORIOT entirely. This is useful to verify that the integration and uplink converter are configured correctly before connecting real hardware. To send a test uplink, you need the HTTP endpoint URL from the integration details.
Go to Integrations center ⇾ Integrations, open the Loriot integration, and copy the HTTP endpoint URL.
Replace $HTTP_ENDPOINT_URL with the copied URL and run:
Without security:
curl -v -X POST \ -H "Content-Type: application/json" \ -d '{"EUI":"BE7A000000000552","data":"00BC614E5F092950","port":1,"cmd":"rx","dr":"SF12 BW125 4/5","snr":1.2,"ack":"false","freq":868500000,"fcnt":1,"rssi":-130,"ts":1613745998000}' \ "$HTTP_ENDPOINT_URL"With security:
curl -v -X POST \ -H "Content-Type: application/json" \ -H "$HEADER:$VALUE" \ -d '{"EUI":"BE7A000000000552","data":"00BC614E5F092950","port":1,"cmd":"rx","dr":"SF12 BW125 4/5","snr":1.2,"ack":"false","freq":868500000,"fcnt":1,"rssi":-130,"ts":1613745998000}' \ "$HTTP_ENDPOINT_URL"Once an uplink is received, a new device named Device BE7A000000000552 (matching the EUI field from the payload) appears in Entities ⇾ Devices:
Inspect event logs
Section titled “Inspect event logs”Go to Integrations center ⇾ Data converters, click the Loriot uplink converter, and open the Events tab — In shows the raw incoming payload bytes, Out shows the decoded result, Metadata shows all LORIOT message fields passed alongside the payload:
Configure and test downlink
Section titled “Configure and test downlink”The downlink converter encodes ThingsBoard Rule Engine messages into LORIOT-compatible payloads. For the full encoder function reference, see Downlink data converter.
The encoder result must include two metadata fields required by the LORIOT API:
EUI— the device EUI (see below)port— the LoRaWAN port (1–223)
To find the device EUI, go to the Devices section of your LORIOT application and open the device.
Add a downlink converter
Section titled “Add a downlink converter”- Go to Integrations center ⇾ Data converters.
- Click + Add data converter ⇾ Create new converter.
- Enter a name:
Loriot Downlink Converter, and set Type to Downlink. - Paste the encoder function below and click Add.
// Encode downlink data from incoming Rule Engine message// msg - JSON message payload// msgType - message type, e.g. 'ATTRIBUTES_UPDATED'// metadata - key-value pairs with additional message datavar result = { // downlink data content type: JSON, TEXT or BINARY (base64 format) contentType: "TEXT", // downlink data data: msg.firmware, // metadata must include EUI and port metadata: { "EUI": metadata.deviceName, "port": 1 }};return result;// Encode downlink data from incoming Rule Engine message// msg - JSON message payload// msgType - message type, e.g. 'ATTRIBUTES_UPDATED'// metadata - key-value pairs with additional message datavar result = { // downlink data content type: JSON, TEXT or BINARY (base64 format) contentType: "TEXT", // downlink data data: msg.firmware, // metadata must include EUI and port metadata: { "EUI": metadata.deviceName, "port": 1 }};return result;After creating the converter, open the Loriot integration, click the edit icon, select Loriot Downlink Converter in the Downlink data converter field, and click Apply changes.
Enable sending downlinks
Section titled “Enable sending downlinks”To send messages from ThingsBoard to LORIOT devices, enable Send downlink in the integration settings and provide the LORIOT API credentials.
- Open the Loriot integration and click the edit icon.
- Enable Send downlink and fill in the required fields:
- Server — the LORIOT server subdomain (e.g.
us1); see Finding server and application ID. - Application ID — the Application ID from your LORIOT project.
- Downlink URL — auto-populated from Server/Application ID (e.g.
https://us1.loriot.io/1/rest); override if your setup uses a custom endpoint. - Application Access Token — generate this in the Access Tokens section of your LORIOT application and paste it here.
- Server — the LORIOT server subdomain (e.g.
- Click Apply changes.
Configure the rule chain
Section titled “Configure the rule chain”To trigger a downlink when a shared attribute changes, add an Integration Downlink node to the Root Rule Chain:
- Open Rule Chains ⇾ Root Rule Chain and click the edit icon.
- Add an Integration Downlink action node and connect it to the Message Type Switch node via the Attributes Updated relation.
- Save the rule chain.
Trigger and verify a downlink
Section titled “Trigger and verify a downlink”- Go to Entities ⇾ Devices and open the device (e.g.
Device BE7A000000000552). - Open the Attributes tab, switch to Shared attributes, and click +.
- Enter key
firmwareand a value (e.g.01052020.v1.1), then click Add. - Click the edit icon next to the attribute, change the value (e.g. to
01052020.v1.2), and click Update.
Go to Integrations center ⇾ Data converters, click the Loriot Downlink Converter, and open the Events tab — In shows the incoming attribute update, Out shows the encoded payload sent to LORIOT:
To confirm the message reached LORIOT, open the device in the LORIOT UI, go to LoRaWAN Parameters, and check the Downlink Queue at the bottom of the page.