Skip to content

[TS0601 / _TZE284_zpvusbtv] Tuya TS0601 two-gang (ZN2S-RS02E) - indicator_mode should be enum; add backlight %, backlight switch, and colors #29607

@cwtchhome

Description

@cwtchhome

What happened?

The current Zigbee2MQTT support for Tuya TS0601 two-gang switch (ZN2S-RS02E / _TZE284_zpvusbtv) handles the datapoint indicator_mode as a boolean (on/off).
However, this device exposes it as an enum with three possible states according to Tuya IoT logs and API data (image1.jpg)

{"1":"Switch 1","2":"Switch 2","7":"Timer 1","8":"Timer 2","13":"Master Switch","14":"Restart Status","15":"Indicator Status","16":"Backlight Switch","19":"Delay-off Schedule","101":"Child Lock","102":"Backlight","103":"ON Color","104":"OFF Color"

Because of this wrong mapping, the indicator LED mode can’t be controlled correctly — setting it to "off" or "switch_position" is ignored, and Z2M only treats it as boolean.

What did you expect to happen?

indicator_mode should support all three modes:
• "off" → completely turns off all LEDs, regardless of relay states.
• "on_off_status" → LEDs reflect relay state.
• "switch_position" → LEDs indicate button position.

Also, the converter should expose:
• backlight (DP102) as a number 0–100.
• backlight_switch (DP16) as a boolean.
• on_color / off_color (DP103/104) as enums.

How to reproduce it (minimal and precise)

1.	Pair the device with Zigbee2MQTT 2.6.3.
2.	Try to send via MQTT: {"indicator_mode":"off"} The command is ignored because Z2M expects a boolean.
3.	If you check via Tuya IoT Device Log, you can see DP15 correctly changing to "off", "on_off_status", or "switch_position".
4.	Also, note that sending: {"backlight":10} has no effect, since DP102 is not exposed.

Zigbee2MQTT version

2.6.3

Adapter firmware version

ZStack3x0 0x00124b0031ddae4d Revision: 20250321

Adapter

ZStack3x0

Setup

  • Zigbee2MQTT running as Home Assistant Add-on
  • Hardware: x86-64 host (VM - Oracle VirtualBox)
  • Zigbee adapter: Sonoff Zigbee 3.0 USB Plus
  • Home Assistant OS
    Core: 2025.11.1
    Supervisor: 2025.11.2
    Operating System: 16.3

uname -a && cat /etc/issue.net
Linux a0d7b954-ssh 6.12.51-haos #1 SMP PREEMPT_DYNAMIC Tue Nov 4 13:52:04 UTC 2025 x86_64 Linux
cat: can't open '/etc/issue.net': No such file or directory

Device database.db entry

{"id":5,"type":"Router","ieeeAddr":"0xa4c138e94c95b83f","nwkAddr":27015,"manufId":4417,"manufName":"_TZE284_zpvusbtv","powerSource":"Mains (single phase)","modelId":"TS0601","epList":[1,242],"endpoints":{"1":{"profId":260,"epId":1,"devId":81,"inClusterList":[4,5,61184,0,60672],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"65503":"�Ϥ0i�Ϥ0i","65506":56,"65508":0,"65534":0,"modelId":"TS0601","manufacturerName":"_TZE284_zpvusbtv","powerSource":1,"zclVersion":3,"appVersion":78,"stackVersion":0,"hwVersion":1,"dateCode":""}}},"binds":[],"configuredReportings":[],"meta":{}},"242":{"profId":41440,"epId":242,"devId":97,"inClusterList":[],"outClusterList":[33],"clusters":{},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":78,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"interviewState":"SUCCESSFUL","meta":{"configured":332242049},"lastSeen":1762977674740}

Debug log

When sending { "indicator_mode": "off" } → ignored
When sending { "indicator_mode": "ON" } → accepted (boolean mapping)

Notes

Device

software_build_id: undefined
date_code: ``
endpoints:

{"1":{"bindings":[],"clusters":{"input":["genGroups","genScenes","manuSpecificTuya","genBasic","zosungIRTransmit"],"output":["genOta","genTime"]},"configured_reportings":[],"scenes":[]},"242":{"bindings":[],"clusters":{"input":[],"output":["greenPower"]},"configured_reportings":[],"scenes":[]}}
Health

time: Wed Nov 12 2025 14:41:15 GMT-0500 (hora estándar de Colombia)
os.load_average: 0.21, 0.16, 0.06
os.memory_percent: 64.4572
process.memory_percent: 5.281
process.uptime_sec: 2405

{"leave_count":0,"messages":2524,"messages_per_sec":1.0516,"network_address_changes":0}

✅ Working features:
• Master switch (DP13)
• Switch L1 (DP1)
• Switch L2 (DP2)
• Backlight switch (DP16)
• Power on behavior (DP14)
• Child lock (DP101)
• Color control ON/OFF (DP103/104)

❌ Issues:
• indicator_mode handled as boolean (should be enum)
• backlight percentage (DP102) missing
• MQTT direct commands (e.g., {"state_l1":"ON"}) revert immediately to OFF, while working fine from Z2M UI (possible optimistic update mismatch)
• Missing indicator_mode options in exposes.

💡 Proposed fix (JS patch for tuya.js)

{
fingerprint: [{modelID: "TS0601", manufacturerName: "_TZE284_zpvusbtv"}],
model: "TS0601_2gang_zpvusbtv",
vendor: "Tuya",
description: "Two gang smart switch with colored backlight (ZN2S-RS02E)",
fromZigbee: [tuya.fz.datapoints],
toZigbee: [tuya.tz.datapoints],
configure: tuya.configureMagicPacket,
exposes: [
tuya.exposes.switch().withEndpoint("l1"),
tuya.exposes.switch().withEndpoint("l2"),
e.binary("backlight_switch", ea.STATE_SET, "ON", "OFF").withDescription("Backlight master switch"),
e.numeric("backlight", ea.STATE_SET).withValueMin(0).withValueMax(100).withUnit("%").withDescription("Backlight brightness"),
e.enum("indicator_mode", ea.STATE_SET, ["off", "on_off_status", "switch_position"]).withDescription("LED indicator mode"),
e.power_on_behavior().withAccess(ea.STATE_SET),
e.binary("child_lock", ea.STATE_SET, "ON", "OFF").withDescription("Child Lock"),
e.enum("on_color", ea.STATE_SET, ["red","blue","green","white","yellow","magenta","cyan","warm_white","warm_yellow"]).withDescription("ON color"),
e.enum("off_color", ea.STATE_SET, ["red","blue","green","white","yellow","magenta","cyan","warm_white","warm_yellow"]).withDescription("OFF color"),
],
meta: {
multiEndpoint: true,
tuyaDatapoints: [
[1, "state_l1", tuya.valueConverter.onOff],
[2, "state_l2", tuya.valueConverter.onOff],
[13, "state", tuya.valueConverter.onOff],
[14, "power_on_behavior", tuya.valueConverter.powerOnBehaviorEnum],
[15, "indicator_mode", tuya.valueConverterBasic.lookup({
off: tuya.enum(0),
on_off_status: tuya.enum(1),
switch_position: tuya.enum(2),
})],
[16, "backlight_switch", tuya.valueConverter.onOff],
[101, "child_lock", tuya.valueConverter.onOff],
[102, "backlight", tuya.valueConverter.raw],
[103, "on_color", tuya.valueConverterBasic.lookup({
red: tuya.enum(0), blue: tuya.enum(1), green: tuya.enum(2), white: tuya.enum(3),
yellow: tuya.enum(4), magenta: tuya.enum(5), cyan: tuya.enum(6), warm_white: tuya.enum(7), warm_yellow: tuya.enum(8),
})],
[104, "off_color", tuya.valueConverterBasic.lookup({
red: tuya.enum(0), blue: tuya.enum(1), green: tuya.enum(2), white: tuya.enum(3),
yellow: tuya.enum(4), magenta: tuya.enum(5), cyan: tuya.enum(6), warm_white: tuya.enum(7), warm_yellow: tuya.enum(8),
})],
],
},
endpoint: () => ({l1: 1, l2: 1}),
}

✅ Tested and confirmed

All these datapoints and modes were verified through Tuya IoT Console → Device Log and DP list, and cross-checked via Zigbee2MQTT external converter.
Tested using MQTT commands and verified correct LED and backlight responses.

Metadata

Metadata

Assignees

No one assigned

    Labels

    problemSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions