My Proprietary Dishwasher Was Actually Tuya, How I Integrated It Locally with Home Assistant

Intro

A while ago I moved into my new house, while selecting kitchen appliances I got the offering for an upgrade to make my dishwasher “smart”, I put down a bit of extra money without actually researching the Home Assistant integration possibilities. I got the dishwasher delivered and followed the basic instructions, which resulted in an “Etna Connect” app on my phone which I could use to turn on the dishwasher, set the timer and start it. (I still need to manually put in detergent and close the thing, the actual quality of life improvement for smart dishwashers are highly debatable, but yet here we are).

Using the amazing jinja template: cheapest energy hours by TheFes, and by analyzing the energy usage pattern for a normal cycle, I know when it’s the best time to start the dishwasher:

:HA dishwasher time

Unfortunately this still required me to read this time in the Home Assistant app. Remember it, open the Etna connect app, select the program, select the time, press start. As you can understand, not really “smart”.

The Etna app does not have an in Home Assistant. On the HA forums there is a lot of discussion on Hisense appliances, as well as a connectlife HACS integration. Although I already had the feeling Etna is somehow related to this, I couldn’t get the thing to work. And it’s all cloud-based, I don’t like cloud-based integrations.

The investigation

I checked my pihole logs to see what the dishwasher tries to connect with, this is often a good and easy start to get to know what’s on the backend:

dishwasher pihole
I was very happy to see that a Tuya server was contacted, Tuya is often used by smart home appliances and is often integrated with Home Assistant.

Also running nmap against the local IP:

PORT     STATE    SERVICE VERSION
53/tcp   filtered domain
6668/tcp open     irc?

6668 is a port often used by Tuya, yay!

The third and last giveaway was that I installed the Tuya app, and it looked suspiciously similar to the Etna Connect app. So we can conclude that Etna uses a white-labeled version of Tuya.

The official Home Assistant Tuya integration states that we can connect to Tuya via a User key. Although the Etna app looks very similar to the Tuya, it doesn’t show an user key in the settings, Bummer.

Therefore I disconnected the dishwasher from the Etna App and account. And tried to link it to my Tuya app (the Etna account was not able to login to Tuya, so there is a slight difference there). Great success! The Etna dishwasher is now in the Tuya app, we can control it as if it’s any other Tuya device

Tuya app

Again some success, as the Tuya app has a user code, so we are able to add the device via the Tuya cloud to Home Assistant. The sad part here is that it’s not supported, although added, we are not able to control the dishwasher or read any of its sensors:

dishwasher HA official Tuya integration

Extracting local keys

Since we didn’t want to use the cloud anyway, we can use a method to extract the local keys, so we can directly talk to the dishwasher, and also extract the function codes we need.

This is the procedure I used, but as it’s a SaaS platform, it might quickly change after I wrote this post

  1. Go to the Tuya IoT Developer Platform and create a free account.
  2. Navigate to Cloud > Development and click Create Cloud Project
    1. Important here is that you select the right region for your account
    2. Select smart home as industry and development method
  3. Open the project, Devices > Link App account > Add App account > Tuya App Account configuration, scan this QR with your Tuya app

If all is good, it shows something like:

Tuya API device

We can open the device and see some ambiguous information

Tuya API device 2

We get some interesting information such as appointment time (this is the start delay), and the switch is the on/off switch for the appliance, but work mode only shows eco or fruit(?). Where in the app, we can set a wide range of modes from hygiene, to auto. Well at least we have remaining time in an entity (I don’t care about this as I mostly run the dishwasher at night)

Let’s continue on our quest, from this we copy the Device ID, and in the Tuya portal we do the following to extract the local key:

  1. Cloud > API explorer
  2. You get “Not subscribed error”, just click subscribe. You need to subscribe to the IoT Core Api, you can click Free Trial, it does not require a credit card.
  3. In the API explorer we look for “Query Device Details” and enter the deviceID saved earlier, the response should contain a local key, save this:
    Tuya local key

Back in Home Assistant we need to add a HACS integration by make-all: https://github.com/make-all/Tuya-local (this is another integration than the Local Tuya in the default HACS repo, make sure you have the correct one). Add the integration and restart HA.

We add the integration and select “Manually provide device connection information” (other methods might work but I have not tested these)

ha setup local Tuya

If you followed all previous steps you should be able to fill in all this information. (Make sure you give your dishwasher a static IP to prevent you from spending an hour of debugging issues in a few years.)

In my case, the device was recognized:

ha setup local Tuya devicetype ha setup local Tuya entities

We now have integrated the device locally! And can run our automation as we see fit! In my case I have created the following:

If the device gets turned on, it will poll the cheapest next time, set the right program and time, so when I close it, it will automatically run on the cheapest time. If I need to run a rinse right now or adjust the program, I can still do that as the automation will only set values on startup.

ha automation triggers ha automation actions

Thanks for reading this blog, I hope you learned a thing or two.

Wessel

If you want the automation YAML, this is a good starting point:

alias: Dishwasher auto start on best time
description: ""
triggers:
  - type: turned_on
    device_id: <dishwasher device id>
    entity_id: <entity id for on/of toggle>
    domain: switch
    trigger: device
conditions: []
actions:
  - device_id: <dishwasher device id>
    domain: select
    entity_id: <entity id for washing mode>
    type: select_option
    option: standard
  - type: toggle
    device_id: <dishwasher device id>
    entity_id: <entity id for timer>
    domain: switch
  - action: time.set_value
    metadata: {}
    target:
      entity_id: time.vaatwasser_timer
    data:
      time: >-
        {% set clean_time = states('sensor.dishwasher_optimal_pricing') |
        replace('+00:00', '') %}
                {% set diff = as_timestamp(clean_time) - as_timestamp(now()) %}
                {{ (diff if diff > 0 else 0) | timestamp_custom('%H:%M:00', false) }}
mode: single

And although highly specific to my situation, the optimal time I use to find the best spot to run the dishwasher. I used an energy meter to find the weightpoints of the load of a run:

  - sensor:
      - unique_id: dishwasher_optimal_pricing
        name: Dishwasher Optimal Pricing
        device_class: timestamp
        state: >
          {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
          {% set source = 'sensor.tibber_ceh_prices' %}
          {{ cheapest_energy_hours(
              sensor=source,
              no_weight_points=4,
              weight=[
                13.4, 7.1, 5.8,
                0.7, 0.7, 0.7,
                0.5, 7.1, 6.8
              ],
              start=now(),
              end=now() + timedelta(hours=12)
          ) }}
· home-assistant, tuya, local-tuya, smart-home, iot