diff --git a/Rs.Cameras/HikCamera.cs b/Rs.Cameras/HikCamera.cs
new file mode 100644
index 0000000..800ee79
--- /dev/null
+++ b/Rs.Cameras/HikCamera.cs
@@ -0,0 +1,467 @@
+using HalconDotNet;
+using MvCamCtrl.NET;
+using Rs.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Rs.Cameras
+{
+ ///
+ /// 方向
+ ///
+ public enum EDir
+ {
+ X,
+ Y
+ }
+
+ public enum ETriggerSource
+ {
+ ///
+ /// 硬触发
+ ///
+ Line0,
+ ///
+ /// 软触发
+ ///
+ Software
+ }
+ public class HikCameras
+ {
+ private static HikCameras instance;
+ public static HikCameras Instance
+ {
+ get
+ {
+ if (instance == null)
+ instance = new HikCameras();
+ return instance;
+ }
+ }
+
+
+ private HikCameras()
+ {
+ cbImage = new MyCamera.cbOutputExdelegate(ImageCallBack);
+ }
+
+ MyCamera.MV_CC_DEVICE_INFO_LIST m_pDeviceList;
+ int apiResult = 0;
+ MyCamera.cbOutputExdelegate cbImage;
+ IntPtr m_BufForDriver = IntPtr.Zero;
+ List cameraInfos = new List();
+
+ private void ImageCallBack(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
+ {
+ HObject image;
+ HOperatorSet.GenEmptyObj(out image);
+ image.Dispose();
+ int nIndex = (int)pUser;
+ HOperatorSet.GenImage1(out image, "byte", pFrameInfo.nWidth, pFrameInfo.nHeight, pData);
+ CameraInfo ci = GetCameraInfo(nIndex);
+ if (ci != null)
+ {
+ ci.AddImage(image);
+ }
+ }
+
+ public List Init()
+ {
+ int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList);
+ if (nRet != 0)
+ {
+ LogHelper.Debug($"MV_CC_EnumDevices_NET ret = {nRet}");
+ //未找到任何相机
+ return null;
+ }
+ else if (m_pDeviceList.nDeviceNum>0)
+ {
+ for (int i = 0; i < m_pDeviceList.nDeviceNum; i++)
+ {
+ string cameraInfo = string.Empty;
+ ///获取相机信息
+ MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
+ if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
+ {
+ MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
+ if(!string.IsNullOrEmpty(gigeInfo.chUserDefinedName))
+ {
+ cameraInfo = gigeInfo.chUserDefinedName;
+ }// gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")";
+ else
+ {
+ cameraInfo = gigeInfo.chSerialNumber;
+ }
+ }
+ else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
+ {
+ MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
+ if (!string.IsNullOrEmpty(usbInfo.chUserDefinedName))
+ {
+ cameraInfo = usbInfo.chUserDefinedName;
+ }
+ else
+ {
+ cameraInfo = usbInfo.chSerialNumber;
+ }
+ }
+
+ MyCamera camera = new MyCamera();
+ apiResult = camera.MV_CC_CreateDevice_NET(ref device);
+ if (apiResult != 0)
+ {
+ LogHelper.Debug($"MV_CC_CreateDevice_NET ret = {apiResult}");
+ //MV_CC_CreateDevice_NET fail;
+ //return ECameraErrorCode.CreateDeviceFail;
+ continue;
+ }
+ apiResult = camera.MV_CC_OpenDevice_NET();
+ if (apiResult != 0)
+ {
+ LogHelper.Debug($"MV_CC_OpenDevice_NET ret = {apiResult}");
+ //return ECameraErrorCode.OpenDeviceFail;
+ continue;
+ }
+ if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
+ {
+ int nPacketSize = camera.MV_CC_GetOptimalPacketSize_NET();
+ if (nPacketSize > 0)
+ {
+ nRet = camera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
+ if (nRet != MyCamera.MV_OK)
+ {
+ LogHelper.Debug($"MV_CC_SetIntValue_NET GevSCPSPacketSize ret = {apiResult}");
+ //return ECameraErrorCode.GevSCPSPacketSizeFail;
+ continue;
+ }
+ }
+ else
+ {
+ //return ECameraErrorCode.GevSCPSPacketSizeFail;
+ continue;
+ }
+ }
+ apiResult = camera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
+ if (nRet != MyCamera.MV_OK)
+ {
+ LogHelper.Debug($"MV_CC_SetIntValue_NET TriggerMode ret = {apiResult}");
+ //return ECameraErrorCode.SetTriggerModeFail;
+ continue;
+ }
+ apiResult = camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
+ if (nRet != MyCamera.MV_OK)
+ {
+ LogHelper.Debug($"MV_CC_SetIntValue_NET TriggerSource ret = {apiResult}");
+ //return ECameraErrorCode.SetTriggerSourceFail;
+ continue;
+ }
+ apiResult = camera.MV_CC_RegisterImageCallBackEx_NET(cbImage, (IntPtr)i);
+ if (apiResult != 0)
+ {
+ LogHelper.Debug($"MV_CC_RegisterImageCallBackEx_NET ret = {apiResult}");
+ continue;
+ //return ECameraErrorCode.RegisterImageCallBackExFail;
+ }
+ CameraInfo ci = new CameraInfo();
+ ci.Camera = camera;
+ ci.CameraName = cameraInfo;
+ ci.Index = i;
+ cameraInfos.Add(ci);
+ LogHelper.Debug($"Find camera {cameraInfo}");
+ }
+
+ }
+ else
+ {
+ //未找到任何相机
+ return null;
+ }
+ return cameraInfos;
+ }
+
+ ///
+ /// 根据相机名称获取相机
+ ///
+ ///
+ ///
+ public CameraInfo GetCameraInfo(string cameraName)
+ {
+ return cameraInfos.Where(c=>c.CameraName==cameraName).FirstOrDefault();
+ }
+
+ ///
+ /// 根据索引获取相机
+ ///
+ ///
+ ///
+ private CameraInfo GetCameraInfo(int index)
+ {
+ return cameraInfos.Where(c => c.Index == index).FirstOrDefault();
+ }
+
+ ///
+ /// 获取所有的相机
+ ///
+ ///
+ public List GetAllCameras()
+ {
+ return cameraInfos;
+ }
+
+ public void Deinit()
+ {
+ foreach (CameraInfo ci in cameraInfos)
+ {
+ ci.Deinit();
+ }
+ }
+ }
+
+ ///
+ /// 相机信息
+ ///
+ public class CameraInfo
+ {
+ public MyCamera Camera { get; set; }
+ public string CameraName { get; set; }
+
+ public int Index { get; set; }
+
+ private List Images;
+
+ int apiResult = -1;
+
+ public CameraInfo()
+ {
+ Images = new List();
+ }
+
+ public void Deinit()
+ {
+ if(Camera != null)
+ {
+ Camera.MV_CC_CloseDevice_NET();
+ Camera.MV_CC_DestroyDevice_NET();
+ }
+ }
+ ///
+ /// 清除内存中的图片
+ ///
+ public void ClearImage()
+ {
+ lock(this)
+ {
+ if (Images != null)
+ {
+ Images.Clear();
+ }
+ }
+
+ }
+
+ ///
+ /// 取图
+ ///
+ ///
+ public int Grab()
+ {
+ if (Camera != null)
+ return Camera.MV_CC_SetCommandValue_NET("TriggerSoftware");
+ return -1;
+ }
+
+ public int StartGrabbing()
+ {
+ if (Camera != null)
+ return Camera.MV_CC_StartGrabbing_NET();
+ return -1;
+ }
+
+ public void AddImage(HObject image)
+ {
+ lock (this)
+ {
+ Images.Add(image);
+ }
+
+ }
+
+ ///
+ /// 设置曝光时间
+ ///
+ ///
+ ///
+ public int SetExposure(float timer)
+ {
+ if (Camera != null)
+ {
+ apiResult = Camera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
+ if (apiResult != 0)
+ {
+
+ return apiResult;
+ }
+ apiResult = Camera.MV_CC_SetFloatValue_NET("ExposureTime", timer);
+ if (apiResult != 0)
+ {
+ return apiResult;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+ ///
+ /// 设置相机增益
+ ///
+ ///
+ ///
+ ///
+ public int SetGain(float gain)
+ {
+ if (Camera != null)
+ {
+ apiResult = Camera.MV_CC_SetEnumValue_NET("GainAuto", 0);
+ if (apiResult != 0)
+ {
+ return apiResult;
+ }
+ apiResult = Camera.MV_CC_SetFloatValue_NET("Gain", gain);
+ if (apiResult != 0)
+ {
+ return apiResult;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+ ///
+ /// 设置相机的触发模式
+ ///
+ ///
+ ///
+ ///
+ public int SetTrigger(ETriggerSource triggerSource = ETriggerSource.Line0)
+ {
+ if(Camera!=null)
+ {
+ if (triggerSource == ETriggerSource.Line0)
+ {
+ apiResult = Camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
+ if (apiResult != 0)
+ {
+ apiResult = Camera.MV_CC_SetEnumValue_NET("TriggerActivation", 0);//设置上升沿触发
+ if (apiResult != 0)
+ {
+ return apiResult;
+ }
+ }
+ else
+ {
+ return apiResult;
+ }
+ }
+ else
+ {
+ apiResult = Camera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
+ if (apiResult != 0)
+ {
+ return apiResult;
+ }
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+ ///
+ /// 设置相机XY方向是否反转
+ ///
+ ///
+ ///
+ ///
+ ///
+ public int SetReverse(string camName, EDir dir = EDir.X, bool reverse = false)
+ {
+ if(Camera!=null)
+ {
+ if (dir == EDir.X)
+ {
+ apiResult = Camera.MV_CC_SetBoolValue_NET("ReverseX", reverse);
+ if (apiResult != 0)
+ return apiResult;
+ }
+ else
+ {
+ apiResult = Camera.MV_CC_SetBoolValue_NET("ReverseY", reverse);
+ if (apiResult != 0)
+ return apiResult;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+ ///
+ /// 获取最后一张图片
+ ///
+ ///
+ public HObject GetLastImage()
+ {
+ lock (this)
+ {
+ if (Images != null && Images.Count > 0)
+ {
+ return Images[Images.Count - 1];
+ }
+ return null;
+ }
+ }
+
+ ///
+ /// 获取所有的图片
+ ///
+ ///
+ public List GetAllImages()
+ {
+ lock (this)
+ {
+ return Images;
+ }
+ }
+
+ ///
+ /// 获取图片数量
+ ///
+ ///
+ public int GetImageCount()
+ {
+ lock (this)
+ {
+ if (Images != null && Images.Count > 0)
+ {
+ return Images.Count;
+ }
+ return 0;
+ }
+ }
+ }
+}
diff --git a/Rs.Cameras/Properties/AssemblyInfo.cs b/Rs.Cameras/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..fc333b8
--- /dev/null
+++ b/Rs.Cameras/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("Rs.Cameras")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Rs.Cameras")]
+[assembly: AssemblyCopyright("Copyright © 2024")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("971d93ff-fd34-4088-9591-c25147290d22")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Rs.Cameras/Rs.Cameras.csproj b/Rs.Cameras/Rs.Cameras.csproj
new file mode 100644
index 0000000..d302df5
--- /dev/null
+++ b/Rs.Cameras/Rs.Cameras.csproj
@@ -0,0 +1,60 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {971D93FF-FD34-4088-9591-C25147290D22}
+ Library
+ Properties
+ Rs.Cameras
+ Rs.Cameras
+ v4.8
+ 512
+ true
+
+
+ true
+ full
+ false
+ ..\Rs.MotionPlat\bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\Rs.MotionPlat\bin\Debug\halcondotnet.dll
+
+
+ ..\Rs.MotionPlat\bin\Debug\MvCameraControl.Net.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {f6dbc74d-4a0b-4d50-9c79-2a5a1518849d}
+ Rs.Framework
+
+
+
+
\ No newline at end of file
diff --git a/Rs.MotionPlat.sln b/Rs.MotionPlat.sln
index e1def4d..45cb0c6 100644
--- a/Rs.MotionPlat.sln
+++ b/Rs.MotionPlat.sln
@@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rs.DataAccess", "Rs.DataAcc
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HWindow_Tool", "HWindow_Tool\HWindow_Tool.csproj", "{0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rs.Cameras", "Rs.Cameras\Rs.Cameras.csproj", "{971D93FF-FD34-4088-9591-C25147290D22}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +53,10 @@ Global
{0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0577B57A-17EF-4754-BE1C-BA45BEFC7BBF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {971D93FF-FD34-4088-9591-C25147290D22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {971D93FF-FD34-4088-9591-C25147290D22}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {971D93FF-FD34-4088-9591-C25147290D22}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {971D93FF-FD34-4088-9591-C25147290D22}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE