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

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

Tuya Integration

Tuya Integration connects ThingsBoard to the Tuya IoT Platform (Tuya Cloud). It subscribes to the Tuya Message Service and receives status reports from devices added in the Smart Life or Tuya Smart app. An uplink data converter turns each report into telemetry and attributes. ThingsBoard can also send downlink commands to the devices through the Tuya OpenAPI.

Use Tuya Integration when:

  • Your devices are Tuya-based and already connected to Tuya Cloud through the Smart Life or Tuya Smart app.
  • You want to monitor them in ThingsBoard dashboards and process their data in the Rule Engine.
  • You need to control them from ThingsBoard, for example switch a smart plug on or off.

This guide uses a Tuya Smart Plug. A virtual Tuya device works for testing too.

  1. Receive data. The device reports its status to Tuya Cloud over Wi-Fi. The integration subscribes to the Message Service (an Apache Pulsar queue) with your cloud project credentials and receives each status report.
  2. Decode the payload. The integration decrypts the report and passes it to the uplink converter, which returns the device name, telemetry, and attributes.
  3. Process the message. ThingsBoard processes the converted data through the Rule Engine. If Allow create devices or assets is enabled, ThingsBoard creates the device on its first report.
  4. Send downlink data (optional). The Rule Engine passes an RPC message to the integration. The downlink converter encodes it as a Tuya command, and the integration sends it to the Tuya OpenAPI, which delivers it to the device.
  • Access to ThingsBoard or ThingsBoard Cloud with integrations enabled for your tenant.
  • Permission to create integrations and data converters, and to edit rule chains for downlink.
  • A Tuya IoT Platform account. To create one, see Create a Tuya IoT Platform Account.
  • An active IoT Core subscription of the cloud project (the free trial is enough) to send commands to devices. Status reports arrive without it. Check it in Cloud ⇾ Cloud Services.
  • A Tuya device (physical or virtual) added in the Smart Life or Tuya Smart app. To add a smart plug, see Register the Smart Plug in the Tuya App.

Add the device to the Tuya app, create a cloud project, enable the Message Service, and link the app account to the project.

  1. Open the Smart Life (or Tuya Smart) app and tap Add Device.
  2. Open the Electrical category and tap Socket (Wi-Fi).
  3. Power the plug off for 10 seconds, then power it back on.
  4. Press and hold the RESET button for 5 seconds.
  5. Check that the indicator blinks rapidly, then tap Next.
  6. Wait until the app adds the device, then tap Done.
  7. Open the device card and tap the power button to check that the plug responds.
  1. Open the Tuya IoT Platform login page and click Sign Up.
  2. Enter your Email, the Verification Code sent to it, a Password, the Organization Name, and the Country/Region. Accept the terms and click Next.
  3. Log in with the new account.
  1. In the sidebar, go to Cloud ⇾ Cloud Project ⇾ Project Management.
  2. Click Create Cloud Project. Enter a Project Name (for example, ThingsBoard), choose an Industry and a Development Method (for example, Custom), and select the Data Center. Click Create.
  3. On the Authorize API Services screen, keep the recommended services (IoT Core is required) and click Authorize.
  4. On the project Overview page, copy the Access ID/Client ID and Access Secret/Client Secret under Authorization Key. You need them, together with the data center, to create the integration.

The Message Service pushes device status reports to subscribers such as the integration. Without it, no uplinks arrive.

  1. In the cloud project, open the Message Service tab and turn on Message Service.
  2. In the Configure Message Service dialog, select the Message Service Type and the Message encryption algorithm, then click OK. The integration decrypts both AES-ECB and AES-GCM messages.
  3. Check that the tab shows the service as Enabled.

A messaging rule defines which messages Tuya pushes. Tuya keeps separate rules and subscriptions for two environments:

Tuya environment Devices Integration Environment
Production Real (physical) devices. PROD
Test Only devices you add as test devices, for example virtual devices. TEST

The rule must be enabled in the environment where your device reports, and the integration must use the same environment. Otherwise the integration connects, but no uplinks arrive.

  1. In the cloud project, open Message Service ⇾ Messaging Rules and select Production Environment for a real device, or Test Environment for a test device.
  2. If the tab shows “No messaging rules apply to the production environment, no messages will be pushed”, click Create Messaging Rules, then Add Message Filtering Rule. If a rule already exists, click Modify Messaging Rules.
  3. Set the rule to BizCode (Message Type) In statusReport (Status Report). Optionally add online and offline: the decoder in this guide stores them as the online attribute. Click Release Rule, then OK.
  4. Turn on the rule and confirm with OK. The tab then shows “The rules for the production environment are in effect … The corresponding message topic is: clientId/out/event”. While the rule is off, it shows “The rules for the production environment are disabled, so all messages will not be pushed”.
  5. Open Subscription Management, select the same environment, and check that the subscription <Access ID>-sub has Status = Good. Consumers shows 1 once the integration is connected.

Linking the app account adds its devices to the cloud project.

  1. Go to Devices ⇾ Link App Account, click Add App Account, and select Tuya App Account Authorization.
  2. Scan the QR code in the Smart Life (or Tuya Smart) app: Me ⇾ Scan.
  3. In the Link App Account dialog, select Automatic Link and click OK.
  4. Confirm the linking. Click Manage Devices on the app account row and check that the smart plug appears as Online.

Create the uplink converter, assign it to a new Tuya integration, and trigger a status report from the device.

The uplink converter receives each status report as JSON, resolves the device by its Tuya ID, and returns its telemetry. Tuya 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 Tuya.

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

  5. Main decoding configuration — the editor opens with the default Tuya decoder, which is the decoder below. Keep it, or write your own. It reads the code–value pairs from the status array and scales the smart plug readings: cur_voltage (V) and cur_power (W) ÷ 10, cur_current (reported in mA) ÷ 1000 to get A. Each value keeps the device time t of its report. It stores online and offline messages as the online attribute and skips other messages, so they do not create or update a device. If the message has no Tuya device ID, it stops with the error Tuya message has no devId. The editor opens in TBEL; use the TBEL / JS toggle to switch to JavaScript.

    /** Decoder **/
    // Tuya Message Service pushes each device report as JSON.
    // This example handles status reports (statusReport) and online/offline messages
    // of a Tuya smart plug. Other messages are skipped.
    // Parse the incoming payload (byte array) into a JSON object.
    var data = decodeToJson(payload);
    // Use the Tuya device ID as the device name.
    // Keep it unchanged: the downlink sends commands to the Tuya device with this ID.
    var deviceName = data.devId;
    if (deviceName == null || deviceName.trim().isEmpty()) {
    raiseError("Tuya message has no devId");
    }

    To adapt:

    • Other data points — add or change the code branches. Codes without a branch are stored as received.
    • Other scaling — change the divisors. For example, some models report add_ele (energy, kWh) that needs ÷ 100 or ÷ 1000.
    • Friendly key names — map codes explicitly, for example cur_voltage to voltage.
    • Server time — to store values with the time ThingsBoard receives them instead of the device time t, push values instead of {ts: data.status[i].t, values: values}.
    • Device properties — add them to attributes, for example productKey: data.productKey in the attributes of the status report result.
    • Device settings — after it reconnects, the plug reports its full state, including settings such as child_lock, light_mode, relay_status, and countdown_1. Store them in attributes instead of telemetry if you do not need their history.
  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 decrypted status report (JSON). Parse it with decodeToJson(payload).
metadata {[key: string]: string} Message Service envelope: topic, t (send time, ms), pv (protocol version), protocol, and sign. Also integrationName and the key–value pairs from the integration’s Metadata field.

Status report fields:

Field Content
devId Tuya device ID, for example bfac3c40adca459c9chaar.
productKey Product key of the device model, for example iq9hwd2bjsdgqiby.
dataId Unique ID of the report.
status Data points. Each entry has code, value, and t (ms). An entry also carries the data point number with the value as a string, for example "1": "false" for switch_1 or "20": "2072" for cur_voltage; the decoder ignores it.

The integration’s Events tab shows each message as { "metadata": {...}, "data": {...} }. The decoder receives only data as payload. To test the decoder with a message from Events, paste only the data object as the payload.

Test the Decoder

Click Test decoder function below the editor. The default payload of a Tuya converter is this status report, with Payload content type set to JSON. If the payload differs, paste the report. Click Test:

{
"dataId": "000657E477596B12C80347616A03002A",
"devId": "bfac3c40adca459c9chaar",
"productKey": "iq9hwd2bjsdgqiby",
"status": [
{ "code": "cur_voltage", "t": 1785490000000, "value": 2086 },
{ "code": "cur_power", "t": 1785490000000, "value": 142 },
{ "code": "cur_current", "t": 1785490000000, "value": 63 }
]
}

The Output panel shows:

{
"deviceName": "bfac3c40adca459c9chaar",
"deviceType": "Tuya device",
"attributes": {},
"telemetry": [
{ "ts": 1785490000000, "values": { "cur_voltage": 208.6 } },
{ "ts": 1785490000000, "values": { "cur_power": 14.2 } },
{ "ts": 1785490000000, "values": { "cur_current": 0.063 } }
]
}

Check that deviceName equals the devId and that telemetry holds the scaled values with the report time ts. If the output shows an error, fix the decoder and test again. An empty result [] means the decoder skipped the message: it has no status and is not online or offline.

  1. Go to Integrations ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Integration type — select Tuya.
    • Name — enter a name, for example Tuya integration.
    • Enable integration and Allow create devices or assets — keep both on, so the device is created on its first report.
    • Click Next.
  3. Uplink data converter:
    • Click Select existing and choose Tuya Uplink Converter.
    • Alternatively, click Create new to write a decoder here.
    • Click Next.
  4. Downlink data converter:
  5. Connection:
    • Region — select the data center of your cloud project.
    • Environment — select PROD for a real device or TEST for a test device.
    • Access Id and Access Key — paste the Access ID/Client ID and Access Secret/Client Secret from the cloud project.
    • See Connection Settings for details.
  6. Click Add.
Parameter Description
Region Data center of the cloud project: China (default), United States (Western America), Europe (Central Europe), or India. Selects the Message Service and OpenAPI endpoints, for example mqe.tuyaeu.com and openapi.tuyaeu.com for Europe.
Environment PROD (default) or TEST. PROD reads the production topic <Access Id>/out/event; TEST reads <Access Id>/out/event-test. Must match the environment of the messaging rule.
Access Id Access ID/Client ID of the cloud project. The integration subscribes as <Access Id>-sub.
Access Key Access Secret/Client Secret of the cloud project. Signs OpenAPI requests and decrypts messages. Keep it secret.
Execute remotely Runs the integration as a separate process outside the ThingsBoard cluster. ThingsBoard generates an Integration key and Integration secret for it. See Remote Integration.
Description In Advanced settings. Free-text description.
Metadata In Advanced settings. Key–value pairs added to the metadata of every message from this integration.

If the connection fails, the integration retries about every two minutes and logs a CONNECT event with the error on its Events tab for each attempt.

Trigger a status report, then confirm that ThingsBoard decoded it and created the device.

Unplug the smart plug and plug it back in, or switch it in the Smart Life app. The device sends a statusReport to Tuya Cloud, which pushes it to the integration.

  • Integration events — go to Integrations ⇾ Integrations, open the integration, and click the Events tab. The uplink appears with status OK. Click ⋅⋅⋅ in the Message column to see the metadata and the report.
  • Converter events — open Tuya Uplink Converter in Integrations ⇾ Data converters and click the Events tab. In shows the report, Out shows the decoded result, and Metadata shows the Message Service envelope.
  • Device — go to Devices & assets ⇾ Devices. The integration has created a device named after the Tuya devId. Open it and check the Latest telemetry tab, for example cur_power, cur_voltage, cur_current, and switch_1. The plug reports each data point in a separate message when it changes, so the keys can arrive at different times. After the plug reconnects, it reports its full state, including settings such as child_lock and relay_status. If the messaging rule includes online and offline, the Attributes tab (Client attributes) shows online.

ThingsBoard sends a command to the device when the Rule Engine routes an RPC request to the integration — for example, when a dashboard switch is toggled. The integration calls the Tuya OpenAPI of the selected region:

  1. It takes the Tuya device ID from deviceId in the encoder’s output metadata, or from deviceName if deviceId is not set.
  2. It sends data to POST /v1.0/iot-03/devices/{deviceId}/commands as { "commands": [...] }.

The encoder’s data must be one of:

data Sent to Tuya
An object with code and value, for example {"code": "switch_1", "value": true} {"commands": [{"code": "switch_1", "value": true}]}
An array of such objects {"commands": [...]} with every command
An object with method set to a query name: getStatus, getFunctions, getSpecification, getLogs, getReportLogs, or getCategory A GET request to the matching OpenAPI endpoint. The response goes to the uplink converter as payload, with msgType = DownlinkResponse and deviceId in metadata.

Any other data, including {"commands": [...]}, fails with “Downlink message format is not correct, downlink message should contain one of the following: code field, service RPC method, commands array!”.

The encoder in this guide sends commands only. To send a query, return data with method, for example {"method": "getStatus"}, from your own encoder, and handle the response in the uplink converter: the response has no devId (the device ID is in metadata.deviceId), so the decoder in this guide stops with an error.

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

The encoder below uses the RPC method as the Tuya command code and the RPC params as its value. ThingsBoard passes RPC params as JSON text, for example true from the Round switch as "true", so the encoder parses the text back into a boolean, number, string, or object. It sets deviceId to the device name, which is the Tuya devId. It stops with an error if the device name is missing, if the message is not an RPC request, or if the RPC has no method or params; see Troubleshooting.

  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 Tuya integration type are preselected.
  3. Enter a name, for example Tuya Downlink Converter.
  4. Main encoding configuration — the editor opens with the default Tuya encoder, which is the encoder below. Keep it, or write your own. The editor opens in TBEL; use the TBEL / JS toggle to switch to JavaScript.
    // Encode downlink data from incoming Rule Engine message
    // msg - JSON message payload downlink message json
    // msgType - type of message, for ex. 'ATTRIBUTES_UPDATED', 'POST_TELEMETRY_REQUEST', etc.
    // metadata - list of key-value pairs with additional data about the message
    // integrationMetadata - list of key-value pairs with additional data defined in Integration executing this converter
    /** Encoder **/
    // Send an RPC request to the Tuya device as a Device Control command:
    // the RPC method becomes the command code, the RPC params become its value.
    // For example, method "switch_1" with params true turns a smart plug on.
    // The device name is the Tuya device ID. Reject the message if it is missing or empty.
    var deviceId = metadata.deviceName != null ? metadata.deviceName.trim() : null;
    if (deviceId == null || deviceId.isEmpty()) {
    raiseError("Message metadata has no deviceName");
    }
    // Only RPC requests are sent as commands. Reject other messages, for example attribute updates.
  5. Click Test encoder function. The defaults are the RPC message {"method":"switch_1","params":"true"} with Message type RPC_CALL_FROM_SERVER_TO_DEVICE, for the device bfac3c40adca459c9chaar of type Tuya device. Click Test and check the output: data is {"code":"switch_1","value":true} and metadata.deviceId is bfac3c40adca459c9chaar.
  6. To record downlink events, click the debug icon next to the name, select All messages, and click Apply.
  7. Click Add, then Apply changes.

RPC messages already carry deviceName in their metadata, so a single integration downlink node is enough.

  1. Go to Data processing ⇾ Rule chains and open the Root Rule Chain.
  2. From the Action section, drag an integration downlink node onto the canvas.
  3. Enter a Name (for example, Downlink to Tuya), select your Tuya integration, and click Add.
  4. Connect the message type switch node to the integration downlink node with the RPC Request to Device relation.
  5. Click Apply changes.

Import the Tuya Smart Plug dashboard. It shows the uplink data and sends commands to the plug:

  • Simple neon gauge — voltage and power; Time series chart — voltage, power, and current.
  • Led indicator — the on/off state from the switch_1 telemetry.
  • Round switch — sends an RPC with method switch_1 and params true or false.
  1. Download tuya_smart_plug_dashboard.json.
  2. Go to Dashboards, click + Add dashboard ⇾ Import dashboard, upload the file, and click Import.
  3. Open the Tuya smart plug dashboard and enter edit mode.
  4. Click the Entity aliases icon, click the pencil icon next to the smartPlug alias, select your device, and click Save. Then click Save in the lower-right corner.
  5. Toggle the Round switch.

If a widget shows no data, edit it and change the data keys in Datasource to the codes your device reports.

  • Device — the plug switches, and the Led indicator follows after the next status report.
  • Converter events — open the downlink converter’s Events tab. In shows the RPC message, Out shows the encoded command, and Metadata shows the message metadata.
  • Integration events — the Downlink event has status SUCCESS. On FAILURE, the event shows “Please contact system administrator” instead of the error; see Troubleshooting to read it.
Symptom Cause Fix
CONNECT event with status FAILURE Wrong Access Id, Access Key, or Region. Copy the credentials from the project Overview page again. Select the Region that matches the project data center.
Integration connects, but no uplinks arrive The messaging rule is off, or enabled in the other environment. Enable the rule with statusReport in the environment that matches Environment. See Configure Messaging Rules.
Same, with the rule enabled The device is not linked to the cloud project. Link the app account. See Link Your Tuya App Account.
Subscription Status is not Good The messaging rule was disabled or changed. Enable the rule for the matching environment and check the subscription again.
Device not created Allow create devices or assets is off, or the decoder skipped the message. Turn the option on. Check Out in the converter events: [] means the message has no status and is not online or offline.
Only switch_1 arrives The plug has no load. Connect a load and wait for the next report.
Downlink event with status FAILURE and “Please contact system administrator” The integration shows this text instead of the error. The causes are in the rows below. On a self-hosted installation, set HTTP_LOG_CONTROLLER_ERROR_STACK_TRACE=true and restart ThingsBoard: the event then shows the full error. A remote integration (Execute remotely) or a separate integration executor always shows the full error. Check the causes below. To see the error returned by Tuya Cloud, send the same command in the Tuya IoT Platform: Cloud ⇾ API Explorer, IoT Core, Device Control(Standard Instruction Set) ⇾ Send commands, with the device ID and the encoder’s data in commands. The response shows the Tuya code and message.
Same, the full error has Tuya code 28841002, “IoT Core service subscription has expired.” The IoT Core subscription has expired. Status reports keep arriving, because the Message Service does not depend on it. Renew IoT Core in Cloud ⇾ Cloud Services.
Same, the full error is “Downlink message format is not correct…” data has neither code, a query method, nor an array of commands. Check Out in the downlink converter events. Make sure the RPC method reaches msg.method.
Same, the full error is “Device identifier not found in metadata” The encoder’s output metadata has neither deviceId nor deviceName. Set deviceId in the encoder’s metadata.
Same, the full error has Illegal character in path The device name is not the raw Tuya devId. Rename the device to its devId. Use Label for a readable name.
Same, the full error is “Tuya integration response error code…” Tuya Cloud rejected the command, for example the code is not writable. Check the writable codes in Device Debugging in the Tuya IoT Platform.
Uplink fails with Tuya message has no devId The message has no devId, for example a query response. Check In in the uplink converter events. Handle this message type in your own decoder.
Downlink converter event with the error Message metadata has no deviceName The RPC message has no deviceName in its metadata. Send the RPC to the device, so the message carries the device name.
Downlink converter event with the error Message is not an RPC request A message that is not an RPC request, for example an attribute update, reached the integration downlink node. Connect the node with the RPC Request to Device relation only.
Downlink converter event with the error RPC request has no method or RPC request has no params The RPC has an empty method, or no value. Set the RPC method (the Tuya command code, for example switch_1) and the value in the widget or the RPC request.
No downlink event The rule chain does not reach the integration downlink node. Connect the node with the RPC Request to Device relation.

To read debug events, open the integration or converter, click Events, and select an event: In is the received data, Out is the converter result, and Error holds the error text.