316 lines
9.3 KiB
C#
316 lines
9.3 KiB
C#
using DispenserCommon.Utils;
|
|
using DispenserHal.Camera.DTO;
|
|
using DispenserHal.Camera.Enum;
|
|
using DispenserHal.Camera.Interface;
|
|
using DispenserHal.Camera.VO;
|
|
using DispenserUI.Exceptions;
|
|
using MvCamCtrl.NET;
|
|
using MvCamCtrl.NET.CameraParams;
|
|
using Serilog;
|
|
|
|
namespace DispenserDriver.CameraMV.Impl;
|
|
|
|
public class CameraMVDriver : AbstractCamera
|
|
{
|
|
private CCameraInfo _cameraInfo;
|
|
private cbOutputExdelegate _cbOutputExdelegate;
|
|
private readonly CCamera _mvCamera = new();
|
|
|
|
public CameraMVDriver(string sn, Dictionary<ParamTypeEnum, string> paramMap) : base(sn, paramMap)
|
|
{
|
|
}
|
|
|
|
protected override CameraResponseVO DoConnect(long timeout)
|
|
{
|
|
_cameraInfo = EnumDeviceBySn(SN);
|
|
if (_cameraInfo == null) return CameraResponseVO.OfFailed($"无法找到{SN}相机");
|
|
|
|
if (!CSystem.IsDeviceAccessible(ref _cameraInfo, MV_ACCESS_MODE.MV_ACCESS_CONTROL))
|
|
return CameraResponseVO.OfFailed($"{SN}相机不可访问");
|
|
|
|
var createHandleResult = _mvCamera.CreateHandle(ref _cameraInfo);
|
|
if (!IsSuccess(createHandleResult)) return CameraResponseVO.OfFailed($"{SN}创建句柄失败");
|
|
|
|
var openDeviceResult = _mvCamera.OpenDevice();
|
|
if (!IsSuccess(openDeviceResult))
|
|
{
|
|
_mvCamera.DestroyHandle();
|
|
CameraResponseVO.OfFailed($"打开{SN}相机失败");
|
|
}
|
|
|
|
_cbOutputExdelegate = ImageCallbackFunc;
|
|
var registerImageCallbackResult =
|
|
_mvCamera.RegisterImageCallBackEx(_cbOutputExdelegate, IntPtr.Zero);
|
|
if (!IsSuccess(registerImageCallbackResult))
|
|
{
|
|
Close();
|
|
CameraResponseVO.OfFailed("注册回调函数失败");
|
|
}
|
|
|
|
return CameraResponseVO.OfSuccess($"连接{SN}相机成功");
|
|
}
|
|
|
|
protected override CameraResponseVO DoClose()
|
|
{
|
|
StopSteaming();
|
|
_mvCamera.CloseDevice();
|
|
_mvCamera.DestroyHandle();
|
|
MarkConnect(false);
|
|
return CameraResponseVO.OfSuccess($"关闭{SN}相机成功");
|
|
}
|
|
|
|
|
|
protected override CameraResponseVO DoStartSteaming()
|
|
{
|
|
var result = _mvCamera.StartGrabbing();
|
|
if (!IsSuccess(result)) return CameraResponseVO.OfFailed($"{SN}开启采集失败,错误码{result}");
|
|
|
|
Started = true;
|
|
return CameraResponseVO.OfSuccess($"{SN}开启采集成功");
|
|
}
|
|
|
|
protected override CameraResponseVO DoStopSteaming()
|
|
{
|
|
var result = _mvCamera.StopGrabbing();
|
|
if (!IsSuccess(result)) return CameraResponseVO.OfFailed($"{SN}关闭采集失败,错误码{result}");
|
|
|
|
Started = false;
|
|
return CameraResponseVO.OfSuccess($"{SN}关闭采集成功");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取一帧的图像
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected override CameraResponseVO DoTokePhoto()
|
|
{
|
|
var resp = SwitchSoftwareTriggerMode();
|
|
// 现切换到软触发模式
|
|
if (resp.IsSuccess())
|
|
// 进行软触发拍照
|
|
SoftwareTrigger();
|
|
|
|
// 拍完之后切换到硬触发状态
|
|
SwitchHardTriggerMode();
|
|
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 开始连续采集
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected override CameraResponseVO DoStartCaptureVideo()
|
|
{
|
|
_mvCamera.SetEnumValue("TriggerMode", 0);
|
|
CapturingVideo = true;
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止连续采集
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected override CameraResponseVO DoStopCaptureVideo()
|
|
{
|
|
SetAcquisitionControlToHardTrigger();
|
|
CapturingVideo = false;
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override bool GetBoolValue(string key)
|
|
{
|
|
var value = false;
|
|
_mvCamera.GetBoolValue(key, ref value);
|
|
return value;
|
|
}
|
|
|
|
public override IntValue GetIntValue(string key)
|
|
{
|
|
var value = new CIntValue();
|
|
_mvCamera.GetIntValue(key, ref value);
|
|
return BeanUtil.CopyProperties<IntValue>(value);
|
|
}
|
|
|
|
public override StringValue? GetStringValue(string key)
|
|
{
|
|
var value = new CStringValue();
|
|
_mvCamera.GetStringValue(key, ref value);
|
|
return BeanUtil.CopyProperties<StringValue>(value);
|
|
}
|
|
|
|
public override EnumItem GetEnumEntrySymbolic(string key, uint supportIndex)
|
|
{
|
|
var entry = new CEnumEntry();
|
|
entry.Value = supportIndex;
|
|
_mvCamera.GetEnumEntrySymbolic(key, ref entry);
|
|
return BeanUtil.CopyProperties<EnumItem>(entry);
|
|
}
|
|
|
|
public override EnumValue? GetEnumValue(string key)
|
|
{
|
|
var value = new CEnumValue();
|
|
_mvCamera.GetEnumValue(key, ref value);
|
|
return BeanUtil.CopyProperties<EnumValue>(value);
|
|
}
|
|
|
|
public override FloatValue? GetFloatValue(string key)
|
|
{
|
|
var value = new CFloatValue();
|
|
_mvCamera.GetFloatValue(key, ref value);
|
|
return BeanUtil.CopyProperties<FloatValue>(value);
|
|
}
|
|
|
|
public override CameraResponseVO SwitchHardTriggerMode()
|
|
{
|
|
SetDigitalIOControlToHardTrigger();
|
|
|
|
SetAcquisitionControlToHardTrigger();
|
|
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override CameraResponseVO SwitchContinuousMode()
|
|
{
|
|
//开启触发模式 0:OFF, 1: ON
|
|
_mvCamera.SetEnumValue("TriggerMode", 0);
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override CameraResponseVO SwitchSoftwareTriggerMode()
|
|
{
|
|
//开启触发模式 0:OFF, 1: ON
|
|
_mvCamera.SetEnumValue("TriggerMode", 1);
|
|
//0:Line0
|
|
//1:Line1
|
|
//2:Line2
|
|
//3.Line3
|
|
//4:Counter0
|
|
//7:Software
|
|
//8:FrequencyConverter
|
|
_mvCamera.SetEnumValue("TriggerSource", 7);
|
|
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override CameraResponseVO SoftwareTrigger()
|
|
{
|
|
var nRet = _mvCamera.SetCommandValue("TriggerSoftware");
|
|
if (CErrorDefine.MV_OK != nRet)
|
|
{
|
|
Log.Error($"{SN}软触发失败");
|
|
return CameraResponseVO.OfFailed($"{SN}软触发失败");
|
|
}
|
|
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override CameraResponseVO SetEnumValue(string strKey, uint nvalue)
|
|
{
|
|
_mvCamera.SetEnumValue(strKey, nvalue);
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override CameraResponseVO SetIntValue(string strKey, long nvalue)
|
|
{
|
|
_mvCamera.SetIntValue(strKey, nvalue);
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override CameraResponseVO SetBoolValue(string strKey, bool nvalue)
|
|
{
|
|
_mvCamera.SetBoolValue(strKey, nvalue);
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
public override CameraResponseVO SetFloatValue(string strKey, float nvalue)
|
|
{
|
|
_mvCamera.SetFloatValue(strKey, nvalue);
|
|
return CameraResponseVO.OfSuccess();
|
|
}
|
|
|
|
private void SetAcquisitionControlToHardTrigger()
|
|
{
|
|
//开启触发模式 0:OFF, 1: ON
|
|
_mvCamera.SetEnumValue("TriggerMode", 1);
|
|
//0:Line0
|
|
//1:Line1
|
|
//2:Line2
|
|
//3.Line3
|
|
//4:Counter0
|
|
//7:Software
|
|
//8:FrequencyConverter
|
|
_mvCamera.SetEnumValue("TriggerSource", 0);
|
|
//0:RisingEdge 触发上升沿
|
|
//1:FallingEdge 下降沿
|
|
//2:LevelHigh 高电平
|
|
//3:LevelLow 低电平等
|
|
_mvCamera.SetEnumValue("TriggerActivation", 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 光源控制器IO硬触发设置
|
|
/// </summary>
|
|
private void SetDigitalIOControlToHardTrigger()
|
|
{
|
|
//IO触发源
|
|
//0:Line0
|
|
//1:Line1
|
|
//2:Line2
|
|
//3:Line3
|
|
//4:Line4
|
|
_mvCamera.SetEnumValue("LineSelector", 1);
|
|
|
|
//LineMode
|
|
//0:Input
|
|
//1:Output
|
|
//2:Trigger
|
|
//8:Strobe 频闪模式
|
|
_mvCamera.SetEnumValue("LineMode", 8);
|
|
|
|
//开启频闪模式
|
|
_mvCamera.SetBoolValue("StrobeEnable", true);
|
|
}
|
|
|
|
private void ImageCallbackFunc(IntPtr pData, ref MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
|
|
{
|
|
var bitmap = _mvCamera.ImageToBitmap(pData, ref pFrameInfo);
|
|
Callback(SN, bitmap);
|
|
}
|
|
|
|
private CCameraInfo? EnumDeviceBySn(string sn)
|
|
{
|
|
var deviceList = new List<CCameraInfo>();
|
|
var result = CSystem.EnumDevices(CSystem.MV_GIGE_DEVICE | CSystem.MV_USB_DEVICE, ref deviceList);
|
|
if (!IsSuccess(result)) return null;
|
|
|
|
CCameraInfo _currentCamera = null;
|
|
foreach (var cCameraInfo in deviceList)
|
|
{
|
|
var _sn = FindSn(cCameraInfo);
|
|
if (sn.Equals(_sn))
|
|
{
|
|
_currentCamera = cCameraInfo;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return _currentCamera;
|
|
}
|
|
|
|
private string FindSn(CCameraInfo cCameraInfo)
|
|
{
|
|
if (cCameraInfo.nTLayerType == CSystem.MV_USB_DEVICE)
|
|
return ((CUSBCameraInfo)cCameraInfo).chSerialNumber;
|
|
if (cCameraInfo.nTLayerType == CSystem.MV_GIGE_DEVICE)
|
|
return ((CGigECameraInfo)cCameraInfo).chSerialNumber;
|
|
if (cCameraInfo.nTLayerType == CSystem.MV_CAMERALINK_DEVICE)
|
|
return ((CCamLCameraInfo)cCameraInfo).chSerialNumber;
|
|
throw new BizException($"不支持的相机类型{cCameraInfo.nTLayerType}");
|
|
}
|
|
|
|
private bool IsSuccess(int result)
|
|
{
|
|
return result == CErrorDefine.MV_OK;
|
|
}
|
|
} |