using MvCodeReaderSDKNet; using System; using System.Collections.Generic; using System.Drawing; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Threading; using static System.Runtime.CompilerServices.RuntimeHelpers; using HighWayIot.Log4net; using HighWayIot.Config; using System.Security.Policy; using HighWayIot.Repository.service; using System.Linq; using HighWayIot.Repository.service.Impl; namespace Aucma.Core.Scanner { public class MvCodeHelper { private static AppConfig appConfig = AppConfig.Instance; public static bool m_bGrabbing = true; private static string SheellLastCode; private static string LinerLastCode; // 内胆扫码器ip private static string LinerScannerIp = appConfig.linerHikRobotIp; // 箱壳扫码器ip private static string ShellScannerIp = appConfig.shellHikRobotIp; private static IRealTaskInfoService _realTaskInfoService = new RealTaskInfoServiceImpl(); #region 全局变量定义 public static DateTime ShellLiveTime = DateTime.Now; public static DateTime LinerLiveTime = DateTime.Now; #endregion #region 委托事件 /// /// 刷新扫码器状态 /// /// /// public delegate void RefreshState(string ip, bool flag); public static event RefreshState RefreshStateEvent; public delegate void RefreshMaterialCodeStr(string materialCodeStr, string ip); public static event RefreshMaterialCodeStr RefreshMaterialCodeStrEvent; //NoRead事件通知 public delegate void MessageNoRead(string storeCode); public static event MessageNoRead MessageNoReadEvent; /// /// 日志信息刷新 /// /// public delegate void RefreshLogMessage(string message); public static event RefreshLogMessage RefreshLogMessageEvent; #endregion public static void ShellImageCallbackFunc(IntPtr pData, IntPtr pstFrameInfoEx2, IntPtr pUser) { var stFrameInfo = (MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)Marshal.PtrToStructure(pstFrameInfoEx2, typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)); MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2 stBcrResult = (MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)Marshal.PtrToStructure(stFrameInfo.UnparsedBcrList.pstCodeListEx2, typeof(MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)); if(stBcrResult.nCodeNum==0) { //更新扫码器存活时间 ShellLiveTime = DateTime.Now; Console.WriteLine("箱壳No Read 处理"); //MessageNoReadEvent(appConfig.shellStoreCode); } else { for (Int32 i = 0; i < stBcrResult.nCodeNum; i++) { string strCode = Encoding.GetEncoding("GB2312").GetString(stBcrResult.stBcrInfoEx2[i].chCode); //Console.WriteLine(DateTime.Now + ":箱壳扫码器==>Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode.Trim().TrimEnd('\0') + "]"); string materialCode = strCode.Trim().TrimEnd('\0'); Console.WriteLine($"{DateTime.Now}====>>>箱壳扫码成功:{materialCode};"); if (string.IsNullOrEmpty(SheellLastCode) || SheellLastCode != strCode.Trim().TrimEnd('\0')) { //更新扫码器存活时间 ShellLiveTime = DateTime.Now; RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), ShellScannerIp); SheellLastCode = strCode.Trim().TrimEnd('\0'); } else { if (_realTaskInfoService == null) { Console.WriteLine("箱壳和上次扫描结果一样,并且任务队列无法获取"); } else { //获取当前条码是否存在入库任务 var taskInfo = _realTaskInfoService.GetTaskInfosForInstore(appConfig.shellStoreCode, 0, 1); if (taskInfo != null) { var infos = taskInfo.Where(x => x.materialCode == materialCode).ToList(); if (infos.Count > 0) { Console.WriteLine("箱壳和上次扫描结果一样,并已存在入库任务"); } else { //更新扫码器存活时间 ShellLiveTime = DateTime.Now; RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), ShellScannerIp); SheellLastCode = strCode.Trim().TrimEnd('\0'); } } } } } } } public static void LinerImageCallbackFunc(IntPtr pData, IntPtr pstFrameInfoEx2, IntPtr pUser) { var stFrameInfo = (MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)Marshal.PtrToStructure(pstFrameInfoEx2, typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)); MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2 stBcrResult = (MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)Marshal.PtrToStructure(stFrameInfo.UnparsedBcrList.pstCodeListEx2, typeof(MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)); if (stBcrResult.nCodeNum == 0) { // 更新存活时间 LinerLiveTime = DateTime.Now; Console.WriteLine("内胆No Read 处理"); //MessageNoReadEvent(appConfig.linerStoreCode); } else { for (Int32 i = 0; i < stBcrResult.nCodeNum; i++) { string strCode = Encoding.GetEncoding("GB2312").GetString(stBcrResult.stBcrInfoEx2[i].chCode); string materialCode = strCode.Trim().TrimEnd('\0'); Console.WriteLine($"{DateTime.Now}====>>>内胆扫码成功:{materialCode};"); if (string.IsNullOrEmpty(LinerLastCode) || LinerLastCode != strCode.Trim().TrimEnd('\0')) { // 更新存活时间 LinerLiveTime = DateTime.Now; RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), LinerScannerIp); LinerLastCode = strCode.Trim().TrimEnd('\0'); } else { if (_realTaskInfoService == null) { Console.WriteLine("内胆和上次扫描结果一样,并且任务队列无法获取"); } else { //获取当前条码是否存在入库任务 var taskInfo = _realTaskInfoService.GetTaskInfosForInstore(appConfig.linerStoreCode, 0, 1); if (taskInfo != null) { var infos = taskInfo.Where(x => x.materialCode == materialCode).ToList(); if (infos.Count > 0) { Console.WriteLine("内胆和上次扫描结果一样,并已存在入库任务"); } else { //更新扫码器存活时间 LinerLiveTime = DateTime.Now; RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0'), LinerScannerIp); LinerLastCode = strCode.Trim().TrimEnd('\0'); } } } } } } } public static void Shell() { ShellLiveTime = DateTime.Now; MvCodeReader.cbOutputEx2delegate ImageCallback; MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2 stFrameInfo = new MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2(); MvCodeReader device = new MvCodeReader(); int nRet = MvCodeReader.MV_CODEREADER_OK; do { try { // ch:枚举设备 | en:Enum device MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST stDevList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST(); nRet = MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref stDevList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); Thread.Sleep(1000 * 10); break; } if (0 == stDevList.nDeviceNum) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); Thread.Sleep(1000 * 10); break; } MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo; // 通用设备信息 int nDevIndex = -1; // ch:打印设备信息 | en:Print device info for (Int32 i = 0; i < stDevList.nDeviceNum; i++) { stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO)); if (MvCodeReader.MV_CODEREADER_GIGE_DEVICE == stDevInfo.nTLayerType) { MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO stGigEDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)MvCodeReader.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)); uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24); uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16); uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8); uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff); string ipStr = nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4; if (ipStr == ShellScannerIp) { nDevIndex = i; Console.WriteLine("device IP :" + ipStr); } } } if (nDevIndex < 0) { Console.WriteLine("未找到箱壳扫码器"); // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); Thread.Sleep(1000 * 30); break; } stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[nDevIndex], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO)); // ch:创建设备 | en:Create device nRet = device.MV_CODEREADER_CreateHandle_NET(ref stDevInfo); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); break; } // ch:打开设备 | en:Open device nRet = device.MV_CODEREADER_OpenDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); break; } // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", true); // ch:注册回调函数 | en:Register image callback ImageCallback = new MvCodeReader.cbOutputEx2delegate(ShellImageCallbackFunc); nRet = device.MV_CODEREADER_RegisterImageCallBackEx2_NET(ImageCallback, IntPtr.Zero); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); break; } // ch:开启抓图 || en: start grab image nRet = device.MV_CODEREADER_StartGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); break; } while (true) { Thread.Sleep(1000 * 60); DateTime dateTime = DateTime.Now; TimeSpan timeSpan = dateTime.Subtract(ShellLiveTime); if (timeSpan.TotalMinutes >= 10) { Console.WriteLine("箱壳扫码器超时"); //CloseShell(); //Shell(); break; } } // Console.ReadLine(); // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); // ch:停止抓图 | en:Stop grabbing nRet = device.MV_CODEREADER_StopGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } // ch:关闭设备 | en:Close device nRet = device.MV_CODEREADER_CloseDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } // ch:销毁设备 | en:Destroy device nRet = device.MV_CODEREADER_DestroyHandle_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } }catch(Exception ex) { Console.WriteLine($"Shell扫码器异常:{ex.Message}"); } } while (false); Thread.Sleep (1000); Shell(); } public static void Liner() { LinerLiveTime = DateTime.Now; MvCodeReader.cbOutputEx2delegate ImageCallback; MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2 stFrameInfo = new MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2(); MvCodeReader device = new MvCodeReader(); int nRet = MvCodeReader.MV_CODEREADER_OK; do { try { // ch:枚举设备 | en:Enum device MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST stDevList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST(); nRet = MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref stDevList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("内胆", false); Thread.Sleep(1000 * 10); break; } if (0 == stDevList.nDeviceNum) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("内胆", false); Thread.Sleep(1000 * 10); break; } MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo; // 通用设备信息 Int32 nDevIndex = -1; // ch:打印设备信息 | en:Print device info for (Int32 i = 0; i < stDevList.nDeviceNum; i++) { stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO)); if (MvCodeReader.MV_CODEREADER_GIGE_DEVICE == stDevInfo.nTLayerType) { MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO stGigEDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)MvCodeReader.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)); uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24); uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16); uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8); uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff); string ip = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8) + "." + (stGigEDeviceInfo.nCurrentIp & 0x000000ff); string ipStr = nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4; if (ipStr == LinerScannerIp) { Console.WriteLine("device IP :" + ipStr); nDevIndex = i; } } } if (nDevIndex < 0) { Console.WriteLine("未找到内胆扫码器"); // 刷新扫码器状态 RefreshStateEvent?.Invoke("内胆", false); Thread.Sleep(1000 * 30); break; } stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[nDevIndex], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO)); // ch:创建设备 | en:Create device nRet = device.MV_CODEREADER_CreateHandle_NET(ref stDevInfo); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } // ch:打开设备 | en:Open device nRet = device.MV_CODEREADER_OpenDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("箱壳", false); break; } // 刷新扫码器状态 RefreshStateEvent?.Invoke("内胆", true); // ch:注册回调函数 | en:Register image callback ImageCallback = new MvCodeReader.cbOutputEx2delegate(LinerImageCallbackFunc); nRet = device.MV_CODEREADER_RegisterImageCallBackEx2_NET(ImageCallback, IntPtr.Zero); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } // ch:开启抓图 || en: start grab image nRet = device.MV_CODEREADER_StartGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } while (true) { Thread.Sleep(1000 * 60); DateTime dateTime = DateTime.Now; TimeSpan timeSpan = dateTime.Subtract(LinerLiveTime); if (timeSpan.TotalMinutes >= 10) { Console.WriteLine("内胆扫码器超时"); //CloseShell(); //Shell(); break; } } //Console.ReadLine(); // ch:停止抓图 | en:Stop grabbing nRet = device.MV_CODEREADER_StopGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } // ch:关闭设备 | en:Close device nRet = device.MV_CODEREADER_CloseDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } // ch:销毁设备 | en:Destroy device nRet = device.MV_CODEREADER_DestroyHandle_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { break; } }catch(Exception ex) { Console.WriteLine($"Liner扫码器异常:{ex.Message}"); } } while (false); Thread.Sleep(1000); Liner(); } public static async Task LinerRobot() { try { while (true) { // 枚举设备 MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST stDevList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST(); var deviceList = await Task.Run(() => MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref stDevList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE)); if (stDevList.nDeviceNum == 0) { await Task.Delay(10000); // 10秒后重试 continue; } // 过滤设备 var linerDevice = stDevList.pDeviceInfo .Select(ptr => (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(ptr, typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO))) .FirstOrDefault(info => { if (info.nTLayerType != MvCodeReader.MV_CODEREADER_GIGE_DEVICE) return false; var gigeDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)MvCodeReader.ByteToStruct(info.SpecialInfo.stGigEInfo, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)); return $"{(gigeDeviceInfo.nCurrentIp & 0xff000000) >> 24}.{(gigeDeviceInfo.nCurrentIp & 0x00ff0000) >> 16}.{(gigeDeviceInfo.nCurrentIp & 0x0000ff00) >> 8}.{gigeDeviceInfo.nCurrentIp & 0x000000ff}" == LinerScannerIp; }); if (stDevList.nDeviceNum == 0) { Console.WriteLine("未找到内胆扫码器"); await Task.Delay(30000); // 30秒后重试 continue; } var device = new MvCodeReader(); // 创建设备 var handleResult = await Task.Run(() => device.MV_CODEREADER_CreateHandle_NET(ref linerDevice)); if (handleResult != MvCodeReader.MV_CODEREADER_OK) continue; // 打开设备 var openResult = await Task.Run(() => device.MV_CODEREADER_OpenDevice_NET()); if (openResult != MvCodeReader.MV_CODEREADER_OK) { RefreshStateEvent?.Invoke("箱壳", false); continue; } // 注册回调函数 var imageCallback = new MvCodeReader.cbOutputEx2delegate(LinerImageCallbackFunc); var registerResult = await Task.Run(() => device.MV_CODEREADER_RegisterImageCallBackEx2_NET(imageCallback, IntPtr.Zero)); if (registerResult != MvCodeReader.MV_CODEREADER_OK) continue; // 开启抓图 var startGrabbingResult = await Task.Run(() => device.MV_CODEREADER_StartGrabbing_NET()); if (startGrabbingResult != MvCodeReader.MV_CODEREADER_OK) continue; // 等待 while (true) { Thread.Sleep(1000 * 60); DateTime dateTime = DateTime.Now; TimeSpan timeSpan = dateTime.Subtract(LinerLiveTime); if (timeSpan.TotalMinutes >= 10) { Console.WriteLine("内胆扫码器超时"); break; } } // 停止抓图 var stopGrabbingResult = await Task.Run(() => device.MV_CODEREADER_StopGrabbing_NET()); if (stopGrabbingResult != MvCodeReader.MV_CODEREADER_OK) continue; // 关闭设备 var closeResult = await Task.Run(() => device.MV_CODEREADER_CloseDevice_NET()); if (closeResult != MvCodeReader.MV_CODEREADER_OK) continue; // 销毁设备 var destroyResult = await Task.Run(() => device.MV_CODEREADER_DestroyHandle_NET()); if (destroyResult != MvCodeReader.MV_CODEREADER_OK) continue; } } catch (Exception ex) { Console.WriteLine($"Liner扫码器异常:{ex.Message}"); } } #region 判断字符编码 /// /// 判断字符编码 /// /// /// public static bool IsTextUTF8(byte[] inputStream) { int encodingBytesCount = 0; bool allTextsAreASCIIChars = true; for (int i = 0; i < inputStream.Length; i++) { byte current = inputStream[i]; if ((current & 0x80) == 0x80) { allTextsAreASCIIChars = false; } // First byte if (encodingBytesCount == 0) { if ((current & 0x80) == 0) { // ASCII chars, from 0x00-0x7F continue; } if ((current & 0xC0) == 0xC0) { encodingBytesCount = 1; current <<= 2; // More than two bytes used to encoding a unicode char. // Calculate the real length. while ((current & 0x80) == 0x80) { current <<= 1; encodingBytesCount++; } } else { // Invalid bits structure for UTF8 encoding rule. return false; } } else { // Following bytes, must start with 10. if ((current & 0xC0) == 0x80) { encodingBytesCount--; } else { // Invalid bits structure for UTF8 encoding rule. return false; } } } if (encodingBytesCount != 0) { // Invalid bits structure for UTF8 encoding rule. // Wrong following bytes count. return false; } // Although UTF8 supports encoding for ASCII chars, we regard as a input stream, whose contents are all ASCII as default encoding. return !allTextsAreASCIIChars; } #endregion } }