enzo 4 недель назад
Родитель
Сommit
e311c81ea3

+ 2 - 2
.gitignore

@@ -1,2 +1,2 @@
-bin/
-obj/
+/bin
+/obj

+ 295 - 0
BitmapFormat.cs

@@ -0,0 +1,295 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Sample
+{
+    public class BitmapFormat
+    {
+        public struct BITMAPFILEHEADER
+        {
+            public ushort bfType;
+            public int bfSize;
+            public ushort bfReserved1;
+            public ushort bfReserved2;
+            public int bfOffBits;
+        }
+
+        public struct MASK
+        {
+            public byte redmask;
+            public byte greenmask;
+            public byte bluemask;
+            public byte rgbReserved;
+        }
+
+        public struct BITMAPINFOHEADER
+        {
+            public int biSize;
+            public int biWidth;
+            public int biHeight;
+            public ushort biPlanes;
+            public ushort biBitCount;
+            public int biCompression;
+            public int biSizeImage;
+            public int biXPelsPerMeter;
+            public int biYPelsPerMeter;
+            public int biClrUsed;
+            public int biClrImportant;
+        }
+
+        /*******************************************
+        * �������ƣ�RotatePic       
+        * �������ܣ���תͼƬ��Ŀ���DZ������ʾ��ͼƬ�밴��ָ�Ʒ���ͬ     
+        * ������Σ�BmpBuf---��תǰ��ָ���ַ���
+        * �������Σ�ResBuf---��ת���ָ���ַ���
+        * �������أ���
+        *********************************************/
+        public static void RotatePic(byte[] BmpBuf, int width, int height, ref byte[] ResBuf)
+        {
+            int RowLoop = 0;
+            int ColLoop = 0;
+            int BmpBuflen = width * height;
+
+            try
+            {
+                for (RowLoop = 0; RowLoop < BmpBuflen;)
+                {
+                    for (ColLoop = 0; ColLoop < width; ColLoop++)
+                    {
+                        ResBuf[RowLoop + ColLoop] = BmpBuf[BmpBuflen - RowLoop - width + ColLoop];
+                    }
+
+                    RowLoop = RowLoop + width;
+                }
+            }
+            catch (Exception ex)
+            {
+                //ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
+                //logger.Append();
+            }
+        }
+
+        /*******************************************
+        * �������ƣ�StructToBytes       
+        * �������ܣ����ṹ��ת�����޷����ַ�������     
+        * ������Σ�StructObj---��ת���Ľṹ��
+        *           Size---��ת���Ľṹ��Ĵ�С
+        * ����������
+        * �������أ��ṹ��ת���������
+        *********************************************/
+        public static byte[] StructToBytes(object StructObj, int Size)
+        {
+            int StructSize = Marshal.SizeOf(StructObj);
+            byte[] GetBytes = new byte[StructSize];
+
+            try
+            {
+                IntPtr StructPtr = Marshal.AllocHGlobal(StructSize);
+                Marshal.StructureToPtr(StructObj, StructPtr, false);
+                Marshal.Copy(StructPtr, GetBytes, 0, StructSize);
+                Marshal.FreeHGlobal(StructPtr);
+
+                if (Size == 14)
+                {
+                    byte[] NewBytes = new byte[Size];
+                    int Count = 0;
+                    int Loop = 0;
+
+                    for (Loop = 0; Loop < StructSize; Loop++)
+                    {
+                        if (Loop != 2 && Loop != 3)
+                        {
+                            NewBytes[Count] = GetBytes[Loop];
+                            Count++;
+                        }
+                    }
+
+                    return NewBytes;
+                }
+                else
+                {
+                    return GetBytes;
+                }
+            }
+            catch (Exception ex)
+            {
+                //ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
+                //logger.Append();
+
+                return GetBytes;
+            }
+        }
+
+        /*******************************************
+        * �������ƣ�GetBitmap       
+        * �������ܣ��������������ݱ���ΪͼƬ     
+        * ������Σ�buffer---ͼƬ����
+        *           nWidth---ͼƬ�Ŀ���
+        *           nHeight---ͼƬ�ĸ߶�
+        * ����������
+        * �������أ���
+        *********************************************/
+        public static void GetBitmap(byte[] buffer, int nWidth, int nHeight, MemoryStream ms)
+        {
+            int ColorIndex = 0;
+            ushort m_nBitCount = 8;
+            int m_nColorTableEntries = 256;
+            byte[] ResBuf = new byte[nWidth * nHeight * 2];
+
+            try
+            {
+                BITMAPFILEHEADER BmpHeader = new BITMAPFILEHEADER();
+                BITMAPINFOHEADER BmpInfoHeader = new BITMAPINFOHEADER();
+                MASK[] ColorMask = new MASK[m_nColorTableEntries];
+
+                int w = (((nWidth + 3) / 4) * 4);
+
+                //ͼƬͷ��Ϣ
+                BmpInfoHeader.biSize = Marshal.SizeOf(BmpInfoHeader);
+                BmpInfoHeader.biWidth = nWidth;
+                BmpInfoHeader.biHeight = nHeight;
+                BmpInfoHeader.biPlanes = 1;
+                BmpInfoHeader.biBitCount = m_nBitCount;
+                BmpInfoHeader.biCompression = 0;
+                BmpInfoHeader.biSizeImage = 0;
+                BmpInfoHeader.biXPelsPerMeter = 0;
+                BmpInfoHeader.biYPelsPerMeter = 0;
+                BmpInfoHeader.biClrUsed = m_nColorTableEntries;
+                BmpInfoHeader.biClrImportant = m_nColorTableEntries;
+
+                //�ļ�ͷ��Ϣ
+                BmpHeader.bfType = 0x4D42;
+                BmpHeader.bfOffBits = 14 + Marshal.SizeOf(BmpInfoHeader) + BmpInfoHeader.biClrUsed * 4;
+                BmpHeader.bfSize = BmpHeader.bfOffBits + ((((w * BmpInfoHeader.biBitCount + 31) / 32) * 4) * BmpInfoHeader.biHeight);
+                BmpHeader.bfReserved1 = 0;
+                BmpHeader.bfReserved2 = 0;
+
+                ms.Write(StructToBytes(BmpHeader, 14), 0, 14);
+                ms.Write(StructToBytes(BmpInfoHeader, Marshal.SizeOf(BmpInfoHeader)), 0, Marshal.SizeOf(BmpInfoHeader));
+
+                //���԰���Ϣ
+                for (ColorIndex = 0; ColorIndex < m_nColorTableEntries; ColorIndex++)
+                {
+                    ColorMask[ColorIndex].redmask = (byte)ColorIndex;
+                    ColorMask[ColorIndex].greenmask = (byte)ColorIndex;
+                    ColorMask[ColorIndex].bluemask = (byte)ColorIndex;
+                    ColorMask[ColorIndex].rgbReserved = 0;
+
+                    ms.Write(StructToBytes(ColorMask[ColorIndex], Marshal.SizeOf(ColorMask[ColorIndex])), 0, Marshal.SizeOf(ColorMask[ColorIndex]));
+                }
+
+                //ͼƬ��ת�����ָ��ͼƬ����������
+                RotatePic(buffer, nWidth, nHeight, ref ResBuf);
+
+                byte[] filter = null;
+                if (w - nWidth > 0)
+                {
+                    filter = new byte[w - nWidth];
+                }
+                for (int i = 0; i < nHeight; i++)
+                {
+                    ms.Write(ResBuf, i * nWidth, nWidth);
+                    if (w - nWidth > 0)
+                    {
+                        ms.Write(ResBuf, 0, w - nWidth);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                // ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
+                // logger.Append();
+            }
+        }
+
+        /*******************************************
+        * �������ƣ�WriteBitmap       
+        * �������ܣ��������������ݱ���ΪͼƬ     
+        * ������Σ�buffer---ͼƬ����
+        *           nWidth---ͼƬ�Ŀ���
+        *           nHeight---ͼƬ�ĸ߶�
+        * ����������
+        * �������أ���
+        *********************************************/
+        public static void WriteBitmap(byte[] buffer, int nWidth, int nHeight)
+        {
+            int ColorIndex = 0;
+            ushort m_nBitCount = 8;
+            int m_nColorTableEntries = 256;
+            byte[] ResBuf = new byte[nWidth * nHeight];
+
+            try
+            {
+
+                BITMAPFILEHEADER BmpHeader = new BITMAPFILEHEADER();
+                BITMAPINFOHEADER BmpInfoHeader = new BITMAPINFOHEADER();
+                MASK[] ColorMask = new MASK[m_nColorTableEntries];
+                int w = (((nWidth + 3) / 4) * 4);
+                //ͼƬͷ��Ϣ
+                BmpInfoHeader.biSize = Marshal.SizeOf(BmpInfoHeader);
+                BmpInfoHeader.biWidth = nWidth;
+                BmpInfoHeader.biHeight = nHeight;
+                BmpInfoHeader.biPlanes = 1;
+                BmpInfoHeader.biBitCount = m_nBitCount;
+                BmpInfoHeader.biCompression = 0;
+                BmpInfoHeader.biSizeImage = 0;
+                BmpInfoHeader.biXPelsPerMeter = 0;
+                BmpInfoHeader.biYPelsPerMeter = 0;
+                BmpInfoHeader.biClrUsed = m_nColorTableEntries;
+                BmpInfoHeader.biClrImportant = m_nColorTableEntries;
+
+                //�ļ�ͷ��Ϣ
+                BmpHeader.bfType = 0x4D42;
+                BmpHeader.bfOffBits = 14 + Marshal.SizeOf(BmpInfoHeader) + BmpInfoHeader.biClrUsed * 4;
+                BmpHeader.bfSize = BmpHeader.bfOffBits + ((((w * BmpInfoHeader.biBitCount + 31) / 32) * 4) * BmpInfoHeader.biHeight);
+                BmpHeader.bfReserved1 = 0;
+                BmpHeader.bfReserved2 = 0;
+
+                Stream FileStream = File.Open("finger.bmp", FileMode.Create, FileAccess.Write);
+                BinaryWriter TmpBinaryWriter = new BinaryWriter(FileStream);
+
+                TmpBinaryWriter.Write(StructToBytes(BmpHeader, 14));
+                TmpBinaryWriter.Write(StructToBytes(BmpInfoHeader, Marshal.SizeOf(BmpInfoHeader)));
+
+                //���԰���Ϣ
+                for (ColorIndex = 0; ColorIndex < m_nColorTableEntries; ColorIndex++)
+                {
+                    ColorMask[ColorIndex].redmask = (byte)ColorIndex;
+                    ColorMask[ColorIndex].greenmask = (byte)ColorIndex;
+                    ColorMask[ColorIndex].bluemask = (byte)ColorIndex;
+                    ColorMask[ColorIndex].rgbReserved = 0;
+
+                    TmpBinaryWriter.Write(StructToBytes(ColorMask[ColorIndex], Marshal.SizeOf(ColorMask[ColorIndex])));
+                }
+
+                //ͼƬ��ת�����ָ��ͼƬ����������
+                RotatePic(buffer, nWidth, nHeight, ref ResBuf);
+
+                //дͼƬ
+                //TmpBinaryWriter.Write(ResBuf);
+                byte[] filter = null;
+                if (w - nWidth > 0)
+                {
+                    filter = new byte[w - nWidth];
+                }
+                for (int i = 0; i < nHeight; i++)
+                {
+                    TmpBinaryWriter.Write(ResBuf, i * nWidth, nWidth);
+                    if (w - nWidth > 0)
+                    {
+                        TmpBinaryWriter.Write(ResBuf, 0, w - nWidth);
+                    }
+                }
+
+                FileStream.Close();
+                TmpBinaryWriter.Close();
+            }
+            catch (Exception ex)
+            {
+                //ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
+                //logger.Append();
+            }
+        }
+    }
+}

+ 258 - 0
FingerprintCaptureManager.cs

@@ -0,0 +1,258 @@
+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}");
+        }
+
+        /// <summary>
+        /// Detect and return the serial number of the first connected USB device with VID=1B55
+        /// </summary>
+        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 "";
+        }
+
+        /// <summary>
+        /// Start fingerprint capture on the detected device with VID=1B55
+        /// </summary>
+        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<USBDeviceInfo>();
+            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; }
+    }
+}

+ 26 - 0
FingerprintScanner.csproj

@@ -5,6 +5,32 @@
     <TargetFramework>net9.0</TargetFramework>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
+    <PlatformTarget>x86</PlatformTarget>
   </PropertyGroup>
 
+  <ItemGroup>
+    <PackageReference Include="Fleck" Version="1.2.0" />
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+    <PackageReference Include="System.Drawing.Common" Version="9.0.8" />
+    <PackageReference Include="System.Management" Version="9.0.8" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <!-- Reference the managed SDK DLL -->
+    <Reference Include="libzkfpcsharp">
+      <HintPath>libs\libzkfpcsharp.dll</HintPath>
+      <Private>true</Private>
+    </Reference>
+
+    <!-- Copy native DLL libzkfp.dll to output folder -->
+    <Content Include="libs\libzkfp.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+
+    <!-- Copy managed DLL to output folder -->
+    <Content Include="libs\libzkfpcsharp.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
 </Project>

+ 15 - 0
Models/FingerprintData.cs

@@ -0,0 +1,15 @@
+namespace Models
+{
+    public class FingerprintData
+    {
+        public string Channel { get; set; }
+        public PayloadData Payload { get; set; }
+    }
+
+    public class PayloadData
+    {
+        public string ImageBase64 { get; set; }
+        public string TemplateBase64 { get; set; }
+        // Add other properties like device info as needed
+    }
+}

+ 57 - 3
Program.cs

@@ -1,4 +1,58 @@
-// See https://aka.ms/new-console-template for more information
-Console.WriteLine("Hello, World!");
+using System;
+using System.Collections.Generic;
+using Fleck;
+using FingerprintScanner;
 
-Console.WriteLine("Run Forrest Run!!!");
+class Program
+{
+    static void Main()
+    {
+        var allSockets = new List<IWebSocketConnection>();
+        var server = new WebSocketServer("ws://0.0.0.0:5000");
+
+        // Start WebSocket server
+        server.Start(socket =>
+        {
+            socket.OnOpen = () =>
+            {
+                Console.WriteLine("Client connected!");
+                allSockets.Add(socket);
+            };
+            socket.OnClose = () =>
+            {
+                Console.WriteLine("Client disconnected!");
+                allSockets.Remove(socket);
+            };
+            socket.OnMessage = message =>
+            {
+                Console.WriteLine("Received: " + message);
+                // You can handle incoming messages here if needed
+            };
+            socket.OnError = error =>
+            {
+                Console.WriteLine("Error: " + error.Message);
+            };
+        });
+
+        var fingerprintManager = new FingerprintCaptureManager();
+
+        // Subscribe to fingerprint captured event and broadcast to all clients
+        fingerprintManager.OnFingerprintCaptured += (jsonData) =>
+        {
+            Console.WriteLine("Broadcasting fingerprint data...");
+            foreach (var socket in allSockets)
+            {
+                socket.Send(jsonData);
+            }
+        };
+
+        // Pass the targetVid string here. Replace with your actual VID if known.
+        fingerprintManager.Start();
+
+        Console.WriteLine("Fingerprint WebSocket server running on ws://0.0.0.0:5000/");
+        Console.WriteLine("Press Enter to stop...");
+        Console.ReadLine();
+
+        fingerprintManager.Stop();
+    }
+}

+ 23 - 11
README.md

@@ -1,18 +1,30 @@
-# Project Name
-Fingerprint Scanner 
+# Fingerprint Scanner
 
 ## Description
-A C# program to read fingerprint data from scanner
+A C# program to read fingerprint data from a scanner.
 
 ## Requirements
-- Donet 9.0 or higher (https://dotnet.microsoft.com/en-us/download)
+- .NET 9.0 or higher  
+  [Download .NET](https://dotnet.microsoft.com/en-us/download)
 
-## Run the program
-- Terminal, run 
-    ```sh
-    dotnet run
-    ```sh
+## Instructions
 
-## License
-Specify the license information here (if applicable).
+### 1. Clean the project
+```sh
+dotnet clean
+```
 
+### 2. Build the project
+```sh
+dotnet build
+```
+
+### 3. Run the project
+```sh
+dotnet run
+```
+
+### 4. Publish the project
+```sh
+dotnet publish -c Release -o ./publish
+```

+ 66 - 0
WebSocketServerManager.cs

@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using Fleck;
+
+public class WebSocketServerManager
+{
+    private List<IWebSocketConnection> _clients = new List<IWebSocketConnection>();
+    private WebSocketServer _server;
+
+    public void Start()
+    {
+        _server = new WebSocketServer("ws://0.0.0.0:5000");
+        _server.Start(socket =>
+        {
+            socket.OnOpen = () =>
+            {
+                Console.WriteLine("Client connected.");
+                _clients.Add(socket);
+            };
+            socket.OnClose = () =>
+            {
+                Console.WriteLine("Client disconnected.");
+                _clients.Remove(socket);
+            };
+            socket.OnMessage = message =>
+            {
+                Console.WriteLine("Received message: " + message);
+                // Optionally echo back or handle messages
+            };
+            socket.OnError = error =>
+            {
+                Console.WriteLine("Socket error: " + error.Message);
+            };
+        });
+
+        Console.WriteLine("WebSocket server started on ws://0.0.0.0:5000");
+    }
+
+    public void BroadcastMessage(string message)
+    {
+        foreach (var client in _clients)
+        {
+            if (client.IsAvailable)
+            {
+                try
+                {
+                    client.Send(message);
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine("Error sending message: " + ex.Message);
+                }
+            }
+        }
+    }
+
+    public void Stop()
+    {
+        foreach (var client in _clients)
+        {
+            client.Close();
+        }
+        _server.Dispose();
+        Console.WriteLine("WebSocket server stopped.");
+    }
+}

BIN
libs/libzkfp.dll


BIN
libs/libzkfpcsharp.dll


+ 159 - 0
publish/FingerprintScanner.deps.json

@@ -0,0 +1,159 @@
+{
+  "runtimeTarget": {
+    "name": ".NETCoreApp,Version=v9.0",
+    "signature": ""
+  },
+  "compilationOptions": {},
+  "targets": {
+    ".NETCoreApp,Version=v9.0": {
+      "FingerprintScanner/1.0.0": {
+        "dependencies": {
+          "Fleck": "1.2.0",
+          "Newtonsoft.Json": "13.0.3",
+          "System.Drawing.Common": "9.0.8",
+          "System.Management": "9.0.8",
+          "libzkfpcsharp": "1.0.0.1"
+        },
+        "runtime": {
+          "FingerprintScanner.dll": {}
+        }
+      },
+      "Fleck/1.2.0": {
+        "runtime": {
+          "lib/netcoreapp2.0/Fleck.dll": {
+            "assemblyVersion": "1.2.0.0",
+            "fileVersion": "1.2.0.0"
+          }
+        }
+      },
+      "Microsoft.Win32.SystemEvents/9.0.8": {
+        "runtime": {
+          "lib/net9.0/Microsoft.Win32.SystemEvents.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.825.36511"
+          }
+        },
+        "runtimeTargets": {
+          "runtimes/win/lib/net9.0/Microsoft.Win32.SystemEvents.dll": {
+            "rid": "win",
+            "assetType": "runtime",
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.825.36511"
+          }
+        }
+      },
+      "Newtonsoft.Json/13.0.3": {
+        "runtime": {
+          "lib/net6.0/Newtonsoft.Json.dll": {
+            "assemblyVersion": "13.0.0.0",
+            "fileVersion": "13.0.3.27908"
+          }
+        }
+      },
+      "System.CodeDom/9.0.8": {
+        "runtime": {
+          "lib/net9.0/System.CodeDom.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.825.36511"
+          }
+        }
+      },
+      "System.Drawing.Common/9.0.8": {
+        "dependencies": {
+          "Microsoft.Win32.SystemEvents": "9.0.8"
+        },
+        "runtime": {
+          "lib/net9.0/System.Drawing.Common.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.825.36801"
+          },
+          "lib/net9.0/System.Private.Windows.Core.dll": {
+            "assemblyVersion": "9.0.0.0",
+            "fileVersion": "9.0.825.36801"
+          }
+        }
+      },
+      "System.Management/9.0.8": {
+        "dependencies": {
+          "System.CodeDom": "9.0.8"
+        },
+        "runtime": {
+          "lib/net9.0/System.Management.dll": {
+            "assemblyVersion": "9.0.0.8",
+            "fileVersion": "9.0.825.36511"
+          }
+        },
+        "runtimeTargets": {
+          "runtimes/win/lib/net9.0/System.Management.dll": {
+            "rid": "win",
+            "assetType": "runtime",
+            "assemblyVersion": "9.0.0.8",
+            "fileVersion": "9.0.825.36511"
+          }
+        }
+      },
+      "libzkfpcsharp/1.0.0.1": {
+        "runtime": {
+          "libzkfpcsharp.dll": {
+            "assemblyVersion": "1.0.0.1",
+            "fileVersion": "1.0.0.1"
+          }
+        }
+      }
+    }
+  },
+  "libraries": {
+    "FingerprintScanner/1.0.0": {
+      "type": "project",
+      "serviceable": false,
+      "sha512": ""
+    },
+    "Fleck/1.2.0": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-bPLXn6QbLAFoviur6XbrKB0Zn6x04E8VibHXyHZeJsoC7bkUl5DVtzM5cZgDuqHkIrBqAXJyTNJwSNIc6wBJ2Q==",
+      "path": "fleck/1.2.0",
+      "hashPath": "fleck.1.2.0.nupkg.sha512"
+    },
+    "Microsoft.Win32.SystemEvents/9.0.8": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-64oQBN8I8EOcyHGNt6+rlcqm4tlcKfqOpswtBCJZnpzBQ15L6IFKqjnbjbOWBpG9wKq9A/aC2LFSmSqplbwTYA==",
+      "path": "microsoft.win32.systemevents/9.0.8",
+      "hashPath": "microsoft.win32.systemevents.9.0.8.nupkg.sha512"
+    },
+    "Newtonsoft.Json/13.0.3": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
+      "path": "newtonsoft.json/13.0.3",
+      "hashPath": "newtonsoft.json.13.0.3.nupkg.sha512"
+    },
+    "System.CodeDom/9.0.8": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-kxg1TE/BMUAaMve/lPH9Bds+CFF4JPrN9WkQqHejc7UP6PO4KDAjZNF0uhvpZmoLR+EvHdRt232J++ZDI7aGqA==",
+      "path": "system.codedom/9.0.8",
+      "hashPath": "system.codedom.9.0.8.nupkg.sha512"
+    },
+    "System.Drawing.Common/9.0.8": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-ineIJmF+yuBEHGft9R153J9kmBFaeEfFL5Put5nzENneRcGGPUb3MvM8zrZ5pERQ0jPPSE3Wqw/clXvOq2F/Kw==",
+      "path": "system.drawing.common/9.0.8",
+      "hashPath": "system.drawing.common.9.0.8.nupkg.sha512"
+    },
+    "System.Management/9.0.8": {
+      "type": "package",
+      "serviceable": true,
+      "sha512": "sha512-D7icHff0OpEEIOLsTgnPL+Ff1VmJ3tzA8y20LNKgv4hx1MFMA3XGAVlWMCkLQfBkyvEwib6rMG6nP27lf98KRA==",
+      "path": "system.management/9.0.8",
+      "hashPath": "system.management.9.0.8.nupkg.sha512"
+    },
+    "libzkfpcsharp/1.0.0.1": {
+      "type": "reference",
+      "serviceable": false,
+      "sha512": ""
+    }
+  }
+}

BIN
publish/FingerprintScanner.dll


BIN
publish/FingerprintScanner.exe


BIN
publish/FingerprintScanner.pdb


+ 13 - 0
publish/FingerprintScanner.runtimeconfig.json

@@ -0,0 +1,13 @@
+{
+  "runtimeOptions": {
+    "tfm": "net9.0",
+    "framework": {
+      "name": "Microsoft.NETCore.App",
+      "version": "9.0.0"
+    },
+    "configProperties": {
+      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+      "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
+    }
+  }
+}

BIN
publish/Fleck.dll


BIN
publish/Microsoft.Win32.SystemEvents.dll


BIN
publish/Newtonsoft.Json.dll


BIN
publish/System.CodeDom.dll


BIN
publish/System.Drawing.Common.dll


BIN
publish/System.Management.dll


BIN
publish/System.Private.Windows.Core.dll


BIN
publish/libs/libzkfp.dll


BIN
publish/libs/libzkfpcsharp.dll


BIN
publish/libzkfpcsharp.dll


BIN
publish/runtimes/win/lib/net9.0/Microsoft.Win32.SystemEvents.dll


BIN
publish/runtimes/win/lib/net9.0/System.Management.dll