Koenkk / Koenkk/zigbee2mqtt

TS0002 _TZ3218_sfjr4fnz (ENGO EREL-16ZB) is a 1-gang relay but matches the 2-gang TS0002 default definition - configure always fails

Open
#33,110 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
15.7k
Forks
2k
Avg merge
18h 55m
Merged PRs (30d)
35

Description

What happened?

The ENGO EREL-16ZB is a single-channel Zigbee relay (1x16A, NO-COM output). Its fingerprint is modelID: TS0002 / manufacturerName: _TZ3218_sfjr4fnz and it exposes one endpoint only (epList: [1]).

There is no definition for this manufacturerName in zigbee-herdsman-converters, so it falls through to the catch-all entry in src/devices/tuya.ts (model: "TS0002", zigbeeModel: ["TS0002"], commented "This is the default for TS0002 devices"). That definition is 2-gang:

endpoint: (device) => { return {l1: 1, l2: 2}; },
configure: async (device, coordinatorEndpoint) => {
    await tuya.configureMagicPacket(device, coordinatorEndpoint);
    await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ["genOnOff"]);
    await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ["genOnOff"]);
},

Endpoint 2 does not exist, so device.getEndpoint(2) returns undefined and configure throws on every attempt, after every restart:

error: z2m: Failed to configure 'ENGO Gas boiler Relay', attempt 3 (TypeError: Cannot read properties of undefined (reading 'bind')
    at Object.bind (zigbee-herdsman-converters/src/lib/reporting.ts:48:24)
    at configure (zigbee-herdsman-converters/src/devices/tuya.ts:8502:29)
    at async Object.configure (zigbee-herdsman-converters/src/index.ts:371:21)
    at async Configure.configure (/app/lib/extension/configure.ts:135:13))

Consequences:

  • The device never reaches the configured state; 3 failed attempts are logged after every restart.
  • state_l2, countdown_l2 and power_on_behavior_l2 are exposed but can never work (permanently unknown in Home Assistant).
  • Endpoint 1 itself is fine: its genOnOff bind runs before the throw, so on/off commands and state updates work normally. This is a definition bug, not a functional outage.

A tuya.whitelabel(...) entry on the existing definition would fix only the displayed vendor/model - configure would still fail, because the generic definition binds endpoint 2 unconditionally.

What did you expect to happen?

The device recognised as a 1-gang relay: configure succeeds, and no l2 exposes are created.

How to reproduce it (minimal and precise)

Pair an ENGO EREL-16ZB ("ENGO Smart Relay EREL-16ZB, 1x16A, NO-COM"). configure fails 3 times on every Zigbee2MQTT start.

Zigbee2MQTT version

2.14.1 (Home Assistant add-on 2.14.1-1), zigbee-herdsman-converters 26.105.0

Adapter firmware version

20260311

Adapter

SMLIGHT SLZB-06 (zstack), connected over TCP

Setup

Home Assistant add-on on Home Assistant OS, x86-64.
Linux 6.18.39-haos #1 SMP PREEMPT_DYNAMIC x86_64, Home Assistant Core 2026.9.1

Device database.db entry
{"type":"Router","manufId":4098,"manufName":"_TZ3218_sfjr4fnz","powerSource":"Mains (single phase)","modelId":"TS0002","epList":[1],"endpoints":{"1":{"profId":260,"epId":1,"devId":256,"inClusterList":[0,3,4,5,6,57345,57344],"outClusterList":[10,25],"clusters":{"genBasic":{"attributes":{"65507":"sdk:1.0.16;cfg:0.0.0;ker:0.0.14-beta.1;","65508":0,"65534":0,"modelId":"TS0002","manufacturerName":"_TZ3218_sfjr4fnz","powerSource":1,"zclVersion":3,"appVersion":73,"stackVersion":1,"hwVersion":1,"dateCode":""}},"genOnOff":{"attributes":{"onOff":0,"onTime":0,"offWaitTime":0,"tuyaBacklightMode":1,"moesStartUpOnOff":2}},"manuSpecificTuya3":{"attributes":{"powerOnBehavior":2,"switchType":0}}},"binds":[{"cluster":6,"type":"endpoint","endpointID":1}],"configuredReportings":[],"meta":{}}},"appVersion":73,"stackVersion":1,"hwVersion":1,"zclVersion":3,"interviewCompleted":true,"interviewState":"SUCCESSFUL"}

(IEEE address and coordinator address removed.)

Notes

Product: ENGO Controls EREL-16ZB, "Smart Relay ZigBee 1x16A, NO-COM" (vendor site: https://engocontrols.com, example retailer listing: https://qualityheating.co.uk/products/engo-erel-16zb-zigbee-smart-relay-1-16a-wireless-boiler-pump-lighting-control).

Suggested fix - a fingerprint-matched 1-gang definition placed before the generic TS0002 entry, following the pattern of the existing TS0002_basic / TS0002_limited variants (all 2-gang today):

{
    fingerprint: tuya.fingerprint("TS0002", ["_TZ3218_sfjr4fnz"]),
    model: "EREL-16ZB",
    vendor: "ENGO",
    description: "ZigBee smart relay 1x16A",
    extend: [
        tuya.modernExtend.tuyaBase(),
        tuya.modernExtend.tuyaOnOff({
            switchType: true,
            powerOnBehavior2: true,
            backlightModeOffOn: true,
            indicatorMode: true,
            onOffCountdown: true,
            inchingSwitch: true,
        }),
        tuya.clusters.addTuyaCommonPrivateCluster(),
    ],
    configure: async (device, coordinatorEndpoint) => {
        await tuya.configureMagicPacket(device, coordinatorEndpoint);
        await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ["genOnOff"]);
    },
}

The feature set matches what the hardware actually has on endpoint 1: tuyaBacklightMode and moesStartUpOnOff in genOnOff, powerOnBehavior / switchType in manuSpecificTuya3 (0xE001), with both 0xE000 and 0xE001 in the input cluster list. Not tested yet - happy to run it as an external converter and report back.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/devices/tuya.ts, comparing the existing TS0002, TS0002_basic, and TS0002_limited definitions. Check the reported fingerprint and endpoint list, then validate the candidate definition with an external converter or the ENGO device. Done means configure succeeds for endpoint 1 and no l2 exposes are produced.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
embedded-iot
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.