Tuya binding missing Channels, can I add it manually?

I got a couple of register booster fans not even knowing they were Tuya devices. I thought they were bascailly self contained.

Anyway, since I discovered they are Tuya I figured there are ways I can automate them that the devices themselves do not support (e.g. auto switch between cool and fan mode when the AC shuts off).

Installing and configuring the Tuya binding went without too much of a problem. I had to manually enter the IP address for the devices (weirdly the devices report a 165 IP inside the app) and the API version (3.5 worked). But the one Channel I need isn’t there in the OH add-on, changing the mode. I can only turn it on/off, enable/disable the child lock, set the temp and get the thermometer reading. I cannot set the fan speed either.

It says in the docs that one can add a Channel but it’s kind of vague and does not really provide any information about how I would discover that dp property for the Channel.

So how do I discover this DP property?

And if this is not going to work like I want with the binding, is there any experience with rustuya-bridge? Could I expect that to be more thorough in finding all the control points?

Or maybe this is it and that’s all the API allows even though all the controls I do need are available in the app. It could save me a day’s worth of experimenting if anyone can provide a little guidance.

Thanks!

Edit 1: Immediately upon posting I discovered in the Tuya Developer Platform there is a “Standard Instruction” and a “DP Instruction” option. So I might be closer to an answer than I thought. More to follow…

Edit 2: I can see all the control points but still can’t figure out how to discover what the DP number is for each one short of trial and error. There seems to be no rhyme nor reason to the numbering. Do I really need to wireshark this or capture the network logs from the browser?

The answer is no. In the Tuya Developer Platform hover over “Cloud” and choose “API Explorer”. Make sure IOT Core is selected at the top and go down to Device Control → Query Properties. Paste in the device ID and the resulting JSON will include the DP numbers for each Channel. For example:

{
  "result": {
    "properties": [
      {
        "code": "switch",
        "custom_name": "",
        "dp_id": 1,
        "time": 1785090872807,
        "type": "bool",
        "value": true
      },
      {
        "code": "mode",
        "custom_name": "",
        "dp_id": 2,
        "time": 1785090872807,
        "type": "enum",
        "value": "FAN"
      },
      {
        "code": "temp_indoor",
        "custom_name": "",
        "dp_id": 9,
        "time": 1785098576999,
        "type": "value",
        "value": 66
      },
      {
        "code": "fan_speed_enum",
        "custom_name": "",
        "dp_id": 12,
        "time": 1785090872807,
        "type": "enum",
        "value": "4"
      },
      {
        "code": "child_lock",
        "custom_name": "",
        "dp_id": 14,
        "time": 1785090872807,
        "type": "bool",
        "value": false
      },
      {
        "code": "temp_set",
        "custom_name": "",
        "dp_id": 45,
        "time": 1785090872807,
        "type": "value",
        "value": 65
      },
      {
        "code": "fan_cool_max_enum",
        "custom_name": "",
        "dp_id": 101,
        "time": 1785090872807,
        "type": "enum",
        "value": "10"
      },
      {
        "code": "brightscreen_set",
        "custom_name": "",
        "dp_id": 102,
        "time": 1785090872807,
        "type": "enum",
        "value": "on"
      },
      {
        "code": "fan_cool_min_enum",
        "custom_name": "",
        "dp_id": 103,
        "time": 1785090872807,
        "type": "enum",
        "value": "1"
      },
      {
        "code": "fan_heat_max_enum",
        "custom_name": "",
        "dp_id": 104,
        "time": 1785090872807,
        "type": "enum",
        "value": "10"
      },
      {
        "code": "fan_heat_min_enum",
        "custom_name": "",
        "dp_id": 105,
        "time": 1785090872807,
        "type": "enum",
        "value": "1"
      },
      {
        "code": "temp_set_1",
        "custom_name": "",
        "dp_id": 106,
        "time": 1785090872807,
        "type": "value",
        "value": 82
      }
    ]
  },
  "success": true,
  "t": 1785099656290,
  "tid": "1881507d893511f1925d82fbf7d4d33a"
}

To find the accepted values for the enums and ranges for the numbers navigate to Cloud → open your project → Devices → Debug Device next to the device you want information about → Device Debugging. That will show you all the valid enums and ranges for each DP.

What I don’t know is whether I need to redescover the Things or what.

So far:

  1. make sure the devices are in DPInstruction mode
  2. discover all the DP numbers for each “channel”
  3. discover the enum values and ranges for each channel
  4. create Channels for the missing ones (I’ve not done this yet, to be continued)

Edit 3: Rediscovering the Thing still only listed the four Channels. But adding the missing Channel I need worked. Woohoo!

@rlkoshak

Just fyi in the Tuya developer Cloud when you search around you will find an option to make the device controlable or writeable my suggestion is do NOT it breaks the devices and you have to remove the device completely (factory reset) and re-add.

I will try to have a look tomorrow at the exact option.

EDIT: its the option to change a device from Device Permission which by default is Read.

The binding does a general query when it connects to a device so if you turn logging up (debug might do, otherwise trace) the pause and resume the Thing you should a DP_QUERY response logged that list all the DPs the device is willing to admit to along with their current values.

Manually adding channels is a bit of a historical oddity but it should still work (i.e. I don’t see any reason it would have broken but I don’t use it myself).

It may be the missing Channels are because the binding is favouring the compiled-in ioBroker schemas rather than what it gets from the cloud. However some DPs also seem to be missing in the Tuya Cloud Project schemas (*_coeff for power switches for example) although they are present when the schema is fetched via the Smart Life API (see addons PR#21041). And I have some contact switches that seem to have no schemas in the Tuya Cloud at all but are in the ioBroker schemas - and somehow work through the Smart Life app too. (Gotta love Tuya… right? … Right…?)

Anyway, I’ve never found a way to query a schema for a product you don’t own so please open an issue with as much information as possible - product ID, jsondb/org.openhab.binding.tuya.Schema.json, a DP_QUERY response, a list of passwords, bank details etc.

I saw that option but since I could control the device while it said “Read”. So I didn’t touch it even though it seemed weird. Glad I didn’t. It’s there in the table under the Devices tab.

I didn’t think to look at the logs for this. I assumed if it didn’t create the channels it’s because it didn’t know about them. I should have looked there first. But at least now I know another way to find that info also that doesn’t require sniffing the network, browser tools, or installing some other tool to extract it.

I don’t expect to ever get another Tuya device so this will suffice for now. I’ve not heard a lot of good things about them in general and I’m a little annoyed by the way it self reports a bogus IP address. Definitely do not have warm fuzzies.

But I am still intrigued by the rustuya-bridge. If I read it correctly, it doesn’t require the developer account at all. :man_shrugging: Maybe not? Don’t know. So long as I can control the fan and the mode on these register boosters I can do everything I need to with them and that seems to be working with the OH add-on, once I’ve added those Channels manually.

This would be of great interest to me. I have a coupe of Tuya devices, but I use them as “manual dumb devices” because I refuse to hand over data by creating an account for “developer access”. If access is possible without this, I could perhaps actually use these devices from OH.

Smoke and mirrors…

rustuya-bridge just uses rustuya to pull data over the local API and push it to MQTT. rustuya requires that you know the device ID and local key. Device ID can come from the device’s broadcast announcements on the local network, the local key HAS to come from the Tuya Cloud. (Incidentally, the Tuya Cloud only sees the final NATted IP. The local IP has to come from broadcast announcements, DHCP logs, etc.)

rustuya and rustuya-bridge are configured using rustuya-manager - which requires you to login to the Tuya Cloud using the scan-a-QR-code-with-the-app method (same as addons PR#21041) so it can discover devices…

Once you have the local keys you can just deny outbound Internet connectivity to your devices. Everything that use the local API, openHAB, rustuya, Smart Life, [*], still works. I think the only thing that doesn’t is firmware updates - Smart Life will tell you there is an update but the device needs to fetch it from the Tuya Cloud itself.

[*] Maybe not home-assistant. There is/was local API support but I seem to remember that the official QR-scanning tuya module only supports the Tuya Cloud MQTT feed. Not that anyone here cares!

Yes, I also found that it wasn’t the case. But, to my surprise, I also found that since the last time I checked, the WBR3 chip that is in the Tuya device I’ve most wanted to get access to, now is supported by ESPHome. Sometimes procrastination pays off! My plan was to replace it with a ESP8266MOD (that I have already flashed), but since the soldering operation using hot air, “flowing” the whole chip at once, is a bit scary to me, I’ve procrastinated. And now I don’t have to, I can just connect the programmer to the WBR3 chip and flash that!

So, I’ll probably be Tuya-free in the near future, running ESPHome instead. That’s much more to my taste :wink:

Just to circle around, here’s the Thing for this specific device:

version: 1
things:
  tuya:tuyaDevice:roRegBooster:
    label: Rich's Office Register Booster Fan
    config:
      deviceId: eb2d93db4b7380b5bdzytg
      localKey: j.H6Fv4X~=pNk8zk
      productId: pjabraecffsfrmxz
      ip: 10.10.1.13
      port: 6668
      protocol: "3.5"
      pollingInterval: 10
    channels:
      switch:
        type: pjabraecffsfrmxz_switch
        config:
          dp: 1
      temp_indoor:
        type: pjabraecffsfrmxz_temp_indoor
        config:
          dp: 9
          min: 32
          max: 199
      child_lock:
        type: pjabraecffsfrmxz_child_lock
        config:
          dp: 14
      temp_set:
        type: pjabraecffsfrmxz_temp_set
        config:
          dp: 45
          min: 32
          max: 122
      mode:
        type: string
        label: Mode
        config:
          dp: 2
          range: "FAN,COOL,HEAT,SLEEP"
      fanSpeec:
        type: string
        label: Fan Speed
        description: Fan Speed 1-10 levels
        config:
          dp: 12
          range: "1,2,3,4,5,6,7,8,9,10"
      fanCoolMax:
        type: string
        label: Fan Cool Max Speed
        description: Maximum speed when in cool mode
        config:
          dp: 101
          range: "1,2,3,4,5,6,7,8,9,10"
      screen:
        type: string
        label: Screen
        description: Control the LED Screen
        config:
          dp: 102
          range: "on,off"
      fanCoolMin:
        type: string
        label: Fan Cool Min Speed
        description: Minimum fan speed when in cool mode
        config:
          dp: 103
          range: "1,2,3,4,5,6,7,8,9,10"
      fanHeatMax:
        type: string
        label: Fan Heat Max Speed
        description: Maximum speed when in heat mode
        config:
          dp: 104
          range: "1,2,3,4,5,6,7,8,9,10"
      fanHeatMin:
        type: string
        label: Fan Heat Min Speed
        description: Minimum fan speed when in heat mode
        config:
          dp: 105
          range: "1,2,3,4,5,6,7,8,9,10"
      temp_set1:
        type: number
        label: Temp Set 2
        description: "Unknown, heat mode temp set?"
        config:
          dp: 106
          min: 32
          max: 122

Unofruntately all the extra Channels are enums so they require some transformations to convert them to proper Items. Here are the Items:

version: 1
items:
  Richs_Office_Register_Booster_Fan_Child_Lock:
    type: Switch
    label: Rich's Office Register Booster Child Lock
    icon: material:toggle_on
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Enabled
      - Switch
    channels:
      tuya:tuyaDevice:roRegBooster:child_lock:
        profile: transform:MAP
        function: '|on=ON;off=OFF'
  Richs_Office_Register_Booster_Fan:
    type: Group
    label: Rich's Office Register Booster Fan
    icon: f7:thermometer
    groups:
      - Rich_Office
    tags:
      - Equipment
  Richs_Office_Register_Booster_Fan_Fan_Cool_Max_Speed:
    type: Number
    label: Rich's Office Register Booster Fan Cool Max Speed
    icon: iconify:mdi:fan
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Airflow
      - Control
    channel: tuya:tuyaDevice:roRegBooster:fanCoolMax
    metadata:
      stateDescription:
        value: ""
        config:
          min: "1"
          max: "10"
          step: "1"
  Richs_Office_Register_Booster_Fan_Fan_Cool_Min_Speed:
    type: Number
    label: Rich's Office Register Booster Fan Cool Min Speed
    icon: iconify:mdi:fan
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Airflow
      - Control
    channel: tuya:tuyaDevice:roRegBooster:fanCoolMin
    metadata:
      stateDescription:
        value: ""
        config:
          min: "1"
          max: "10"
          step: "1"
  Richs_Office_Register_Booster_Fan_Fan_Heat_Max_Speed:
    type: Number
    label: Rich's Office Register Booster Fan Heat Max Speed
    icon: iconify:mdi:fan
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Airflow
      - Control
    channel: tuya:tuyaDevice:roRegBooster:fanHeatMax
    metadata:
      stateDescription:
        value: ""
        config:
          min: "1"
          max: "10"
          step: "1"
  Richs_Office_Register_Booster_Fan_Fan_Heat_Min_Speed:
    type: Number
    label: Rich's Office Register Booster Fan Heat Min Speed
    icon: iconify:mdi:fan
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Airflow
      - Control
    channel: tuya:tuyaDevice:roRegBooster:fanHeatMin
    metadata:
      stateDescription:
        value: ""
        config:
          min: "1"
          max: "10"
          step: "1"
  Richs_Office_Register_Booster_Fan_Fan_Speed:
    type: Number
    label: Rich's Office Register Booster Fan Speed
    icon: iconify:mdi:fan
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Airflow
      - Control
    channel: tuya:tuyaDevice:roRegBooster:fanSpeec
    metadata:
      stateDescription:
        value: ""
        config:
          min: "1"
          max: "10"
          step: "1"
  Richs_Office_Register_Booster_Fan_Mode:
    type: String
    label: Rich's Office Register Booster Mode
    icon: f7:thermometer
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Control
      - Mode
    channel: tuya:tuyaDevice:roRegBooster:mode
  Richs_Office_Register_Booster_Fan_Screen:
    type: Switch
    label: Rich's Office Register Booster Screen
    icon: material:toggle_on
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Control
      - Enabled
    channel: tuya:tuyaDevice:roRegBooster:screen
  Richs_Office_Register_Booster_Fan_Switch:
    type: Switch
    label: Rich's Office Register Booster Switch
    icon: material:toggle_on
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Switch
    channel: tuya:tuyaDevice:roRegBooster:switch
  Richs_Office_Register_Booster_Fan_Number:
    type: Number
    dimension: Temperature
    label: Rich's Office Register Booster Temp Set 2
    icon: f7:thermometer
    unit: °F
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Setpoint
      - Temperature
    channel: tuya:tuyaDevice:roRegBooster:temp_set1
  Richs_Office_Register_Booster_Fan_Temperature_Indoor:
    type: Number
    dimension: Temperature
    label: Rich's Office Register Booster Temperature
    icon: f7:thermometer
    unit: °F
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Measurement
      - Temperature
    channel: tuya:tuyaDevice:roRegBooster:temp_indoor
  Richs_Office_Register_Booster_Fan_Temperature_Set:
    type: Number
    dimension: Temperature
    label: Rich's Office Register Booster Temperature Set
    icon: f7:thermometer
    unit: °F
    groups:
      - Richs_Office_Register_Booster_Fan
    tags:
      - Setpoint
      - Temperature
    channel: tuya:tuyaDevice:roRegBooster:temp_set

I linked all the Channels just for testing purposes but will probably just end up linking the fan speed, mode, and temp setpoints. I’m still not positive what the second temp setpoint is for. The state descriptions will make the slider which is the default widget for a Number tagged with “Setpoint” work correctly out-of-the-box.