-- Tuya smart lock (_TYST12_ie5b1vhe / TY0A01) -- Tuya EF00 DP protocol. -- -- DRAFT (option B). The device speaks only the Tuya manufacturer-specific -- cluster 0xEF00 (endpoints in:[0,10,4,5,61184]); it has no standard ZCL -- Door Lock cluster (0x0101), so the builtin `door_lock` converter cannot be -- used. Data flows as EF00 datapoints instead. -- -- The DP numbers below are GUESSES based on Tuya's standard smart-lock -- (category "ms") DPID set. This exact fingerprint is NOT in zigbee2mqtt, so -- nothing here is authoritative yet. -- -- HOW TO CALIBRATE --------------------------------------------------------- -- As soon as this converter loads (tuyaDatapoints non-empty), the gateway logs -- EVERY incoming EF00 datapoint at INF level, even ones not mapped below: -- Tuya DP rx: device=0x403059fffe6177be dp=.. type=0x.. len=.. data=.. -- Operate the lock (unlock by fingerprint / password / card / mechanical key, -- trigger a low-battery / tamper alarm, let it report battery) and match the -- observed dp/type/data to the entries below, then correct them. local device = {} device.model = "TY0A01" device.vendor = "Tuya" device.description = "Smart lock (EF00 DP) [draft]" device.zigbeeModel = {} device.fingerprint = { { model = "TY0A01", manufacturer = "_TYST12_ie5b1vhe" }, } device.exposes = { { type = "lock", features = { -- Most low-cost Tuya Zigbee locks are report-only and cannot be locked -- remotely. Keep `state` read-only (access = 1) until a writable -- lock/unlock DP is confirmed from the logs; bump to 7 if it works. { type = "binary", name = "state", property = "state", access = 1, value_on = "LOCK", value_off = "UNLOCK" }, }}, { type = "numeric", name = "battery", property = "battery", access = 1, unit = "%", min = 0, max = 100 }, } device.tuyaDatapoints = { -- === UNVERIFIED: confirm every dp / converter against "Tuya DP rx" logs === { dp = 15, name = "battery", converter = "raw" }, -- residual_electricity % { dp = 12, name = "alarm_raw", converter = "raw" }, -- alarm_lock enum (decode later) { dp = 1, name = "unlock_fingerprint", converter = "raw" }, -- member id { dp = 2, name = "unlock_password", converter = "raw" }, { dp = 5, name = "unlock_card", converter = "raw" }, { dp = 6, name = "unlock_key", converter = "raw" }, -- Candidate lock/unlock state DP — number unknown, mapping left disabled so -- it can't publish a wrong state. Uncomment and set the real dp once the -- logs reveal it (then also raise the `state` expose access to 7): -- { dp = ??, name = "state", converter = "lockUnlock", access = "rw" }, } return device