1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! # zkteco
//!
//! A pure-Rust, synchronous client for **ZKTeco** biometric attendance and
//! access-control terminals (fingerprint / RFID / face devices that speak the
//! ZK TCP/UDP protocol on port 4370).
//!
//! This crate is a faithful port of the Python library
//! [`pyzk`](https://github.com/fananimi/pyzk). It supports connecting and
//! authenticating, reading and writing users, reading attendance logs,
//! fingerprint templates, enrollment, live capture, and device control.
//!
//! ## Quick start
//!
//! ```no_run
//! use zkteco::Zk;
//!
//! fn main() -> zkteco::ZkResult<()> {
//! // Build and connect (TCP by default, port 4370).
//! let mut zk = Zk::builder("192.168.1.201").build();
//! zk.connect()?;
//!
//! // Best practice: disable the device during bulk reads, then re-enable.
//! zk.disable_device()?;
//! let users = zk.get_users()?;
//! let logs = zk.get_attendance()?;
//! zk.enable_device()?;
//!
//! println!("{} users, {} attendance records", users.len(), logs.len());
//! zk.disconnect()?;
//! Ok(())
//! }
//! ```
//!
//! ## Live capture
//!
//! [`Zk::live_capture`] returns an iterator of attendance punches as they
//! happen. Timeout "ticks" (`Ok(None)`) let you check a stop flag:
//!
//! ```no_run
//! use std::time::Duration;
//! use zkteco::Zk;
//!
//! # fn main() -> zkteco::ZkResult<()> {
//! let mut zk = Zk::builder("192.168.1.201").build();
//! zk.connect()?;
//! let mut capture = zk.live_capture(Duration::from_secs(10))?;
//! let stop = capture.stop_handle();
//! for event in &mut capture {
//! match event? {
//! Some(att) => println!("punch: {att}"),
//! None => { /* timeout tick — poll your own stop condition here */ }
//! }
//! # stop.store(true, std::sync::atomic::Ordering::SeqCst);
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Using from async code
//!
//! All calls block. Inside an async runtime, run them on a blocking thread, e.g.
//! `tokio::task::spawn_blocking(move || { zk.connect()?; zk.get_users() })`.
//!
//! ## Compatibility & notes
//!
//! - Works over **TCP** (default) and **UDP** (`force_udp`). The newer 72-byte
//! ("ZK8") and older 28-byte ("ZK6") user record layouts are auto-detected.
//! - Strings are encoded/decoded as **UTF-8** (lossy). Legacy code pages are not
//! supported, keeping the dependency footprint to just `chrono`.
//! - Timestamps are returned as [`chrono::NaiveDateTime`] in the device's local
//! time (the device has no timezone concept).
pub use Attendance;
pub use ;
pub use ;
pub use Finger;
pub use ZkHelper;
pub use ;