using Cognex.VisionPro;
using Cognex.VisionPro.ToolBlock;
using CSScripting;
using Microsoft.Win32;
using NPOI.SS.Formula.Functions;
using SR7Link;
using SRAPI;
using SRCSharpDemo;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TeamAAS_VP.Enums;
using TeamAAS_VP.Interfaces;
using TeamAAS_VP.Models;
namespace TeamAAS_VP.Core.Cameras
{
public class SSZNCamera : ICamera, INotifyPropertyChanged
{
#region 字段
private Thread m_hReceiveThread;
// 用于序列化对同一相机实例的操作,防止同一实例被并发操作
private readonly SemaphoreSlim _operationSemaphore = new SemaphoreSlim(1, 1);
// 用于保护状态变量(例如 IsGrabbing)的并发访问
private readonly object _stateLock = new object();
private SR7ApiOneTimeCallbackImpl iSR7APi = new SR7ApiOneTimeCallbackImpl();
public SRCSharpTools srcsharpTools = new SRCSharpTools();
private SR7IFGetDataCallBack GetDataDelegate;
#endregion
#region define
private int lastTotalPoints = 0; // 记录上次的总点数 / Record the last total points
public int coutCallbackPoints;//统计总回调行数 / Count the total number of callback rows
public uint profile16Bits = 0;//0:32bit 1:16bit
//define
public const int INVALID_VALUE_MIN = -1000000000;
public const int INVALID_VALUE_MAX = 1000000000;
#endregion
#region Image cache variable
//image cache
public int[][] ImgBuff32; // 32-bit height data
public short[][] ImgBuff16; // 16-bit height data
public byte[][] GrayBuff; // Grayscale data
public int[][] Encoder; // Encoder data
#endregion
#region 属性
public CameraBrand CameraBrand { get => CameraBrand.SSZN; }
public string Name { get; private set; }
public Guid ID { get; private set; }
public int Index { get; set; }
public string ManufacturerName { get; private set; }
public bool IsFindByIp { get; private set; }
public string ModelName { get; private set; }
public string SerialNumber { get; private set; }
public string CameraIp { get; private set; }
public CameraType CameraType { get; private set; }
public UInt32 ImageWidth { get; private set; }
public UInt32 ImageHeight { get; private set; }
private bool _IsGrabbing;
///
/// 正在采集
///
public bool IsGrabbing
{
get { return _IsGrabbing; }
private set { SetProperty(ref _IsGrabbing, value); }
}
private ICogImage _Image;
public ICogImage Image
{
get { return _Image; }
private set { SetProperty(ref _Image, value); }
}
public bool IsConnected { get; private set; }
///
/// 采集用时
///
public TimeSpan TotalTime { get; private set; }
///
/// 错误信息
///
public string ErrorMessage { get; private set; }
#endregion
#region 事件
public event Action ImageCallbackEvent;
public event Action CameraConnectChangedEvent;
#endregion
public SSZNCamera(Guid id, int index, string name, string serialNumber, string cameraip, bool isFindByIp)
{
ID = id;
Name = serialNumber;
Index = index;
CameraIp = cameraip;
SerialNumber = serialNumber;
IsFindByIp = isFindByIp;
IsConnected = false;
}
#region 方法
///
/// 获取设备
///
///
public static CameraInfo[] GetDevices()
{
List cameras = new List();
try
{
if (!CheckSoftwareInstalled().isInstalled)
{
LogHelper.WriteLogInfo("未安装MVS");
return cameras.ToArray();
}
SR7ApiOneTimeCallbackImpl sR7Api=new SR7ApiOneTimeCallbackImpl();
List cameraIPs = new List();
if (!sR7Api.SearchCameraIP(out cameraIPs))
{
return cameras.ToArray();
}
else
{
for (int i = 0; i < cameraIPs.Count; i++)
{
cameras.Add(new CameraInfo()
{
CameraNo = i + 1,
CameraName = "SSZN_" + cameraIPs[i],
CameraBrand = CameraBrand.SSZN,
CameraType = CameraType.GIGE,
ManufacturerName = "SSZN",
Model = "SSZN_Model",
SerialNumber = "SSZN_SerialNumber",
CameraIp = cameraIPs[i],
IsFindByIp = true,
});
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("搜索深视3D相机列表时出错!", ex);
}
return cameras.ToArray();
}
///
/// 检查相机软件是否安装
///
///
public static (bool isInstalled, string version) CheckSoftwareInstalled()
{
return (true, "");
}
///
/// 打开相机
///
///
///
public bool OpenDevice()
{
_operationSemaphore.Wait();
try
{
if (!iSR7APi.CameraBOnline)
{
SR7Link.ErrConnectCallBack ErrConnectDelegate = new SR7Link.ErrConnectCallBack(ErrConnectFunc);
ErrConnectDelegate = new ErrConnectCallBack(ErrConnectFunc);
int nOpenRet = iSR7APi.Open(0, CameraIp, 2000, ErrConnectDelegate);
if (nOpenRet == (int)SR7Link.SR7IF_ERROR.SR7IF_OK)
{
//设置相机参数,否则无法取图 / Set the camera parameters, otherwise you will not be able to take pictures
//一次回调和无限回调可以设置批处理测量On,批处理数据接收无和循环 / One-time callback and infinite callback can set batch measurement On, batch data receiving None and loop
//异步回调必须在Ed软件中设置 / Asynchronous callbacks must be set in the EdgeImaging software
int nReadBastchValue = -1;
int nSetParamRet = -1;
int getParamRet = iSR7APi.GetParams(0, -1, SR7IF_SETTING_ITEM.BATCH_ON_OFF, out nReadBastchValue);
if (nReadBastchValue != 1)
{
nSetParamRet = iSR7APi.SetParams(0, (int)SAVEPOWEROFF.ESAPO_SAVE, -1, SR7IF_SETTING_ITEM.BATCH_ON_OFF, 1);
LogHelper.WriteLogInfo($"Set Batch On Off: {nSetParamRet}");
}
nSetParamRet = iSR7APi.SetParams(0, (int)SAVEPOWEROFF.ESAPO_SAVE, -1, SR7IF_SETTING_ITEM.CYCLICAL_PATTERN, 0);
int nSetParamRet1 = iSR7APi.SetParams(0, (int)SAVEPOWEROFF.ESAPO_SAVE, -1, SR7IF_SETTING_ITEM.SEGMENT_BUFER, 0);
LogHelper.WriteLogInfo($"Set Batch Data Receive: {nSetParamRet1}{nSetParamRet1}");
GetDataDelegate = new SR7IFGetDataCallBack(GetDataCallBack);
iSR7APi.Init(0,0,2000, GetDataDelegate);
}
LogHelper.WriteLogInfo($"Connect Camera {nOpenRet} {GetSDKErrMsgByCode(nOpenRet)}");
}
if (!IsConnected)
{
if (iSR7APi.CameraBOnline)
{
CameraConnectChangedEvent?.Invoke(ID, true);
}
}
IsConnected = iSR7APi.CameraBOnline;
return IsConnected;
}
finally
{
_operationSemaphore.Release();
}
}
///
/// 打开相机异步
///
///
public Task OpenDeviceAsync()
{
return Task.Run(() =>
{
return OpenDevice();
});
}
///
/// 关闭相机
///
public void CloseDevice()
{
// ch:关闭设备 | en:Close Device
_operationSemaphore.Wait();
try
{
if (iSR7APi==null)
{
return;
}
int nRet = iSR7APi.Close();
LogHelper.WriteLogInfo($"Close Camera: {nRet}{GetSDKErrMsgByCode(nRet)}");
}
finally
{
_operationSemaphore.Release();
}
}
///
/// 采集图像
///
///
public ICogImage Grab()
{
_operationSemaphore.Wait();
try
{
return Image;
}
finally
{
_operationSemaphore.Release();
}
}
///
/// 开始采集图像
///
public void StartGrabbing()
{
lock (_stateLock)
{
if (IsGrabbing)
return;
IsGrabbing = true;
}
m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
m_hReceiveThread.Start();
}
///
/// 停止采集图像
///
public void StopGrabbing()
{
try
{
lock (_stateLock)
{
IsGrabbing = false;
}
Thread.Sleep(1000);
if (m_hReceiveThread != null)
{
m_hReceiveThread.Abort();
m_hReceiveThread = null;
}
}
catch (Exception)
{
}
}
///
/// 设置曝光时间
///
///
///
public bool SetExposureTime(float ExposureTime)
{
//_operationSemaphore.Wait();
//try
//{
// if (!mvCameraAcq.bIsOpened)
// return false;
// mvCameraAcq.ExposureTime = (double)ExposureTime;
// return true;
//}
//finally
//{
// _operationSemaphore.Release();
//}
return true;
}
///
/// 获取曝光时间
///
///
public float GetExposureTime()
{
//_operationSemaphore.Wait();
//try
//{
// if (!mvCameraAcq.bIsOpened)
// return 0;
// return (float)mvCameraAcq.ExposureTime;
//}
//finally
//{
// _operationSemaphore.Release();
//}
return 0;
}
///
/// 设置增益
///
///
///
public bool SetGain(float Gain)
{
//_operationSemaphore.Wait();
//try
//{
// if (!mvCameraAcq.bIsOpened)
// return false;
// mvCameraAcq.AnalogGain = (double)Gain;
// return true;
//}
//finally
//{
// _operationSemaphore.Release();
//}
return true;
}
///
/// 获取增益
///
///
public float GetGain()
{
//_operationSemaphore.Wait();
//try
//{
// if (!mvCameraAcq.bIsOpened)
// return 0;
// return (float)mvCameraAcq.AnalogGain;
//}
//finally
//{
// _operationSemaphore.Release();
//}
return 0;
}
private void GetStreamThreadProc()
{
//while (IsGrabbing)
//{
// try
// {
// Grab();
// ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
// }
// catch (Exception)
// {
// }
// Thread.Sleep(10);
//}
IsGrabbing = false;
}
///
///
///
/// 单条轮廓宽度数据 / Returns a single contour width data
/// 返回的批处理行数 / The number of rows in the batch returned
/// 回调函数执行状态,根据不同模式自定义 / Callback function execution status, customized according to different modes
/// 错误码,0无错误 / Error code, 0 no error
/// Sync callback 0:32bit data, 1:16bit data
private void GetDataCallBack(int nProfileWidth, int nHighlen, int nFlag, int nStatusCode, int ProfileBits)
{
profile16Bits = (uint)ProfileBits;
if (nStatusCode == 0)
{
//Log($"Into GetDataFunc W:{nProfileWidth},H:{nHighlen},ErrCode:{nStatusCode}({GetSDKErrMsgByCode(nStatusCode)})");
//这里拿到相机数据做显示,可以根据其他具体业务实现自己的逻辑
//The camera data is obtained here for display, and you can implement your own logic according to other specific businesses
int nTempWidth = nProfileWidth;// iSR7APi.GetProfileDataWidth();
//双相机时,一次回调和异步回调nProfileWidth=3200,无限循环回调nProfileWidth=6400
//For dual cameras, nProfileWidth=3200 for one-time callback and asynchronous callback, and nProfileWidth=6400 for infinite loop callback
//if (iSR7APi.CameraBOnline && m_callbackMode == 2)//双相机 / dual camera
// nTempWidth /= 2;
int offset = coutCallbackPoints * nTempWidth;
//iSR7APi.BatchPoints = nHighlen;
SImagePro.SPointCloudHead pcHead = new SImagePro.SPointCloudHead(0, 0, 0, 0, 0);
pcHead.width = (uint)nTempWidth;
pcHead.height = (uint)iSR7APi.BatchPoints;
pcHead.xInterval = iSR7APi.GetProfileData_XPitch();
pcHead.yInterval = iSR7APi.GetProfileData_XPitch();
if (ProfileBits == 0)
{
int[] tempHeightDataA = new int[nTempWidth * nHighlen];
byte[] tempGrayDataA = new byte[nTempWidth * nHighlen];
iSR7APi.GetData(tempHeightDataA, tempGrayDataA, Encoder[0], (int)pcHead.width, (int)nHighlen, 0);
Array.Copy(tempHeightDataA, 0, ImgBuff32[0], offset, nTempWidth * nHighlen);
Array.Copy(tempGrayDataA, 0, GrayBuff[0], offset, nTempWidth * nHighlen);
//if (ImgBuff32 != null && ImgBuff32.Length != 0 && ImgBuff32[0] != null)
//{
// ShowRGBImage(ImgBuff32[0], pcHead, pictureBoxA);
//}
CogImage16Range cogImage16Range = SSZNCognexParser.SSZNParser.LoadSSZN3DImage(ImgBuff32[0], (int)pcHead.width, (int)pcHead.height, pcHead.xInterval, pcHead.yInterval);
Image= cogImage16Range;
ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
}
else
{
short[] temp16bitDataA = new short[nTempWidth * nHighlen];
byte[] tempGrayDataA = new byte[nTempWidth * nHighlen];
iSR7APi.GetData(temp16bitDataA, tempGrayDataA, Encoder[0], (int)pcHead.width, (int)nHighlen, 0);
Array.Copy(temp16bitDataA, 0, ImgBuff16[0], offset, nTempWidth * nHighlen);
Array.Copy(tempGrayDataA, 0, GrayBuff[0], offset, nTempWidth * nHighlen);
CogImage16Range cogImage16Range = SSZNCognexParser.SSZNParser.LoadSSZN3DImage(ImgBuff32[0], (int)pcHead.width, (int)pcHead.height, pcHead.xInterval, pcHead.yInterval);
Image = cogImage16Range;
ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
//int[] showtemp16bitDataA = new int[pcHead.width * pcHead.height];
//ShowTiff16Data(ImgBuff16[0], showtemp16bitDataA);
//if (ImgBuff16 != null && ImgBuff16.Length != 0 && ImgBuff16[0] != null)
//{
// ShowRGBImage(showtemp16bitDataA, pcHead, pictureBoxA);
//}
}
//if (iSR7APi.CameraBOnline && ImgBuff32[1] != null)
//{
// if (ProfileBits == 0)
// {
// int[] tempHeightDataB = new int[nTempWidth * nHighlen];
// byte[] tempGrayDataB = new byte[nTempWidth * nHighlen];
// iSR7APi.GetData(tempHeightDataB, tempGrayDataB, Encoder[1], (int)pcHead.width, (int)nHighlen, 1);
// Array.Copy(tempHeightDataB, 0, ImgBuff32[1], offset, nTempWidth * nHighlen);
// Array.Copy(tempGrayDataB, 0, GrayBuff[1], offset, nTempWidth * nHighlen);
// //ShowRGBImage(ImgBuff32[1], pcHead, pictureBoxB);
// }
// else
// {
// short[] tempHeightDataB = new short[nTempWidth * nHighlen];
// byte[] tempGrayDataB = new byte[nTempWidth * nHighlen];
// iSR7APi.GetData(tempHeightDataB, tempGrayDataB, Encoder[1], (int)pcHead.width, (int)nHighlen, 1);
// Array.Copy(tempHeightDataB, 0, ImgBuff16[1], offset, nTempWidth * nHighlen);
// Array.Copy(tempGrayDataB, 0, GrayBuff[1], offset, nTempWidth * nHighlen);
// int[] showtemp16bitDataB = new int[pcHead.width * pcHead.height];
// //ShowTiff16Data(ImgBuff16[1], showtemp16bitDataB);
// //ShowRGBImage(showtemp16bitDataB, pcHead, pictureBoxB);
// }
//}
coutCallbackPoints += nHighlen;
}
else
{
LogHelper.WriteLogInfo($"Data CallBack Exception:{nStatusCode}({GetSDKErrMsgByCode(nStatusCode)})");
//callbackEvent.Set();
}
}
public void ErrConnectFunc(int dwDeviceId, int nErrCode)
{
LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{GetSDKErrMsgByCode(nErrCode)}");
iSR7APi.CameraAOnline = false;
iSR7APi.CameraBOnline = false;
//:1:Data overflow,3:Disconnect, 4:Wrong version
//Non-asynchronous mode: -1 represents a general error, such as link failure, setup failure, data acquisition failure, etc., -1000;
switch (nErrCode)
{
case 1:
LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_1")}");
break;
case 3:
LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_3")}");
break;
case 4:
LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_3")}");
break;
case -1:
LogHelper.WriteLogInfo($"Into ConnectExceptionCallback Error Code: {nErrCode}{srcsharpTools.GetTranslation("CAMERA_EXCEPTION_N1")}");
break;
default:
break;
}
}
public string GetSDKErrMsgByCode(int nErrCode)
{
string strErrMsg;
switch ((SR7Link.SR7IF_ERROR)nErrCode)
{
case SR7IF_ERROR.SR7IF_ERROR_NOT_FOUND: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_NOT_FOUND"); break;
case SR7IF_ERROR.SR7IF_ERROR_COMMAND: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_COMMAND"); break;
case SR7IF_ERROR.SR7IF_ERROR_PARAMETER: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_PARAMETER"); break;
case SR7IF_ERROR.SR7IF_ERROR_UNIMPLEMENTED: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_UNIMPLEMENTED"); break;
case SR7IF_ERROR.SR7IF_ERROR_HANDLE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_HANDLE"); break;
case SR7IF_ERROR.SR7IF_ERROR_MEMORY: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_MEMORY"); break;
case SR7IF_ERROR.SR7IF_ERROR_TIMEOUT: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_TIMEOUT"); break;
case SR7IF_ERROR.SR7IF_ERROR_DATABUFFER: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_DATABUFFER"); break;
case SR7IF_ERROR.SR7IF_ERROR_STREAM: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_STREAM"); break;
case SR7IF_ERROR.SR7IF_ERROR_CLOSED: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_CLOSED"); break;
case SR7IF_ERROR.SR7IF_ERROR_VERSION: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_VERSION"); break;
case SR7IF_ERROR.SR7IF_ERROR_ABORT: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ABORT"); break;
case SR7IF_ERROR.SR7IF_ERROR_ALREADY_EXISTS: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ALREADY_EXISTS"); break;
case SR7IF_ERROR.SR7IF_ERROR_FRAME_LOSS: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_FRAME_LOSS"); break;
case SR7IF_ERROR.SR7IF_ERROR_ROLL_DATA_OVERFLOW: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ROLL_DATA_OVERFLOW"); break;
case SR7IF_ERROR.SR7IF_ERROR_ROLL_BUSY: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_ROLL_BUSY"); break;
case SR7IF_ERROR.SR7IF_ERROR_MODE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_MODE"); break;
case SR7IF_ERROR.SR7IF_ERROR_CAMERA_NOT_ONLINE: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR_CAMERA_NOT_ONLINE"); break;
case SR7IF_ERROR.SR7IF_ERROR: strErrMsg = srcsharpTools.GetTranslation("SR7IF_ERROR"); break;
case SR7IF_ERROR.SR7IF_NORMAL_STOP: strErrMsg = srcsharpTools.GetTranslation("SR7IF_NORMAL_STOP"); break;
case SR7IF_ERROR.SR7IF_OK: strErrMsg = ""; break;
default:
strErrMsg = "";
break;
}
return strErrMsg;
}
#endregion
#region 属性通知
///
/// Occurs when a property value changes.
///
public event PropertyChangedEventHandler PropertyChanged;
///
/// Checks if a property already matches a desired value. Sets the property and
/// notifies listeners only when necessary.
///
/// Type of the property.
/// Reference to a property with both getter and setter.
/// Desired value for the property.
/// Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers that
/// support CallerMemberName.
/// True if the value was changed, false if the existing value matched the
/// desired value.
protected virtual bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(storage, value)) return false;
storage = value;
RaisePropertyChanged(propertyName);
return true;
}
///
/// Checks if a property already matches a desired value. Sets the property and
/// notifies listeners only when necessary.
///
/// Type of the property.
/// Reference to a property with both getter and setter.
/// Desired value for the property.
/// Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers that
/// support CallerMemberName.
/// Action that is called after the property value has been changed.
/// True if the value was changed, false if the existing value matched the
/// desired value.
protected virtual bool SetProperty(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(storage, value)) return false;
storage = value;
onChanged?.Invoke();
RaisePropertyChanged(propertyName);
return true;
}
///
/// Raises this object's PropertyChanged event.
///
/// Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers
/// that support .
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
///
/// Raises this object's PropertyChanged event.
///
/// The PropertyChangedEventArgs
protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChanged?.Invoke(this, args);
}
#endregion
}
}