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.

391 lines
17 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 Admin.Core.Common;
using log4net;
using MvCodeReaderSDKNet;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Text;
using UAParser;
using static System.Runtime.CompilerServices.RuntimeHelpers;
namespace Aucma.Core.Scanner
{
public class MvCodeHelper
{
#region 委托事件
#region 条码绑定上位机委托事件
/// <summary>
/// code1扫码信息刷新
/// </summary>
/// <param name="Code1"></param>
public delegate void ReceiveCode1(string code1);
public static event ReceiveCode1? ReceiveCode1Event;
/// <summary>
/// code2扫码信息刷新,记录表更新
/// </summary>
/// <param name="Code1"></param>
public delegate void ReceiveCode2(string code2);
public static event ReceiveCode2? ReceiveCode2Event;
#endregion
#region 成品下线上位机委托事件
/// <summary>
/// code扫码信息刷新
/// </summary>
/// <param name="Code1"></param>
public delegate void ReceiveCode(string code, int scannerNo);
public static event ReceiveCode? ReceiveCodeEvent;
#endregion
#endregion
private static readonly log4net.ILog log = LogManager.GetLogger(typeof(MvCodeHelper));
// 获取到的所有设备
public static MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST m_stDeviceList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST();
// 连接上的设备和其ip(string)集合
public static Dictionary<MvCodeReader, string> m_cMyDevices = new Dictionary<MvCodeReader, string>();
#region 设备连接状态
/// <summary>
/// 获取不到任务设备即连接失败
/// </summary>
/// <returns></returns>
public bool ConnectionStatus(string ip)
{
// 遍历所有已打开相机
foreach (KeyValuePair<MvCodeReader, string> hashmap in m_cMyDevices)
{
if (ip.Equals(hashmap.Value))
{
return true;
}
}
return false;
}
#endregion
#region 获取设备列表
/// <summary>
/// 获取设备列表
/// </summary>
public static void DeviceListAcqAndOpen()
{
try
{
log.Info("获取扫码器设备列表,进入DeviceListAcq()方法");
System.GC.Collect();
m_stDeviceList.nDeviceNum = 0;
// 获取设备列表
int nRet = MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref m_stDeviceList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE);
if (0 != nRet)
{
log.Info("获取扫码器列表失败,扫码器错误码:" + nRet);
return;
}
if (0 == m_stDeviceList.nDeviceNum)
{
log.Info("获取扫码器数量为0请检查扫码器连接:");
return;
}
MvCodeReader m_cMyDevice = new MvCodeReader();
//打开所有设备
for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
{
MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO));
if (stDevInfo.nTLayerType == MvCodeReader.MV_CODEREADER_GIGE_DEVICE)
{
IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(stDevInfo.SpecialInfo.stGigEInfo, 0);
MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO stGigEDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO));
// 获取ip
string ip = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16) + "." + ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8) + "." + (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
// Console.WriteLine($"打印扫码设备信息,下标:{i}IP{ip}");
log.Info("扫码器设备[" + i + "],ip:" + ip);
// 打开第i个设备
stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO));
nRet = m_cMyDevice.MV_CODEREADER_CreateHandle_NET(ref stDevInfo);//创建设备
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
log.Error("创建第" + i + "个扫码器设备失败,ip:" + ip);
return;
}
log.Info("创建第" + i + "个扫码器设备成功,ip:" + ip);
nRet = m_cMyDevice.MV_CODEREADER_OpenDevice_NET();//打开设备
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
log.Error("打开第" + i + "个扫码器设备失败,销毁设备,ip:" + ip);
m_cMyDevice.MV_CODEREADER_DestroyHandle_NET();
return;
}
else
{
m_cMyDevices.Add(m_cMyDevice, ip);
log.Info("打开第" + i + "个扫码器设备成功,ip:" + ip);
}
// ch:设置触发模式为off || en:set trigger mode as off
if (MvCodeReader.MV_CODEREADER_OK != m_cMyDevice.MV_CODEREADER_SetEnumValue_NET("TriggerMode", 0))
{
log.Error("设置第" + i + "个扫码器设备触发模式失败ip:" + ip);
return;
}
log.Info("第" + i + "个扫码器设备设置采集连续模式成功ip:" + ip);
// ch:开启抓图 | en:start grab
nRet = m_cMyDevice.MV_CODEREADER_StartGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
log.Error("设置第" + i + "个扫码器设备开启抓图失败ip:" + ip);
return;
}
log.Info("*****************************************************************");
log.Info("第" + i + "个扫码器设备创建打开开启连续抓图设置成功ip:" + ip);
}
}
}
catch (Exception ex)
{
log.Error("获取打开设备异常:" + ex);
}
}
#endregion
#region 开启扫描
public static void StartGrab()
{
try
{
// 所有已打开相机开始扫码
foreach (KeyValuePair<MvCodeReader, string> hashmap in m_cMyDevices)
{
Task.Run(() =>
{
// 记录相机上一次扫描到的条码
string lastStr = string.Empty;
int nRet = MvCodeReader.MV_CODEREADER_OK;
IntPtr pData = IntPtr.Zero;
MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2 stFrameInfoEx2 = new MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2();
IntPtr pstFrameInfoEx2 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)));
Marshal.StructureToPtr(stFrameInfoEx2, pstFrameInfoEx2, false);
int nCount = 0;
while (true)
{
nRet = hashmap.Key.MV_CODEREADER_GetOneFrameTimeoutEx2_NET(ref pData, pstFrameInfoEx2, 1000);
// ch:获取一帧图像 | en:Get one image
if (MvCodeReader.MV_CODEREADER_OK == nRet)
{
stFrameInfoEx2 = (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(stFrameInfoEx2.UnparsedBcrList.pstCodeListEx2, 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 = System.Text.Encoding.Default.GetString(stBcrResult.stBcrInfoEx2[i].chCode);
string strCode = Encoding.UTF8.GetString(stBcrResult.stBcrInfoEx2[i].chCode);
log.Info("bIsValidUTF8:: 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).Trim().TrimEnd('\0');
log.Info("相机ip:" + hashmap.Value + " Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode + "]");
if (!string.IsNullOrEmpty(strCode))
{
if (strCode != lastStr)
{
// 处理业务
// 扫码器1处理扫码器1的业务
if (hashmap.Value.Equals(Appsettings.app("Middleware", "Scanner1", "Ip")))
{
#region 条码绑定业务处理
ReceiveCode1Event?.Invoke(strCode);
#endregion
}
else if (hashmap.Value.Equals(Appsettings.app("Middleware", "Scanner2", "Ip"))) // 扫码器2处理扫码器2的业务
{
#region 条码绑定业务处理
ReceiveCode2Event?.Invoke(strCode);
#endregion
}
}
lastStr = strCode;
}
}
}
}
Thread.Sleep(500);
}
});
}
}
catch (Exception ex)
{
log.Error("开启相机扫描异常:" + ex);
}
}
#endregion
#region 关闭设备
public static void CloseDevice()
{
try
{
log.Info("开始关闭所有设备");
int nRet = MvCodeReader.MV_CODEREADER_OK;
// 关闭所有已打开相机
foreach (KeyValuePair<MvCodeReader, string> hashmap in m_cMyDevices)
{
// ch:停止抓图 | en:Stop grab image
nRet = hashmap.Key.MV_CODEREADER_StopGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
log.Error("设备ip:" + hashmap.Value + "停止抓图失败");
Console.WriteLine("Stop grabbing failed{0:x8}", nRet);
}
// ch:关闭设备 | en:Close device
nRet = hashmap.Key.MV_CODEREADER_CloseDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
log.Error("设备ip:" + hashmap.Value + "关闭失败");
}
// ch:销毁设备 | en:Destroy device
nRet = hashmap.Key.MV_CODEREADER_DestroyHandle_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
log.Error("设备ip:" + hashmap.Value + "销毁失败");
}
log.Error("设备ip:" + hashmap.Value + "关闭成功!");
}
}
catch (Exception ex)
{
log.Error("设备关闭异常:" + ex);
}
}
#endregion
#region 判断字符编码
/// <summary>
/// 判断字符编码
/// </summary>
/// <param name="inputStream"></param>
/// <returns></returns>
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
#region 将Byte转换为结构体类型
//将Byte转换为结构体类型
public static object ByteToStruct(byte[] bytes, Type type)
{
int size = Marshal.SizeOf(type);
if (size > bytes.Length)
{
return null;
}
//分配结构体内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将byte数组拷贝到分配好的内存空间
Marshal.Copy(bytes, 0, structPtr, size);
//将内存空间转换为目标结构体
object obj = Marshal.PtrToStructure(structPtr, type);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
return obj;
}
#endregion
}
}