Skip to content

Cookie preferences

We use cookies for our own analytics, to see how our campaigns perform and, if you allow it, to load content from other services such as the Google site search. We never sell your data. Necessary cookies keep the site working and cannot be switched off. See our Cookie Policy for details and our Privacy Policy for how we handle personal data.

Security, load balancing and remembering your cookie choice.

Show us which pages people read, how they find the site and where they get stuck, so we can improve it (Google Analytics, Microsoft Clarity).

Show us which of our ad campaigns bring visitors to the site and remember the campaign or partner link you arrived from (Google Ads, LinkedIn, Meta, partner program). We do not use these cookies to build advertising profiles.

Load the site search from Google when you use it. Google sets its own cookies and shows ads in the search results.

© 2026 The ThingsBoard Authors
22.6k Try for free

ThingsBoard Cloud

Choose your data region

Your data stays in the region you choose, for residency and compliance. No credit card required.

Rather run it yourself? Install on your own servers

UDP Integration

UDP Integration lets devices that use their own text or binary protocol send data to ThingsBoard as UDP datagrams. An uplink data converter transforms each datagram into device or asset data, including telemetry and attributes. ThingsBoard can also send a downlink datagram back to the device’s source address. UDP Integration runs only as a remote integration: a standalone process that binds the UDP port and connects to ThingsBoard over gRPC.

Use UDP Integration when:

  • Devices send a custom text or binary protocol over raw UDP.
  • Firmware sends fire-and-forget datagrams to a fixed host and port and cannot be changed.
  • Low transport overhead matters more than delivery guarantees, for example for battery-powered sensors or high-frequency telemetry.
  1. Receive data. A device sends a datagram to the configured port (default 11560) on the remote integration host. The handler turns it into the converter payload: text, JSON, raw bytes, or a hex envelope.
  2. Decode the payload. The uplink converter identifies the device or asset and extracts attributes and telemetry.
  3. Process the message. ThingsBoard processes the converted data through the Rule Engine. If Allow create devices or assets is enabled, ThingsBoard can create an entity that does not exist yet.
  4. Send downlink data (optional). The integration remembers each device’s source address. The downlink converter encodes the Rule Engine message, and the integration sends it as a datagram to that address.
  • Access to ThingsBoard Cloud with integrations enabled for your tenant.
  • Permission to create integrations and data converters.
  • A host for the remote integration process. Incoming UDP traffic must reach the integration port (default 11560), and the host needs outbound access to the ThingsBoard gRPC port (9090 by default).
  • A sample of the payload your device sends.
  • nc (netcat) to send test datagrams.

Create the uplink converter, assign it to a new UDP integration, start the remote integration process, and send a test datagram.

In this guide, device Thermostat-01 sends its serial number and temperature to port 11560. The integration supports four payload formats:

Comma-separated values with a fixed field order (deviceName,deviceType,serialNumber,temperature):

Thermostat-01,thermostat,SN-12345,25.5

The uplink converter reads the payload prepared by the handler and maps it to ThingsBoard entities and data. UDP Integration uses the Generic converter: you write the decoder in TBEL or JavaScript. For converter types and the full decoder reference, see Uplink data converter.

  1. Go to Integrations ⇾ Data converters and click + Add data converter ⇾ Create new converter.

  2. Converter type — keep Uplink.

  3. Integration type — select UDP.

  4. Name — enter a name, for example UDP Uplink Converter.

  5. Main decoding configuration — the editor is pre-filled with the default decoder template for JSON payloads. For JSON, you can keep it. For text, binary, or hex payloads, replace it with the decoder for your payload format below and, if needed, adapt the field names to your device. The editor opens in TBEL; use the TBEL / JS toggle to switch to JavaScript.

    /** Decoder **/
    // decode payload to string
    var strArray = decodeToString(payload);
    var payloadArray = strArray.replaceAll("\"", "").replaceAll("\\\\n", "").split(',');
    // Result object with device attributes/telemetry data
    var result = {
    deviceName: payloadArray[0],
    deviceType: payloadArray[1],
    attributes: {
    serialNumber: payloadArray[2]
    },
    telemetry: {
    temperature: parseFloat(payloadArray[3])
    }
    };
    /** Helper functions 'decodeToString' and 'decodeToJson' are already built-in **/

    Expected format: deviceName,deviceType,serialNumber,temperature — fixed field order.

    To adapt:

    • Another delimiter — replace split(','), for example with split(';').
    • Another field order — change the payloadArray indexes.
    • More values — add them to telemetry, for example batteryLevel: parseFloat(payloadArray[4]).
    • Attributes or telemetry — move a field between the attributes and telemetry maps.
  6. Click Test decoder function and check the result (see Test the Decoder).

  7. Click Add.

Decoder Inputs

The decoder signature is function decoder(payload, metadata): object | object[].

Variable Type Content
payload byte array The datagram, prepared by the handler type (see the table below).
metadata {[key: string]: string} integrationName and the key–value pairs from the integration’s Metadata field. The sender’s IP address and port are not included.

What reaches payload for each handler type:

Handler type payload content
Text The datagram decoded with Charset Name and serialized as a JSON string, so the text arrives in double quotes. The Text decoder template strips them. Empty datagrams are ignored.
JSON The datagram bytes, unchanged. An empty datagram also reaches the decoder, and JSON parsing fails.
Binary The datagram bytes, unchanged. Empty datagrams are ignored.
Hex A JSON envelope with the datagram as a lowercase hex string: {"reports":[{"value":"546865..."}]}. The Hex decoder template reads reports[0].value. An empty datagram arrives as {"reports":[{"value":""}]}.

Built-in helpers include decodeToString(payload), decodeToJson(payload), and, in TBEL, hexToBytes, bytesToString, and parseBytesToInt. For other patterns, see Common scripting patterns.

Test the Decoder

Click Test decoder function below the editor. The dialog opens with pre-filled Metadata rows, Payload content type set to JSON, and a sample JSON payload. Replace the payload with a sample in the format your handler produces. For the Hex handler, paste the JSON envelope, for example {"reports":[{"value":"546865726d6f737461742d3031746865726d6f73746174534e2d313233343532352e35"}]}.

Click Test. The Output panel shows deviceName Thermostat-01, deviceType thermostat, serialNumber SN-12345 in attributes, and temperature 25.5 in telemetry. If the output is empty or shows an error, fix the decoder and test again.

  1. Go to Integrations ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Integration type — select UDP.
    • Name — keep the default UDP integration or enter your own.
    • Enable integration and Allow create devices or assets — keep both on, so the device is created on its first uplink.
    • Click Next.
  3. Uplink data converter:
    • Click Select existing and choose UDP Uplink Converter.
    • Alternatively, click Create new to write a decoder here.
    • Click Next.
  4. Downlink data converter:
  5. Connection:
  6. Click Add.
Parameter Description
Port UDP port the integration listens on. Default: 11560. Must be free on the remote integration host.
Size of the buffer for inbound socket (in KB) Receive buffer of the UDP socket. Default: 64. Increase it if datagrams are dropped under load.
Enable broadcast Accepts datagrams sent to a broadcast address. On by default.
Execute remotely Always on for UDP. ThingsBoard generates the Integration key and Integration secret for the remote process.
Cache Size Shown only when a downlink converter is assigned. Maximum number of device addresses remembered for downlink delivery. Default: 1000; minimum 1. When the cache is full, older entries are evicted.
Cache time to live in minutes Shown only when a downlink converter is assigned. How long a device address stays valid after its last uplink. Default: 1440 (24 hours); range 1–525600.
Metadata In Advanced settings. Key–value pairs added to the metadata of every message from this integration.

The handler defines how the integration prepares each datagram for the converter. Each datagram is one message; UDP needs no framing. A datagram of up to 65,507 bytes (the UDP maximum) reaches the converter in full. Select it in Handler Type (default: Binary).

For custom binary protocols. No settings needed.

See Decoder Inputs for the exact payload each handler passes to the converter.

Install and start the UDP Integration service by following the Remote Integration guide. Configure it with the Integration key and Integration secret from the integration’s connection settings.

Send a datagram to the integration port, then confirm that ThingsBoard decoded it and created the device.

Make sure the remote integration process is running. Send a test datagram with nc in UDP mode (-u). Replace localhost with the remote integration host if you send from another machine:

Terminal window
echo 'Thermostat-01,thermostat,SN-12345,25.5' | nc -u -w1 localhost 11560

UDP has no acknowledgment, so nc prints nothing on success.

  • Integration events — go to Integrations ⇾ Integrations, open the integration, and click the Events tab. The uplink appears with status OK.
  • Converter events — open UDP Uplink Converter in Integrations ⇾ Data converters and click the Events tab. In shows the payload from the handler, Out shows the decoded result, and Error shows the error text, if any.
  • Device — go to Devices & assets ⇾ Devices. The integration has created Thermostat-01. Open it and confirm temperature = 25.5 on the Latest telemetry tab and serialNumber = SN-12345 on the Attributes tab (Client attributes).

The integration sends downlinks as datagrams to the source IP address and port of the device’s latest uplink. It learns that address only from uplinks, so a device must send at least one uplink first.

  • If the device’s address is cached, the downlink is sent immediately, including several downlinks in a row.
  • Otherwise, the downlink waits until the next uplink from that device.
  • After each downlink payload, the integration sends a second datagram with the line separator of the remote host’s OS (\n on Linux and macOS, \r\n on Windows). Device-side parsers must ignore it.

To receive downlinks, the device must listen on the same port it sends from. A one-shot echo ... | nc -u uses a random source port that closes right after sending.

The downlink converter turns a Rule Engine message into the datagram bytes. For the full encoder reference, see Downlink data converter.

  1. Open the integration in Integrations ⇾ Integrations and click Toggle edit mode (pencil icon).
  2. In the Downlink data converter field, click Create new. The Downlink converter type and UDP integration type are preselected.
  3. Enter a name, for example UDP Downlink Converter.
  4. Main encoding configuration opens with a default encoder. Use the encoder below or your own.
  5. To record downlink events, click the debug icon next to the name, select All messages, and click Apply.
  6. Click Add. Review Cache Size and Cache time to live in minutes in the connection settings, then click Apply changes.

Encoder used in this guide:

/** Encoder **/
// Encode downlink data from the incoming Rule Engine message.
// msg: JSON message payload.
// msgType: message type, e.g. 'ATTRIBUTES_UPDATED', 'POST_TELEMETRY_REQUEST', etc.
// metadata: key-value pairs containing additional message data.
// integrationMetadata: key-value pairs configured in the integration.
var result = {
// Specify the response body format: JSON, TEXT, or BINARY.
contentType: "JSON",
// Serialize the incoming message and use it as the UDP payload.
data: JSON.stringify(msg),
// Add optional metadata when required by the integration.
metadata: {}
};
return result;

The integration sends the encoded data bytes as the datagram.

To send downlinks through the integration, modify the Root Rule Chain:

  1. Go to Data processing ⇾ Rule chains and open the Root Rule Chain.
  2. Find the integration downlink node in the node library panel on the left. Drag it onto the canvas.
  3. In the node configuration dialog, enter a name (e.g. Downlink to UDP integration) and select your UDP integration. Click Add.
  4. Connect the message type switch node to the newly created integration downlink node using the Post attributes and Attributes Updated relation types to trigger downlinks whenever shared attributes are created or updated.
  5. Apply the changes.

Update a shared attribute to queue a downlink, then send an uplink to receive it.

  1. Go to Devices & assets ⇾ Devices, select your device, and open the Attributes tab.

  2. Select Shared attributes and click +.

  3. Set Key to temperatureUploadFrequency, Type to Integer, Value to 60, and click Add. ThingsBoard queues the downlink.

  4. Send an uplink and keep the socket open for 10 seconds so nc can receive the reply:

    Terminal window
    echo 'Thermostat-01,thermostat,SN-12345,25.5' | nc -w10 -u localhost 11560
  • Terminal output — nc prints the downlink payload: {"temperatureUploadFrequency":60}.
  • Converter events — open the downlink converter’s Events tab. In shows the Rule Engine message and Out shows the encoded payload sent to the device address.
Symptom Cause Fix
No events in the integration The remote process is not running, or the datagram did not reach the port. Check that the remote process is running and connected. Open the UDP port in the firewall. Check the target host and port.
Remote process cannot connect to ThingsBoard Wrong host, port, key, or secret. Check the connection settings and Integration key / Integration secret in tb-remote-integration.yml. Make sure the gRPC port (9090 by default) is reachable.
Port already in use Another process or integration uses the port. Pick another Port. The integration retries binding every 5 seconds until the port is free.
Decoded values are wrong The Handler Type does not match the decoder template. Use the same format for the handler and the template. Capture raw datagrams to compare, for example tcpdump -i any udp port 11560 -X.
The events show Device name is missing. Provide deviceName in the payload. The converter uses the default template, and the message has no deviceName, or it is empty. Add deviceName to the message, or adapt the decoder to read the name from another field.
The events show an error about deviceName or assetName, for example Either 'deviceName' or 'assetName' should be present in the converter output! A custom decoder returned no deviceName (for example {}) or an empty one. Check In and Error in the converter events. Make sure the decoder extracts deviceName.
Converter error The decoder threw an exception. Open the converter’s Events tab, read the Error field, and reproduce it with Test decoder function.
Telemetry not saved, no error The decoder returns [] or empty telemetry. Make sure telemetry holds at least one key.
Wrong timestamp The device sends ts in seconds; ThingsBoard expects milliseconds. Convert it. In the default template: timestamp = data.ts * 1000;. In a custom decoder: ts: data.ts * 1000.
Device does not receive downlinks The device sends from a changing source port, or its cached address expired. Send and listen on a fixed source port, for example with nc -p. Increase Cache time to live in minutes if needed.