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
|
{
|
/// <summary>
|
/// 华睿读码器实现类
|
/// </summary>
|
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;
|
}
|
|
/// <summary>
|
/// 获取在线的华睿读码器列表
|
/// </summary>
|
public override List<string> GetDeviceList()
|
{
|
List<string> snList = new List<string>();
|
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) return false;
|
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()
|
{
|
if (!IsConnected) return true;
|
|
try
|
{
|
if (IsConnected)
|
{
|
StopGrabbing();
|
_camera.eidCloseDevice_Net();
|
_camera.eidReleaseHandle_Net();
|
_camera?.eidCloseDevice_Net();
|
}
|
// 无论是否连接,都尝试释放句柄
|
_camera?.eidReleaseHandle_Net();
|
|
// 释放回调句柄
|
if (_callbackHandle.IsAllocated)
|
{
|
_callbackHandle.Free();
|
}
|
|
// 释放相机对象引用,确保SDK资源完全释放
|
_camera = null;
|
|
this.IsConnected = false;
|
this.SN = string.Empty;
|
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;
|
}
|
|
/// <summary>
|
/// SDK帧回调处理
|
/// </summary>
|
private void OnFrameReceived(ref EidCamera.EidFrameInfo frameInfo, IntPtr userData)
|
{
|
try
|
{
|
List<string> barcodes = new List<string>();
|
List<BarcodeInfo> barcodeInfos = new List<BarcodeInfo>();
|
// 解析条码
|
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))
|
{
|
barcodes.Add(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)
|
{
|
// 这里简化处理,如果是Jpeg则直接从内存加载,如果是Raw则需转换
|
// 实际项目中可根据 frameInfo.format 进行处理
|
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, barcodes, bitmap));
|
OnBarcodeRead(new BarcodeEventArgs(this.SN, barcodeInfos, bitmap));
|
}
|
catch (Exception ex)
|
{
|
// TODO: Log error
|
}
|
}
|
|
public override void Dispose()
|
{
|
Close();
|
base.Dispose();
|
}
|
}
|
}
|