diff --git a/SlnMesnac.Business/base/BaseBusiness.cs b/SlnMesnac.Business/base/BaseBusiness.cs index 42f1efe..755fc91 100644 --- a/SlnMesnac.Business/base/BaseBusiness.cs +++ b/SlnMesnac.Business/base/BaseBusiness.cs @@ -38,15 +38,12 @@ namespace SlnMesnac.Business.@base private readonly StringChange stringChange; - private readonly HIDMode hIDMode; - public BaseBusiness(List plcFactories, List rfidFactories, HIDMode hIDModes) + public BaseBusiness(List plcFactories, List rfidFactories) { _plcFactories = plcFactories; _rfidFactories = rfidFactories; - //示例 - //stringChange = stringChanges; - hIDMode = hIDModes; + } /// diff --git a/SlnMesnac.Business/business/RecordRfidInfoBusniess.cs b/SlnMesnac.Business/business/RecordRfidInfoBusniess.cs deleted file mode 100644 index 4110fc8..0000000 --- a/SlnMesnac.Business/business/RecordRfidInfoBusniess.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SlnMesnac.Business.business -{ - /// - /// 记录Rfid信息 - /// - public class RecordRfidInfoBusniess - { - - } -} diff --git a/SlnMesnac.Business/business/RfidHandleBusniess.cs b/SlnMesnac.Business/business/RfidHandleBusniess.cs index 85d077e..aecf886 100644 --- a/SlnMesnac.Business/business/RfidHandleBusniess.cs +++ b/SlnMesnac.Business/business/RfidHandleBusniess.cs @@ -1,14 +1,71 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; +using ConsoleApp; +using Microsoft.Extensions.DependencyInjection; +using SlnMesnac.Common; namespace SlnMesnac.Business.business { /// - /// RFID打卡机业务逻辑类 + /// RFID打卡业务逻辑类 /// public class RfidHandleBusniess { + private readonly HidUtils _utils; + + + public RfidHandleBusniess(HidUtils utils) + { + this._utils = utils; + } + + string staffInfo = ""; + string tagInfoStr = ""; + + /// + /// 上班打卡 + /// + public void CheckIn() + { + _utils.StartScan(); + } + + /// + /// 下班打卡 + /// + public void CheckOut() + { + _utils.StartScan(); + } + + /// + /// 结束打卡 + /// + public void CloseRfid() + { + _utils.StopScan(); + } + + ///// + ///// 获取标签信息 + ///// + //private void GetTagInfo() + //{ + // utils.pushReceiveDataEvent += (bytes, str) => + // { + // Console.WriteLine($"收到打卡信息:{str}"); + // }; + //} + ///// + ///// 获取员工信息 + ///// + //public string GetStaffInfo() + //{ + // staffInfo = baseStaffInfoService.GetStaffByCardIdAsync(highRfid.GetTagInfo()).ToString(); + // return staffInfo; + //} } } diff --git a/SlnMesnac.Common/HIDInterface.cs b/SlnMesnac.Common/HIDInterface.cs new file mode 100644 index 0000000..a88cec3 --- /dev/null +++ b/SlnMesnac.Common/HIDInterface.cs @@ -0,0 +1,262 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +#region << 版 本 注 释 >> +/*-------------------------------------------------------------------- +* 版权所有 (c) 2024 WenJY 保留所有权利。 +* CLR版本:4.0.30319.42000 +* 机器名称:T14-GEN3-7895 +* 命名空间:ConsoleApp +* 唯一标识:156ff13b-84fd-4062-a001-afc6a5d185b2 +* +* 创建者:WenJY +* 电子邮箱: +* 创建时间:2024-05-22 11:15:41 +* 版本:V1.0.0 +* 描述: +* +*-------------------------------------------------------------------- +* 修改人: +* 时间: +* 修改说明: +* +* 版本:V1.0.0 +*--------------------------------------------------------------------*/ +#endregion << 版 本 注 释 >> +namespace ConsoleApp +{ + public class HIDInterface : IDisposable + { + + public enum MessagesType + { + Message, + Error + } + + public struct ReusltString + { + public bool Result; + public string message; + } + + public struct HidDevice + { + public UInt16 vID; + public UInt16 pID; + public string serial; + } + HidDevice lowHidDevice = new HidDevice(); + + public delegate void DelegateDataReceived(object sender, byte[] data); + public DelegateDataReceived DataReceived; + + public delegate void DelegateStatusConnected(object sender, bool isConnect); + public DelegateStatusConnected StatusConnected; + + public bool bConnected = false; + + + public Hid oSp = new Hid(); + private static HIDInterface m_oInstance; + + public struct TagInfo + { + public string AntennaPort; + public string EPC; + } + + public HIDInterface() + { + m_oInstance = this; + oSp.DataReceived = HidDataReceived; + oSp.DeviceRemoved = HidDeviceRemoved; + } + + protected virtual void RaiseEventConnectedState(bool isConnect) + { + if (null != StatusConnected) StatusConnected(this, isConnect); + } + + protected virtual void RaiseEventDataReceived(byte[] buf) + { + if (null != DataReceived) DataReceived(this, buf); + } + + public void AutoConnect(HidDevice hidDevice) + { + lowHidDevice = hidDevice; + ContinueConnectFlag = true; + ReadWriteThread.DoWork += ReadWriteThread_DoWork; + ReadWriteThread.WorkerSupportsCancellation = true; + ReadWriteThread.RunWorkerAsync(); //Recommend performing USB read/write operations in a separate thread. Otherwise, + } + + public void StopAutoConnect() + { + try + { + ContinueConnectFlag = false; + Dispose(); + } + catch + { + + } + } + + ~HIDInterface() + { + Dispose(); + } + + public bool Connect(HidDevice hidDevice) + { + ReusltString result = new ReusltString(); + + Hid.HID_RETURN hdrtn = oSp.OpenDevice(hidDevice.vID, hidDevice.pID, hidDevice.serial); + + if (hdrtn == Hid.HID_RETURN.SUCCESS) + { + + bConnected = true; + + #region 消息通知 + result.Result = true; + result.message = "Connect Success!"; + RaiseEventConnectedState(result.Result); + #endregion + + + return true; + } + + bConnected = false; + + #region 消息通知 + result.Result = false; + result.message = "Device Connect Error"; + RaiseEventConnectedState(result.Result); + + #endregion + return false; + } + + + public bool Send(byte[] byData) + { + byte[] sendtemp = new byte[byData.Length + 1]; + sendtemp[0] = (byte)byData.Length; + Array.Copy(byData, 0, sendtemp, 1, byData.Length); + + Hid.HID_RETURN hdrtn = oSp.Write(new report(0, sendtemp)); + + if (hdrtn != Hid.HID_RETURN.SUCCESS) + { + return false; + } + return true; + } + + public bool Send(string strData) + { + //获得报文的编码字节 + byte[] data = Encoding.Unicode.GetBytes(strData); + return Send(data); + } + + + + public void DisConnect() + { + bConnected = false; + + Thread.Sleep(200); + if (oSp != null) + { + oSp.CloseDevice(); + } + } + + + void HidDeviceRemoved(object sender, EventArgs e) + { + bConnected = false; + #region 消息通知 + ReusltString result = new ReusltString(); + result.Result = false; + result.message = "Device Remove"; + RaiseEventConnectedState(result.Result); + #endregion + if (oSp != null) + { + oSp.CloseDevice(); + } + + } + + public void HidDataReceived(object sender, report e) + { + + try + { + //第一个字节为数据长度,因为Device 的HID数据固定长度为64字节,取有效数据 + byte[] buf = new byte[e.reportBuff[0]]; + Array.Copy(e.reportBuff, 1, buf, 0, e.reportBuff[0]); + + //推送数据 + RaiseEventDataReceived(buf); + } + catch + { + #region 消息通知 + ReusltString result = new ReusltString(); + result.Result = false; + result.message = "Receive Error"; + RaiseEventConnectedState(result.Result); + #endregion + } + + } + + public void Dispose() + { + try + { + this.DisConnect(); + oSp.DataReceived -= HidDataReceived; + oSp.DeviceRemoved -= HidDeviceRemoved; + ReadWriteThread.DoWork -= ReadWriteThread_DoWork; + ReadWriteThread.CancelAsync(); + ReadWriteThread.Dispose(); + } + catch + { } + } + + Boolean ContinueConnectFlag = true; + private BackgroundWorker ReadWriteThread = new BackgroundWorker(); + private void ReadWriteThread_DoWork(object sender, DoWorkEventArgs e) + { + while (ContinueConnectFlag) + { + try + { + if (!bConnected) + { + Connect(lowHidDevice); + + } + Thread.Sleep(500); + } + catch { } + } + } + + } +} diff --git a/SlnMesnac.Common/HIDMode.cs b/SlnMesnac.Common/HIDMode.cs deleted file mode 100644 index d3ad0ea..0000000 --- a/SlnMesnac.Common/HIDMode.cs +++ /dev/null @@ -1,42 +0,0 @@ -using HighRFIDSendCardDemo; -using System; -using System.Collections.Generic; -using System.Text; - -namespace SlnMesnac.Common -{ - public class HIDMode - { - public DeviceClass deviceClass = new DeviceClass(); - public string ButtonText = ""; - - public HIDMode() - { - deviceClass.pushTagData = GetTag; - } - - /// - /// 连接或断开打卡机 - /// - public void ConnectRfidHid() - { - deviceClass.ConnectDevice(); - } - - /// - /// 断开打卡机 - /// - public void DisconnectRfidHid() - { - deviceClass.Close(); - } - - /// - /// 获取标签 - /// - public void GetTag(Tag tag) - { - string tagInfo = tag.ToString(); - } - } -} diff --git a/SlnMesnac.Common/Hid.cs b/SlnMesnac.Common/Hid.cs new file mode 100644 index 0000000..46a9c02 --- /dev/null +++ b/SlnMesnac.Common/Hid.cs @@ -0,0 +1,554 @@ +using Microsoft.Win32.SafeHandles; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Management; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +#region << 版 本 注 释 >> +/*-------------------------------------------------------------------- +* 版权所有 (c) 2024 WenJY 保留所有权利。 +* CLR版本:4.0.30319.42000 +* 机器名称:T14-GEN3-7895 +* 命名空间:ConsoleApp +* 唯一标识:bda7394f-e114-4f8c-b573-8a6cecb7dcf7 +* +* 创建者:WenJY +* 电子邮箱: +* 创建时间:2024-05-22 11:14:15 +* 版本:V1.0.0 +* 描述: +* +*-------------------------------------------------------------------- +* 修改人: +* 时间: +* 修改说明: +* +* 版本:V1.0.0 +*--------------------------------------------------------------------*/ +#endregion << 版 本 注 释 >> +namespace ConsoleApp +{ + public class report : EventArgs + { + public readonly byte reportID; + public readonly byte[] reportBuff; + public report(byte id, byte[] arrayBuff) + { + reportID = id; + reportBuff = arrayBuff; + } + } + + public class Hid : object + { + private IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); + private const int MAX_USB_DEVICES = 64; + private bool deviceOpened = false; + private FileStream hidDevice = null; + private IntPtr hHubDevice; + + int outputReportLength; + public int OutputReportLength { get { return outputReportLength; } } + int inputReportLength; + public int InputReportLength { get { return inputReportLength; } } + + /// + /// 打开指定信息的设备 + /// + /// 设备的vID + /// 设备的pID + /// 设备的serial + /// + public HID_RETURN OpenDevice(UInt16 vID, UInt16 pID, string serial) + { + if (deviceOpened == false) + { + Guid hUSB = Guid.Empty; + + HidD_GetHidGuid(ref hUSB); + + List deviceList = new List(); + GetHidDeviceList(ref deviceList); + + if(deviceList.Count > 0) + { + foreach(string item in deviceList) + { + string deviceId = item.Replace("\\", "#"); + string concatenatedPath = $"\\\\?\\{deviceId}#{hUSB.ToString("B").ToUpper()}"; + IntPtr device = CreateFile(concatenatedPath, + DESIREDACCESS.GENERIC_READ | DESIREDACCESS.GENERIC_WRITE, + 0, + 0, + CREATIONDISPOSITION.OPEN_EXISTING, + FLAGSANDATTRIBUTES.FILE_FLAG_OVERLAPPED, + 0); + if (device != INVALID_HANDLE_VALUE) + { + HIDD_ATTRIBUTES attributes; + IntPtr serialBuff = Marshal.AllocHGlobal(512); + HidD_GetAttributes(device, out attributes); + HidD_GetSerialNumberString(device, serialBuff, 512); + string deviceStr = Marshal.PtrToStringAuto(serialBuff); + Marshal.FreeHGlobal(serialBuff); + if (attributes.VendorID == vID && attributes.ProductID == pID && deviceStr.Contains(serial)) + { + IntPtr preparseData; + HIDP_CAPS caps; + HidD_GetPreparsedData(device, out preparseData); + HidP_GetCaps(preparseData, out caps); + HidD_FreePreparsedData(preparseData); + outputReportLength = caps.OutputReportByteLength; + inputReportLength = caps.InputReportByteLength; + + hidDevice = new FileStream(new SafeFileHandle(device, false), FileAccess.ReadWrite, inputReportLength, true); + deviceOpened = true; + BeginAsyncRead(); + + hHubDevice = device; + return HID_RETURN.SUCCESS; + } + } + } + } + + return HID_RETURN.DEVICE_NOT_FIND; + } + else + return HID_RETURN.DEVICE_OPENED; + } + + /// + /// 获取所有连接的hid的设备路径 + /// + /// 包含每个设备路径的字符串数组 + public static void GetHidDeviceList(ref List deviceList) + { + deviceList.Clear(); + + ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity"); + + foreach (ManagementObject obj in searcher.Get()) + { + + deviceList.Add(obj["DeviceID"].ToString()); + } + } + + /// + /// 关闭打开的设备 + /// + public void CloseDevice() + { + if (deviceOpened == true) + { + deviceOpened = false; + hidDevice.Close(); + } + } + + /// + /// 开始一次异步读 + /// + private void BeginAsyncRead() + { + byte[] inputBuff = new byte[InputReportLength]; + hidDevice.BeginRead(inputBuff, 0, InputReportLength, new AsyncCallback(ReadCompleted), inputBuff); + } + + /// + /// 异步读取结束,发出有数据到达事件 + /// + /// 这里是输入报告的数组 + private void ReadCompleted(IAsyncResult iResult) + { + byte[] readBuff = (byte[])(iResult.AsyncState); + try + { + hidDevice.EndRead(iResult);//读取结束,如果读取错误就会产生一个异常 + byte[] reportData = new byte[readBuff.Length - 1]; + for (int i = 1; i < readBuff.Length; i++) + reportData[i - 1] = readBuff[i]; + report e = new report(readBuff[0], reportData); + OnDataReceived(e); //发出数据到达消息 + if (!deviceOpened) return; + BeginAsyncRead();//启动下一次读操作 + } + catch //读写错误,设备已经被移除 + { + //MyConsole.WriteLine("设备无法连接,请重新插入设备"); + EventArgs ex = new EventArgs(); + OnDeviceRemoved(ex);//发出设备移除消息 + CloseDevice(); + + } + } + + public delegate void DelegateDataReceived(object sender, report e); + //public event EventHandler StatusConnected; + + public DelegateDataReceived DataReceived; + + /// + /// 事件:数据到达,处理此事件以接收输入数据 + /// + + protected virtual void OnDataReceived(report e) + { + if (DataReceived != null) DataReceived(this, e); + } + + /// + /// 事件:设备断开 + /// + + public delegate void DelegateStatusConnected(object sender, EventArgs e); + public DelegateStatusConnected DeviceRemoved; + protected virtual void OnDeviceRemoved(EventArgs e) + { + if (DeviceRemoved != null) DeviceRemoved(this, e); + } + + /// + /// + /// + /// + /// + public HID_RETURN Write(report r) + { + if (deviceOpened) + { + try + { + byte[] buffer = new byte[outputReportLength]; + buffer[0] = r.reportID; + int maxBufferLength = 0; + if (r.reportBuff.Length < outputReportLength - 1) + maxBufferLength = r.reportBuff.Length; + else + maxBufferLength = outputReportLength - 1; + + for (int i = 0; i < maxBufferLength; i++) + buffer[i + 1] = r.reportBuff[i]; + hidDevice.Write(buffer, 0, OutputReportLength); + return HID_RETURN.SUCCESS; + } + catch + { + EventArgs ex = new EventArgs(); + OnDeviceRemoved(ex);//发出设备移除消息 + CloseDevice(); + return HID_RETURN.NO_DEVICE_CONECTED; + } + } + return HID_RETURN.WRITE_FAILD; + } + + #region<连接USB返回的结构体信息> + /// + /// 连接USB返回的结构体信息 + /// + public enum HID_RETURN + { + SUCCESS = 0, + NO_DEVICE_CONECTED, + DEVICE_NOT_FIND, + DEVICE_OPENED, + WRITE_FAILD, + READ_FAILD + + } + #endregion + + + // 以下是调用windows的API的函数 + /// + /// The HidD_GetHidGuid routine returns the device interface GUID for HIDClass devices. + /// + /// a caller-allocated GUID buffer that the routine uses to return the device interface GUID for HIDClass devices. + [DllImport("hid.dll")] + private static extern void HidD_GetHidGuid(ref Guid HidGuid); + + /// + /// The SetupDiGetClassDevs function returns a handle to a device information set that contains requested device information elements for a local machine. + /// + /// GUID for a device setup class or a device interface class. + /// A pointer to a NULL-terminated string that supplies the name of a PnP enumerator or a PnP device instance identifier. + /// A handle of the top-level window to be used for a user interface + /// A variable that specifies control options that filter the device information elements that are added to the device information set. + /// a handle to a device information set + [DllImport("setupapi.dll", SetLastError = true)] + private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, uint Enumerator, IntPtr HwndParent, DIGCF Flags); + + /// + /// The SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory. + /// + /// A handle to the device information set to delete. + /// returns TRUE if it is successful. Otherwise, it returns FALSE + [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet); + + /// + /// The SetupDiEnumDeviceInterfaces function enumerates the device interfaces that are contained in a device information set. + /// + /// A pointer to a device information set that contains the device interfaces for which to return information + /// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet + /// a GUID that specifies the device interface class for the requested interface + /// A zero-based index into the list of interfaces in the device information set + /// a caller-allocated buffer that contains a completed SP_DEVICE_INTERFACE_DATA structure that identifies an interface that meets the search parameters + /// + [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr deviceInfoSet, IntPtr deviceInfoData, ref Guid interfaceClassGuid, UInt32 memberIndex, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData); + + /// + /// The SetupDiGetDeviceInterfaceDetail function returns details about a device interface. + /// + /// A pointer to the device information set that contains the interface for which to retrieve details + /// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the interface in DeviceInfoSet for which to retrieve details + /// A pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA structure to receive information about the specified interface + /// The size of the DeviceInterfaceDetailData buffer + /// A pointer to a variable that receives the required size of the DeviceInterfaceDetailData buffer + /// A pointer buffer to receive information about the device that supports the requested interface + /// + [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] + private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr deviceInfoSet, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, IntPtr deviceInterfaceDetailData, int deviceInterfaceDetailDataSize, ref int requiredSize, SP_DEVINFO_DATA deviceInfoData); + + /// + /// The HidD_GetAttributes routine returns the attributes of a specified top-level collection. + /// + /// Specifies an open handle to a top-level collection + /// a caller-allocated HIDD_ATTRIBUTES structure that returns the attributes of the collection specified by HidDeviceObject + /// + [DllImport("hid.dll")] + private static extern Boolean HidD_GetAttributes(IntPtr hidDeviceObject, out HIDD_ATTRIBUTES attributes); + /// + /// The HidD_GetSerialNumberString routine returns the embedded string of a top-level collection that identifies the serial number of the collection's physical device. + /// + /// Specifies an open handle to a top-level collection + /// a caller-allocated buffer that the routine uses to return the requested serial number string + /// Specifies the length, in bytes, of a caller-allocated buffer provided at Buffer + /// + [DllImport("hid.dll")] + private static extern Boolean HidD_GetSerialNumberString(IntPtr hidDeviceObject, IntPtr buffer, int bufferLength); + + /// + /// The HidD_GetPreparsedData routine returns a top-level collection's preparsed data. + /// + /// Specifies an open handle to a top-level collection. + /// Pointer to the address of a routine-allocated buffer that contains a collection's preparsed data in a _HIDP_PREPARSED_DATA structure. + /// HidD_GetPreparsedData returns TRUE if it succeeds; otherwise, it returns FALSE. + [DllImport("hid.dll")] + private static extern Boolean HidD_GetPreparsedData(IntPtr hidDeviceObject, out IntPtr PreparsedData); + + [DllImport("hid.dll")] + private static extern Boolean HidD_FreePreparsedData(IntPtr PreparsedData); + + [DllImport("hid.dll")] + private static extern uint HidP_GetCaps(IntPtr PreparsedData, out HIDP_CAPS Capabilities); + + + /// + /// This function creates, opens, or truncates a file, COM port, device, service, or console. + /// + /// a null-terminated string that specifies the name of the object + /// Type of access to the object + /// Share mode for object + /// Ignored; set to NULL + /// Action to take on files that exist, and which action to take when files do not exist + /// File attributes and flags for the file + /// Ignored + /// An open handle to the specified file indicates success + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr CreateFile(string fileName, uint desiredAccess, uint shareMode, uint securityAttributes, uint creationDisposition, uint flagsAndAttributes, uint templateFile); + + /// + /// This function closes an open object handle. + /// + /// Handle to an open object + /// + [DllImport("kernel32.dll")] + private static extern int CloseHandle(IntPtr hObject); + + /// + /// This function reads data from a file, starting at the position indicated by the file pointer. + /// + /// Handle to the file to be read + /// Pointer to the buffer that receives the data read from the file + /// Number of bytes to be read from the file + /// Pointer to the number of bytes read + /// Unsupported; set to NULL + /// + [DllImport("Kernel32.dll", SetLastError = true)] + private static extern bool ReadFile(IntPtr file, byte[] buffer, uint numberOfBytesToRead, out uint numberOfBytesRead, IntPtr lpOverlapped); + + /// + /// This function writes data to a file + /// + /// Handle to the file to be written to + /// Pointer to the buffer containing the data to write to the file + /// Number of bytes to write to the file + /// Pointer to the number of bytes written by this function call + /// Unsupported; set to NULL + /// + [DllImport("Kernel32.dll", SetLastError = true)] + private static extern bool WriteFile(IntPtr file, byte[] buffer, uint numberOfBytesToWrite, out uint numberOfBytesWritten, IntPtr lpOverlapped); + + /// + /// Registers the device or type of device for which a window will receive notifications + /// + /// A handle to the window or service that will receive device events for the devices specified in the NotificationFilter parameter + /// A pointer to a block of data that specifies the type of device for which notifications should be sent + /// A Flags that specify the handle type + /// If the function succeeds, the return value is a device notification handle + [DllImport("User32.dll", SetLastError = true)] + private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags); + + /// + /// Closes the specified device notification handle. + /// + /// Device notification handle returned by the RegisterDeviceNotification function + /// + [DllImport("user32.dll", SetLastError = true)] + private static extern bool UnregisterDeviceNotification(IntPtr handle); + } + #region + /// + /// SP_DEVICE_INTERFACE_DATA structure defines a device interface in a device information set. + /// + public struct SP_DEVICE_INTERFACE_DATA + { + public int cbSize; + public Guid interfaceClassGuid; + public int flags; + public int reserved; + } + + /// + /// SP_DEVICE_INTERFACE_DETAIL_DATA structure contains the path for a device interface. + /// + [StructLayout(LayoutKind.Sequential, Pack = 2)] + internal struct SP_DEVICE_INTERFACE_DETAIL_DATA + { + internal int cbSize; + internal short devicePath; + } + + /// + /// SP_DEVINFO_DATA structure defines a device instance that is a member of a device information set. + /// + [StructLayout(LayoutKind.Sequential)] + public class SP_DEVINFO_DATA + { + public int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA)); + public Guid classGuid = Guid.Empty; // temp + public int devInst = 0; // dumy + public int reserved = 0; + } + /// + /// Flags controlling what is included in the device information set built by SetupDiGetClassDevs + /// + public enum DIGCF + { + DIGCF_DEFAULT = 0x00000001, // only valid with DIGCF_DEVICEINTERFACE + DIGCF_PRESENT = 0x00000002, + DIGCF_ALLCLASSES = 0x00000004, + DIGCF_PROFILE = 0x00000008, + DIGCF_DEVICEINTERFACE = 0x00000010 + } + /// + /// The HIDD_ATTRIBUTES structure contains vendor information about a HIDClass device + /// + public struct HIDD_ATTRIBUTES + { + public int Size; + public ushort VendorID; + public ushort ProductID; + public ushort VersionNumber; + } + + public struct HIDP_CAPS + { + public ushort Usage; + public ushort UsagePage; + public ushort InputReportByteLength; + public ushort OutputReportByteLength; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] + public ushort[] Reserved; + public ushort NumberLinkCollectionNodes; + public ushort NumberInputButtonCaps; + public ushort NumberInputValueCaps; + public ushort NumberInputDataIndices; + public ushort NumberOutputButtonCaps; + public ushort NumberOutputValueCaps; + public ushort NumberOutputDataIndices; + public ushort NumberFeatureButtonCaps; + public ushort NumberFeatureValueCaps; + public ushort NumberFeatureDataIndices; + } + /// + /// Type of access to the object. + /// + static class DESIREDACCESS + { + public const uint GENERIC_READ = 0x80000000; + public const uint GENERIC_WRITE = 0x40000000; + public const uint GENERIC_EXECUTE = 0x20000000; + public const uint GENERIC_ALL = 0x10000000; + } + /// + /// Action to take on files that exist, and which action to take when files do not exist. + /// + static class CREATIONDISPOSITION + { + public const uint CREATE_NEW = 1; + public const uint CREATE_ALWAYS = 2; + public const uint OPEN_EXISTING = 3; + public const uint OPEN_ALWAYS = 4; + public const uint TRUNCATE_EXISTING = 5; + } + /// + /// File attributes and flags for the file. + /// + static class FLAGSANDATTRIBUTES + { + public const uint FILE_FLAG_WRITE_THROUGH = 0x80000000; + public const uint FILE_FLAG_OVERLAPPED = 0x40000000; + public const uint FILE_FLAG_NO_BUFFERING = 0x20000000; + public const uint FILE_FLAG_RANDOM_ACCESS = 0x10000000; + public const uint FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000; + public const uint FILE_FLAG_DELETE_ON_CLOSE = 0x04000000; + public const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; + public const uint FILE_FLAG_POSIX_SEMANTICS = 0x01000000; + public const uint FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000; + public const uint FILE_FLAG_OPEN_NO_RECALL = 0x00100000; + public const uint FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000; + } + /// + /// Serves as a standard header for information related to a device event reported through the WM_DEVICECHANGE message. + /// + [StructLayout(LayoutKind.Sequential)] + public struct DEV_BROADCAST_HDR + { + public int dbcc_size; + public int dbcc_devicetype; + public int dbcc_reserved; + } + /// + /// Contains information about a class of devices + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct DEV_BROADCAST_DEVICEINTERFACE + { + public int dbcc_size; + public int dbcc_devicetype; + public int dbcc_reserved; + public Guid dbcc_classguid; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string dbcc_name; + } + #endregion +} diff --git a/SlnMesnac.Common/HidUtils.cs b/SlnMesnac.Common/HidUtils.cs new file mode 100644 index 0000000..1b082f8 --- /dev/null +++ b/SlnMesnac.Common/HidUtils.cs @@ -0,0 +1,357 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +#region << 版 本 注 释 >> +/*-------------------------------------------------------------------- +* 版权所有 (c) 2024 WenJY 保留所有权利。 +* CLR版本:4.0.30319.42000 +* 机器名称:T14-GEN3-7895 +* 命名空间:ConsoleApp +* 唯一标识:988d1fd9-7907-40bb-9147-51a2c953d9f8 +* +* 创建者:WenJY +* 电子邮箱: +* 创建时间:2024-05-22 11:19:23 +* 版本:V1.0.0 +* 描述: +* +*-------------------------------------------------------------------- +* 修改人: +* 时间: +* 修改说明: +* +* 版本:V1.0.0 +*--------------------------------------------------------------------*/ +#endregion << 版 本 注 释 >> +namespace ConsoleApp +{ + public class HidUtils + { + #region parameter Define + HIDInterface hid = new HIDInterface(); + + + struct connectStatusStruct + { + public bool preStatus; + public bool curStatus; + } + + connectStatusStruct connectStatus = new connectStatusStruct(); + + /// + /// 推送连接状态信息 + /// + /// + public delegate void PushConnectedDelegate(bool isConnected); + public PushConnectedDelegate pushConnectedDelegateEvent; + + + /// + /// 推送接收数据信息 + /// + /// + /// + public delegate void PushReceiveDataDele(byte[] datas,string str); + public PushReceiveDataDele pushReceiveDataEvent; + + /// + /// 推送设备状态修改 + /// + /// + public delegate void PushDeviceStatusDelegate(bool isFlag); + public PushDeviceStatusDelegate pushDeviceStatusDelegateEvent; + + /// + /// ReadBlock + /// + /// + public delegate void PushReadBlockDelegate(TagBlock tagBlock); + public PushReadBlockDelegate pushReadBlockDelegateEvent; + + #endregion + + public void Initial() + { + + hid.StatusConnected = StatusConnected; + hid.DataReceived = DataReceived; + + HIDInterface.HidDevice hidDevice = new HIDInterface.HidDevice(); + hidDevice.vID = (ushort)1285; + hidDevice.pID = (ushort)20560; + hidDevice.serial = ""; + hid.AutoConnect(hidDevice); + + } + + public void Close() + { + hid.StopAutoConnect(); + } + + public bool SendBytes(byte[] data) + { + + return hid.Send(data); + + } + + public void StartScan() + { + byte[] array = new byte[12] + { + 12, 87, 89, 8, 0, 0, 255, 255, 1, 0, + 210, 15 + }; + ushort value = CalculateCRC(array); + byte[] bytes = BitConverter.GetBytes(value); + array[array.Length - 2] = bytes[0]; + array[array.Length - 1] = bytes[1]; + SendBytes(array); + } + + public void StopScan() + { + byte[] array = new byte[12] + { + 12, 87, 89, 8, 0, 0, 255, 255, 0, 0, + 210, 15 + }; + ushort value = CalculateCRC(array); + byte[] bytes = BitConverter.GetBytes(value); + array[array.Length - 2] = bytes[0]; + array[array.Length - 1] = bytes[1]; + SendBytes(array); + + + } + + public void ReadBlockData(string BlockAddr, string BlockNum) + { + byte[] data = Get_Order(0, 0, 16, 0, 36, new byte[10] + { + 112, + 105, + 180, + 242, + 80, + 1, + 4, + 224, + Convert.ToByte(BlockAddr, 16), + Convert.ToByte(BlockNum, 16) + }); + + SendBytes(data); + + } + + public void WriteBlock(string BlockAddr, string BlockNum, List BlockList) + { + int num = int.Parse(BlockNum); + if (num / 2 > BlockList.Count) + { + Console.WriteLine( "输入数据有误!"); + return; + } + + int num2 = 10 + num * 2; + byte[] array = new byte[num2]; + int num3 = 0; + array[num3++] = 138; + array[num3++] = 138; + array[num3++] = 186; + array[num3++] = 242; + array[num3++] = 80; + array[num3++] = 1; + array[num3++] = 4; + array[num3++] = 224; + array[num3++] = Convert.ToByte(BlockAddr, 16); + array[num3++] = Convert.ToByte(BlockNum, 16); + if (num % 2 != 0) + { + num++; + } + + for (int i = 0; i < num / 2; i++) + { + string text = BlockList[i]; + if (text.Length != 8 && text.Length != 4) + { + Console.WriteLine("长度不符合!"); + return; + } + + foreach (char c in text) + { + if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')) + { + Console.WriteLine("数据含有不合法字符!"); + return; + } + } + + for (int k = 0; k < text.Length / 2; k++) + { + array[num3++] = Convert.ToByte(text.Substring(k * 2, 2), 16); + } + } + + byte[] data = Get_Order(0, 0, 1, 0, 37, array); + SendBytes(data); + } + + public void DataReceived(object sender, byte[] bytes) + { + if (bytes[7] == 31 && (bytes[8] == 0 || bytes[8] == 1)) //修改设备返回信息 + { + bool isFlag = false; + if (bytes[10] == 1 && bytes[11] == 1) + { + isFlag = false; + } + else + { + isFlag = true; + } + + if (pushDeviceStatusDelegateEvent != null) + pushDeviceStatusDelegateEvent(isFlag); + } + + if (bytes[7] == 31 && bytes[8] == 36) + { + TagBlock tagBlock = new TagBlock(); + tagBlock.Block = new List(); + int num = 0; + int num2 = 0; + string text = ""; + if (bytes[bytes.Length - 3] == 1 && bytes[bytes.Length - 4] == 1) + { + tagBlock.State = false; + return; + } + + for (int i = 10; i < bytes.Length - 4; i++) + { + text += bytes[i].ToString("X2"); + num2++; + if (num2 == 4) + { + tagBlock.Block.Add(text); + num++; + num2 = 0; + text = ""; + } + } + + if (text.Length > 0) + { + tagBlock.Block.Add(text); + num++; + num2 = 0; + text = ""; + } + + if (pushReadBlockDelegateEvent != null) + pushReadBlockDelegateEvent(tagBlock); + } + + if (bytes[7] == 31 && bytes[8] == 37) //写入结果 + { + + bool isFlag = false; + if (bytes[10] == 1 && bytes[11] == 1) + { + isFlag = false; + } + else + { + isFlag = true; + } + } + + if (bytes[7] == 31 && bytes[8] == 17) + { + string str = ""; + for (int index = 10; index <= bytes.Length - 6; ++index) + { + str += bytes[index].ToString("X2"); + if (index != bytes.Length - 6) + str += " "; + } + if (pushReceiveDataEvent != null) + pushReceiveDataEvent(bytes, str); + } + } + + + public void StatusConnected(object sender, bool isConnect) + { + connectStatus.curStatus = isConnect; + if (connectStatus.curStatus == connectStatus.preStatus) //connect + return; + connectStatus.preStatus = connectStatus.curStatus; + + if (connectStatus.curStatus) + { + Console.WriteLine("连接成功"); + } + else + { + Console.WriteLine("无法连接"); + } + + if (pushConnectedDelegateEvent != null) + pushConnectedDelegateEvent(connectStatus.curStatus); + } + + private byte[] Get_Order(byte Source_Address_0, byte Source_Address_1, byte Destination_Address_0, byte Destination_Address_1, byte Type, byte[] data) + { + int num = 12 + data.Length; + byte[] array = new byte[num]; + int num2 = 0; + array[num2++] = (byte)num; + array[num2++] = 87; + array[num2++] = 89; + array[num2++] = (byte)(num - 4); + array[num2++] = Source_Address_0; + array[num2++] = Source_Address_1; + array[num2++] = Destination_Address_0; + array[num2++] = Destination_Address_1; + array[num2++] = Type; + array[num2++] = 0; + for (int i = 0; i < data.Length; i++) + { + array[num2++] = data[i]; + } + + ushort value = CalculateCRC(array); + byte[] bytes = BitConverter.GetBytes(value); + array[num2++] = bytes[0]; + array[num2++] = bytes[1]; + return array; + } + + private ushort CalculateCRC(byte[] data) + { + ushort num1 = ushort.MaxValue; + foreach (byte num2 in data) + { + num1 ^= (ushort)num2; + for (int index = 0; index < 8; ++index) + { + if (((int)num1 & 1) == 1) + num1 = (ushort)((int)num1 >> 1 ^ 33800); + else + num1 >>= 1; + } + } + return num1; + } + } +} \ No newline at end of file diff --git a/SlnMesnac.Common/SlnMesnac.Common.csproj b/SlnMesnac.Common/SlnMesnac.Common.csproj index d2f2774..3b8369c 100644 --- a/SlnMesnac.Common/SlnMesnac.Common.csproj +++ b/SlnMesnac.Common/SlnMesnac.Common.csproj @@ -8,11 +8,12 @@ + - C:\Users\Administrator\Desktop\信明橡塑\Tool For HID Mode_V1.0.0\Tool For HID Mode_V1.0.0\HighRFIDSendCardDLL.dll + C:\Users\Administrator\Desktop\信明橡塑\测试文件\ConsoleApp\Library\HighRFIDSendCardDLL.dll diff --git a/SlnMesnac.Common/TagBlock.cs b/SlnMesnac.Common/TagBlock.cs new file mode 100644 index 0000000..54ed38f --- /dev/null +++ b/SlnMesnac.Common/TagBlock.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +#region << 版 本 注 释 >> +/*-------------------------------------------------------------------- +* 版权所有 (c) 2024 WenJY 保留所有权利。 +* CLR版本:4.0.30319.42000 +* 机器名称:T14-GEN3-7895 +* 命名空间:ConsoleApp +* 唯一标识:7c94ad53-5ae7-4c24-98b7-6b6296ccdbb4 +* +* 创建者:WenJY +* 电子邮箱: +* 创建时间:2024-05-22 17:48:43 +* 版本:V1.0.0 +* 描述: +* +*-------------------------------------------------------------------- +* 修改人: +* 时间: +* 修改说明: +* +* 版本:V1.0.0 +*--------------------------------------------------------------------*/ +#endregion << 版 本 注 释 >> +namespace ConsoleApp +{ + public class TagBlock + { + public List Block { get; set; } + + public bool State { get; set; } + } +} diff --git a/SlnMesnac.Ioc/DependencyConfigurator.cs b/SlnMesnac.Ioc/DependencyConfigurator.cs index 6234bb9..5ecd9ff 100644 --- a/SlnMesnac.Ioc/DependencyConfigurator.cs +++ b/SlnMesnac.Ioc/DependencyConfigurator.cs @@ -49,7 +49,7 @@ namespace SlnMesnac.Ioc RegisterTypeTransient(builder, Assembly.LoadFrom("SlnMesnac.Rfid.dll")); //注入通用类 - RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Common.dll")); + //RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Common.dll")); //注入MQTT RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Mqtt.dll")); diff --git a/SlnMesnac.Model/domain/BaseStaffInfo.cs b/SlnMesnac.Model/domain/BaseStaffInfo.cs new file mode 100644 index 0000000..2b379dd --- /dev/null +++ b/SlnMesnac.Model/domain/BaseStaffInfo.cs @@ -0,0 +1,98 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace SlnMesnac.Model.domain +{ + [SugarTable("base_staff_info"), TenantAttribute("mes")] + [DataContract(Name = "BaseStaffInfo 员工信息")] + #pragma warning disable CS8618 + public class BaseStaffInfo + { + /// + /// + /// + [SugarColumn(ColumnName = "obj_id", IsPrimaryKey = true)] + public int ObjId { get; set; } + + /// + /// 员工id + /// + [SugarColumn(ColumnName = "staff_id")] + public string StaffId { get; set; } + + /// + /// 员工名称 + /// + [SugarColumn(ColumnName = "staff_name")] + public string StaffName { get; set; } + + /// + /// 卡号1 + /// + [SugarColumn(ColumnName = "card_id")] + public string CardId { get; set; } + + /// + /// 班组编号 + /// + [SugarColumn(ColumnName = "team_code")] + public string TeamCode { get; set; } + + /// + /// 手机号 + /// + [SugarColumn(ColumnName = "phone_number")] + public string PhoneNumber { get; set; } + + /// + /// 用户性别 + /// + [SugarColumn(ColumnName = "sex")] + public string Sex { get; set; } + + /// + /// 卡密 + /// + [SugarColumn(ColumnName = "pass_word")] + public string Password { get; set; } + + /// + /// 删除标志 + /// + [SugarColumn(ColumnName = "del_flag")] + public string DelFlag { get; set; } + + /// + /// 创建者 + /// + [SugarColumn(ColumnName = "create_by")] + public string CreateBy { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "create_time")] + public string CreateTime { get; set; } + + /// + /// 更新者 + /// + [SugarColumn(ColumnName = "update_by")] + public string UpdateBy { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "update_time")] + public string UpdateTime { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + public string Remark { get; set; } + } +} diff --git a/SlnMesnac.Model/domain/ProdPLanInfo.cs b/SlnMesnac.Model/domain/ProdPLanInfo.cs new file mode 100644 index 0000000..97a7b94 --- /dev/null +++ b/SlnMesnac.Model/domain/ProdPLanInfo.cs @@ -0,0 +1,116 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace SlnMesnac.Model.domain +{ + [SugarTable("prod_plan_info"), TenantAttribute("mes")] + [DataContract(Name = "ProdPLanInfo 员工信息")] + public class ProdPLanInfo + { + /// + /// + /// + [SugarColumn(ColumnName = "obj_id", IsPrimaryKey = true)] + public int ObjId { get; set; } + + /// + /// 工单编号 + /// + [SugarColumn(ColumnName = "plan_code")] + public string PlanCode { get; set; } + + /// + /// ERP订单编号 + /// + [SugarColumn(ColumnName = "order_code")] + public string StaffId { get; set; } + + /// + /// 物料编号 + /// + [SugarColumn(ColumnName = "material_code")] + public string MaterialCode { get; set; } + + /// + /// 物料名称 + /// + [SugarColumn(ColumnName = "material_name")] + public string MaterialName { get; set; } + + /// + /// 计划工位 + /// + [SugarColumn(ColumnName = "product_line_code")] + public string ProductLineCode { get; set; } + + /// + /// 计划班组 + /// + [SugarColumn(ColumnName = "team_code")] + public string TeamCode { get; set; } + + /// + /// 计划数量 + /// + [SugarColumn(ColumnName = "plan_amount")] + public string PlanAmount { get; set; } + + /// + /// 完成数量 + /// + [SugarColumn(ColumnName = "complete_amount")] + public string CompleteAmount { get; set; } + + /// + /// 实际开始时间 + /// + [SugarColumn(ColumnName = "begin_time")] + public string BeginTIme { get; set; } + + /// + /// 实际完成时间 + /// + [SugarColumn(ColumnName = "end_time")] + public string EndTime { get; set; } + + /// + /// 完成标识 + /// + [SugarColumn(ColumnName = "comp_flag")] + public string CompFlag { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "created_by")] + public string CreatedBy { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "created_time")] + public string CreatedTime { get; set; } + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "updated_by")] + public string UpdatedBy { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "updated_time")] + public string UpdatedTime { get; set; } + + /// + /// 设备编号 + /// + [SugarColumn(ColumnName = "device_code")] + public string DeviceCode { get; set; } + + } +} diff --git a/SlnMesnac.Model/domain/RecordStaffAttendance.cs b/SlnMesnac.Model/domain/RecordStaffAttendance.cs new file mode 100644 index 0000000..f93d35d --- /dev/null +++ b/SlnMesnac.Model/domain/RecordStaffAttendance.cs @@ -0,0 +1,80 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace SlnMesnac.Model.domain +{ + [SugarTable("record_staff_attendance"), TenantAttribute("mes")] + [DataContract(Name = "RecordStaffAttendance 记录员工打卡")] + public class RecordStaffAttendance + { + /// + /// + /// + [SugarColumn(ColumnName = "obj_id", IsPrimaryKey = true)] + public int ObjId { get; set; } + + /// + /// 员工id + /// + [SugarColumn(ColumnName = "staff_id")] + public string StaffId { get; set; } + + /// + /// 打卡类型 + /// + [SugarColumn(ColumnName = "attendance_type")] + public string AttendanceType { get; set; } + + /// + /// 班组编号 + /// + [SugarColumn(ColumnName = "team_code")] + public string TeamCode { get; set; } + + /// + /// 班次 + /// + [SugarColumn(ColumnName = "classes")] + public string Classes { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + public string Remark { get; set; } + + /// + /// 是否标识 + /// + [SugarColumn(ColumnName = "is_flag")] + public string IsFlag { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "created_by")] + public string CreatedBy { get; set; } + + /// + /// 打卡时间 + /// + [SugarColumn(ColumnName = "created_time")] + public string CreatedTime { get; set; } + + + /// + /// 更新人 + /// + [SugarColumn(ColumnName = "updated_by")] + public string UpdatedBy { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(ColumnName = "updated_time")] + public string UpdatedTime { get; set; } + } +} diff --git a/SlnMesnac.Repository/service/IBaseStaffService.cs b/SlnMesnac.Repository/service/IBaseStaffService.cs new file mode 100644 index 0000000..4568de8 --- /dev/null +++ b/SlnMesnac.Repository/service/IBaseStaffService.cs @@ -0,0 +1,25 @@ +using SlnMesnac.Model.domain; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.Repository.service +{ + public interface IBaseStaffService : IBaseService + { + + /// + /// 获取所有员工信息 + /// + /// + List GetStaffInfos(); + + /// + /// 通过卡号获取员工信息 + /// + /// + /// + BaseStaffInfo GetStaffInfoByCardId(string cardId); + } +} diff --git a/SlnMesnac.Repository/service/IRecordStaffAttendanceService.cs b/SlnMesnac.Repository/service/IRecordStaffAttendanceService.cs new file mode 100644 index 0000000..920c114 --- /dev/null +++ b/SlnMesnac.Repository/service/IRecordStaffAttendanceService.cs @@ -0,0 +1,24 @@ +using SlnMesnac.Model.domain; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.Repository.service +{ + public interface IRecordStaffAttendanceService : IBaseService + { + /// + /// 获取记录员工打卡信息 + /// + /// + List GetRecordStaffAttendances(); + + /// + /// 验证添加用户信息,有一个错误时进行回滚 + /// + /// + /// + bool InsertRecordStaffAttendance(List recordStaffAttendances); + } +} diff --git a/SlnMesnac.Repository/service/Impl/BaseStaffServiceImpl.cs b/SlnMesnac.Repository/service/Impl/BaseStaffServiceImpl.cs new file mode 100644 index 0000000..46db4d0 --- /dev/null +++ b/SlnMesnac.Repository/service/Impl/BaseStaffServiceImpl.cs @@ -0,0 +1,55 @@ +using Microsoft.Extensions.Logging; +using SlnMesnac.Model.domain; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.Repository.service.Impl +{ + public class BaseStaffServiceImpl : BaseServiceImpl, IBaseStaffService + { + private ILogger _logger; + public BaseStaffServiceImpl(Repository repository, ILogger logger) : base(repository) + { + _logger = logger; + } + + /// + /// 通过卡号获取员工信息 + /// + /// + /// + public BaseStaffInfo GetStaffInfoByCardId(string cardId) + { + BaseStaffInfo staffInfo = null; + try + { + staffInfo = base._rep.GetFirst(x => x.CardId == cardId); + } + catch (Exception ex) + { + _logger.LogError($"根据卡号获取员工信息异常:{ex.Message}"); + } + return staffInfo; + } + + /// + /// 获取所有的员工信息 + /// + /// + public List GetStaffInfos() + { + List staffInfos = null; + try + { + staffInfos = base._rep.GetList(); + } + catch (Exception ex) + { + _logger.LogError($"获取员工信息异常:{ex.Message}"); + } + return staffInfos; + } + } +} diff --git a/SlnMesnac.Repository/service/Impl/RecordStaffAttendanceServiceImpl.cs b/SlnMesnac.Repository/service/Impl/RecordStaffAttendanceServiceImpl.cs new file mode 100644 index 0000000..132d24e --- /dev/null +++ b/SlnMesnac.Repository/service/Impl/RecordStaffAttendanceServiceImpl.cs @@ -0,0 +1,50 @@ +using Microsoft.Extensions.Logging; +using SlnMesnac.Model.domain; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.Repository.service.Impl +{ + public class RecordStaffAttendanceServiceImpl : BaseServiceImpl,IRecordStaffAttendanceService + { + private readonly ILogger _logger; + + public RecordStaffAttendanceServiceImpl(Repository rep, ILogger logger) : base(rep) + { + _logger = logger; + } + + public List GetRecordStaffAttendances() + { + List records = null; + try + { + records = base._rep.GetList(); + } + catch (Exception ex) + { + _logger.LogError($"获取员工打卡信息异常{ex.Message}"); + } + return records; + } + + public bool InsertRecordStaffAttendance(List records) + { + bool result = false; + try + { + base._rep.AsTenant().BeginTran(); + result = base._rep.InsertRange(records); + base._rep.AsTenant().CommitTran(); + } + catch (Exception ex) + { + base._rep.AsTenant().RollbackTran(); + _logger.LogError($"员工打卡信息添加异常:{ex.Message}"); + } + return result; + } + } +} diff --git a/SlnMesnac.Repository/service/ProdPlanInfoService.cs b/SlnMesnac.Repository/service/ProdPlanInfoService.cs new file mode 100644 index 0000000..3c782ae --- /dev/null +++ b/SlnMesnac.Repository/service/ProdPlanInfoService.cs @@ -0,0 +1,17 @@ +using SlnMesnac.Model.domain; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.Repository.service +{ + public interface ProdPlanInfoService : IBaseService + { + /// + /// 获取工单信息 + /// + /// + List GetRecordStaffAttendances(); + } +} diff --git a/SlnMesnac.WPF/App.xaml.cs b/SlnMesnac.WPF/App.xaml.cs index ea819ab..1d18174 100644 --- a/SlnMesnac.WPF/App.xaml.cs +++ b/SlnMesnac.WPF/App.xaml.cs @@ -10,6 +10,8 @@ using Autofac.Extensions.DependencyInjection; using SlnMesnac.Plc; using System.Collections.Generic; using SlnMesnac.Rfid; +using SlnMesnac.Common; +using ConsoleApp; namespace SlnMesnac.WPF { @@ -46,6 +48,13 @@ namespace SlnMesnac.WPF var logPath = $"{appConfig.logPath}/Logs/{DateTime.UtcNow:yyyy-MM-dd}/"; Log.Information($"系统初始化完成,日志存放路径:{appConfig.logPath}"); + var hidUtils = ServiceProvider.GetService(); + hidUtils.Initial(); + hidUtils.pushReceiveDataEvent += (bytes, str) => + { + Console.WriteLine($"收到打卡信息:{str}"); + }; + } /// @@ -67,6 +76,10 @@ namespace SlnMesnac.WPF { base.OnExit(e); + var hidUtils = ServiceProvider.GetService(); + hidUtils.Close(); + //hidUtils.StopScan(); + Log.Information($"系统退出,当前时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); // 释放资源 // ... diff --git a/SlnMesnac.WPF/SlnMesnac.WPF.csproj b/SlnMesnac.WPF/SlnMesnac.WPF.csproj index fa19b62..b751418 100644 --- a/SlnMesnac.WPF/SlnMesnac.WPF.csproj +++ b/SlnMesnac.WPF/SlnMesnac.WPF.csproj @@ -45,7 +45,7 @@ - C:\Users\Administrator\Desktop\信明橡塑\Tool For HID Mode_V1.0.0\Tool For HID Mode_V1.0.0\HighRFIDSendCardDLL.dll + C:\Users\Administrator\Desktop\信明橡塑\测试文件\ConsoleApp\Library\HighRFIDSendCardDLL.dll diff --git a/SlnMesnac.WPF/Startup.cs b/SlnMesnac.WPF/Startup.cs index f65ebe7..5b89385 100644 --- a/SlnMesnac.WPF/Startup.cs +++ b/SlnMesnac.WPF/Startup.cs @@ -12,6 +12,9 @@ using SlnMesnac.Rfid; using SlnMesnac.Ioc; using SlnMesnac.Plc; using SlnMesnac.Extensions; +using SlnMesnac.Common; +using HighRFIDSendCardDemo; +using ConsoleApp; namespace SlnMesnac.WPF { @@ -45,6 +48,12 @@ namespace SlnMesnac.WPF //注册RFID工厂 services.AddRfidFactorySetup(); + + services.AddSingleton(); + + //services.AddSingleton(); + + services.AddSingleton(); } /// diff --git a/SlnMesnac.WPF/UserControls/EmployeeLoginPage.xaml b/SlnMesnac.WPF/UserControls/EmployeeLoginPage.xaml index e837645..fddd41b 100644 --- a/SlnMesnac.WPF/UserControls/EmployeeLoginPage.xaml +++ b/SlnMesnac.WPF/UserControls/EmployeeLoginPage.xaml @@ -91,6 +91,7 @@ + @@ -114,10 +115,10 @@ - public partial class EmployeeLoginPage : UserControl { - HIDMode hIDMode = new HIDMode(); - DeviceClass deviceClass = new DeviceClass(); + //HIDMode hIDMode = new HIDMode(); + //DeviceClass deviceClass = new DeviceClass(); DispatcherTimer timer; + + public EmployeeLoginPage() { InitializeComponent(); - //timer = new DispatcherTimer(); - //timer.Interval = TimeSpan.FromSeconds(5); - //timer.Tick += Timer_Tick; - + timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromSeconds(5); + timer.Tick += Timer_Tick; this.DataContext = new EmployeeLoginViewModel(); } + + /// /// 定时器 /// @@ -55,7 +57,5 @@ namespace SlnMesnac.WPF.Page //hIDMode.ConnectRfidHid(); //timer.Start(); } - - } } diff --git a/SlnMesnac.WPF/ViewModel/EmployeeLoginViewModel.cs b/SlnMesnac.WPF/ViewModel/EmployeeLoginViewModel.cs index 5c2195a..9c1964c 100644 --- a/SlnMesnac.WPF/ViewModel/EmployeeLoginViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/EmployeeLoginViewModel.cs @@ -2,51 +2,199 @@ using GalaSoft.MvvmLight.Command; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using SlnMesnac.Business.business; using SlnMesnac.Common; +using SlnMesnac.Repository.service; +using SlnMesnac.Repository.service.Impl; +using SqlSugar; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; +using System.Windows.Input; namespace SlnMesnac.WPF.ViewModel { - public class EmployeeLoginViewModel : ViewModelBase + public class EmployeeLoginViewModel : ViewModelBase,INotifyPropertyChanged { + private readonly RfidHandleBusniess rfidHandle; private readonly ILogger _logger; - public EmployeeLoginViewModel() - { - CheckInCommand = new RelayCommand(CheckIn); - } + private IBaseStaffService baseStaffService; + public string _isCheckInButtonEnabled; + private string _isCheckOutButtonEnabled; + private string _checkInButtonColor; + private string _checkOutButtonColor = "#009999"; /// - /// 获取标签信息 + /// 按钮文字转换事件 /// - private void GetTagInfo() - { + public event PropertyChangedEventHandler PropertyChanged; + /// + /// 上班命令 + /// + public ICommand CheckInCommand { get; private set; } + /// + /// 下班命令 + /// + public ICommand CheckOutCommand { get; private set; } + /// + /// 结束命令 + /// + public ICommand OverCommand { get; private set; } + private string _checkInButtonText = "上班打卡"; + private string _checkOutButtonText = "下班打卡"; + + /// + /// 上班打卡文本 + /// + public string CheckInButtonText + { + get { return _checkInButtonText; } + set + { + _checkInButtonText = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheckInButtonText))); + } } - #region 事件定义 /// /// 上班打卡 /// - public RelayCommand CheckInCommand { get; set; } + public string IsCheckInButtonEnabled + { + get { return _isCheckInButtonEnabled; } + set + { + _isCheckInButtonEnabled = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsCheckInButtonEnabled))); + } + } + + /// + ///下班打卡文本 + /// + public string CheckOutButtonText + { + get { return _checkOutButtonText; } + set + { + _checkOutButtonText = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheckOutButtonText))); + } + } /// /// 下班打卡 /// - public RelayCommand CheckOutCommand { get; set; } - #endregion - - public void CheckIn() + public string IsCheckOutButtonEnabled { - var str = ""; + get { return _isCheckOutButtonEnabled; } + set + { + _isCheckOutButtonEnabled = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsCheckOutButtonEnabled))); + } + } - var hid = App.ServiceProvider.GetService(); + /// + /// 上班打卡按钮颜色 + /// + public string CheckInButtonColor + { + get { return _checkInButtonColor; } + set + { + _checkInButtonColor = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheckInButtonColor))); + } + } - hid.ConnectRfidHid(); + /// + /// 下班打卡按钮颜色 + /// + public string CheckOutButtonColor + { + get { return _checkOutButtonColor; } + set + { + _checkOutButtonColor = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheckOutButtonColor))); + } + } + public EmployeeLoginViewModel() + { + CheckInCommand = new RelayCommand(CheckIn); + CheckOutCommand = new RelayCommand(CheckOut); + OverCommand = new RelayCommand(Over); + rfidHandle = App.ServiceProvider.GetService(); + baseStaffService = App.ServiceProvider.GetService(); + IsCheckInButtonEnabled = "True"; + IsCheckOutButtonEnabled = "True"; + CheckInButtonColor = "#009999"; + CheckOutButtonColor = "#009999"; + } + + /// + /// 上班打卡事件 + /// + private void CheckIn() + { + if (CheckInButtonText == "上班打卡") + { + // 执行上班打卡逻辑 + CheckInButtonText = "结束打卡"; + IsCheckOutButtonEnabled = "False"; // Disable CheckOutButton + CheckOutButtonColor = "Gray"; + rfidHandle.CheckIn(); + } + else + { + // 执行结束打卡逻辑 + CheckInButtonText = "上班打卡"; + IsCheckOutButtonEnabled = "True"; // Enable CheckOutButton + CheckOutButtonColor = "#009999"; + rfidHandle.CloseRfid(); + } + } + + /// + /// 下班打卡事件 + /// + private void CheckOut() + { + if (CheckOutButtonText == "下班打卡") + { + // 执行下班打卡逻辑 + CheckOutButtonText = "结束打卡"; + IsCheckInButtonEnabled = "False"; // Disable CheckInButton + //IsCheckOutButtonEnabled = "True"; + CheckInButtonColor = "Gray"; + rfidHandle.CheckOut(); + } + else + { + // 执行结束打卡逻辑 + CheckOutButtonText = "下班打卡"; + IsCheckInButtonEnabled = "True"; // Enable CheckInButton + //IsCheckOutButtonEnabled="False"; + CheckInButtonColor = "#009999"; + rfidHandle.CloseRfid(); + } + } + + /// + /// 结束打卡事件 + /// + private void Over() + { + // 执行结束打卡的逻辑 + CheckInButtonText = "上班打卡"; + CheckOutButtonText = "下班打卡"; } } } diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json index 9346894..c1eaf1b 100644 --- a/SlnMesnac.WPF/appsettings.json +++ b/SlnMesnac.WPF/appsettings.json @@ -13,13 +13,13 @@ { "configId": "mes", "dbType": 1, - "connStr": "server=.;uid=sa;pwd=123456;database=JiangYinMENS" - }, - { - "configId": "mcs", - "dbType": 3, - "connStr": "Data Source=175.27.215.92/helowin;User ID=aucma_scada;Password=aucma" + "connStr": "server=121.37.164.0;uid=sa;pwd=Yq123456;database=xmxs_os" } + //{ + // "configId": "mcs", + // "dbType": 3, + // "connStr": "Data Source=121.37.164.0/helowin;User ID=aucma_scada;Password=aucma" + //} ], "PlcConfig": [ { diff --git a/SlnMesnac.sln b/SlnMesnac.sln index b713cfb..6c9ca4a 100644 --- a/SlnMesnac.sln +++ b/SlnMesnac.sln @@ -33,9 +33,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Ioc", "SlnMesnac. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Generate", "SlnMesnac.Generate\SlnMesnac.Generate.csproj", "{00FC9358-2381-4C1B-BD45-6D31DD1DB7D3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlnMesnac.Extensions", "SlnMesnac.Extensions\SlnMesnac.Extensions.csproj", "{6D929802-24AA-42A7-92C5-303C3D59A990}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Extensions", "SlnMesnac.Extensions\SlnMesnac.Extensions.csproj", "{6D929802-24AA-42A7-92C5-303C3D59A990}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlnMesnac.Redis", "SlnMesnac.Redis\SlnMesnac.Redis.csproj", "{0E041719-E755-43CD-8A0E-DF62E0B2E463}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Redis", "SlnMesnac.Redis\SlnMesnac.Redis.csproj", "{0E041719-E755-43CD-8A0E-DF62E0B2E463}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "TestProject\TestProject.csproj", "{3B9521EC-E6B7-4372-B62B-848F9DC9EB04}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -111,6 +113,10 @@ Global {0E041719-E755-43CD-8A0E-DF62E0B2E463}.Debug|Any CPU.Build.0 = Debug|Any CPU {0E041719-E755-43CD-8A0E-DF62E0B2E463}.Release|Any CPU.ActiveCfg = Release|Any CPU {0E041719-E755-43CD-8A0E-DF62E0B2E463}.Release|Any CPU.Build.0 = Release|Any CPU + {3B9521EC-E6B7-4372-B62B-848F9DC9EB04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B9521EC-E6B7-4372-B62B-848F9DC9EB04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B9521EC-E6B7-4372-B62B-848F9DC9EB04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B9521EC-E6B7-4372-B62B-848F9DC9EB04}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TestProject/GlobalUsings.cs b/TestProject/GlobalUsings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/TestProject/GlobalUsings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/TestProject/TestProject.csproj b/TestProject/TestProject.csproj new file mode 100644 index 0000000..c63dea2 --- /dev/null +++ b/TestProject/TestProject.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + + diff --git a/TestProject/UnitTest1.cs b/TestProject/UnitTest1.cs new file mode 100644 index 0000000..2c9f600 --- /dev/null +++ b/TestProject/UnitTest1.cs @@ -0,0 +1,25 @@ +using SlnMesnac.Common; + +namespace TestProject +{ + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void Test1() + { + + while (true) + { + Thread.Sleep(1000); + } + + + // Assert.Pass(); + } + } +} \ No newline at end of file