Skip to content
Stand with Ukraine flag

The Things Stack Community Integration

The Things Stack Community (TTN) integration connects ThingsBoard to a TTN 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 TTN API.

  1. Go to the TTN console, open the Applications section, and press Add application.
  2. Fill in the required fields:
    • Application ID — e.g. thingsboard-connection
    • Handler registration — identifies the region where the application will be registered (e.g. eu1 for the EU region)
  3. Press Create application.
  1. In the application, open the Devices page and press Register device.
  2. Fill in the required fields:
    • Device ID — e.g. thermostat-a
    • Device EUI — press Generate to create a random identifier
    • AppEUI — can be filled with zeros
    • AppKey — press Generate to create a random identifier
  3. Press Register.

An access key is required to authenticate the ThingsBoard integration with TTN.

  1. In the TTN console, go to API keys in your application menu.
  2. Press Add API key, enter a name, and select the required permissions.
  3. Press Generate key and copy the key immediately — it will not be shown again.

The Things Stack Community integration uses a Typed converter. ThingsBoard automatically extracts and maps standard TTN fields — eui, fPort, decoded, location, signal metadata, and more — so the decoder script only needs to handle the device payload bytes. 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.

  1. Go to Integrations center ⇾ Data converters.
  2. Click + Add data converter ⇾ Create new converter.
  3. Set Converter type to Uplink (default).
  4. Select Integration type: The Things Stack Community.
  5. Enter a converter name: The Things Stack Community Uplink Converter.
  6. The Main decoding parameters section specifies:
    • A naming template for automatic device creation — Device $eui — change this if you prefer a different naming scheme.
    • Leave the decoder function at its default for this tutorial.
  7. In Advanced decoding parameters, all fields are pre-populated for The Things Stack Community — device profile defaults to $applicationId, label to $deviceId, and the telemetry, attributes, and update-only key lists are pre-filled with standard TTN metadata keys. Adjust as needed; see the Advanced decoding parameters reference for field descriptions.

  8. Click Add.

The decoder function used in this tutorial:

/**
* 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 is the timestamp parsed from the incoming message's time, or returns the current time if it cannot be parsed.
// 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: convertDateToTimestamp(extractDateFromMetadata()),
// 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;

The decoder receives the raw binary payload (frm_payload) from TTN as a byte array. If your TTN application uses a payload formatter, decoded_payload will already be parsed JSON — in that case, access fields directly as a JSON object instead of using parseBytesToInt.

The decoder assumes a fixed binary payload structure. It reads byte ranges using parseBytesToInt(input, offset, length) and produces:

  • Attributesn: serial number from bytes 0–3
  • Telemetrybattery (byte 4), temperature (bytes 5–6, divided by 100), saturation (byte 7), all timestamped with metadata.ts
BytesFieldOutput typeNotes
0–3snattributeDevice serial number
4batterytelemetryBattery level
5–6temperaturetelemetryRaw value ÷ 100
7saturationtelemetrySaturation level

Example payload (hex):

00BC614E5F092950

Example output:

{
"attributes": { "sn": 12345678 },
"telemetry": {
"ts": 1690000000000,
"values": {
"battery": 95,
"temperature": 23.45,
"saturation": 80
}
}
}

To adapt this converter to your device:

  • Different device name — change the Device name pattern in Main decoding configuration (e.g. replace Device $eui with $deviceId or a fixed name).
  • Different byte layout — adjust the offset and length in each parseBytesToInt() call to match your payload structure.
  • Different field names — rename battery, temperature, or saturation to match your data model; add or remove fields as needed.
  • TTN payload formatter — if your TTN application uses a payload formatter, the pre-parsed result is available as decoded in the Telemetry list. In that case you can access fields directly as JSON in the decoder script instead of using parseBytesToInt.
  • Additional attributes — add more keys to result.attributes (e.g. firmware version, hardware revision).

The decoder script controls device sensor data — the fields written to result.attributes and result.telemetry.values. The Advanced decoding parameters control TTN network metadata (signal quality, location, LoRa settings) that ThingsBoard extracts automatically. You do not need to add your sensor field names to the Telemetry or Attributes lists there.

  1. Go to Integrations center ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Set Integration type to The Things Stack Community.
    • Enable integration and Allow create devices or assets are on by default.
    • Click Next.
  3. Uplink data converter:
    • Select existing — choose a previously created The Things Stack Community Uplink Converter from the list.
    • Click Next.
  4. Downlink data converter:
    • Click Skip — the downlink converter is only needed for sending commands to devices and can be added later.
  5. Connection settings:
    • Region — the region where your TTN application is registered (e.g. eu1).
    • Port8883.
    • Credentials:
      • Username — your TTN Application ID with @ttn appended (e.g. my-thingsboard@ttn).
      • Password — the API key generated in Generate an API access key step.
    • Enable SSL and Use API v3 are on by default — leave them enabled.
    Read more about each parameter in connection settings.
  6. Optionally click Check connection — the wizard advances to a verification step showing Connected when successful.
  7. Click Add to complete the integration setup.

Host type

ValueDescription
RegionConnect to a standard TTN cluster. Enter the Region identifier (e.g. eu1) — ThingsBoard constructs the host as {region}.cloud.thethings.network.
CustomSpecify a fully custom broker hostname (e.g. for a private TTN deployment).

Port

ParameterDefaultDescription
Port8883MQTT broker port. 8883 is the standard TLS port used by TTN.

Credentials

ParameterDescription
UsernameThe TTN Application ID (e.g. my-thingsboard).
PasswordThe API access key generated in your TTN application.

Enable SSL

Encrypts the MQTT connection using TLS. Enabled by default and required for connections to TTN public clusters.

Use API v3

Switches the MQTT topic structure between TTN API v2 and v3.

ValueTopic format
Enabledv3/{appId}/devices/{devId}/up (TTN v3 topic format)
Disabled+/devices/+/up (TTN v2 topic format)

Topic filters

Defines which MQTT topics ThingsBoard subscribes to for uplink messages. The default filter is pre-configured based on the Use API v3 setting.

FieldDescription
TopicMQTT topic filter. + matches a single topic level. Automatically set based on the API version.
QoS0 — at most once (fire and forget); 1 — at least once (may deliver duplicates); 2 — exactly once

Execute remotely

When enabled, ThingsBoard generates an Integration key and Integration secret that allow external services to push messages into this integration via the Integration API.

Advanced settings

ParameterDefaultDescription
Protocol versionMQTT 3.1.1MQTT protocol version used for the broker connection.
Max bytes in message32368Maximum payload size in bytes. Messages exceeding this limit are dropped.
Connection timeout (sec)10Seconds ThingsBoard waits for a broker response before marking the connection as failed.
Downlink topic pattern${applicationId}/devices/${devId}/downMQTT topic used for publishing downlink messages to TTN devices. ${applicationId} and ${devId} are resolved from the downlink converter output metadata.

Use the TTN console to simulate an uplink message and confirm that ThingsBoard receives and decodes it correctly.

  1. In the TTN console, go to the device thermostat-a ⇾ Messaging tab ⇾ Simulate uplink.
  2. In the Payload field, enter the test payload:
    00BC614E5F092950
  3. Click Simulate uplink.

This payload matches the byte layout from the uplink converter: sn = 12345678, battery = 95, temperature = 23.45, saturation = 80.

After sending, go to Entities ⇾ Devices in ThingsBoard. A new device is automatically provisioned by the integration. Open it and check the Latest Telemetry tab — you should see temperature, battery, saturation, and other decoded fields.

Additional fields such as rssi, snr, and latitude come from the TTN network metadata, stored as telemetry via the Advanced decoding parameters configured in Create an uplink converter.

To send a command to a TTN device from ThingsBoard, three things must be in place: a downlink converter attached to the integration, a Rule Chain node that forwards messages to that integration, and a trigger — in this tutorial, a shared attribute change.

The downlink converter encodes ThingsBoard commands into TTN-compatible messages. For the full encoder reference, see Downlink data converter. The output must contain a downlinks array with f_port, frm_payload, and priority fields.

Expected output structure:

{
"downlinks": [{
"f_port": 2,
"frm_payload": "vu8=",
"priority": "NORMAL"
}]
}

The result object must follow this format:

  • contentType — how data is encoded: TEXT, JSON, or BINARY
  • data — the actual payload sent to the device. See the TTN API documentation for details.
  • metadata — must include devId to identify the target device in TTN

This converter reads the powerState field from the incoming ThingsBoard message and sends it as a base64-encoded payload to device thermostat-a.

Add the downlink converter to the existing integration:

  1. Go to Integrations center ⇾ Integrations and open the The Things Stack Community integration.
  2. Click Toggle edit mode.
  3. In the Downlink data converter field, click Create new.
  4. Enter converter name.
  5. Paste the encoder function by copying it below:

    var data = {
    downlinks: [{
    f_port: 2,
    confirmed: false,
    frm_payload: btoa(msg.powerState),
    priority: "NORMAL"
    }]
    };
    var result = {
    contentType: "JSON",
    data: JSON.stringify(data),
    metadata: {
    devId: 'thermostat-a'
    }
    };
    return result;
  6. Click Add to save the converter, then click Apply changes to update the integration.

The encoder reads msg.powerState from the incoming message — this is the shared attribute you will create in the Test the downlink section. The result is base64-encoded and sent to device thermostat-a.

To adapt this converter to your device:

  • Different device — replace thermostat-a in devId with your device name.
  • Different command field — replace msg.powerState with whichever attribute or RPC parameter carries the command value.
  • Different port — change f_port to match the port your device listens on.

Configure the Root Rule Chain to forward attribute changes to the TTN integration.

  1. Open Rule Chains ⇾ Root Rule Chain and click the edit icon.
  2. Find the Integration Downlink node in the node panel and drag it onto the canvas.
  3. Set the Name, select The Things Stack Community integration, and click Add.
  4. Connect the Message Type Switch node to the Integration Downlink node using the Attributes Updated relation. The Attributes Updated relation fires whenever a shared attribute is created or changed — this is what triggers the downlink.
  5. Click Apply changes to save the rule chain.

Trigger a downlink by adding a shared attribute to the ThingsBoard device provisioned during the uplink test:

  1. Go to Entities ⇾ Devices, open the device provisioned by the integration, and click the Attributes tab.
  2. Switch to Shared attributes and click + to add a new attribute.
  3. Enter the key powerState and value on, then click Add.

Adding the attribute triggers a downlink to TTN device thermostat-a with the powerState value encoded in the payload. Go to the TTN console and open thermostat-a ⇾ Live data — the downlink event appears in the list.