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) 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; } /// /// SDK帧回调处理 /// private void OnFrameReceived(ref EidCamera.EidFrameInfo frameInfo, IntPtr userData) { try { List barcodes = new List(); 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)) { 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(); } } }