using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using EasyIDSDK_Net;
namespace LB_VisionProcesses.BarcodeReaders.Huayray
{
///
/// 华睿读码器实现类
///
public class HRBarcodeReader : BarcodeReaderBase
{
private EidCamera _camera;
private EidCamera.EidFrameCallback _frameCallback;
private GCHandle _callbackHandle;
public override BarcodeReaderBrand Brand => BarcodeReaderBrand.Huayray;
public HRBarcodeReader()
{
_camera = new EidCamera();
_frameCallback = OnFrameReceived;
}
///
/// 获取在线的华睿读码器列表
///
public override List GetDeviceList()
{
List snList = new List();
try
{
EidCamera.EidDeviceList devList = new EidCamera.EidDeviceList();
int nRet = EidCamera.eidEnumDevices_Net(ref devList, 0);
if (nRet == EidCamera.eidErrorOK && devList.num > 0)
{
for (int i = 0; i < devList.num; i++)
{
EidCamera.EidDeviceInfo deviceInfo = (EidCamera.EidDeviceInfo)Marshal.PtrToStructure(
devList.infos + Marshal.SizeOf(typeof(EidCamera.EidDeviceInfo)) * i,
typeof(EidCamera.EidDeviceInfo));
snList.Add(deviceInfo.serialNumber);
}
}
}
catch (Exception ex)
{
// TODO: Log error
}
return snList;
}
public override bool Open(string sn)
{
if (IsConnected) Close();
try
{
// 先进行一次枚举,确保 SDK 能够发现设备(部分 SDK 要求在打开前必须执行枚举)
GetDeviceList();
// 如果之前失败过,重新创建相机对象确保干净状态
if (_camera == null)
{
_camera = new EidCamera();
}
// 确保之前的句柄已释放
try { _camera.eidReleaseHandle_Net(); } catch { }
// 创建句柄
int nRet = _camera.eidCreateDevice_Net(sn, EidCamera.EidDeviceDataType.eidDeviceDataTypeSN);
if (nRet != EidCamera.eidErrorOK)
{
_camera = null;
return false;
}
// 分配固定句柄给委托,防止被 GC 回收
if (!_callbackHandle.IsAllocated)
{
_callbackHandle = GCHandle.Alloc(_frameCallback);
}
// 打开设备
nRet = _camera.eidOpenDevice_Net();
if (nRet != EidCamera.eidErrorOK)
{
_camera.eidReleaseHandle_Net();
if (_callbackHandle.IsAllocated) _callbackHandle.Free();
_camera = null;
return false;
}
// 注册回调
nRet = _camera.eidRegisterFrameCallback_Net(_frameCallback, IntPtr.Zero);
if (nRet != EidCamera.eidErrorOK)
{
_camera.eidCloseDevice_Net();
_camera.eidReleaseHandle_Net();
if (_callbackHandle.IsAllocated) _callbackHandle.Free();
_camera = null;
return false;
}
this.SN = sn;
this.IsConnected = true;
return true;
}
catch
{
// 发生异常时确保释放资源
try { _camera?.eidCloseDevice_Net(); } catch { }
try { _camera?.eidReleaseHandle_Net(); } catch { }
if (_callbackHandle.IsAllocated) _callbackHandle.Free();
// 发生异常时释放相机对象,确保下次创建新实例
_camera = null;
return false;
}
}
public override bool Close()
{
try
{
if (IsConnected)
{
StopGrabbing();
_camera?.eidCloseDevice_Net();
}
// 无论是否连接,都尝试释放句柄
_camera?.eidReleaseHandle_Net();
// 释放回调句柄
if (_callbackHandle.IsAllocated)
{
_callbackHandle.Free();
}
// 释放相机对象引用,确保SDK资源完全释放
_camera = null;
this.IsConnected = false;
this.IsGrabbing = false;
return true;
}
catch
{
return false;
}
}
public override bool StartGrabbing()
{
if (!IsConnected) return false;
if (IsGrabbing) return true;
int nRet = _camera.eidStartGrabbing_Net(0);
if (nRet == EidCamera.eidErrorOK)
{
this.IsGrabbing = true;
return true;
}
return false;
}
public override bool StopGrabbing()
{
if (!IsGrabbing) return true;
int nRet = _camera.eidStopGrabbing_Net();
this.IsGrabbing = false;
return nRet == EidCamera.eidErrorOK;
}
public override bool SoftTrigger()
{
if (!IsConnected || !IsGrabbing) return false;
int nRet = _camera.eidExecCommandFeature_Net("TriggerSoftware");
return nRet == EidCamera.eidErrorOK;
}
public override bool SetTriggerMode(bool isSoftware)
{
if (!IsConnected) return false;
int nRet;
if (isSoftware)
{
// 软触发模式
nRet = _camera.eidSetEnumFeatureSymbol_Net("TriggerType", "SingleFrame");
if (nRet != EidCamera.eidErrorOK) return false;
nRet = _camera.eidSetEnumFeatureSymbol_Net("TriggerSource", "Software");
}
else
{
// 自由运行或硬触发 (此处默认设为自由运行,可根据需要扩展)
nRet = _camera.eidSetEnumFeatureSymbol_Net("TriggerType", "FreeRun");
}
return nRet == EidCamera.eidErrorOK;
}
///
/// SDK帧回调处理
///
private void OnFrameReceived(ref EidCamera.EidFrameInfo frameInfo, IntPtr userData)
{
try
{
List barcodeInfos = new List();
// 解析条码
for (int i = 0; i < frameInfo.codeNum; i++)
{
EidCamera.EidCodeInfo codeInfo = (EidCamera.EidCodeInfo)Marshal.PtrToStructure(
frameInfo.codeList + Marshal.SizeOf(typeof(EidCamera.EidCodeInfo)) * i,
typeof(EidCamera.EidCodeInfo));
string data = Marshal.PtrToStringAnsi(codeInfo.data);
if (!string.IsNullOrEmpty(data))
{
BarcodeInfo info = new BarcodeInfo
{
Text = data,
Points = new Point[]
{
new Point((int)codeInfo.position[0].x, (int)codeInfo.position[0].y),
new Point((int)codeInfo.position[1].x, (int)codeInfo.position[1].y),
new Point((int)codeInfo.position[2].x, (int)codeInfo.position[2].y),
new Point((int)codeInfo.position[3].x, (int)codeInfo.position[3].y)
}
};
barcodeInfos.Add(info);
}
}
// 转换图像
Bitmap bitmap = null;
if (frameInfo.imageDataLen > 0 && frameInfo.imageData != IntPtr.Zero)
{
if (frameInfo.isJpeg)
{
byte[] managedArray = new byte[frameInfo.imageDataLen];
Marshal.Copy(frameInfo.imageData, managedArray, 0, (int)frameInfo.imageDataLen);
using (var ms = new System.IO.MemoryStream(managedArray))
{
bitmap = new Bitmap(ms);
}
}
}
// 触发事件
OnBarcodeRead(new BarcodeEventArgs(this.SN, barcodeInfos, bitmap));
}
catch (Exception ex)
{
// TODO: Log error
}
}
public override void Dispose()
{
Close();
base.Dispose();
}
}
}