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/MvCodeHelper.cs

386 lines
16 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 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;
namespace Aucma.Core.Scanner
{
public class MvCodeHelper
{
private static AppConfig appConfig = AppConfig.Instance;
public static bool m_bGrabbing = true;
#region 委托事件
public delegate void RefreshMaterialCodeStr(string storeCode, string materialCodeStr);
public static event RefreshMaterialCodeStr RefreshMaterialCodeStrEvent;
/// <summary>
/// 日志信息刷新
/// </summary>
/// <param name="message"></param>
public delegate void RefreshLogMessage(string message);
public static event RefreshLogMessage RefreshLogMessageEvent;
#endregion
// 获取到的所有设备
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 static bool ConnectionStatus(string ip)
{
// 遍历所有已打开相机
foreach (KeyValuePair<MvCodeReader, string> hashmap in m_cMyDevices)
{
if (ip.Equals(hashmap.Value))
{
return true;
}
}
// 没有连接上,重新获取并创建设备
Task.Run(() =>
{
DeviceListAcq();
});
return false;
}
#endregion
#region 获取并创建设备列表
/// <summary>
/// 获取并创建设备列表
/// </summary>
public static void DeviceListAcq()
{
try
{
RefreshLogMessageEvent?.Invoke("获取扫码器设备列表,进入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)
{
RefreshLogMessageEvent?.Invoke("获取扫码器列表失败,扫码器错误码:" + nRet);
return;
}
if (0 == m_stDeviceList.nDeviceNum)
{
RefreshLogMessageEvent?.Invoke("获取扫码器数量为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}");
Console.Write("扫码器设备[" + 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)
{
Console.WriteLine("创建第" + i + "个扫码器设备失败,ip:" + ip);
return;
}
// 打开设备
nRet = m_cMyDevice.MV_CODEREADER_OpenDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
m_cMyDevice.MV_CODEREADER_DestroyHandle_NET();
Console.WriteLine("Device open fail!");
return;
}
RefreshLogMessageEvent?.Invoke("创建并打开第" + i + "个扫码器设备成功,ip:" + ip);
//设置触发模式
nRet = m_cMyDevice.MV_CODEREADER_SetEnumValue_NET("TriggerMode", (uint)MvCodeReader.MV_CODEREADER_TRIGGER_MODE.MV_CODEREADER_TRIGGER_MODE_ON);
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("设置触发模式失败");
return;
}
//添加到集合
m_cMyDevices.Add(m_cMyDevice, ip);
}
}
}
catch (Exception ex)
{
Console.WriteLine("获取和创建设备异常:" + ex);
}
}
#endregion
#region 光电触发扫码器接收条码处理业务
public static void StartGrab()
{
try
{
int nRet = MvCodeReader.MV_CODEREADER_OK;
// 3.开启抓图
int nCount = 0;
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);
foreach (KeyValuePair<MvCodeReader, string> hashmap in m_cMyDevices)
{
nRet = hashmap.Key.MV_CODEREADER_StartGrabbing_NET();
while (m_bGrabbing)
{
// 光电触发了有图像
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);
// logHelper.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');
RefreshLogMessageEvent?.Invoke("相机ip:" + hashmap.Value + " Get CodeNum: " + "CodeNum[" + i.ToString() + "], CodeString[" + strCode + "]");
if (!string.IsNullOrEmpty(strCode))
{
// 获取到条码处理业务
if (appConfig.shellHikRobotIp == hashmap.Value)
{
RefreshMaterialCodeStrEvent?.Invoke(appConfig.shellStoreCode, strCode);
}else if(appConfig.linerHikRobotIp == hashmap.Value)
{
RefreshMaterialCodeStrEvent?.Invoke(appConfig.linerHikRobotIp, strCode);
}
}
}
}
}
Thread.Sleep(500);
}
}
}
catch (Exception ex)
{
Console.WriteLine("扫码异常:" + ex);
}
}
#endregion
#region 关闭所有设备
public static void CloseAllDevice()
{
try
{
Console.WriteLine("开始关闭所有设备");
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)
{
Console.WriteLine("设备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)
{
Console.WriteLine("设备ip:" + hashmap.Value + "关闭失败");
}
// ch:销毁设备 | en:Destroy device
nRet = hashmap.Key.MV_CODEREADER_DestroyHandle_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("设备ip:" + hashmap.Value + "销毁失败");
}
Console.WriteLine("设备ip:" + hashmap.Value + "关闭成功!");
}
}
catch (Exception ex)
{
Console.WriteLine("设备关闭异常:" + ex);
}
}
#endregion
#region 关闭指定设备
public void CloseDevice(KeyValuePair<MvCodeReader, string> hashmap)
{
try
{
int nRet = MvCodeReader.MV_CODEREADER_OK;
// ch:停止抓图 | en:Stop grab image
nRet = hashmap.Key.MV_CODEREADER_StopGrabbing_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("设备ip:" + hashmap.Value + "停止抓图失败");
Console.WriteLine("Stop grabbing failed{0:x8}", nRet);
return;
}
// ch:关闭设备 | en:Close device
nRet = hashmap.Key.MV_CODEREADER_CloseDevice_NET();
if (MvCodeReader.MV_CODEREADER_OK != nRet)
{
Console.WriteLine("设备ip:" + hashmap.Value + "关闭失败");
return;
}
}
catch (Exception ex)
{
Console.WriteLine("设备关闭异常:" + 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
}
}