zkteco
A pure-Rust, synchronous client for ZKTeco biometric attendance and
access-control terminals — the fingerprint / RFID / face devices that speak the
ZK TCP/UDP protocol on port 4370.
This crate is a faithful port of the well-known Python library
pyzk. If you have used pyzk, the API will
feel familiar.
Features
- Connect & authenticate (with the scrambled comm-key when a device password is set)
- TCP (default) and UDP transports; auto-detects the 28-byte "ZK6" and 72-byte "ZK8" user record layouts
- Users: list, create/update, delete, clear all data
- Attendance: download all records, clear records
- Fingerprint templates: list, fetch one, save (single & bulk high-rate), delete, enroll
- Live capture: stream punches in real time as an iterator
- Device info: firmware, serial, platform, MAC, name, fingerprint/face versions, network params, capacities
- Device control: get/set time, restart, power off, refresh, free buffer, unlock door, lock state, test voice, write/clear LCD
- Only one dependency (
chrono);#![forbid(unsafe_code)]
Install
Quick start
use Zk;
Configuration (builder)
use Duration;
use Zk;
let zk = builder
.port // default 4370
.password // device comm password (default 0 = none)
.timeout// socket read timeout (default 60s)
.force_udp // default false (TCP)
.omit_ping // skip ICMP ping probe (useful when ICMP is blocked)
.verbose // print protocol diagnostics to stderr
.build;
Usage
Device info & capacities
# use Zk;
#
Create & delete a user
# use ;
#
Fingerprint templates
# use Zk;
#
Live capture
use Duration;
use Zk;
#
Device control
# use Local;
# use Zk;
#
Using from async code (tokio, etc.)
Every method blocks. From an async runtime, run the work on a blocking task:
# use ;
# async
Error handling
All fallible calls return ZkResult<T>
= Result<T, ZkError>. ZkError distinguishes NotConnected, Unauthenticated,
Response (device returned a failure code), NotSupported, Network (socket/timeout),
and Parse (malformed reply). It implements std::error::Error, so it works with
?, anyhow, thiserror, etc.
Encoding
User names and passwords are encoded/decoded as UTF-8 (lossy). Legacy code-page encodings (e.g. GBK) are intentionally not supported to keep the crate dependency-light.
Timestamps
ZK devices have no timezone concept; times are returned as
chrono::NaiveDateTime in the device's local time.
Troubleshooting
- Can't connect / hangs on connect: many networks block ICMP. Pass
.omit_ping(true)so the crate skips the ping reachability probe. - Timeouts: increase
.timeout(...). Large attendance/template downloads can take a while. - Wrong/garbled user names: check the device's character encoding — only UTF-8 is supported here.
Unauthenticated: set the correct device communication password with.password(...).- UDP-only devices: pass
.force_udp(true).
Compatibility
Tested in spirit against the same device families pyzk targets (ZK6/ZK8 firmware
generations) over both TCP and UDP. Behavior is a direct translation of pyzk's
proven protocol handling. If you hit a device quirk that pyzk handles
differently, please open an issue.
Acknowledgements
This is a port of pyzk by Fanani M. Ihsan
and contributors. All protocol knowledge is derived from that project.
License
Licensed under the GNU General Public License v2.0 or later
(GPL-2.0-or-later). Because this is a derivative of the GPL-licensed pyzk, the
port inherits the same license. See LICENSE.