How I got Pioneer Diamante WYS Heat Pump / Split AC HVAC working with LocalTuya

It took me an hour to get working due to Tuya making it unnecessarily hard and confusing, but with these notes it would have been much faster. I wrote this in the hope it’ll help others. Three general things to know before starting:

  1. Things are always changing due to different components changing (HA itself, HA integrations and vendor software/firmware). So, what worked for me in Sept 24 may not work for you a year from now. When searching for solutions online it helps to restrict search results in time to the last year (or whatever is relevant).

  2. Everyone’s configuration is different (network, routers, etc). So, what worked in one user’s configuration then may not work the same way in yours now.

  3. The default app that Pioneer uses is Tuya Smart (Tuya and their various partners have similar apps under different names (like Smart Life)). Most of them talk to the Tuya Cloud Platform, so they use the same account info.

Note: This post is for differences specific to setting up the Pioneer Split AC (or similar), you should use it alongside one of the general guides for overall Tuya setup.

For reliability and security, our goal is to control our devices locally without any vendor’s app or connection to their cloud platform. With Tuya Platform based systems this is currently possible (because I just did it (however, it may not always be if Tuya changes it).

Which Wifi Adapter Does Your Pioneer Have?
There are two different types of Wifi modules that can plug into the USB port inside Pioneer Diamante units, the older WYT and the newer WYS. The firmware in both defaults to using the Tuya Cloud Platform but it’s possible to use them locally with Home Assistant. If you’re just starting out you may want to consider avoiding this entire Tuya mess by buying a non-Tuya-based USB Wifi module (they are ~$15). A guide for that is here: Pioneer Mini-split ESPHome - XtremeOwnage.com. Since that module uses the open source ESPHome firmware, it’ll always be local and fully in your control. I may eventually change over to that module because as long as there’s Tuya firmware in the wifi module, it’s possible it could update itself and stop working locally. After getting a Tuya-based device working locally, some people block the Wifi module’s direct access to the internet and report it continues to work fine. However, some other people report some Tuya devices might develop problems if prevented from phoning home.

This guide covers the WYS Tuya-based wifi module supplied by Pioneer because it already came included with my unit. The central info needed to control your Tuya device locally is the “Local Key”. This is a secret password the device firmware requires to be controlled over wifi. Tuya should just show users their devices’ Local Key in an About screen in the app. Tuya doesn’t make it easy for users to get the Local Key because it keeps us reliant on their app and cloud. But there are two ways to get the Local Key:

  1. Detect when the Tuya app sends the Local Key to your device over your network by “sniffing” the network packets and decrypting the Local Key. There are various tools for doing this and they change often because when Tuya changes things, the needed technique can change. An example tool is explained here: https://www.reddit.com/r/homeassistant/comments/oglpgc/absolute_beginners_guide_to_setting_up_local_tuya/. There are others you can find.

  2. Get your device’s Local Key from the Tuya Platform yourself. This involves setting up a special developer account with Tuya, which is separate from the Tuya user account in the Tuya app. Creating a developer accounts is currently free but they expire after six months of non-use (some users report this six months can be extended by emailing Tuya developer support and asking for a dormant account to be reactivated.) Ideally you only need to get the Local Key once so your developer account shouldn’t matter after that, however some users have reported if the device somehow loses it’s stored settings and you have to reinitialize it, that process can create a new key you’ll need to get. Also, if you don’t block the device from the internet after configuring it, then Tuya could cause the Local Key to reset if they decide to. If you continue to use a Tuya Platform-based app to also control your device from outside your home and ever need to reset the Tuya user account, that could also cause the Local Key to reset (or not, it depends on what the Tuya app does at that time).

I went with Option #2. Unfortunately, Tuya is always changing their Developer site (iot.tuya.com) which moves all the various secret “strings of digits” you need to get around. I did this process with a different device a couple years ago and it was all completely different now. This is why the various Home Assistant integrations supporting local Tuya use can’t tell you where to find each piece of info on Tuya’s site. Also, the HA integrations can occasionally use a slightly different name for a piece of required info. As an example:

  • There are two different things which can arguably be called “User ID” you’ll need at different times to complete this process and they are, of course, found in different places on the Tuya site. Trying to put the “wrong one” of the two User IDs into the integration config screen cost me a good half-hour of checking and rechecking each item was correct.

Keep all IDs organized in a text file. When you’re done, label it clearly and back it up several places. Here’s mine (with some unique digits obfuscated):

User ID: 45D###### (for Developer Account)
(found here: Tuya Smart Developer Center (once logged in). Use this to set up the account in the HA integration.)

Access ID / Client ID: g9we###############
Access Secret/Client Secret: fcbbf5#####################
(found from Tuya Smart Developer Center click Overview tab)

Device Name: gg-11102#################
Device ID: eb2########################
(found from Tuya Smart Developer Center click “All Devices” tab)

User ID: az1################# (Device UID)
(found from Tuya Smart Developer Center click “Link App Account” tab. Use this to set up the Device in the HA integration.)

Local Key: h@######
((found from Tuya Smart Developer Center expand Device Management side-list, click “Query Device Details in Bulk”, enter your Device Id and press Enter)

This wiki software makes all those links look the same but some of them are different. Those links should work until Tuya changes their site again. Otherwise, you’ll have to hunt around to find them, but at least now you have a list of the info you need to find from Tuya site.

Choose an Integration for Home Assistant
There are several different open source Home Assistant integrations for using Tuya devices locally created by volunteer developers. Two popular ones are the similarly named “Tuya Local” and “Local Tuya”. They are both very similar because they are both based on the same original code. Each of these integrations adds direct support for different devices at different times and they can do so in slightly different ways. You’ll find different opinions online about which is “better” but I think it’s down to how each integration supported that user’s particular device at the time that user tried it.

I’m pretty sure either one can work with the Pioneer Diamante, however, I started with Tuya Local first and, although I got the Pioneer doing power on/off and reporting temp pretty easily, but I found configuring the other Entities like Fan Mode challenging. But I’d never assigned an HA entity to each feature of a device before. After spending some time struggling to figure it out, I switched to the LocalTuya integration and it all came together pretty quickly. So, I currently recommend LocalTuya for Pioneer Diamante integration with Home Assistant.

What are DPs (DPids)
Each supported device feature (like Fan Mode) is identified by a number called a DP or DPid. For example, on the Pioneer, power on/off is #1, desired temp is #2, etc. I’ve put the list of DPs I managed to query from the Tuya developer site down below in case it’s helpful.

What’s the difference between “Tuya Local” and “Local Tuya”?
I’m no expert but I think, for this device - at this time, TuyaLocal is more open-ended - relying on the user to assign the correct entity to the correct DP. This is probably more flexible but since I’ve never done it, I had more trouble configuring it all correctly. Whereas, LocalTuya happened to assign the DPs for me. A key thing to know is that right now LocalTuya doesn’t have the Pioneer listed as a device, so you should select “Daizuki” as the device during setup, (if you use Fahrenheit) or “Starlight” (if you use Celsius), as described here: Request support for Pioneer WYT Diamante Mini-Split AC/Heat Pump · Issue #820 · make-all/tuya-local · GitHub. Both are very similar to the Pioneer AC and seem to use the same codes (they may all come from the same factory).

So, for this device on this day, my keys to success were to:

  • Know where to find the info on Tuya’s developer site.
  • Understand that your device’s “User ID” (also called “UID”) and your developer account “User ID” are different things in different places on the Tuya site.
  • Use LocalTuya instead of TuyaLocal
  • Select Daizuki as the device in LocalTuya (or Starlight if you use temps in Celsius).

Here’s the list of DPs I managed to query from the Tuya developer site. Note: I think “Wind” means “Fan speed”. “Energy” or “Money” may refer to the Eco mode but I’m not sure. (please add to this post if you find out):

{
  "result": {
    "properties": [
      {
        "code": "Power",
        "custom_name": "",
        "dp_id": 1,
        "time": 1725735959573,
        "type": "bool",
        "value": true
      },
      {
        "code": "temp_set",
        "custom_name": "",
        "dp_id": 2,
        "time": 1725743816033,
        "type": "value",
        "value": 820
      },
      {
        "code": "temp_current",
        "custom_name": "",
        "dp_id": 3,
        "time": 1725750440828,
        "type": "value",
        "value": 28
      },
      {
        "code": "mode",
        "custom_name": "",
        "dp_id": 4,
        "time": 1725735959573,
        "type": "enum",
        "value": "cold"
      },
      {
        "code": "windspeed",
        "custom_name": "",
        "dp_id": 5,
        "time": 1725735959573,
        "type": "enum",
        "value": "low"
      },
      {
        "code": "humidity_current",
        "custom_name": "",
        "dp_id": 18,
        "time": 1725735959573,
        "type": "value",
        "value": 0
      },
      {
        "code": "Fault",
        "custom_name": "",
        "dp_id": 20,
        "time": 1725735959573,
        "type": "bitmap",
        "value": 0
      },
      {
        "code": "pm25",
        "custom_name": "",
        "dp_id": 101,
        "time": 1725734512360,
        "type": "value",
        "value": 0
      },
      {
        "code": "sleep",
        "custom_name": "",
        "dp_id": 105,
        "time": 1725735959573,
        "type": "enum",
        "value": "off"
      },
      {
        "code": "markbit",
        "custom_name": "",
        "dp_id": 110,
        "time": 1725735959573,
        "type": "bitmap",
        "value": 2241084
      },
      {
        "code": "up_down_sweep",
        "custom_name": "",
        "dp_id": 113,
        "time": 1725735959573,
        "type": "enum",
        "value": "0"
      },
      {
        "code": "left_right_sweep",
        "custom_name": "",
        "dp_id": 114,
        "time": 1725735959573,
        "type": "enum",
        "value": "0"
      },
      {
        "code": "totalN",
        "custom_name": "",
        "dp_id": 115,
        "time": 1725734514883,
        "type": "value",
        "value": 30
      },
      {
        "code": "totalP",
        "custom_name": "",
        "dp_id": 116,
        "time": 1725750219175,
        "type": "value",
        "value": 13090
      },
      {
        "code": "money",
        "custom_name": "",
        "dp_id": 119,
        "time": 1725735959573,
        "type": "enum",
        "value": "0"
      },
      {
        "code": "energy",
        "custom_name": "",
        "dp_id": 120,
        "time": 1725735959573,
        "type": "enum",
        "value": "off"
      },
      {
        "code": "fault2",
        "custom_name": "",
        "dp_id": 122,
        "time": 1725734508825,
        "type": "bitmap",
        "value": 0
      },
      {
        "code": "boolCode",
        "custom_name": "",
        "dp_id": 123,
        "time": 1725735959573,
        "type": "string",
        "value": "0019"
      },
      {
        "code": "airquality",
        "custom_name": "",
        "dp_id": 125,
        "time": 1725734512360,
        "type": "enum",
        "value": "great"
      },
      {
        "code": "up_down_freeze",
        "custom_name": "",
        "dp_id": 126,
        "time": 1725735959573,
        "type": "enum",
        "value": "0"
      },
      {
        "code": "left_right_freeze",
        "custom_name": "",
        "dp_id": 127,
        "time": 1725735959573,
        "type": "enum",
        "value": "0"
      },
      {
        "code": "style",
        "custom_name": "",
        "dp_id": 128,
        "time": 1725735959573,
        "type": "enum",
        "value": "0"
      },
      {
        "code": "kwh",
        "custom_name": "",
        "dp_id": 129,
        "time": 1725735959573,
        "type": "enum",
        "value": "1"
      },
      {
        "code": "savemoney_temp",
        "custom_name": "",
        "dp_id": 130,
        "time": 1725735959573,
        "type": "value",
        "value": 26
      },
      {
        "code": "dirty_filter",
        "custom_name": "",
        "dp_id": 131,
        "time": 1725735959573,
        "type": "bool",
        "value": false
      },
      {
        "code": "hot_cold_wind",
        "custom_name": "",
        "dp_id": 132,
        "time": 1725735959573,
        "type": "bool",
        "value": false
      },
      {
        "code": "wind",
        "custom_name": "",
        "dp_id": 133,
        "time": 1725735959573,
        "type": "enum",
        "value": "0"
      },
      {
        "code": "work_time",
        "custom_name": "",
        "dp_id": 134,
        "time": 1725735959573,
        "type": "string",
        "value": "{\"t\":1725735958,\"s\":false,\"clr\":true}"
      },
      {
        "code": "run_time",
        "custom_name": "",
        "dp_id": 135,
        "time": 1725750579464,
        "type": "value",
        "value": 1
      },
      {
        "code": "temp_set_f",
        "custom_name": "",
        "dp_id": 136,
        "time": 1725734508825,
        "type": "value",
        "value": 61
      }
}