# Tuya Binding
This add-on connects Tuya Wi-Fi devices with openHAB or compatible systems. The control and status reporting is done on the local network. Cloud access is only needed for discovery and initial connection.
Devices need to be connected to a Tuya account (Tuya Smart app or Smart Life app). Each device has a unique "local key" (password/secret) which needs to be added during Thing creation. It is highly recommended to use the discovery feature for that, but you can also sniff the local key with a MITM proxy during pairing.
Please note that only one local connection is allowed per device. Using the app (or other tools like tuya-mqtt) and the binding in parallel is not supported by Tuya devices and will cause problems such as inability to discover the IP address and/or inability to control the devices. The other app (and/or tuya-mqtt) must be closed in order for this binding to operate properly.
# Supported Things
There are four things: project, tuyaDevice, tuyaGateway and tuyaSubDevice.
The project Thing represents a Tuya developer portal cloud project (see below).
project things must be configured manually and are needed for discovery only.
tuyaDevice things represent a single device.
They can be configured manually or by discovery.
tuyaGateway things represent a device that relays for other devices, e.g. a Bluetooth or ZigBee gateway.
Apart from being a bridge for its sub-devices, a tuyaGateway behaves exactly like a tuyaDevice and has its own channels.
tuyaSubDevice things represent a device that is reached through a gateway.
A tuyaSubDevice has no connection of its own: all its traffic is relayed by the tuyaGateway it is a child of.
Note that project is a regular Thing and not a bridge.
tuyaDevice things communicate with the device directly over the local network and do not need a bridge at runtime.
Only tuyaSubDevice things need a bridge, namely the tuyaGateway they are connected to.
# Discovery
Discovery is supported for tuyaDevice, tuyaGateway and tuyaSubDevice things.
By using discovery all necessary settings of the device are retrieved from your cloud account.
Devices that turn out to have sub-devices in the cloud account are discovered as tuyaGateway instead of tuyaDevice, and their sub-devices are discovered underneath them.
A tuyaSubDevice cannot exist without its bridge, so sub-devices are only reported once their gateway has been added as a Thing.
Add the gateway first, then run discovery again to get its sub-devices (background discovery picks them up within a few minutes).
If you already added a gateway as a tuyaDevice, you have to delete it and add it again as tuyaGateway before its sub-devices can be used.
# Thing Configuration
# project
First create and link a Tuya Developer Account:
- Go to
iot.tuya.com(the Tuya developer portal) and create an account. You can choose any credentials (email/password) you like (it is not necessary that they are the same as in the app). After confirming your account, log in to your new account. - On the left navigation bar, select "Cloud", then "Create new Cloud project" (upper right corner). Enter a name (e.g. "My Smarthome"), select "Smart Home" for "Industry" and "Development Method". For security reasons, select only the "Data Center" that your app is connected to (you can change that later if you select the wrong one). Select "IoT Core", "Authorization" and "Device Status Notification" as APIs.
- You should be redirected to the "Overview" tab of your project. Write down (or copy) "Access ID/Client ID" and "Access Secret/Client Secret" (you can always look it up in your account).
- In the upper menu bar, select the "Devices" tab, then go to "Link Tuya App Account" and link your app account.
The next steps are performed in openHAB's Main UI:
Add a project and enter your credentials (username/password, from the app — not your cloud account!) and the cloud project credentials (accessId/accessSecret).
The countryCode is the international dial prefix of the country you registered your app in (e.g. 49 for Germany or 43 for Austria).
Depending on the app you use, set schema to tuyaSmart (for the Tuya Smart app) or smartLife (for the Smart Life app).
The dataCenter needs to be set to the same value as in your IoT project.
The Thing should come online immediately.
If the Thing does not come online, check
- if you really used the app and not the developer portal credentials
- if you entered the correct country code (check in the app if you accidentally chose a wrong country)
- check if you selected the correct "Data Center" in your cloud project (you can select more than one for testing).
# tuyaDevice
The best way to configure a tuyaDevice is using the discovery service.
The mandatory parameters are deviceId, productId and localKey.
The deviceId is used to identify the device, the productId identifies the type of the device and the localKey is a kind of password for access control.
These parameters are set during discovery.
If you want to manually configure the device, you can also read those values from the cloud project above.
For line-powered devices on the same subnet, the ip address and protocol version are automatically detected.
Tuya devices announce their presence via UDP broadcast packets, which is usually not available in other subnets.
Battery-powered devices do not announce their presence at all.
If automatic protocol version detection does not work there is no clear rule how to determine if a device has protocol 3.3 or 3.1.
In this case it is recommended to start with 3.3 and watch the log file. If 3.3 does not work, try using 3.1.
The port defaults to 6668, which is the TCP port used by Tuya devices.
Change this only if the device is reached through a NAT/port mapping, e.g. when Tuya/IoT devices are isolated in a separate network and exposed through port forwarding.
Some devices do not automatically refresh channels or only refresh at fairly long intervals even though the data is sampled at a much higher rate (e.g., some power meters only send updates every 10 minutes but sample continuously).
The pollingInterval can be used to adjust how often channels are updated and can be set to 0 (off) or to any integer value of 10 seconds or higher. The default is 10 seconds.
Note that this has no practical effect on battery powered devices. These only wake up when they have something to say and then go straight back to sleep.
The advanced option reloadSchema acts as a trigger: enable it and save the Thing to retrieve the schema of the device from the cloud again.
The stored schema of the product is replaced, all things of this product are re-initialized with the channels of the new schema and the option resets itself.
Channels generated from the previous schema whose data point no longer exists are removed, manually added channels are kept.
This requires a project Thing that is ONLINE; if several projects are ONLINE, each is tried until one knows the device.
In textual configuration the option triggers the reload whenever the Thing is loaded from the file, so remove it after use.
The option is available for tuyaGateway and tuyaSubDevice things as well.
In case something is not working, please open an issue on GitHub (opens new window) and add TRACE level logs.
# tuyaGateway
A tuyaGateway takes exactly the same parameters as a tuyaDevice, and they have the same meaning.
Use this Thing type instead of tuyaDevice for devices that other devices are paired to, such as Bluetooth or ZigBee gateways.
# tuyaSubDevice
The mandatory parameters are deviceId, productId and subDeviceId, and the Thing must be a child of the tuyaGateway the device is paired to.
All of these are set during discovery.
The deviceId and productId have the same meaning as for a tuyaDevice.
The subDeviceId is the node ID that identifies the device towards its gateway (node_id in the cloud account).
A sub-device has no ip, port, protocol or localKey: it is reached through the gateway, which supplies all of these.
The pollingInterval works as for a tuyaDevice, except that the gateway is asked for the full state of the sub-device on every poll, as sub-devices do not support partial refreshes.
# Channels
Channels are added automatically based on device schemas on first startup. The binding first tries to get it from a database of known device schemas. If no schema is found a schema retrieved from the cloud during discovery is used (if applicable).
The device will change to OFFLINE status if no device schema could be determined.
Channels can also be added manually.
The available channel-types are color, dimmer, number, string and switch.
Depending on the channel one or more parameters are available.
If a schema is available (which should be the case in most setups), these parameters are auto-configured.
All channels have at least the dp parameter which is used to identify the channel when communicating with the device.
# Type color
The color channel has a second optional parameter dp2.
This parameter identifies the ON/OFF switch that is usually available on color lights.
# Type dimmer
The dimmer channel has two additional mandatory parameters min and max, one optional parameter dp2 and one advanced parameter reversed.
The min and max parameters define the range allowed for controlling the brightness (most common are 0-255 or 10-1000).
The dp2 parameter identifies the ON/OFF switch that is usually available on dimmable lights.
The reversed parameter changes the direction of the scale (e.g. 0 becomes 100, 100 becomes 0).
It defaults to false.
# Type number/quantity
The number and quantity channels have two additional mandatory parameters min and max.
The min and max parameters define the range allowed (e.g. 0-86400 for turn-off "countdown").
# Type string
The string channel has one additional optional parameter range.
It contains a comma-separated list of command options for this channel (e.g. white,colour,scene,music for the "workMode" channel).
# Type ir-code
IR code types:
Tuya DIY-mode- use learned codes from real remotes.Make a virtual remote control in DIY, learn virtual buttons.
Tuya Codes Library (check Advanced options)- use codes from the template library.Make a virtual remote control from pre-defined type of devices.
Select the Advanced checkbox to configure other parameters:
irCode- decoding parameterirSendDelay- send delay parameterirCodeType- code library type parameter
NEC- IR Code in NEC formatSamsung- IR Code in Samsung format.
Additional options:
Active Listening- Device will always be in learning mode. After sending a command with a key code, the device stays in learning modeDP Study Key- Advanced. DP number for study key. Used to receive key codes in learning mode. Change at your own risk.
If the linked Item receives a command with a Key Code (code library parameter), the device sends the appropriate key code.
# How to use an IR code in NEC format
Example, from Tasmota you need to use Data parameter, it can be with or without 0x
{"Time": "2023-07-05T18:17:42", "IrReceived": {"Protocol": "NEC", "Bits": 32, "Data": "0x10EFD02F"}}
Another example: use the hex parameter
{ "type": "nec", "uint32": 284151855, "address": 8, "data": 11, "hex": "10EFD02F" }
# How to get key codes without Tasmota or others
The channel can receive a learned key (auto-detects the format and puts the auto-detected code in the channel).
To start learning codes, add a new channel with type String, set DP = 1, and set Range to send_ir,study,study_exit,study_key.
Link an Item to this channel and send the command study.
The device will enter learning mode and will be able to receive codes from the remote control.
Press a button on the remote control and you will see the key code in the ir-code channel.
If the type of the ir-code channel is NEC or Samsung, you will see just a hex code.
If the type of the ir-code channel is Tuya DIY-mode, you will see the code format type and a hex code.
After pressing buttons and copying codes, assign the codes to the Item which controls the device (adjust State Description and Command Options as desired).
After receiving the key code, learning mode automatically continues until you send the study_exit command or send a key code via the Item containing a code.
# Console Commands
The binding registers the console command openhab:tuya for inspecting and refreshing device schemas.
| Command | Description |
|---|---|
openhab:tuya schema <productId> | Shows the stored schema of a product: data point IDs, codes, types, access, units and ranges. |
openhab:tuya reload <thingUID> | Retrieves the schema of a device Thing from the cloud again, replaces the stored schema of its product, discards the generated channel types and re-initializes all things that use this product. |
reload requires a project Thing that is ONLINE.
Schemas that are built into the binding cannot be reloaded.
Use reload when the channels of a device do not match the data points reported by the cloud, for example after updating to a binding version that supports additional data point types.
The same can be done in the UI with the advanced option reloadSchema of a tuyaDevice, tuyaGateway or tuyaSubDevice Thing.
# Full Example
tuya.things:
// Only needed for discovery and for looking up device credentials.
// This is a regular Thing, not a bridge.
Thing tuya:project:cloud "Tuya Cloud Project" [
username="me@example.com",
password="app-password",
accessId="ACCESS_ID",
accessSecret="ACCESS_SECRET",
countryCode="49",
schema="smartLife",
dataCenter="https://openapi.tuyaeu.com"
]
// Devices are standalone: no bridge reference, not nested in a Bridge block.
Thing tuya:tuyaDevice:plug "Smart Plug" [
deviceId="DEVICE_ID",
productId="PRODUCT_ID",
localKey="LOCAL_KEY",
ip="192.168.1.100",
protocol="3.3",
pollingInterval=10
] {
Channels:
Type switch : power [ dp=1 ]
Type string : work_mode [ dp=4, range="white,colour,scene,music" ]
Type number : countdown "Countdown" [ dp=9, min=0, max=86400 ]
}
A gateway and its sub-devices:
Bridge tuya:tuyaGateway:gateway "ZigBee Gateway" [
deviceId="GATEWAY_DEVICE_ID",
productId="GATEWAY_PRODUCT_ID",
localKey="GATEWAY_LOCAL_KEY",
ip="192.168.1.101",
protocol="3.3"
] {
Thing tuyaSubDevice sensor "Door Sensor" [
deviceId="SUB_DEVICE_ID",
productId="SUB_DEVICE_PRODUCT_ID",
subDeviceId="NODE_ID"
] {
Channels:
Type switch : doorcontact_state [ dp=1 ]
}
}
tuya.items:
Switch Plug_Power "Power" { channel="tuya:tuyaDevice:plug:power" }
String Plug_WorkMode "Work mode" { channel="tuya:tuyaDevice:plug:work_mode" }
Number Plug_Countdown "Countdown [%d s]" { channel="tuya:tuyaDevice:plug:countdown" }
Switch Door_Contact "Door" { channel="tuya:tuyaSubDevice:gateway:sensor:doorcontact_state" }
# Troubleshooting
- If a
tuyaDevicestays in stateUNINITIALIZED (BRIDGE_UNINITIALIZED), it is configured with a bridge. Remove the bridge reference (and any surroundingBridge { ... }block) from the Thing definition, as described in Supported Things. - If the
projectThing is not comingONLINE, check if you see your devices in the cloud account oniot.tuya.com. If the list is empty, most likely you selected the wrong data center. - If channels are missing or have an unexpected type (e.g. a
Stringchannel for a numeric fault data point), the stored schema may be outdated. Reload it from the cloud by enabling the advanced optionreloadSchemaof the Thing and saving (seetuyaDevice), or check it withopenhab:tuya schema <productId>and refresh it withopenhab:tuya reload <thingUID>(see Console Commands). - Check if there are errors in the log and if you see messages like
Configuring IP address '192.168.1.100' for Thing 'tuya:tuya:tuyaDevice:bf3122fba012345fc9pqa'. If this is missing, try configuring the IP manually. The MAC of your device can be found in the auto-discovered Thing properties (this helps to identify the device in your router). - Provide TRACE level logs.
Type
log:set TRACE org.openhab.binding.tuyaon the Karaf console to enable TRACE logging. Uselog:tailto display the log. You can revert to normal logging withlog:set DEFAULT org.openhab.binding.tuya - At least disable/enable the Thing when providing logs. For most details better remove the device, use discovery and re-add the device. Please use PasteBin or a similar service, do not use JPG or other images, they can't be analyzed properly. Check that the log doesn't contain any credentials.
- Add the Thing configuration to your report (in the UI use the "Code" view).