You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Aucma.Scada/Aucma.Scada.HikRobot/GrabImage.cs

328 lines
13 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using HighWayIot.Config;
using HighWayIot.Log4net;
using MvCodeReaderSDKNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Aucma.Scada.HikRobot
{
/// <summary>
/// 海康扫码器
/// </summary>
public class GrabImage
{
#region 单例实现
private static readonly Lazy<GrabImage> lazy = new Lazy<GrabImage>(() => new GrabImage());
public static GrabImage Instance
{
get
{
return lazy.Value;
}
}
#endregion
#region 对象引用
private AppConfig appConfig = AppConfig.Instance;
private LogHelper logHelper = LogHelper.Instance;
#endregion
#region 委托事件
public delegate void RefreshMaterialCodeStr(string materialCodeStr);
public event RefreshMaterialCodeStr RefreshMaterialCodeStrEvent;
/// <summary>
/// 日志信息刷新
/// </summary>
/// <param name="message"></param>
public delegate void RefreshLogMessage(string message);
public event RefreshLogMessage RefreshLogMessageEvent;
#endregion
#region 私有变量
private List<MvCodeReader> mvCodeReaders = new List<MvCodeReader>();
private string lastStr = string.Empty;
#endregion
private GrabImage()
{
}
public void InitHikRobot()
{
int nRet = MvCodeReader.MV_CODEREADER_OK;
MvCodeReader device = new MvCodeReader();
do
{
// 枚举设备
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)
{
Console.WriteLine("Enum device failed:{0:x8}", nRet);
break;
}
RefreshLogMessageEvent?.Invoke("海康扫码器初始化枚举设备信息Enum device count : " + Convert.ToString(stDevList.nDeviceNum));
if (0 == stDevList.nDeviceNum)
{
break;
}
MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo; // 通用设备信息
// 打印设备信息 ,选择指定IP的设备
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));
string ip = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8) + "." + (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
RefreshLogMessageEvent?.Invoke($"打印扫码设备信息,下标:{i}IP{ip}");
if (ip == appConfig.foamHikRobotIp)
{
Grab(i, stDevList, stDevInfo, device);
continue;
}
}
}
} while (false);
}
private void Grab(int index,MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST stDevList, MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo,MvCodeReader device)
{
try
{
Task.Run(() =>
{
int nRet = MvCodeReader.MV_CODEREADER_OK;
do
{
stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[index], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO));
// 创建设备
nRet = device.MV_CODEREADER_CreateHandle_NET(ref stDevInfo);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
RefreshLogMessageEvent?.Invoke($"Create device failed:{nRet}");
break;
}
else
{
RefreshLogMessageEvent?.Invoke("泡后库扫码器创建成功");
}
// 打开设备
nRet = device.MV_CODEREADER_OpenDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
RefreshLogMessageEvent?.Invoke("Open device failed:{nRet}");
break;
}
else
{
mvCodeReaders.Add(device);
RefreshLogMessageEvent?.Invoke("泡后库扫码器打开成功");
}
// 设置触发模式为off
if (MvCodeReader.MV_CODEREADER_OK != device.MV_CODEREADER_SetEnumValue_NET("TriggerMode", 0))
{
Console.WriteLine("Set TriggerMode failed!");
break;
}
else
{
RefreshLogMessageEvent?.Invoke("泡后库扫码器设置触发模式为off");
}
// 开启抓图
nRet = device.MV_CODEREADER_StartGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("Start grabbing failed:{0:x8}", nRet);
break;
}
else
{
RefreshLogMessageEvent?.Invoke("泡后库扫码器开启抓图");
}
int nCount = 0;
IntPtr pBufForDriver = IntPtr.Zero;
MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2 stFrameInfo = new MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2();
IntPtr pstFrameInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)));
Marshal.StructureToPtr(stFrameInfo, pstFrameInfo, false);
while (nCount++ != 10)
{
nRet = device.MV_CODEREADER_GetOneFrameTimeoutEx2_NET(ref pBufForDriver, pstFrameInfo, 1000);
// 获取一帧图像
if (MvCodeReader.MV_CODEREADER_OK == nRet)
{
stFrameInfo = (MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)Marshal.PtrToStructure(pstFrameInfo, typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2));
// 分配条码内存空间
MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2 stBcrResult = (MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)Marshal.PtrToStructure(stFrameInfo.pstCodeListEx, typeof(MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2));
for (int 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
{
byte[] buffer = new byte[22];
if (stBcrResult.stBcrInfoEx2[i].chCode.Length > 0)
{
Array.Copy(stBcrResult.stBcrInfoEx2[i].chCode, buffer, 22);
}
string strCode = Encoding.GetEncoding("UTF-8").GetString(buffer);
RefreshLogMessageEvent?.Invoke("Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode.Trim().TrimEnd('\0') + "]");
if (!string.IsNullOrEmpty(strCode))
{
if(strCode != lastStr)
{
RefreshMaterialCodeStrEvent?.Invoke(strCode);
}
lastStr = strCode;
}
}
}
continue;
}
else
{
Console.WriteLine("No data:{0:x8}", nRet);
}
Thread.Sleep(3000);
}
} while (false);
});
}catch(Exception ex)
{
logHelper.Error("扫码异常", ex);
}
}
public void ExitHikRobot()
{
int nRet = MvCodeReader.MV_CODEREADER_OK;
foreach (var device in mvCodeReaders)
{
// 停止抓图
nRet = device.MV_CODEREADER_StopGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("Stop grabbing failed{0:x8}", nRet);
continue;
}
// 关闭设备
nRet = device.MV_CODEREADER_CloseDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("Close device failed{0:x8}", nRet);
continue;
}
// 销毁设备
nRet = device.MV_CODEREADER_DestroyHandle_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("Destroy device failed:{0:x8}", nRet);
continue;
}
}
mvCodeReaders = new List<MvCodeReader>();
}
// 判断字符编码
private 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;
}
}
}