"Tuya" WF-FL01

Hi guys.
I recently purchased a WF-FL01 fan/light switch as a bit of a test.

I tried to flash it with tasmota using tuya-convert, but it looks like it has the newer firmware and didnt work.
So i set it up in the smart life app, and added the tuya config to HA. — but im getting nothing.

Any advice ? Either on the tuya itself, or some way to flash it with the non standard firmware?


Did you get these to work?

Nope – Im ordered a different device to test … I didnt like that it wasnt fixed fan speeds, it worked like a dimmer.

I ended up going down a fairly complicated path to get it working, using IFTTT

Setup a scene in smart life app for each fan speed setting, fan off, light on, light off
Create IFTTT rules for an incoming webhook connected to the smart life scene

In ha – an input_boolean for the light, the fan state, and an input_select for the fan speed
a template light and a template fan

Node Red rules to call the relevant ifttt.trigger based on state changes on the input booleans and input select.

Its complicated, a little slow, and requires internet – but it works!

In case anyone ever stumbles across this thread I thought it worth updating my new setup.

IFTTT was too slow to be usable, plus SmartLife is dropping support for it.

So, i have a new (and much better) solution, using this:

I followed the instructions to get the device id and key, and then rolled my own NodeJS app using this and mqtt.

The light switch is controlled by an mqtt light, and the fan by mqtt fan. All works perfectly.

Happy to share if anyone is interested. The app itself is pretty ugly, i got it to the point where its working but it could definitely use some refactoring.

Please share ! I’m a bit stuck on integrating it with Hassio

I have a “better” version of this thats had some refactoring to make it usable, but this defintely works as is

const TuyAPI = require('tuyapi');

const device = new TuyAPI({
  id: 'LOCAL_ID_HERE',
  key: 'LOCAL_KEY_HERE'});

// Find device on network
device.find().then(() => {
  // Connect to device

// Add event listeners
device.on('connected', () => {
  console.log('Connected to device!');

device.on('disconnected', () => {
  console.log('Disconnected from device.');
  device.find().then(() => {

device.on('error', error => {
  console.log('Error!', error);

const mqtt = require('mqtt');
var options = {
   clientId: 'mqtt-node-js'

const client = mqtt.connect('mqtt://', options);

var light_on = false;
var fan_on = false;
var fan_speed = 1;
var last_data = false;
var fan_status = "OFF";
var fan_on_payload = "0";
var speed_value = "1";
var sleep = require('sleep');

client.on('connect', () => {

device.on('data', data => {
  if (data != last_data) {
    if (typeof data.dps['1'] !== 'undefined') {
       fan_on = data.dps['1'];
       if (fan_on) {
           fan_on_payload = "1";
       } else {
           fan_on_payload = "0";
    if (typeof data.dps['9'] !== 'undefined') {
        light_on =  data.dps['9'];
    if (typeof data.dps['3'] !== 'undefined') {
        fan_speed = data.dps['3'];

    if (!fan_on) {
        fan_status = "off"
    } else if (fan_speed == "1") {
        fan_status = "low"
    } else if (fan_speed == "2") {
        fan_status = "med"
    } else if (fan_speed == "3") {
        fan_status = "high"
    } else {
        fan_status = "low"

    client.publish('master/state/fan_status', fan_status);
    client.publish('master/state/fan', fan_on_payload);
    client.publish('master/state/fan_speed', fan_status);

    if (light_on) {
        light_status = "1";
    } else {
        light_status = "0";
    client.publish('master/state/light', light_status);

    last_data = data;

client.on('message', (topic, message) => {
  (async () => {
    light_on = await device.get({dps: 9});
    fan_on =  await device.get({dps: 1});
    fan_speed = await device.get({dps: 3});
    console.log(`light: ${light_on} fan: ${fan_on} speed: ${fan_speed}`);

  switch (topic) {
    case 'master/cmd/light':
      light_on = message.toString();
      if (light_on == "0") {
         light_on = false;
      if (light_on == "1") {
        light_on = true;
      device.set({dps: 9, set: light_on});
    case 'master/cmd/fan_speed':
      fan_speed = message.toString();
      if (fan_speed == "low") {
        speed_value = "1";
      } else if (fan_speed == "med") {
        speed_value = "2";
      } else if (fan_speed == "high") {
        speed_value = "3";
      } else {
        speed_value = "1";
      if (fan_speed == "off") {
        device.set({dps: 1, set: false});
      } else {
        device.set({dps: 3, set: speed_value});
        device.set({dps: 1, set: true});
    case 'master/cmd/fan':
      old_state = fan_on;
      fan_on = message.toString();
      if (fan_on == "0") {
        fan_on = false;
      if (fan_on == "1") {
        fan_on = true;
      if (fan_on != old_state) {
          device.set({dps: 1, set: fan_on});


Save that to a file somewhere. I run it on base OS (ubuntu) that HA is running on via docker, but it could run anywhere.
You can run it with just node and voila :slight_smile:

HA config is a simple mqtt light, and an mqtt fan.

Thanks for your reply!
I ended up going with a not so ideal solution using Node Red and “tuya-local” nodes.
It’s very similar to your solution, looking at their code, they also sue tuyapi. It weirdly disconnects very often, but I managed to make a workflow to enqueue my commands and reconnect.

I don’t suppose you have had a problem with the switch itself failing?

The first one I ever got has been fine, but all additional ones capacitors on the fan speed controller keep failing after a few hours and the fan goes to full speed.

I actually can’t tell because of how the wiring on my fan works. I use the switch only as on/off for the fan. The speed is controlled by the fan’s original switch because it has a crazy wiring scheme.