using HighWayIot.Config; using HighWayIot.Log4net; using MvCodeReaderSDKNet; using System; using System.Runtime.InteropServices; using System.Text; using System.Threading; namespace Aucma.Core.Scanner { public class MvCodeHelper { private static LogHelper logHelper = LogHelper.Instance; private static AppConfig appConfig = AppConfig.Instance; public static bool m_bGrabbing = true; private static string SheellLastCode; private static string LinerLastCode; // 入库扫码器ip private static string ShellScannerIp = appConfig.foamHikRobotIp; // 出库扫码器ip private static string LinerScannerIp = appConfig.foamOutHikRobotIp; #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; //NoRead事件通知 public delegate void MessageNoRead(); public static event MessageNoRead MessageNoReadEvent; //入库扫码 public delegate void RefreshMaterialCodeStr(string materialCodeStr); public static event RefreshMaterialCodeStr RefreshMaterialCodeStrEvent; //出库扫码 public delegate void OutMaterialCodeStr(string materialCodeStr); public static event OutMaterialCodeStr OutMaterialCodeStrEvent; /// /// 日志信息刷新 /// /// 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)); // Console.WriteLine("CodeNum[" + Convert.ToString(stBcrResult.nCodeNum) + "]"); if (stBcrResult.nCodeNum == 0) { //更新扫码器存活时间 ShellLiveTime = DateTime.Now; Console.WriteLine("入库No Read 处理"); MessageNoReadEvent?.Invoke(); } for (Int32 i = 0; i < stBcrResult.nCodeNum; i++) { bool bIsValidUTF8 = IsTextUTF8(stBcrResult.stBcrInfoEx2[i].chCode); if (bIsValidUTF8) { string strCode = Encoding.UTF8.GetString(stBcrResult.stBcrInfoEx2[i].chCode); Console.WriteLine("Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode.Trim().TrimEnd('\0') + "]"); } else { string strCode = Encoding.GetEncoding("GB2312").GetString(stBcrResult.stBcrInfoEx2[i].chCode); Console.WriteLine(DateTime.Now + ":入库扫码器==>Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode.Trim().TrimEnd('\0') + "]"); if (string.IsNullOrEmpty(SheellLastCode) || SheellLastCode != strCode.Trim().TrimEnd('\0')) { //更新扫码器存活时间 ShellLiveTime = DateTime.Now; RefreshMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0')); SheellLastCode = strCode.Trim().TrimEnd('\0'); } if (SheellLastCode == strCode.Trim().TrimEnd('\0')) { Console.WriteLine("入库和上次扫描结果一样,不作处理"); } } } MvCodeReader.MV_CODEREADER_OCR_INFO_LIST stOcrInfo = (MvCodeReader.MV_CODEREADER_OCR_INFO_LIST)Marshal.PtrToStructure(stFrameInfo.UnparsedOcrList.pstOcrList, typeof(MvCodeReader.MV_CODEREADER_OCR_INFO_LIST)); for (int i = 0; i < stOcrInfo.nOCRAllNum; i++) { string strOcrCharCode = Encoding.UTF8.GetString(stOcrInfo.stOcrRowInfo[i].chOcr); Console.WriteLine("Get OcrInfo:" + "ocrNum[" + i.ToString() + "], ocrLen[" + Convert.ToString(stOcrInfo.stOcrRowInfo[i].nOcrLen) + "], ocrChar[" + strOcrCharCode.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)); // Console.WriteLine("CodeNum[" + Convert.ToString(stBcrResult.nCodeNum) + "]"); if (stBcrResult.nCodeNum == 0) { // 更新存活时间 LinerLiveTime = DateTime.Now; Console.WriteLine("出库No Read 处理"); MessageNoReadEvent(); } for (Int32 i = 0; i < stBcrResult.nCodeNum; i++) { bool bIsValidUTF8 = IsTextUTF8(stBcrResult.stBcrInfoEx2[i].chCode); if (bIsValidUTF8) { string strCode = Encoding.UTF8.GetString(stBcrResult.stBcrInfoEx2[i].chCode); Console.WriteLine("Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode.Trim().TrimEnd('\0') + "]"); } else { string strCode = Encoding.GetEncoding("GB2312").GetString(stBcrResult.stBcrInfoEx2[i].chCode); Console.WriteLine(DateTime.Now + ":出库扫码器==>Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode.Trim().TrimEnd('\0') + "]"); if (string.IsNullOrEmpty(LinerLastCode) || LinerLastCode != strCode.Trim().TrimEnd('\0')) { // 更新存活时间 LinerLiveTime = DateTime.Now; OutMaterialCodeStrEvent?.Invoke(strCode.Trim().TrimEnd('\0')); LinerLastCode = strCode.Trim().TrimEnd('\0'); } if (LinerLastCode == strCode.Trim().TrimEnd('\0')) { Console.WriteLine("出库和上次扫描一样,不作处理"); } } } MvCodeReader.MV_CODEREADER_OCR_INFO_LIST stOcrInfo = (MvCodeReader.MV_CODEREADER_OCR_INFO_LIST)Marshal.PtrToStructure(stFrameInfo.UnparsedOcrList.pstOcrList, typeof(MvCodeReader.MV_CODEREADER_OCR_INFO_LIST)); Console.WriteLine("ocrAllNum[" + Convert.ToString(stOcrInfo.nOCRAllNum) + "]"); for (int i = 0; i < stOcrInfo.nOCRAllNum; i++) { string strOcrCharCode = Encoding.UTF8.GetString(stOcrInfo.stOcrRowInfo[i].chOcr); Console.WriteLine("Get OcrInfo:" + "ocrNum[" + i.ToString() + "], ocrLen[" + Convert.ToString(stOcrInfo.stOcrRowInfo[i].nOcrLen) + "], ocrChar[" + strOcrCharCode.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 { // 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); RefreshStateEvent?.Invoke("入库", false); Thread.Sleep(1000 * 10); Console.WriteLine("Enum device failed:{0:x8}", nRet); break; } Console.WriteLine("Enum device count : " + Convert.ToString(stDevList.nDeviceNum)); if (0 == stDevList.nDeviceNum) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("入库", false); 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); // Console.WriteLine("\n" + i.ToString() + ": [GigE] User Define Name : " + stGigEDeviceInfo.chUserDefinedName); // Console.WriteLine("device IP :" + nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4); 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) { Console.WriteLine("Create device failed:{0:x8}", nRet); // 刷新扫码器状态 RefreshStateEvent?.Invoke("入库", false); break; } // ch:打开设备 | en:Open device nRet = device.MV_CODEREADER_OpenDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Open device failed:{0:x8}", 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) { Console.WriteLine("Register image callback failed!"); // 刷新扫码器状态 RefreshStateEvent?.Invoke("入库", false); break; } // ch:开启抓图 || en: start grab image nRet = device.MV_CODEREADER_StartGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Start grabbing failed:{0:x8}", nRet); // 刷新扫码器状态 RefreshStateEvent?.Invoke("入库", false); break; } Console.WriteLine("Press enter to exit"); Console.WriteLine(DateTime.Now.ToString()); while (true) { Thread.Sleep(1000 * 60); DateTime dateTime = DateTime.Now; TimeSpan timeSpan = dateTime.Subtract(ShellLiveTime); if (timeSpan.TotalMinutes >= 10) { Console.WriteLine("入库扫码器超时"); break; } } // Console.ReadLine(); // 刷新扫码器状态 RefreshStateEvent?.Invoke("入库", false); // ch:停止抓图 | en:Stop grabbing nRet = device.MV_CODEREADER_StopGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Stop grabbing failed{0:x8}", nRet); break; } // ch:关闭设备 | en:Close device nRet = device.MV_CODEREADER_CloseDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Close device failed{0:x8}", nRet); break; } // ch:销毁设备 | en:Destroy device nRet = device.MV_CODEREADER_DestroyHandle_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Destroy device failed:{0:x8}", nRet); break; } } 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 { // 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); RefreshStateEvent?.Invoke("出库", false); Thread.Sleep(1000 * 10); Console.WriteLine("Enum device failed:{0:x8}", nRet); break; } Console.WriteLine("Enum device count : " + Convert.ToString(stDevList.nDeviceNum)); if (0 == stDevList.nDeviceNum) { // 刷新扫码器状态 RefreshStateEvent?.Invoke("入库", false); 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); // Console.WriteLine("\n" + i.ToString() + ": [GigE] User Define Name : " + stGigEDeviceInfo.chUserDefinedName); 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) { Console.WriteLine("Create device failed:{0:x8}", nRet); break; } // ch:打开设备 | en:Open device nRet = device.MV_CODEREADER_OpenDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Open device failed:{0:x8}", 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) { Console.WriteLine("Register image callback failed!"); break; } // ch:开启抓图 || en: start grab image nRet = device.MV_CODEREADER_StartGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Start grabbing failed:{0:x8}", nRet); break; } Console.WriteLine("Press enter to exit"); Console.WriteLine(DateTime.Now.ToString()); 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) { Console.WriteLine("Stop grabbing failed{0:x8}", nRet); break; } // ch:关闭设备 | en:Close device nRet = device.MV_CODEREADER_CloseDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Close device failed{0:x8}", nRet); break; } // ch:销毁设备 | en:Destroy device nRet = device.MV_CODEREADER_DestroyHandle_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Destroy device failed:{0:x8}", nRet); break; } } while (false); if (MvCodeReader.MV_CODEREADER_OK != nRet) { // ch:销毁设备 | en:Destroy device nRet = device.MV_CODEREADER_DestroyHandle_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Destroy device failed:{0:x8}", nRet); } } Thread.Sleep(1000); Liner(); } #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 } }