[Release] Tuya WiFi Access Control Keypad Driver — Local Control with Unlock Method & User Detection

What Is This Driver?

This driver provides full local control of Tuya-compatible WiFi access control keypads (TFLCD category) directly from Hubitat — no cloud required after initial setup.

These are the keypad/access control units you'll find on Amazon and AliExpress that connect via WiFi to the SmartLife or Tuya app and support multiple unlock methods: app remote unlock, PIN code, RFID card, and/or fingerprint. They're commonly used on doors, gates, and secondary entry points.


Why Do You Need This Driver?

Tuya cloud integration requires internet connectivity and is inherently slower as commands travel to the Tuya server and back to the Hubitat hub. The built-in Tuya Integration (beta) on Hubitat discovers these devices but maps them as a generic switch — you get on/off control only. You do not have all the rich access control data: who unlocked, what method they used, device configuration, and real-time event detection.

This driver gives you:

  • :white_check_mark: Unlock method detection — fingerprint, RFID card, PIN code, or app remote
  • :white_check_mark: User slot identification — know which credential was used (e.g. slot 1 = User1 fingerprint, slot 2 = guest RFID, etc.)
  • :white_check_mark: Real-time events — persistent TCP connection means unlock events arrive instantly, not on a poll cycle
  • :white_check_mark: Device configuration — read and change volume, language, unlock mode, auto lock time directly from Hubitat
  • :white_check_mark: Auto-reconnect — driver recovers automatically from dropped connections
  • :white_check_mark: Connection watchdog — detects and recovers from hung connection attempts automatically
  • :white_check_mark: Doorbell detection — if your device has a doorbell button wired to a WiFi DP
  • :white_check_mark: Rule Machine integration — trigger automations based on who unlocked and how

Confirmed Compatible Devices

This driver has been developed and tested against a TFLCD model Tuya WiFi access control keypad with LCD screen. Other Tuya WiFi keypads in the same category should work, but DP numbers may vary by firmware. If you find differences, please post in this thread. Debug logs will be required through PM.


Setup Instructions

Step 1 — Physical Installation

Install the keypad and connect it to power per the manufacturer's instructions, usually 12-24V DC to the red (+) and black (-) wires.

Step 2 — Connect to WiFi via App

  1. Download the SmartLife or Tuya Smart app
  2. Create or log into an existing account and add the device following the in-app pairing instructions
  3. Verify the device works in the app before proceeding

Step 3 — Set a Static IP Address

This is critical. The driver connects to the device by IP address, and if the IP changes (e.g. after a reboot) the driver will lose connection.

In your router, create a DHCP reservation for the keypad's MAC address. The MAC address can usually be found in your router's DHCP client list once the device is connected. Assign it a fixed IP outside your DHCP pool (e.g. 192.168.1.150).

Step 4 — Get the Device ID and Local Key

You need two pieces of information from the Tuya cloud:

Option A — Tuya IoT Platform

  1. Go to iot.tuya.com and create a free developer account
  2. Create a Cloud Project and link your SmartLife account to it
  3. In your project, go to Devices and find your keypad
  4. Note the Device ID and Local Key

Option B — via Hubitat's Built-in Tuya Integration
The built-in Tuya Integration (beta) can also retrieve these values during device discovery (see Step 5).

Step 5 — Add via Hubitat's Tuya Integration (beta)

  1. In Hubitat, go to Apps → Add Built-in App → Tuya Integration (beta)
  2. Configure it with your Tuya/SmartLife credentials
  3. Run Scan LAN for Devices — your keypad should appear
  4. Let it create the device (it will appear as a switch — that's expected)

Step 6 — Install This Driver

  1. In Hubitat, go to Drivers Code → New Driver
  2. Click Import and paste this URL:
    https://raw.githubusercontent.com/neeravmodi/Hubitat/refs/heads/main/Drivers/tuya-access-control-keypad.groovy
  3. Click Import then Save

Step 7 — Switch the Device to This Driver

  1. Go to Devices and open your keypad device
  2. In the Type dropdown, select the Tuya Access Control Keypad driver
  3. Click Save Device

Step 8 — Configure the Driver

Enter the following in the device preferences and click Save Preferences:

Preference Value
Device IP Address The static IP you assigned in Step 3
Device ID From the Tuya IoT Platform or Tuya Integration
Device Local Key From the Tuya IoT Platform or Tuya Integration

Step 9 — Initialize

Click the Initialize button on the device page. The connectionStatus attribute should change to connected within a few seconds.


Preferences Reference

Preference Default Description
Device IP Address Local IP of the keypad (must be static)
Device ID Tuya device identifier
Device Local Key AES encryption key for local communication
Hubitat remote unlock relock delay 5s How long before Hubitat re-locks after an unlockDoor command. Note: physical unlocks use the device's own auto lock timer (DP 31)
Relay DP number 40 The DP that controls the relay. Confirmed 40 for TFLCD devices
Doorbell DP number 0 Set to the DP number for doorbell if your device supports it (0 = auto-detect)
Heartbeat interval 25s How often the driver sends a status request to keep the connection alive. Do not exceed 31 seconds — device TCP idle timeout is 32 seconds
Reconnect delay 3s How long to wait before reconnecting after a dropped connection
Enable debug logging Off Enables verbose logging. Auto-disables after 30 minutes

Commands Reference

Command Parameters Description
unlockDoor Triggers the relay to open the door from Hubitat
connectSocket Manually open the TCP connection
disconnectSocket Manually close the TCP connection
setVolume mute / low / middle / high Set the keypad speaker volume
setLanguage english / chinese_simplified Set the keypad voice language
setAutomaticLock true / false Enable or disable auto-lock after opening
setRelayOpenTime 1–99 (seconds) How long the relay stays open before auto-locking
setUnlockMode see below Set which unlock methods are accepted

Unlock Mode Values:

Value SmartLife Label
single_unlock Disability (no verification required)
finger_password Unlock by code
finger_card Unlock by card
finger_face Unlock by card/fingerprint + code
password_card Unlock by card or fingerprint or code
password_face Unlock by fingerprint

Attributes Reference

Attribute Description
lock Current lock state: locked / unlocked
unlockMethod How the door was last unlocked: fingerprint, card, password, remote
unlockUserId The credential slot number used (e.g. slot 1 = User1's fingerprint)
lastUnlockInfo Human-readable summary: "Fingerprint - User slot 1"
lastUnlockTimestamp Timestamp of last unlock event — always changes, use this as the Rule Machine trigger
lastHeartbeat Timestamp of last successful device response — confirms connection is alive
alarmStatus Access alarm events (wrong finger, wrong card, tamper, etc.)
doorbell pushed / idle — if your device has a doorbell button
connectionStatus connected / disconnected / connecting
unlockMode Current unlock mode setting (DP 25)
volume Current volume setting (DP 26)
language Current language setting (DP 27)
automaticLock Whether auto-lock is enabled (DP 30)
autoLockTime Auto-lock time in seconds (DP 31)
failedAttempts Number of failed access attempts since last reboot (DP 34)

Using Unlock Events in Rule Machine

The driver doesn't know your users' names — it reports slot numbers. You map slot numbers to names in Rule Machine.

To find a user's slot number, have them unlock the door once with debug logging enabled and look for the ACCESS GRANTED line in the Hubitat log. Alternately, when adding a user/method to a keypad with a screen, note the slot number displayed.

Recommended Rule Structure

This structure ensures the rule fires reliably on every unlock — even when the same user unlocks with the same method consecutively.

Variables to create:

  • unlockUserID — Number
  • accessMethod — String
  • userName — String
  • unlockMethod — String
  • accessMessage — String

Trigger:

  • Attribute — your keypad device — lastUnlockTimestamp — changes

Actions:

1 — Capture current values into variables

Set unlockUserID = keypad unlockUserId
Set accessMethod = keypad unlockMethod

2 — Ignore app remote unlocks

IF accessMethod = 'remote'
    Log: "App remote unlock attempted — ignored (use smart home controls)"
    Notify: "App remote unlock attempted — ignored"
    Exit Rule
END-IF

3 — Resolve user name from slot number

IF unlockUserID = [User1 slots]
    Set userName = 'User1'
ELSE IF unlockUserID = [User2 slots]
    Set userName = 'User2'
ELSE
    Set userName = 'Unknown User (slot %unlockUserID%)'
END-IF

4 — Resolve unlock method label

IF accessMethod = 'fingerprint'
    Set unlockMethod = 'Fingerprint'
ELSE IF accessMethod = 'password'
    Set unlockMethod = 'PIN'
ELSE IF accessMethod = 'card'
    Set unlockMethod = 'Keyfob'
ELSE
    Set unlockMethod = 'Unknown method'
END-IF

5 — Build message, trigger door, notify

Set accessMessage = '%userName% unlocked the garage door (%unlockMethod%)'
Open: [your garage door device]
Notify: '%accessMessage%'
Log: '%accessMessage%'

Maintenance: Adding a new user requires only one new ELSE IF block in step 3. Everything else stays the same.


Known Limitations

  • Doorbell button — on most TFLCD devices the doorbell button triggers a physical Wiegand output only and does not send a WiFi DP event. Detection via this driver may not work depending on firmware. Connect the doorbell wire (probably pink) along with a wire to ground (black) to a dry contact sensor.
  • Cloud-only settings — the following SmartLife settings are stored in Tuya's cloud and cannot be read or changed via local protocol: Remote unlock setting, Permission settings, Alarm time, Multiple verification mode.
  • User names — the driver reports slot numbers, not names. Name mapping must be done in Rule Machine or another Hubitat app.
  • Device reboot — no confirmed local DP for rebooting the device remotely.
  • Single connection — Tuya devices only allow one local TCP connection at a time. If another integration also connects to the device, it will drop this driver's connection. The driver will auto-reconnect within 3 seconds. However, the competing integration will continue to cause dropped connections. Ensure there are no other integrations. An open App should not cause problems.
  • Periodic disconnects — the device firmware maintains its own connection to the Tuya cloud. This can occasionally cause brief disconnects of the local connection. The driver recovers automatically within 3 seconds.

Troubleshooting

connectionStatus shows "disconnected" and keeps reconnecting

  • Verify the IP address is correct and the device is online
  • Check that the Local Key is correct — an incorrect key causes decrypt failures
  • Ensure no other integration (cloud driver) is actively connected to the device simultaneously
  • Brief periodic disconnects are normal — the device's own firmware connects to the Tuya cloud occasionally and may briefly interrupt the local connection. The driver recovers automatically.

connectionStatus stuck on "connecting"

  • The driver includes a 30-second connection watchdog — if stuck in connecting for 30 seconds it will automatically retry
  • If it persists, click Initialize on the device page to force a fresh connection attempt

ACCESS GRANTED fires but wrong method shown

  • The DP map is confirmed for TFLCD devices — if you're seeing wrong methods, your device firmware may use different DP numbers. Enable debug logging, unlock the door, and look for Unknown DP XX = ... entries. Post your findings in this thread.

Rule Machine rule doesn't fire on consecutive unlocks by the same user

  • Make sure you are triggering on lastUnlockTimestamp — not lastUnlockInfo. The timestamp always changes on every unlock event.

Settings commands (setVolume, etc.) don't seem to work

  • Some settings may require a device reboot to take effect
  • Verify the device is connected (connectionStatus = connected) before sending commands

GitHub: Hubitat/Drivers/tuya-access-control-keypad.groovy at main · neeravmodi/Hubitat · GitHub
Import URL: https://raw.githubusercontent.com/neeravmodi/Hubitat/refs/heads/main/Drivers/tuya-access-control-keypad.groovy


Changelog

  • v1.1 — Connection reliability improvements: heartbeat keepalive (25s default, max 31s), connection watchdog for hung connect() calls, improved error logging, added lastHeartbeat and lastUnlockTimestamp attributes.
  • v1.0 — Initial public release.

Credits & License

  • Driver by Neerav Modi
  • Developed with the assistance of Claude.ai (Anthropic)
  • Based on the Tuya Generic Device driver pattern by iholand
  • Licensed under the Apache License 2.0
  • Full development history and source: GitHub

Feedback, bug reports, and pull requests welcome!

3 Likes

(reserved)

Thanks... Another thing I now want but don't need. :rofl:

2 Likes

Totally understand. I have a few devices I've inherited which are looking for some way to use them. There are also devices on the market that I keep eying for which I have absolutely no need!

1 Like

v1.1 Released

I've pushed v1.1 to GitHub. You can update by re-importing using the import URL in the first post.

What's new in v1.1:

  • Connection watchdog — the driver can get stuck in "connecting" state if the device is unreachable at the exact moment of a connection attempt. The watchdog detects this after 30 seconds and forces a retry automatically. No more manually clicking Initialize.

  • Heartbeat keepalive — through live testing, confirmed that the device's TCP idle timeout is exactly 32 seconds. The driver now sends a status request every 25 seconds (configurable, max 31s) to keep the connection alive and detect stale connections after a device power loss.

  • Improved error logging — unexpected disconnects and unknown device error codes are now logged at error level so they're always visible without debug logging enabled. Known/expected responses are logged at debug level only.

  • lastHeartbeat attribute — updates with a timestamp on every successful device response. Glance at the device page to confirm the connection is alive without enabling debug logging.

  • lastUnlockTimestamp attribute — updates with the current timestamp on every unlock event. Important for Rule Machine users: use this attribute as your trigger instead of lastUnlockInfo. This ensures your rule fires every time, even when the same user unlocks with the same method consecutively. lastUnlockInfo would not change in that scenario and your rule would not fire.

I've also updated the first post with revised Rule Machine instructions reflecting the improved rule structure — worth a read if you've already built a rule based on the original instructions.

As always, feedback and reports welcome. If you see any error level log entries with frame hex, please post them or send via PM so I can investigate.