### Complete Fingerprint Authentication Application Example Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt A comprehensive C# example demonstrating a full fingerprint enrollment and verification workflow. It utilizes `SourceAFIS` for template matching and `ZkTecoFingerPrint` for device interaction, including proper resource management via `IDisposable`. ```csharp using System.Reactive.Linq; using SourceAFIS; using ZkTecoFingerPrint; public class FingerprintAuthenticationService : IDisposable { private IDisposable? _subscription; private readonly Dictionary _enrolledUsers = new(); public void Start() { var initResult = ZkTecoFingerHost.Initialize(); if (!initResult.IsSuccess) { throw new InvalidOperationException($"Failed to initialize: {initResult.Response}"); } var deviceCount = ZkTecoFingerHost.GetDeviceCount(); if (deviceCount == 0) { throw new InvalidOperationException("No fingerprint device found"); } Console.WriteLine($"Starting fingerprint service with {deviceCount} device(s)"); _subscription = ZkTecoFingerHost.ObserveDevice(0, pollingDelayMs: 50) .Where(r => r.IsSuccess) .Select(r => r.Value!) .Subscribe(OnFingerprintCaptured); } public void EnrollUser(string userId, ZkFingerPrintResult fingerprint) { _enrolledUsers[userId] = fingerprint.Template; Console.WriteLine($"User {userId} enrolled with template hash: {fingerprint.TemplateHash}"); } private void OnFingerprintCaptured(ZkFingerPrintResult fingerprint) { // Try to identify user var match = _enrolledUsers .Select(kvp => (UserId: kvp.Key, Score: fingerprint.Match(kvp.Value))) .Where(x => x.Score >= 50) .OrderByDescending(x => x.Score) .FirstOrDefault(); if (match.UserId != null) { Console.WriteLine($"Authenticated: {match.UserId} (score: {match.Score:F2})"); OnUserAuthenticated?.Invoke(match.UserId); } else { Console.WriteLine("Fingerprint not recognized"); OnAuthenticationFailed?.Invoke(); } } public event Action? OnUserAuthenticated; public event Action? OnAuthenticationFailed; public void Dispose() { _subscription?.Dispose(); ZkTecoFingerHost.Close(); } } // Usage using var authService = new FingerprintAuthenticationService(); authService.OnUserAuthenticated += userId => Console.WriteLine($"Welcome, {userId}!"); authService.OnAuthenticationFailed += () => Console.WriteLine("Access denied"); authService.Start(); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); ``` -------------------------------- ### Installation Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Install the ZkTecoFingerPrint NuGet package using the .NET CLI. ```APIDOC ## Installation Install the ZkTecoFingerPrint NuGet package using the .NET CLI. ```bash dotnet add package ZkTecoFingerPrint ``` ``` -------------------------------- ### Install ZkTecoFingerPrint via NuGet Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Use the .NET CLI to add the library package to your project. ```powershell dotnet add package ZkTecoFingerPrint ``` -------------------------------- ### Handle ZkResponse Enumeration for Status Codes Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt The `ZkResponse` enum provides detailed status codes for library operations, essential for robust error handling and user feedback. This example demonstrates a switch statement to process different response types after initialization. ```csharp using ZkTecoFingerPrint; // Complete error handling example var initResult = ZkTecoFingerHost.Initialize(); switch (initResult.Response) { case ZkResponse.Ok: Console.WriteLine("Success"); break; case ZkResponse.AlreadyInit: Console.WriteLine("Library was already initialized"); break; case ZkResponse.InitLibrary: case ZkResponse.Init: Console.WriteLine("Failed to initialize - check DLL availability"); break; case ZkResponse.NoDevice: Console.WriteLine("No fingerprint device connected"); break; case ZkResponse.InvalidHandle: Console.WriteLine("Invalid device handle"); break; case ZkResponse.Busy: Console.WriteLine("Device is busy - try again"); break; case ZkResponse.Timeout: Console.WriteLine("Operation timed out"); break; case ZkResponse.NotEnoughMemory: Console.WriteLine("Insufficient memory"); break; case ZkResponse.NotInit: Console.WriteLine("Library not initialized - call Initialize() first"); break; case ZkResponse.AlreadyOpened: Console.WriteLine("Device already opened by another process"); break; default: Console.WriteLine($"Error: {initResult.Response}"); break; } ``` -------------------------------- ### Initialize and Query ZkTeco Devices Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Initialize the library and retrieve the count of connected fingerprint devices. ```csharp ZkTecoFingerHost.Initialize(); var deviceCount = ZkTecoFingerHost.GetDeviceCount(); ``` -------------------------------- ### ZkTecoFingerHost.Initialize Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Initializes the ZkTeco fingerprint library. This must be called before any other library operations. ```APIDOC ## ZkTecoFingerHost.Initialize Initializes the ZkTeco fingerprint library. This must be called before any other library operations. Returns a `ZkResult` containing the initialization status. ```csharp using ZkTecoFingerPrint; // Initialize the ZkTeco Library - required before any device operations var initResult = ZkTecoFingerHost.Initialize(); if (initResult.IsSuccess) { Console.WriteLine("ZkTeco library initialized successfully"); } else { Console.WriteLine($"Initialization failed: {initResult.Response}"); // Possible responses: InitLibrary, Init, NotEnoughMemory, AlreadyInit } ``` ``` -------------------------------- ### Device Management and Observation Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Methods to initialize the library, count connected devices, and observe fingerprint events reactively. ```APIDOC ## ZkTecoFingerHost Methods ### Description Initializes the library, detects connected hardware, and provides an observable stream for fingerprint data. ### Methods - **Initialize()**: Initializes the ZkTeco library. - **GetDeviceCount()**: Returns the number of connected ZkTeco devices. - **ObserveDevice(int deviceIndex)**: Returns an IObservable for real-time fingerprint capture. ### Parameters #### Path Parameters - **deviceIndex** (int) - Required - The index of the device to observe (0-based). ### Request Example ZkTecoFingerHost.Initialize(); var deviceCount = ZkTecoFingerHost.GetDeviceCount(); var deviceObservable = ZkTecoFingerHost.ObserveDevice(0); ``` -------------------------------- ### Initialize ZkTeco Library Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Initializes the ZkTeco fingerprint library. This method must be called before performing any other device operations to ensure the native DLLs are loaded correctly. ```csharp using ZkTecoFingerPrint; var initResult = ZkTecoFingerHost.Initialize(); if (initResult.IsSuccess) { Console.WriteLine("ZkTeco library initialized successfully"); } else { Console.WriteLine($"Initialization failed: {initResult.Response}"); } ``` -------------------------------- ### ZkTecoFingerHost.ObserveDevice (Reactive Fingerprint Monitoring) Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Creates a reactive observable that continuously monitors a device for fingerprint acquisitions. This is the recommended approach for real-time fingerprint capture. ```APIDOC ## ZkTecoFingerHost.ObserveDevice (Reactive Fingerprint Monitoring) Creates a reactive observable that continuously monitors a device for fingerprint acquisitions. This is the recommended approach for real-time fingerprint capture. The observable handles device opening/closing automatically and supports cancellation. ```csharp using System.Reactive.Linq; using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); // Create an observable that watches device 0 for fingerprints var subscription = ZkTecoFingerHost.ObserveDevice( deviceIndex: 0, pollingDelayMs: 100, // Delay between acquisition attempts releaseOnFailure: false) // Re-initialize on failure .Where(result => result.IsSuccess) .Select(result => result.Value!) .Do(fingerprint => { // Process each captured fingerprint Console.WriteLine($"Fingerprint captured from: {fingerprint.DeviceInfo?.Name}"); Console.WriteLine($"Template hash: {fingerprint.TemplateHash}"); // Save the bitmap image File.WriteAllBytes( $"fingerprint_{DateTime.Now.ToFileTime()}.bmp", fingerprint.Bitmap); }) .Subscribe( onNext: _ => { }, onError: ex => Console.WriteLine($"Error: {ex.Message}"), onCompleted: () => Console.WriteLine("Monitoring stopped") ); Console.WriteLine("Press any key to stop monitoring..."); Console.ReadKey(); // Stop monitoring and cleanup subscription.Dispose(); ZkTecoFingerHost.Close(); ``` ``` -------------------------------- ### Identify User with Fingerprint using ZkTecofingerprint and SourceAFIS Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Identifies a user from a collection of enrolled candidates by comparing a captured fingerprint against multiple stored templates. Returns the matching user or null if no match is found above the specified threshold. Dependencies include ZkTecoFingerPrint and SourceAFIS. Input is a captured fingerprint and a list of users with templates; output is a User object or null. ```csharp using SourceAFIS; using ZkTecoFingerPrint; // Define a User class with fingerprint data public class User { public int Id { get; set; } public string Name { get; set; } public FingerprintTemplate FingerprintTemplate { get; set; } } // Retrieve all users with enrolled fingerprints from database List enrolledUsers = await database.GetAllUsersAsync(); ZkTecoFingerHost.Initialize(); var subscription = ZkTecoFingerHost.ObserveDevice(0) .Where(r => r.IsSuccess) .Select(r => r.Value!) .Subscribe(fingerprint => { // Identify user from the captured fingerprint User? matchedUser = fingerprint.Identify( candidates: enrolledUsers, templateSelector: user => user.FingerprintTemplate, threshold: 50.0 // Minimum similarity score required ); if (matchedUser != null) { Console.WriteLine($"User identified: {matchedUser.Name} (ID: {matchedUser.Id})"); // Log access, update attendance, grant permissions, etc. } else { Console.WriteLine("Unknown fingerprint - user not found in database"); // Prompt for manual authentication or deny access } }); Console.ReadKey(); subscription.Dispose(); ZkTecoFingerHost.Close(); ``` -------------------------------- ### Compare Fingerprint Template with ZkTecofingerprint and SourceAFIS Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Compares a captured fingerprint against a stored template using SourceAFIS for biometric comparison. Returns a similarity score, indicating the match quality. Dependencies include ZkTecoFingerPrint and SourceAFIS libraries. Input is a captured fingerprint and a stored FingerprintTemplate, output is a double similarity score. ```csharp using SourceAFIS; using ZkTecoFingerPrint; // Assume we have a stored template from a previous enrollment FingerprintTemplate storedTemplate = /* retrieved from database */; ZkTecoFingerHost.Initialize(); var subscription = ZkTecoFingerHost.ObserveDevice(0) .Where(r => r.IsSuccess) .Select(r => r.Value!) .Subscribe(fingerprint => { // Compare captured fingerprint against stored template double similarityScore = fingerprint.Match(storedTemplate); // Typical threshold values: 40-60 depending on security requirements const double threshold = 50.0; if (similarityScore >= threshold) { Console.WriteLine($"MATCH! Similarity: {similarityScore:F2}"); // Grant access, authenticate user, etc. } else { Console.WriteLine($"No match. Similarity: {similarityScore:F2}"); // Deny access, request retry, etc. } }); Console.ReadKey(); subscription.Dispose(); ZkTecoFingerHost.Close(); ``` -------------------------------- ### Observe Fingerprint Device Events Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Use an observable pattern to monitor a device for fingerprint events, capturing bitmaps and templates. ```csharp var deviceObservable = ZkTecoFingerHost.ObserveDevice(deviceIndex: 0) .Where(deviceResult => deviceResult.IsSuccess) .Select(deviceResult => deviceResult.Value) .Do(fingerPrintResult => { var bitmapImage = fingerPrintResult.Bitmap; var fingerPrintTemplate = fingerPrintResult.Template; }) .Subscribe(); ``` -------------------------------- ### Manage Device Lifecycle Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Properly dispose of the observable and close the device connection to release resources. ```csharp deviceObservable.Dispose(); ZkTecoFingerHost.Close(); ``` -------------------------------- ### ZkTecoFingerHost.GetDeviceCount Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Returns the number of ZkTeco fingerprint devices currently connected to the system. Call this after initialization to discover available devices. ```APIDOC ## ZkTecoFingerHost.GetDeviceCount Returns the number of ZkTeco fingerprint devices currently connected to the system. Call this after initialization to discover available devices. ```csharp using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); int deviceCount = ZkTecoFingerHost.GetDeviceCount(); if (deviceCount > 0) { Console.WriteLine($"Found {deviceCount} ZkTeco device(s)"); // Device indices are 0-based: 0, 1, 2, ... (deviceCount - 1) } else { Console.WriteLine("No ZkTeco devices found. Please connect a device."); } ``` ``` -------------------------------- ### ZkTecoFingerHost.OpenDevice Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Opens a specific fingerprint device by index. Returns a `ZkDeviceResult` containing the device handle with information like serial number, device name, and capture dimensions. ```APIDOC ## ZkTecoFingerHost.OpenDevice Opens a specific fingerprint device by index. Returns a `ZkDeviceResult` containing the device handle with information like serial number, device name, and capture dimensions. Note: An opened device is exclusive to the application and cannot be used elsewhere until closed. ```csharp using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); var deviceCount = ZkTecoFingerHost.GetDeviceCount(); if (deviceCount > 0) { // Open the first device (index 0) using var deviceResult = ZkTecoFingerHost.OpenDevice(0); if (deviceResult.IsSuccess) { var device = deviceResult.Value; Console.WriteLine($"Device opened: {device.Name}"); Console.WriteLine($"Serial Number: {device.SerialNumber}"); Console.WriteLine($"Image dimensions: {device.Width}x{device.Height} @ {device.Dpi} DPI"); // Device is automatically closed when disposed } else { Console.WriteLine($"Failed to open device: {deviceResult.Response}"); // Possible responses: InvalidHandle, Open, NotInit, AlreadyOpened } } ``` ``` -------------------------------- ### Acquire Fingerprint Asynchronously with ZkTecofingerprint Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Asynchronously acquires a single fingerprint from an opened ZkTecofingerprint device. It returns a ZkResult containing fingerprint bitmap and template data, suitable for manual polling. Dependencies include the ZkTecoFingerPrint library. Input is a CancellationToken, and output is a ZkFingerPrintResult. ```csharp using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); if (ZkTecoFingerHost.GetDeviceCount() > 0) { using var deviceResult = ZkTecoFingerHost.OpenDevice(0); if (deviceResult.IsSuccess) { var device = deviceResult.Value!; Console.WriteLine("Place your finger on the scanner..."); // Continuous polling loop while (true) { using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); var fingerprintResult = await device.AcquireFingerprintAsync(cts.Token); if (fingerprintResult.IsSuccess) { var fingerprint = fingerprintResult.Value!; Console.WriteLine("Fingerprint acquired successfully!"); Console.WriteLine($"Template hash: {fingerprint.TemplateHash}"); // Access fingerprint data byte[] bitmapData = fingerprint.Bitmap; // BMP image bytes var template = fingerprint.Template; // SourceAFIS template break; // Exit after successful capture } else if (fingerprintResult.Response == ZkResponse.Timeout) { Console.WriteLine("Timeout - please try again"); } await Task.Delay(100); // Small delay between attempts } } } ZkTecoFingerHost.Close(); ``` -------------------------------- ### Open ZkTeco Fingerprint Device Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Opens a specific fingerprint device by its index. Returns a device handle containing metadata like serial number and capture dimensions. ```csharp using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); using var deviceResult = ZkTecoFingerHost.OpenDevice(0); if (deviceResult.IsSuccess) { var device = deviceResult.Value; Console.WriteLine($"Device opened: {device.Name}"); } ``` -------------------------------- ### Compare and Identify Fingerprints Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Match a captured fingerprint template against another template or identify a user from a collection of candidates. ```csharp var similarityRatio = fingerPrintResult.Match(template: anotherTemplate); var matchedUser = fingerPrintResult.Identify(candidates: users, templateSelector: user => user.ingerPrintTemplate, threshold: 50); ``` -------------------------------- ### Observe Fingerprint Events Reactively Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Uses System.Reactive to monitor a device for fingerprint captures in real-time. It handles polling and provides an observable stream of captured fingerprint data. ```csharp using System.Reactive.Linq; using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); var subscription = ZkTecoFingerHost.ObserveDevice(0, 100, false) .Where(result => result.IsSuccess) .Subscribe(result => { Console.WriteLine($"Fingerprint captured: {result.Value.TemplateHash}"); }); // Cleanup subscription.Dispose(); ZkTecoFingerHost.Close(); ``` -------------------------------- ### Discover Connected ZkTeco Devices Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Retrieves the count of connected ZkTeco fingerprint readers. This should be called after initialization to verify hardware availability. ```csharp using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); int deviceCount = ZkTecoFingerHost.GetDeviceCount(); if (deviceCount > 0) { Console.WriteLine($"Found {deviceCount} ZkTeco device(s)"); } else { Console.WriteLine("No ZkTeco devices found. Please connect a device."); } ``` -------------------------------- ### Manual Fingerprint Polling Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Manually open a device and poll for fingerprints using an asynchronous loop. ```csharp ZkTecoFingerHost.Initialize(); var deviceCount = ZkTecoFingerHost.GetDeviceCount(); if (deviceCount > 0) { var deviceResult = ZkTecoFingerHost.OpenDevice(0); if (deviceResult.IsSuccess) { while (true) { var fingerprintResult = await AcquireFingerprintAsync(); if (fingerprintResult.IsSuccess) { var fingerprint = fingerprintResult.Value; } } } } ``` -------------------------------- ### Close ZkTeco Fingerprint Library Source: https://context7.com/rainxh11/zktecofingerprint/llms.txt Terminates the ZkTeco library and releases all resources. This method should be called when fingerprint operations are complete. It also triggers the `OnClosing` event for automatic disposal of device handles. ```csharp using ZkTecoFingerPrint; ZkTecoFingerHost.Initialize(); // ... perform fingerprint operations ... // Clean up when done var closeResponse = ZkTecoFingerHost.Close(); if (closeResponse == ZkResponse.Ok) { Console.WriteLine("Library closed successfully"); } else { Console.WriteLine($"Close failed: {closeResponse}"); } ``` -------------------------------- ### Fingerprint Matching and Identification Source: https://github.com/rainxh11/zktecofingerprint/blob/master/README.md Methods for comparing captured fingerprint templates against stored templates or identifying users from a database. ```APIDOC ## Fingerprint Match/Identify ### Description Compares a captured fingerprint template against a reference template or a collection of user objects. ### Methods - **Match(byte[] template)**: Compares the current result against a provided template. - **Identify(IEnumerable candidates, Func templateSelector, int threshold)**: Identifies a user from a list based on a similarity threshold. ### Parameters #### Request Body - **template** (byte[]) - Required - The template to compare against. - **candidates** (IEnumerable) - Required - List of objects containing templates. - **threshold** (int) - Required - Minimum similarity score (0-100). ### Response #### Success Response (200) - **similarityRatio** (int) - The calculated match score. - **matchedUser** (object) - The user object matching the criteria. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.