using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Management;
using System.Text.RegularExpressions;
using System.Threading;
using libzkfpcsharp;
using Newtonsoft.Json.Linq;
using Sample;
namespace FingerprintScanner
{
public class FingerprintCaptureManager
{
public delegate void FingerprintCapturedHandler(string jsonData);
public event FingerprintCapturedHandler OnFingerprintCaptured;
private IntPtr _deviceHandle = IntPtr.Zero;
private byte[] _fpBuffer;
private byte[] _templateBuffer = new byte[2048];
private int _width = 0;
private int _height = 0;
private int _dpi = 0;
private string _deviceId = "";
private string _deviceStatus = "INACTIVE";
private Thread _captureThread;
private volatile bool _isCapturing = false;
private const string TargetVid = "1B55";
public void SetDeviceInfo(string deviceId, string deviceStatus)
{
_deviceId = deviceId;
_deviceStatus = deviceStatus;
Console.WriteLine($"[Info] Device info set: ID={_deviceId}, Status={_deviceStatus}");
}
///
/// Detect and return the serial number of the first connected USB device with VID=1B55
///
public string DetectDeviceByVid()
{
Console.WriteLine($"[Info] Detecting USB devices with VID={TargetVid}...");
var devices = GetConnectedUSBDevices();
foreach (var dev in devices)
{
int lastIndex = dev.DeviceID.LastIndexOf('\\');
string serialNumber = lastIndex >= 0 ? dev.DeviceID.Substring(lastIndex + 1) : "";
string vid = GetMatch(dev.DeviceID, @"VID_(\w{4})");
Console.WriteLine($"[Debug] Device found - VID: {vid}, Serial: {serialNumber}");
if (vid.Equals(TargetVid, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[Info] Matching device detected: Serial={serialNumber}");
return serialNumber;
}
}
Console.WriteLine("[Warning] No matching USB device with target VID found.");
return "";
}
///
/// Start fingerprint capture on the detected device with VID=1B55
///
public void Start()
{
if (_isCapturing)
{
Console.WriteLine("[Warning] Capture already running.");
return;
}
string detectedSerial = DetectDeviceByVid();
if (string.IsNullOrEmpty(detectedSerial))
{
Console.WriteLine("[Error] No target USB device detected, aborting capture start.");
return;
}
Console.WriteLine("[Info] Initializing zkfp2 SDK...");
int ret = zkfp2.Init();
if (ret != zkfperrdef.ZKFP_ERR_OK)
{
Console.WriteLine($"[Error] zkfp2.Init failed with code: {ret}");
return;
}
int deviceCount = zkfp2.GetDeviceCount();
Console.WriteLine($"[Info] SDK reports {deviceCount} fingerprint device(s) connected.");
if (deviceCount == 0)
{
Console.WriteLine("[Error] No fingerprint devices detected by SDK.");
zkfp2.Terminate();
return;
}
// Open device only at index 0 (matching old working code behavior)
Console.WriteLine($"[Info] Trying to open device at index 0...");
_deviceHandle = zkfp2.OpenDevice(0);
if (_deviceHandle == IntPtr.Zero)
{
Console.WriteLine("[Error] Failed to open device at index 0.");
zkfp2.Terminate();
return;
}
Console.WriteLine("[Info] Opened device at index 0.");
// Get device parameters
byte[] paramValue = new byte[4];
int size = 4;
zkfp2.GetParameters(_deviceHandle, 1, paramValue, ref size);
zkfp2.ByteArray2Int(paramValue, ref _width);
Console.WriteLine($"[Info] Device width: {_width}");
size = 4;
zkfp2.GetParameters(_deviceHandle, 2, paramValue, ref size);
zkfp2.ByteArray2Int(paramValue, ref _height);
Console.WriteLine($"[Info] Device height: {_height}");
size = 4;
zkfp2.GetParameters(_deviceHandle, 3, paramValue, ref size);
zkfp2.ByteArray2Int(paramValue, ref _dpi);
Console.WriteLine($"[Info] Device DPI: {_dpi}");
_fpBuffer = new byte[_width * _height];
_deviceStatus = "ACTIVE";
_deviceId = detectedSerial;
_isCapturing = true;
_captureThread = new Thread(CaptureLoop)
{
IsBackground = true
};
_captureThread.Start();
Console.WriteLine($"[Info] Fingerprint capture started on device {_deviceId}");
}
public void Stop()
{
Console.WriteLine("[Info] Stopping fingerprint capture...");
_isCapturing = false;
_captureThread?.Join();
if (_deviceHandle != IntPtr.Zero)
{
Console.WriteLine("[Info] Closing device handle...");
zkfp2.CloseDevice(_deviceHandle);
_deviceHandle = IntPtr.Zero;
}
Console.WriteLine("[Info] Terminating SDK...");
zkfp2.Terminate();
_deviceStatus = "INACTIVE";
Console.WriteLine("[Info] Fingerprint capture stopped.");
}
private void CaptureLoop()
{
Console.WriteLine("[Info] Capture loop started.");
while (_isCapturing)
{
int templateLength = 2048;
int ret = zkfp2.AcquireFingerprint(_deviceHandle, _fpBuffer, _templateBuffer, ref templateLength);
if (ret == zkfp.ZKFP_ERR_OK)
{
Console.WriteLine("[Info] Fingerprint acquired.");
using (MemoryStream ms = new MemoryStream())
{
BitmapFormat.GetBitmap(_fpBuffer, _width, _height, ms);
byte[] bmpBytes = ms.ToArray();
string bmpBase64 = Convert.ToBase64String(bmpBytes);
string templateBase64 = Convert.ToBase64String(_templateBuffer, 0, templateLength);
var json = new JObject
{
["deviceInfo"] = new JObject
{
["deviceId"] = _deviceId,
["deviceStatus"] = _deviceStatus,
["width"] = _width,
["height"] = _height,
["dpi"] = _dpi
},
["imageData"] = bmpBase64,
["templateData"] = templateBase64
};
// Safe event invoke
OnFingerprintCaptured?.Invoke(json.ToString());
}
}
else if (ret == -7)
{
// No finger detected, silently wait
}
else if (ret == -8)
{
// Capture timeout or bad scan, silently wait
}
else
{
Console.WriteLine($"[Warning] AcquireFingerprint returned unexpected code: {ret}");
}
Thread.Sleep(200); // match old working code
}
Console.WriteLine("[Info] Capture loop ended.");
}
public static USBDeviceInfo[] GetConnectedUSBDevices()
{
var usbDevices = new ManagementObjectSearcher("SELECT * FROM Win32_USBHub").Get();
var list = new System.Collections.Generic.List();
foreach (var device in usbDevices)
{
string deviceId = device.GetPropertyValue("DeviceID")?.ToString() ?? "";
string desc = device.GetPropertyValue("Description")?.ToString() ?? "";
list.Add(new USBDeviceInfo { DeviceID = deviceId, Description = desc });
}
return list.ToArray();
}
public static string GetMatch(string input, string pattern)
{
var match = Regex.Match(input, pattern);
if (match.Success && match.Groups.Count > 1)
return match.Groups[1].Value;
return "";
}
}
public class USBDeviceInfo
{
public string DeviceID { get; set; }
public string Description { get; set; }
}
}