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
}
}