Help with Setting Up TS0601 Watering Device with Zigbee2MQTT

Hi everyone, and apologies if this is a beginner question. I’m trying to set up the TS0601 watering device I purchased from AliExpress. I know there are many posts like this, and I truly appreciate any guidance.

The Issue:

When I try to connect the device, I get the following message:

2m: Device '0x4c97a1fffef0bffd' with Zigbee model 'TS0601' and manufacturer name '_TZE284_fhvpaltk' is NOT supported, please follow https://www.zigbee2mqtt.io/advanced/support-new_devices/01_support_new_devices.html

What I’ve Tried:

Based on the information above, I did some research and found that zigbee-herdsman-converters might help. I discovered a PR recently raised to add this device. So, I tried creating a custom converter to get this working.

Here’s what I came up with (I’m a beginner, so please excuse any mistakes!):

const { exposes, ea } = require('zigbee-herdsman-converters');
const tuya = require('zigbee-herdsman-converters/lib/tuya');

const valve_config = {
    fingerprint: tuya.fingerprint("TS0601", ["_TZE284_eaet5qt5", "_TZE284_fhvpaltk"]),
    model: "TS0601_water_switch",
    vendor: "Tuya",
    description: "Dual water valve",
    fromZigbee: [
        tuya.fz.datapoints,  // Handles general Tuya datapoints
        fz.battery,          // Battery level support
    ],
    toZigbee: [
        tuya.tz.datapoints,  // Handles sending Tuya datapoints
    ],
    onEvent: tuya.onEventSetTime,
    configure: tuya.configureMagicPacket,
    exposes: [
        // Valve 1 Status
        exposes.enum("valve_status_l1", ea.STATE, ["manual", "auto", "idle"]).withDescription("Valve 1 status").withEndpoint("l1"),
        
        // Valve 2 Status
        exposes.enum("valve_status_l2", ea.STATE, ["manual", "auto", "idle"]).withDescription("Valve 2 status").withEndpoint("l2"),

        // Valve 1 Control (on/off)
        exposes.switch().withEndpoint("l1").withDescription("Valve 1 on/off").withLabel("Valve 1"),

        // Valve 2 Control (on/off)
        exposes.switch().withEndpoint("l2").withDescription("Valve 2 on/off").withLabel("Valve 2"),

        // Valve 1 Countdown Timer
        exposes.numeric("countdown_l1", ea.STATE_SET).withUnit("min").withDescription("Valve 1 countdown in minutes").withValueMin(0).withValueMax(1440).withEndpoint("l1"),

        // Valve 2 Countdown Timer
        exposes.numeric("countdown_l2", ea.STATE_SET).withUnit("min").withDescription("Valve 2 countdown in minutes").withValueMin(0).withValueMax(1440).withEndpoint("l2"),

        // Valve 1 Duration (last irrigation)
        exposes.numeric("valve_duration_l1", ea.STATE).withUnit("s").withDescription("Valve 1 irrigation last duration in seconds").withEndpoint("l1"),

        // Valve 2 Duration (last irrigation)
        exposes.numeric("valve_duration_l2", ea.STATE).withUnit("s").withDescription("Valve 2 irrigation last duration in seconds").withEndpoint("l2"),

        // Battery
        exposes.battery(),

        // Battery Voltage
        exposes.battery_voltage(),
    ],
    meta: {
        tuyaSendCommand: "sendData",
        tuyaDatapoints: [
            [1, "state_l1", tuya.valueConverter.onOff], // Valve 1 on/off
            [2, "state_l2", tuya.valueConverter.onOff], // Valve 2 on/off
            [13, "countdown_l1", tuya.valueConverter.raw], // Valve 1 countdown
            [14, "countdown_l2", tuya.valueConverter.raw], // Valve 2 countdown
            [25, "valve_duration_l1", tuya.valueConverter.raw], // Valve 1 duration
            [26, "valve_duration_l2", tuya.valueConverter.raw], // Valve 2 duration
            [104, "valve_status_l1", tuya.valueConverterBasic.lookup({manual: 0, auto: 1, idle: 2})], // Valve 1 status
            [105, "valve_status_l2", tuya.valueConverterBasic.lookup({manual: 0, auto: 1, idle: 2})], // Valve 2 status
        ],
        multiEndpoint: true, // Enable multi-endpoint support
    },
    endpoint: (device) => {
        return {
            l1: 1, // Valve 1 uses endpoint 1
            l2: 1, // Valve 2 also uses endpoint 1
        };
    },
};

module.exports = valve_config;

Next, I added this to the top of my configuration.yaml:

version: 4
homeassistant:
  enabled: true
external_converters:
  - '/config/zigbee2mqtt/valve_converter.js'

However, when I try to use the device, it still shows as unsupported, and the Exposes list only shows Linkquality.

My Questions:

  1. What mistake have I made in the converter?
  2. Is there anything else I need to do to integrate this device properly?

Thanks in advance for your help!

Remove those last 2 lines which you just added. That is not how you define external converters.

You need to create an external_converters folder inside your z2m folder first, so the actual path is /config/zigbee2mqtt/external_converters. See this

You can then save your valve_converter.js inside that new folder (you can use the UI to add it) and restart Z2M to have it detected.

Thank you so much that worked seems I had missed that new doc! Thanks again!

1 Like

Hey,
I have thew same solution but your solution do not work on me side. He renames the .js file every time to .js.invalid.

But I do not know what is wrong in the file because he do not tell.

z2m: Invalid external converter 'valve_converter.js' was ignored and renamed to prevent interference with Zigbee2MQTT.

Hi @Mechdude, I bought exactly the same watering controller and would appreciate some help. How do I use your converter code?

I’m using Zigbee2mqtt as well and the device is already connected but I’m not sure what next. I’ve saved /opt/zigbee2mqtt/external_converters/valve_converter.js and I’ve restarted and re-interviewed the device but it’ s still coming up as Unsupported. How I can tell z2m to use that converter for my water timer?

Sorry, very new on my HA journey so any help is appreciated.

BTW, my configuration.yaml is in /opt/zigbee2mqtt/.

I am in the same game, as i wrote my ha Identity the file as invalide. I switched my Z2M to Edge where the Update is active. But i can not switch any of the 2 valve ports via ha.

There is a fix inthe related PR. Works for me.

Hi @Aenos ,

Thanks a lot for that link.

Finally seems like it’s working, at least it’s showing up as supported and I can see what’s beeing exposed.

so I copied the code from here Added new Tuya SGW08Z Dual water valve by mrestivill · Pull Request #8898 · Koenkk/zigbee-herdsman-converters · GitHub to /root/config/zigbee2mqtt/external_converters/ ts0601_valve_custom.js
and restarted HA… still it doesn’t see any Exposes… what an I doing wrong?

got it to work with this:

it is zha not zigbee2mqtt of course.

Confirm that it works for me too. No need to add any lines to configuration.yaml file (chatGPT suggests that you have to). And also calling it “external” - works, rather than “custom”. Also using latest Zigbee2MQTT Edge (if not latest for you, delete it and install again)

Code seems to be merged as of time of writing, so there won’t be any need to switch to Edge from the beginning of July.

Posting the above for anyone who reads this after 07/2025 ^^