Experience integrating Duux products?

Im currently not in the possesion of a multimeter (mine died unfortunately) however im going to buy a new one so when that arrives im going to look into the pins situation for flashing esphome

1 Like

Fan arrived today, a quick measurement gives me the following information (transposed onto the photo that was made earlier in this topic):

I do not have a logic analyser so I have not been able to figure out which is the 3.3V and which is the Tx out of those two, nor which of the three 0V ones would be the Rx or reset pin and such.

EDIT: Looks like I may have drawn some lines onto the wrong pins, will make an update post later with some additional measurements and a table instead.

The connector is a Tag-Comnect (https://www.tag-connect.com/), they connect to a JTAG debugger so it’s entirely possible it has a standard pin-out.

I’ve not had time to look more into this and I still haven’t replaced my logic analyzer as I spent enough replacing my laptop and heater already :sob:

I def. do not have anything for JTAG related stuff to check that sadly. I honestly just assumed the connector is masking a classic TTL UART since it’s an ESP board. I suppose that’s not a guarantee but I can’t line up the multitool measurements with what I can find as a supposed pin-out for JTAG either.
That said, I’ve almost never done this so I’m probably not looking in the right place, measuring incorrectly or JTAG has multiple standards/variants or something.

In the mean time, continuing under the assumption it is just a TTL UART masked under this connector, I took some new/additional measurements with the device connected and powered on (not just continuity testing). For the pins numbered as:

screenshot_2024-07-22T15:19:05

it becomes something along the lines of the following:

Pin R → GND Voltage Possible Options
1 ~1.1k ~3.28 3.3V
2 - ~3.26 3.3V
3 - ~3.55-3.56 3.3V
4 ~3.1M ~3.25 3.3V
5 11k ~3.28 3.3V
6 3.2M 0 ↔ ~3.28 TX
7 - ~0.5m RX, RST
8 0.1 0 GND
9 - ~0.2m RX, RST
10 - ~1.5m RX, RST

It would be great if someone with the right tools and know-how could actually check things out though :wink:

1 Like

My multimeter will arrive tomorrow so i will have a look at the pins.

My plan is using the pinout of the esp package as a source and just figuring out where they go. I think it will be difficult though since i think the pcb is 3 layers (correct me if im wrong)

Also i must mention i ordered a logic analyzer too!

My multimeter arrived and i got straight to work. What i have found now is:

U0TXD = P11
GPIO0 = P13
U0RXD = P10
GND = P3
these refer to the pads on the back, so i think we dont need the 10 pin for flashing(??). Besides that i would also like to dump the current firmware so we can maybe figure out a way for OTA flashing

i have gotten some success on connecting to the pins, and i got some interesting output (i put it in 2 parts, because of the changing baud rate)

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4852
load:0x40078000,len:13688
load:0x40080400,len:3904
entry 0x40080688```
HW_VERSION: 20
FW_VERSION: 14.3.9
Fri Jun9 10:30:24 2023
Mac Address : <mac addr>
====FACTORY TEST MODE ACTIVE!====

{"tune":2,"fw":"14.3.9","id":"<mac addr>","pin":1}

 Sending Tuya: CMD=0x00VERSION=0 DATA=[(0)] INIT_STATE=0
 Name: DUUX.1.229173
Local time: Thu Jan 1 01:00:03 1970
[E][cg_cloud_device.cpp:693] readAndHandleConfigFile(): No time sync, abort!
[WIFI] start scan
 [WIFI] Connecting to <wifi> @ ch11
Sending heartbeat
 Sending Tuya: CMD=0x00 VERSION=0 DATA=[(0)] INIT_STATE=0
 [WIFI]Connect timeout: 6
 [WiFi]Connect Timeout > Failed with status 4
 [WIFI] start scan
[WIFI] Connecting to <wifi> @ ch11
[WiFi]connected 192.168.2.18
null
[E][cg_cloud_device.cpp:1072] mqtt_event_handler_cb(): MQTT_EVENT_CONNECTED
[mqtt]connected!
TOPIC=sensor/<mac addr>/command

Running: 'tune set power 1'
 Usage: tune device not connected!
[mqtt]No method tune set power 1 found
TOPIC=sensor/<mac addr>/config
Sending heartbeat
 Sending Tuya: CMD=0x00 VERSION=0 DATA=[(0)] INIT_STATE=0
 null
 [E][cg_time.cpp:13] time_sync_notification_cb(): Got NTP sync!
Local time: Wed Jul 24 14:05:26 2024
Local time: Wed Jul 24 14:05:26 2024
Sending heartbeat
 Sending Tuya: CMD=0x00 VERSION=0 DATA=[(0)] INIT_STATE=0
 Sending heartbeat
Sending Tuya: CMD=0x00 VERSION=0 DATA=[(0)] INIT_STATE=0
{"bt":1721822727}
 Sending heartbeat
Sending Tuya: CMD=0x00 VERSION=0 DATA=[(0)] INIT_STATE=0
Sending heartbeat
Sending Tuya: CMD=0x00 VERSION=0 DATA=[(0)] INIT_STATE=0
null
Sending heartbeat
 Sending Tuya: CMD=0x00 VERSION=0 DATA=[(0)] INIT_STATE=0

This is funny though, since it seems they left it in factory test mode
EDIT: i got esptool to work and i am now in progress of dumping the firmware

EDIT2: Since i cant reply to the topic, ill just edit this message.

I got ESPhome on the wifi module, however iam having a VERY weird issue. The MCU just keeps logging [I][tuya:156]: MCU restarted however when i open the logs on homeassistant it suddenly start working and im able to control the fan. Does anyone maybe know what this could relate to?

The “mqtt/dns hack” works perfectly well with the Duux Whisper Flex connected fan…

Same topics as above (sensor/mac address/in, /online and /update).

The status info for this fan is

{
	"sub": {
		"Tune": [
			{
				"uid": "<some identifier>",
				"id": 1,
				"power": 1,
				"mode": 2,
				"speed": 1,
				"swing": 1,
				"tilt": 0,
				"timer": 0
			}
		]
	}
}

The commands are sent to sensors/mac address/command with the same set tune name value commands:

  • set tune power 1/0 => turn the fan on or off
  • set tune speed 1/26 => select the speed of the fan
  • set tilt 0/1 => enable/disable the vertical swing
  • set swing 0/1 => enable/disable the horizontal swing
  • set mode 0/1/2 => fan mode (0 = normal, 1 = natural wind, 2 = night)
  • set timer 0…12 => auto-off (from 0=off to 12 hours)

K.

That is correct, however im looking for a more permanent solution that doesnt require you to mess with DNS.

Dont get me wrong, its a good solution. Just not the one im personally looking for

I fixed the restarting issue, yay!

the problem was that the duux fan expects a cloud connection (so wifi status 0x04) but it was sending 0x03, i was able to fix this by adding it to homeassistant and it immediately started working!

So if anyone wants to convert their fan, just connect the UART pins i described and when flashing make sure GPIO0 is low (so connected to ground). My esphome config is:

esphome:
  name: duux-fan
  friendly_name: Duux Fan

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:
# Enable Home Assistant API
api:
  encryption:
    key: "<redacted>"

ota:
  - platform: esphome
    password: "<redacted>"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  use_address: 10.17.167.118
  power_save_mode: none
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "<redacted>"
    password: "<redacted>"

captive_portal:
web_server:
  port: 80

uart:
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600

# Register the Tuya MCU connection
tuya:
fan:
  - platform: "tuya"
    name: None
    switch_datapoint: 1
    speed_datapoint: 3
    speed_count: 26

select:
  - platform: "tuya"
    name: "Oscillate horizontally"
    icon: mdi:arrow-left-right
    enum_datapoint: 4
    optimistic: true
    options:
      0: "off"
      1: "on"


  - platform: "tuya"
    name: "Oscillate vertically"
    icon: mdi:arrow-up-down
    enum_datapoint: 5
    optimistic: true
    options:
      0: "off"
      1: "on"

  - platform: "tuya"
    name: "Mode"
    enum_datapoint: 2
    optimistic: true
    options:
      0: "Manual Mode"
      1: "Natural Mode"
      2: "Sleep Mode"

  - platform: "tuya"
    name: "Timer"
    icon: mdi:fan-clock
    enum_datapoint: 6
    optimistic: true
    options:
      0: "off"
      1: "1h"
      2: "2h"
      3: "3h"
      4: "4h"
      5: "5h"
      6: "6h"
      7: "7h"
      8: "8h"
      9: "9h"
      10: "10h"
      11: "11h"
      12: "12h"

sensor:
  - platform: wifi_signal
    name: "Wifi Signal"
    update_interval: 60s
    icon: mdi:wifi

  - platform: uptime
    name: "Uptime"
    update_interval: 60s
    icon: mdi:clock-outline

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "IP Address"
    ssid:
      name: "Wi-Fi SSID"
    bssid:
      name: "Wi-Fi BSSID"
  - platform: version
    name: "ESPHome Version"
    hide_timestamp: true

Also: i wont be posting the dumped firmware due to privacy (and maybe legal) concerns

1 Like

Using the pins on the back makes so much more sense :man_facepalming:
Used those to flash ESPHome no problem (pins as described by @Wolfo-Gaming ).
My config is very similar to the one above, the main difference is that I use esp-idf for the framework type instead of arduino.

I also added the following line to the fan entry:
oscillation_datapoint: 4
this makes it so that homeassistant can toggle the oscillation on the fan component instead of a seperate select

As someone new to flash firmware etc. Could you provide some details on how to go about doing this? Especially any tools that may be required?

To confirm, this is also working for model DXCF54?

Thanks in advanced!

I bought a cheap usb to ttl adapter (CP2102) and i hooked this up to the pins i described above, what i must note though is for flashing you have to connect the 5v pin on the mcu too (because it shouldnt be connected to the mainboard) and after flashing you can just plug it in and only leave rx and tx and gnd attached if you still want serial output, otherwise you can just remove the wires after flashing and use ota for esphome

I cant give more explaination at the moment, as iam currently on vacation

Thanks for the swift response. The part that confuses me is about the 5V. When you’re back from vacation (honestly there is no rush), I would appreciate a little more clarification on that part!

Enjoy the vacation!

I’ve had a read through of this thread, and the options for integration of the Duux fans to HASS do seem promising, but I’m not clear if the solutions above for flashing one of the boards will work with my Whisper Flex as well as the 360 discussed above?

I got a new Duux fan recently to replace my old dumb fan and was hopeful that I could just use Tuya to control it but sadly it’s a Gen 2. The MQTT hack seems like it would be good and I’ve set up a DNS record in my Pi-hole to redirect traffic to my local MQTT broker but I can’t seem to get it to work.

I’ve never used MQTT before and the documentation for it is a bit :face_with_spiral_eyes: and I fear I may have got in over my head. I’m using Home Assistant OS with the Mosquitto broker addon.

I’ve also generated a self-signed certificate which it seems to be detecting:

s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
cont-init: info: running /etc/cont-init.d/mosquitto.sh
[18:13:18] INFO: Certificates found: SSL is available
cont-init: info: /etc/cont-init.d/mosquitto.sh exited 0
cont-init: info: running /etc/cont-init.d/nginx.sh
cont-init: info: /etc/cont-init.d/nginx.sh exited 0
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun mosquitto (no readiness notification)
services-up: info: copying legacy longrun nginx (no readiness notification)
[18:13:18] INFO: Starting NGINX for authentication handling...
s6-rc: info: service legacy-services successfully started
[18:13:19] INFO: Starting mosquitto MQTT broker...
2024-08-23 18:13:19: Warning: Mosquitto should not be run as root/administrator.
2024-08-23 18:13:19: mosquitto version 2.0.18 starting
2024-08-23 18:13:19: Config loaded from /etc/mosquitto/mosquitto.conf.
2024-08-23 18:13:19: Loading plugin: /usr/share/mosquitto/go-auth.so
2024-08-23 18:13:19:  ├── Username/password checking enabled.
2024-08-23 18:13:19:  ├── TLS-PSK checking enabled.
2024-08-23 18:13:19:  └── Extended authentication not enabled.
2024-08-23 18:13:19: Opening ipv4 listen socket on port 1883.
2024-08-23 18:13:19: Opening ipv6 listen socket on port 1883.
2024-08-23 18:13:19: Opening websockets listen socket on port 1884.
2024-08-23 18:13:19: Opening ipv4 listen socket on port 8883.
2024-08-23 18:13:19: Opening ipv6 listen socket on port 8883.
2024-08-23 18:13:19: Opening websockets listen socket on port 8884.
2024-08-23 18:13:19: mosquitto version 2.0.18 running
2024-08-23 18:13:19: New connection from ::1:39590 on port 1883.
2024-08-23 18:13:19: Client <unknown> disconnected due to protocol error.
[18:13:19] INFO: Successfully send discovery information to Home Assistant.
[18:13:19] INFO: Successfully send service information to the Supervisor.
2024-08-23 18:13:23: New connection from 172.30.32.1:33613 on port 1883.
2024-08-23 18:13:23: New client connected from 172.30.32.1:33613 as 0fEW0NmhyHtS6jBLIaLFBW (p2, c1, k60, u'homeassistant').

If someone wouldn’t mind helping me out, preferably explaining things to me like I’m a 5 year old or something that would be amazing. :pray:

Hi

The Mosquitto addon in HA uses the default ports (unsecured:1883, TLS:8883).
The Duux Fan expects to find a MQTT broker running on port 443 (TLS).

If this port (default HTTPS port) is not currently used on your HA server (reverse proxy, etc.), you should probably be able to edit the mosquitto configuration to change the “listener 8883” by “listener 443”. You can keep the unsecured port as 1883.

Please note that this will also impact all your other MQTT TLS clients and you’ll have to update their config to also use port 443. This will have no impact for unsecured clients that will continue to use port 1883.

If you are already using HTTPS on port 443 on your HA server, you’ll have to run mosquitto outside of your HA instance on a server where port 443 is free (and update your DNS record for collector3.cloudgarden.nl to that machine IP address of course).

In my case, I have my main MQTT broker used by HA and other tools configured to run with the default ports, and I added a secondary broker as a docker container, dedicated for the Duux fan, listening on port 443 and bridged with my main broker.

K.

Thanks to all the contributors above who helped me connect my DUUX Whisper fan to my own MQTT broker! I used the MiTM approach using dnat to redirect all DUUX traffick on port 443 to Mosquitto on port 8883. I haven’t really discovered anything new but I just wanted to share my process, as there were a few steps that were giving me some trouble to figure out.

My setup is that I have a MikroTik router, Mosquitto running in Docker on a Synology NAS, and my DUUX whisper connected to a different subnetwork than the NAS (the latter likely impacts the dnat setup).

I first setup Mosquitto with a new listener that uses TLS, on port 8883 (since another program on the NAS is already using 443. There are many sites that explain the process, I used this one: http://www.steves-internet-guide.com/mosquitto-tls/

My listener section for DUUX of mosquitto.conf now reads:

per_listener_settings true

listener 8883
protocol mqtt
allow_anonymous true
cafile /mosquitto/config/ca.crt 
certfile /mosquitto/config/server.crt 
keyfile /mosquitto/config/server.key

Then I setup dnat on the MikroTik to redirect all DUUX traffick to Mosquitto:

/ip firewall nat
add action=dst-nat chain=dstnat dst-port=443 \
    protocol=tcp src-address=[DUUX ip address] to-addresses=[IP of NAS where Mosquitto is running] to-ports=8883

I think I am lucky that my DUUX and NAS are on different subnetworks, otherwise I would have to set up a hairpin NAT with additional rules.

Finally I connected an MQTT desktop client to Mosquitto to see the DUUX messages. Subscribing to the right topics actually took me a while. I subsribed to sensor/[DUUX MAC address]/# but was not seeing any messages. Until I finally realized that for a topic case matters, and I was using uppercase letters in the MAC address, while DUUX uses lowercase. Easy fix.

Now I can control my fan, sending commands in plaintext. e.g. to turn the fan on:

tune set power 1

If you run MQTT on a docker container, you can use macvlan network driver from docker to make it appear as a physical device on your network. It will get an ip from you dhcp.
You can then use 443 port freely ( and keep 1883 / 8883 open too )

I run mine on a dedicated LXC container, it also has routable IP from the main network.