ChirpStack to ThingsBoard: Forward Decoded LoRaWAN Uplinks

Connect ChirpStack to ThingsBoard: MQTT integration, uplink converter, device matching by DevEUI and downlink control, with real v4 event JSON.

LoRaWAN
Architecture

The data flow

ChirpStack decodes your LoRaWAN payloads, ThingsBoard turns them into dashboards, alarms and control. This guide shows the full path: MQTT integration, uplink converter, device matching by DevEUI and downlink control back to the device, with a real v4 event and working converters.

Sensor / controller

Measures or controls in the field and sends LoRaWAN uplinks.

LoRaWAN gateway

Receives the radio packets and forwards them to the server.

ChirpStack

Network server: manages sessions and decodes the payload.

ThingsBoard / Grafana

Dashboards, alarms, rules and reports.

What a ChirpStack v4 uplink looks like

ChirpStack has already decoded the payload, the values sit in the object field. That is the field ThingsBoard maps onto telemetry. The prerequisite is a working payload codec on the device profile.

{
  "deviceInfo": {
    "applicationId": "00372e31-0620-4671-8270-237632a4e227",
    "applicationName": "cold-chain",
    "deviceProfileName": "EM300-TH",
    "deviceName": "coldroom-01",
    "devEui": "24e124136b502217"
  },
  "fPort": 85,
  "fCnt": 128,
  "data": "AXVkA2etAARoSw==",
  "object": { "battery": 100, "temperature": 17.3, "humidity": 57.5 },
  "rxInfo": [{ "gatewayId": "24e124fffef54092", "rssi": -51, "snr": 13.8 }],
  "txInfo": { "frequency": 868100000 }
}

Step 1: ChirpStack integration

In the ChirpStack application under Integrations, enable the MQTT (or HTTP) integration with the marshaler set to JSON. Every uplink event is then published to application/{ApplicationID}/device/{DevEUI}/event/up.

Step 2: Uplink converter in ThingsBoard

The fastest path: pick the ChirpStack integration type when creating the converter, and ThingsBoard ships a pre-filled decoder with extracted metadata. For a generic, transparent version:

// payload = ChirpStack event (JSON), metadata = auto-extracted fields
var data = decodeToJson(payload);

var result = {
  deviceName: data.deviceInfo.devEui,             // stable, unique key
  deviceType: data.deviceInfo.deviceProfileName,  // e.g. "EM300-TH"
  attributes: {
    applicationName: data.deviceInfo.applicationName,
    fPort: data.fPort
  },
  telemetry: {
    ts: new Date(data.time).getTime(),
    values: data.object                           // pass the decoded values through
  }
};

// signal quality as telemetry (optional, but useful)
if (data.rxInfo && data.rxInfo.length > 0) {
  result.telemetry.values.rssi = data.rxInfo[0].rssi;
  result.telemetry.values.snr  = data.rxInfo[0].snr;
}

return result;

ThingsBoard provisions the device on the first message and identifies it by the DevEUI, not the display name. The mapping stays stable even if you rename devices.

Step 3: Connect the MQTT integration

Add a ThingsBoard MQTT integration that connects to the ChirpStack broker and subscribes to application/+/device/+/event/up. Assign the uplink converter from step 2, and the data flows into Latest Telemetry.

Downlink: control back to the device

For controllable devices (UC300 relay, WT102 thermostat) you build a downlink converter. It turns a ThingsBoard RPC or a shared-attribute change into a ChirpStack downlink enqueue:

// Triggered via the Rule Engine (integration downlink node).
// metadata carries the target DevEUI and ApplicationID.
var fPort = 85;
var payloadBase64 = msg.dataBase64;   // your encoded command, Base64

var result = {
  contentType: "JSON",
  data: JSON.stringify({
    devEui: metadata.devEui,    // must match the DevEUI in the topic
    confirmed: false,
    fPort: fPort,               // must be greater than 0
    data: payloadBase64         // Base64; ChirpStack encrypts before sending
  }),
  metadata: {
    topic: "application/" + metadata.applicationId +
           "/device/" + metadata.devEui + "/command/down"
  }
};

return result;

The downlink is triggered in the rule chain via an integration downlink node. Note: for Class A devices the downlink is delivered in the RX window after the next uplink, for Class C (e.g. UC300) almost immediately.

ThingsBoard PE/Cloud vs Community Edition

Integrations and data converters are a Professional Edition and ThingsBoard Cloud feature. The Community Edition does not have them: there you push the data through ChirpStack's HTTP integration to the ThingsBoard HTTP device API, or put a small bridge in front. For controllable multi-tenant setups we run PE and operate both as ThingsBoard managed hosting alongside ChirpStack hosting; for pure data capture CE is often enough.

Pitfalls from the field

  • Region prefix: The ChirpStack v4 default config prepends the region to the topic (e.g. eu868/application/...). If you only subscribe to application/#, nothing arrives. Either subscribe with the prefix or remove it in chirpstack.toml.
  • v3 to v4: Decoded data sits in the object field in v4, formerly in the objectJSON string. Old converters using JSON.parse(data.objectJSON) break.
  • DevEUI as the key: Match devices by devEui, not by name.
  • fPort greater than 0: Downlinks with fPort 0 are rejected.

Frequently asked questions

v4 is recommended, the event format is cleaner (decoded values sit in the object field instead of the objectJSON string). We migrate v3 converters as part of an upgrade.
MQTT when ThingsBoard and ChirpStack can reach the same broker, which is more robust and bidirectional. HTTP when only a push across firewall boundaries is possible.
By the DevEUI in the event. The uplink converter returns it as deviceName, and ThingsBoard provisions new devices on first contact.
Yes, via a downlink converter and the integration downlink node. For Class C devices like the UC300 the command applies in near real time, for Class A after the next uplink.
Yes, both as managed hosting on European infrastructure, including the integration and converters. You keep ownership of the data.

Let's discuss your infrastructure. Digital and on-site.

Whether it's IoT platform development, hardware selection, managed hosting for ChirpStack, ThingsBoard, Grafana or NetBird VPN, or migration from a self-hosted setup - we'll find the right solution for your use case. Book a free 30-minute consultation, no commitment required.

Timo Wevelsiep

Your contact

Timo Wevelsiep

Founder, merkaio

15 minutes, no commitment, directly with Timo.

By submitting, you agree to our Privacy Policy.

merkaio is an independent integrator and is not affiliated with Milesight.