You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
514 lines
20 KiB
514 lines
20 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Runtime.InteropServices; |
|
using System.Text; |
|
using System.Threading; |
|
using System.Threading.Tasks; |
|
using static Guidaoji.Camera.CHCNetSDK; |
|
|
|
namespace Guidaoji.Camera |
|
{ |
|
public class CHNetHelp |
|
{ |
|
private int counter = 0; |
|
private static CHNetHelp _instance; |
|
// 私有构造函数以防止外部实例化 |
|
public CHNetHelp() { } |
|
//海康辅助函数:add by lee start |
|
private static uint iLastErr = 0; |
|
private static Int32 m_lUserID = -1; |
|
private static bool m_bInitSDK = false; |
|
private static bool m_bRecord = false; |
|
private static bool m_bTalk = false; |
|
private static Int32 m_lRealHandle = -1;//m_lRealHandle |
|
private static int lVoiceComHandle = -1; |
|
private static string str; |
|
//相机参数通过PtzGet()获得 |
|
private static float WPanPos, WTiltPos, WZoomPos; |
|
private static bool m_param_get_flag = false;//当获取成功后设置为true |
|
private static int[] iChannelNum = new int[96]; |
|
|
|
// 公共静态方法用于获取类的实例 |
|
public static CHNetHelp GetInstance() |
|
{ |
|
if (_instance == null) |
|
{ |
|
_instance = new CHNetHelp(); |
|
} |
|
return _instance; |
|
} |
|
|
|
|
|
//登录相关 |
|
static CHCNetSDK.REALDATACALLBACK RealData = null; |
|
static CHCNetSDK.LOGINRESULTCALLBACK LoginCallBack = null; |
|
public static CHCNetSDK.NET_DVR_PTZPOS m_struPtzCfg; |
|
public static CHCNetSDK.NET_DVR_USER_LOGIN_INFO struLogInfo; |
|
public static CHCNetSDK.NET_DVR_DEVICEINFO_V40 DeviceInfo; |
|
|
|
public delegate void UpdateTextStatusCallback(string strLogStatus, IntPtr lpDeviceInfo); |
|
|
|
//云台相关 |
|
private bool bAuto = false; |
|
//private uint iLastErr = 0; |
|
public static int PreSetNo = 0; |
|
//public CHCNetSDK.NET_DVR_PTZPOS m_struPtzCfg; |
|
public static CHCNetSDK.NET_DVR_PTZSCOPE m_struPtzCfg1; |
|
public static CHCNetSDK.NET_DVR_PRESET_NAME[] m_struPreSetCfg = new CHCNetSDK.NET_DVR_PRESET_NAME[300]; |
|
|
|
public static void cbLoginCallBack(int lUserID, int dwResult, IntPtr lpDeviceInfo, IntPtr pUser) |
|
{ |
|
string strLoginCallBack = "登录设备,lUserID:" + lUserID + ",dwResult:" + dwResult; |
|
|
|
if (dwResult == 0) |
|
{ |
|
uint iErrCode = CHCNetSDK.NET_DVR_GetLastError(); |
|
strLoginCallBack = strLoginCallBack + ",错误号:" + iErrCode; |
|
} |
|
} |
|
|
|
//初始化并用固定IP的登录 |
|
public static bool CameraInit(string sIP, string sPassword) |
|
{ |
|
PrintInfo("登录....."); |
|
for (int i = 0; i < 64; i++) |
|
{ |
|
iChannelNum[i] = i; |
|
} |
|
m_bInitSDK = CHCNetSDK.NET_DVR_Init(); |
|
if (m_bInitSDK == false) |
|
{ |
|
//MessageBox.Show("NET_DVR_Init error!"); |
|
return false; |
|
} |
|
else |
|
{ |
|
//保存SDK日志 To save the SDK log |
|
CHCNetSDK.NET_DVR_SetLogToFile(3, "C:\\SdkLog\\", true); |
|
} |
|
//MessageBox.Show("camera Init m_bInitSDK=="+ m_bInitSDK); |
|
|
|
//登录 |
|
// 固定的设备IP地址192.168.10.102 |
|
string fixedIP = sIP; |
|
byte[] byIP = System.Text.Encoding.Default.GetBytes(fixedIP); |
|
struLogInfo.sDeviceAddress = new byte[129]; |
|
byIP.CopyTo(struLogInfo.sDeviceAddress, 0); |
|
|
|
//设备用户名 |
|
string fixedName = "admin"; |
|
byte[] byUserName = System.Text.Encoding.Default.GetBytes(fixedName); |
|
struLogInfo.sUserName = new byte[64]; |
|
byUserName.CopyTo(struLogInfo.sUserName, 0); |
|
|
|
//设备密码ch123456 |
|
string fixedPassword = sPassword; |
|
byte[] byPassword = System.Text.Encoding.Default.GetBytes(fixedPassword); |
|
struLogInfo.sPassword = new byte[64]; |
|
byPassword.CopyTo(struLogInfo.sPassword, 0); |
|
|
|
struLogInfo.wPort = ushort.Parse("8000");//设备服务端口号 |
|
if (LoginCallBack == null) |
|
{ |
|
LoginCallBack = new CHCNetSDK.LOGINRESULTCALLBACK(cbLoginCallBack);//注册回调函数 |
|
} |
|
struLogInfo.cbLoginResult = LoginCallBack; |
|
struLogInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是 |
|
DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V40(); |
|
|
|
//登录设备 Login the device |
|
m_lUserID = CHCNetSDK.NET_DVR_Login_V40(ref struLogInfo, ref DeviceInfo); |
|
if (m_lUserID < 0) |
|
{ |
|
iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
str = "NET_DVR_Login_V40 failed, error code= " + iLastErr; //登录失败,输出错误号 |
|
//MessageBox.Show(str); |
|
} |
|
else |
|
{ |
|
//登录成功 |
|
//MessageBox.Show("Login Success!"); |
|
} |
|
PrintInfo("登录结束....."); |
|
return true; |
|
} |
|
|
|
//显示视频画面 |
|
//public static void StartStopLiveView(System.Windows.Forms.Panel panel, string channel, bool isStreamID = false, string streamID = "") |
|
//{ |
|
// if (m_lUserID < 0) |
|
// { |
|
// MessageBox.Show("Please login to the device first."); |
|
// return; |
|
// } |
|
|
|
// if (m_lRealHandle < 0) |
|
// { |
|
// CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO(); |
|
// lpPreviewInfo.hPlayWnd = panel.Handle; // 预览窗口 |
|
// lpPreviewInfo.lChannel = Int16.Parse(channel); // 预览的设备通道 |
|
|
|
// lpPreviewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推 |
|
// lpPreviewInfo.dwLinkMode = 0;//连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP |
|
// lpPreviewInfo.bBlocked = true; //0- 非阻塞取流,1- 阻塞取流 |
|
// lpPreviewInfo.dwDisplayBufNum = 1; //播放库播放缓冲区最大缓冲帧数 |
|
// lpPreviewInfo.byProtoType = 0; |
|
// lpPreviewInfo.byPreviewMode = 0; |
|
|
|
// if (isStreamID) |
|
// { |
|
// lpPreviewInfo.lChannel = -1; |
|
// byte[] byStreamID = System.Text.Encoding.Default.GetBytes(streamID); |
|
// lpPreviewInfo.byStreamID = new byte[32]; |
|
// byStreamID.CopyTo(lpPreviewInfo.byStreamID, 0); |
|
// } |
|
|
|
// // ... 实时流回调函数和预览逻辑 ... |
|
// if (RealData == null) |
|
// { |
|
// RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数 |
|
// } |
|
|
|
// m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, RealData, IntPtr.Zero); |
|
// if (m_lRealHandle < 0) |
|
// { |
|
// // ... 处理预览失败逻辑 ... |
|
// iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
// str = "NET_DVR_RealPlay_V40 failed, error code= " + iLastErr; //预览失败,输出错误号 |
|
// MessageBox.Show(str); |
|
// return; |
|
// } |
|
// } |
|
// else |
|
// { |
|
// // 停止预览 |
|
// if (CHCNetSDK.NET_DVR_StopRealPlay(m_lRealHandle)) |
|
// { |
|
// m_lRealHandle = -1; |
|
// } |
|
// else |
|
// { |
|
// // ... 处理停止预览失败逻辑 ... |
|
// } |
|
// } |
|
//} |
|
|
|
//你可以定义一个方法 RealDataCallBack,它将在有新的视频数据到达时被调用。 |
|
public static void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser) |
|
{ |
|
if (dwBufSize > 0) |
|
{ |
|
byte[] sData = new byte[dwBufSize]; |
|
Marshal.Copy(pBuffer, sData, 0, (Int32)dwBufSize); |
|
|
|
string str = "实时流数据.ps"; |
|
FileStream fs = new FileStream(str, FileMode.Create); |
|
int iLen = (int)dwBufSize; |
|
fs.Write(sData, 0, iLen); |
|
fs.Close(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 抓拍并保存图片 |
|
/// </summary> |
|
/// <param name="iSelIndex">选择通道</param> |
|
/// <param name="sFilePath">照片存放路径</param> |
|
/// <returns></returns> |
|
|
|
public static bool JPEG(int iSelIndex, string sFilePath) |
|
{ |
|
PrintInfo("抓图开始....."); |
|
int lChannel = iChannelNum[iSelIndex]; //通道号 Channel number |
|
|
|
CHCNetSDK.NET_DVR_JPEGPARA lpJpegPara = new CHCNetSDK.NET_DVR_JPEGPARA(); |
|
lpJpegPara.wPicQuality = 0; //图像质量 Image quality |
|
lpJpegPara.wPicSize = 0xff; //抓图分辨率 Picture size: 0xff-Auto(使用当前码流分辨率) |
|
//抓图分辨率需要设备支持,更多取值请参考SDK文档 |
|
|
|
//JPEG抓图保存成文件 Capture a JPEG picture |
|
//string sJpegPicFileName; |
|
//sJpegPicFileName = "filetest.jpg";//图片保存路径和文件名 the path and file name to save |
|
if (!CHCNetSDK.NET_DVR_CaptureJPEGPicture(m_lUserID, lChannel, ref lpJpegPara, sFilePath)) |
|
{ |
|
iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
str = "NET_DVR_CaptureJPEGPicture failed, error code= " + iLastErr; |
|
PrintInfo(str); |
|
return false; |
|
} |
|
else |
|
{ |
|
str = "NET_DVR_CaptureJPEGPicture succ and the saved file is " + sFilePath; |
|
PrintInfo(str); |
|
} |
|
|
|
//JEPG抓图,数据保存在缓冲区中 Capture a JPEG picture and save in the buffer |
|
uint iBuffSize = 400000; //缓冲区大小需要不小于一张图片数据的大小 The buffer size should not be less than the picture size |
|
byte[] byJpegPicBuffer = new byte[iBuffSize]; |
|
uint dwSizeReturned = 0; |
|
|
|
if (!CHCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(m_lUserID, lChannel, ref lpJpegPara, byJpegPicBuffer, iBuffSize, ref dwSizeReturned)) |
|
{ |
|
iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
str = "NET_DVR_CaptureJPEGPicture_NEW failed, error code= " + iLastErr; |
|
PrintInfo(str); |
|
return false; |
|
} |
|
else |
|
{ |
|
//将缓冲区里的JPEG图片数据写入文件 save the data into a file |
|
FileStream fs = new FileStream(sFilePath, FileMode.Create); |
|
int iLen = (int)dwSizeReturned; |
|
fs.Write(byJpegPicBuffer, 0, iLen); |
|
fs.Close(); |
|
|
|
str = "NET_DVR_CaptureJPEGPicture_NEW succ and save the data in buffer to 'buffertest.jpg'."; |
|
PrintInfo(str); |
|
} |
|
PrintInfo("抓图结束....."); |
|
return true; |
|
} |
|
|
|
/// <summary> |
|
/// 设置摄像头移动 |
|
/// </summary> |
|
/// <param name="operationType">运动类型</param> |
|
/// <param name="fP">水平移动</param> |
|
/// <param name="fT">垂直移动</param> |
|
/// <param name="fZ">焦距</param> |
|
public static bool PtzSet(OperationType operationType, float fP, float fT, float fZ) |
|
{ |
|
PrintInfo("摄像头移动开始....."); |
|
int flag = 1; |
|
String str1, str2, str3; |
|
|
|
switch ((int)operationType)//操作类型 |
|
{ |
|
case 0: |
|
flag = 0; |
|
m_struPtzCfg.wAction = 1; |
|
|
|
str1 = Convert.ToString(fP * 10); |
|
m_struPtzCfg.wPanPos = (ushort)(Convert.ToUInt16(str1, 16)); |
|
str2 = Convert.ToString(fT * 10); |
|
m_struPtzCfg.wTiltPos = (ushort)(Convert.ToUInt16(str2, 16)); |
|
str3 = Convert.ToString(fZ * 10); |
|
m_struPtzCfg.wZoomPos = (ushort)(Convert.ToUInt16(str3, 16)); |
|
break; |
|
case 1: |
|
flag = 0; |
|
m_struPtzCfg.wAction = 2; |
|
|
|
str1 = Convert.ToString(fP * 10); |
|
m_struPtzCfg.wPanPos = (ushort)(Convert.ToUInt16(str1, 16)); |
|
break; |
|
case 2: |
|
flag = 0; |
|
m_struPtzCfg.wAction = 3; |
|
|
|
str2 = Convert.ToString(fT * 10); |
|
m_struPtzCfg.wTiltPos = (ushort)(Convert.ToUInt16(str2, 16)); |
|
break; |
|
case 3: |
|
flag = 0; |
|
m_struPtzCfg.wAction = 4; |
|
|
|
str3 = Convert.ToString(fZ * 10); |
|
m_struPtzCfg.wZoomPos = (ushort)(Convert.ToUInt16(str3, 16)); |
|
break; |
|
case 4: |
|
flag = 0; |
|
m_struPtzCfg.wAction = 5; |
|
|
|
str1 = Convert.ToString(fP * 10); |
|
m_struPtzCfg.wPanPos = (ushort)(Convert.ToUInt16(str1, 16)); |
|
str2 = Convert.ToString(fT * 10); |
|
m_struPtzCfg.wTiltPos = (ushort)(Convert.ToUInt16(str2, 16)); |
|
break; |
|
} |
|
|
|
bool bFlag = false; |
|
if (flag == 0) |
|
{ |
|
Int32 nSize = Marshal.SizeOf(m_struPtzCfg); |
|
IntPtr ptrPtzCfg = Marshal.AllocHGlobal(nSize); |
|
Marshal.StructureToPtr(m_struPtzCfg, ptrPtzCfg, false); |
|
|
|
if (!CHCNetSDK.NET_DVR_SetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_SET_PTZPOS, 1, ptrPtzCfg, (UInt32)nSize)) |
|
{ |
|
iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
str = "NET_DVR_SetDVRConfig failed, error code= " + iLastErr; |
|
//设置POS参数失败 |
|
//MessageBox.Show(str); |
|
} |
|
else |
|
{ |
|
bFlag = true; |
|
//MessageBox.Show("设置成功!"); |
|
} |
|
Marshal.FreeHGlobal(ptrPtzCfg); |
|
} |
|
PrintInfo("摄像头移动结束....."); |
|
return bFlag; |
|
} |
|
|
|
//获取相机焦距位置相关,P,T(ilt),zoom,m_param_get_flag 设置为true; |
|
public static float[] PtzGet() |
|
{ |
|
float[] ret = { -1F, -1F, -1F }; |
|
UInt32 dwReturn = 0; |
|
Int32 nSize = Marshal.SizeOf(m_struPtzCfg); |
|
IntPtr ptrPtzCfg = Marshal.AllocHGlobal(nSize); |
|
Marshal.StructureToPtr(m_struPtzCfg, ptrPtzCfg, false); |
|
//获取参数失败 |
|
if (!CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_PTZPOS, -1, ptrPtzCfg, (UInt32)nSize, ref dwReturn)) |
|
{ |
|
iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
str = "NET_DVR_GetDVRConfig failed, error code= " + iLastErr; |
|
//MessageBox.Show(str); |
|
return ret; |
|
} |
|
else |
|
{ |
|
m_struPtzCfg = (CHCNetSDK.NET_DVR_PTZPOS)Marshal.PtrToStructure(ptrPtzCfg, typeof(CHCNetSDK.NET_DVR_PTZPOS)); |
|
//成功获取显示ptz参数 |
|
ushort wPanPos = Convert.ToUInt16(Convert.ToString(m_struPtzCfg.wPanPos, 16)); |
|
ret[0] = WPanPos = wPanPos * 0.1f; |
|
//textBoxPanPos.Text = Convert.ToString(WPanPos); |
|
ushort wTiltPos = Convert.ToUInt16(Convert.ToString(m_struPtzCfg.wTiltPos, 16)); |
|
ret[1] = WTiltPos = wTiltPos * 0.1f; |
|
// textBoxTiltPos.Text = Convert.ToString(WTiltPos); |
|
ushort wZoomPos = Convert.ToUInt16(Convert.ToString(m_struPtzCfg.wZoomPos, 16)); |
|
ret[2] = WZoomPos = wZoomPos * 0.1f; |
|
//textBoxZoomPos.Text = Convert.ToString(WZoomPos); |
|
m_param_get_flag = true; |
|
return ret; |
|
} |
|
|
|
} |
|
|
|
/// <summary> |
|
/// 保存录像 |
|
/// </summary> |
|
/// <param name="bTranscribe">true:开始录像;false:停止录像</param> |
|
/// <param name="iSelIndex">选择通道</param> |
|
/// <param name="sViedoPath">视频保存路径</param> |
|
public static bool SaveViedo(bool bTranscribe, int iSelIndex, string sViedoPath) |
|
{ |
|
PrintInfo(sViedoPath); |
|
if (bTranscribe == true) |
|
{ |
|
PrintInfo("保存录像开始....."); |
|
//强制I帧 Make one key frame |
|
int lChannel = iChannelNum[iSelIndex]; //通道号 Channel number |
|
CHCNetSDK.NET_DVR_MakeKeyFrame(m_lUserID, lChannel); |
|
|
|
//开始录像 Start recording |
|
if (!CHCNetSDK.NET_DVR_SaveRealData(m_lRealHandle, sViedoPath)) |
|
{ |
|
iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
str = "NET_DVR_SaveRealData failed, error code= " + iLastErr; |
|
PrintInfo(str); |
|
return false; |
|
} |
|
else |
|
{ |
|
PrintInfo("NET_DVR_SaveRealData succ!"); |
|
return true; |
|
} |
|
} |
|
else |
|
{ |
|
PrintInfo("保存录像结束....."); |
|
//停止录像 Stop recording |
|
if (!CHCNetSDK.NET_DVR_StopSaveRealData(m_lRealHandle)) |
|
{ |
|
iLastErr = CHCNetSDK.NET_DVR_GetLastError(); |
|
str = "NET_DVR_StopSaveRealData failed, error code= " + iLastErr; |
|
PrintInfo(str); |
|
return false; |
|
} |
|
else |
|
{ |
|
str = "NET_DVR_StopSaveRealData succ and the saved file is " + sViedoPath; |
|
PrintInfo(str); |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 移动摄像头过程 |
|
/// </summary> |
|
/// <param name="operationType">控制类型</param> |
|
/// <param name="fP">水平移动</param> |
|
/// <param name="fT">垂直移动</param> |
|
/// <param name="fZ">焦距</param> |
|
/// <param name="iSelIndex">选择通道</param> |
|
/// <param name="sFilePath">抓拍路径</param> |
|
/// <returns></returns> |
|
public static bool SetCameraProcess(OperationType operationType, float fP, float fT, float fZ, int iSelIndex, string sFilePath) |
|
{ |
|
//移动摄像头 |
|
if (PtzSet(operationType, fP, fT, fZ)) |
|
{ |
|
while (true) |
|
{ |
|
float[] fCameraPose = PtzGet(); |
|
if (fCameraPose[0] == fP && fCameraPose[1] == fT && fCameraPose[2] == fZ) |
|
{ |
|
break; |
|
} |
|
Thread.Sleep(100); |
|
} |
|
//拍照 |
|
if (JPEG(iSelIndex, sFilePath)) |
|
return true; |
|
else return false; |
|
} |
|
else |
|
return false; |
|
} |
|
|
|
public static void PrintInfo(string str) |
|
{ |
|
string Folder = Environment.CurrentDirectory + @"\Logs"; |
|
string FileNamme = Environment.CurrentDirectory + @"\Logs\Info_" + DateTime.Now.ToString("yyyyMMdd") + ".txt"; |
|
if (!System.IO.Directory.Exists(Folder)) |
|
{ |
|
System.IO.Directory.CreateDirectory(Folder); |
|
} |
|
using (TextWriter fw = new StreamWriter(FileNamme, true)) |
|
{ |
|
try |
|
{ |
|
FileInfo fi = new FileInfo(FileNamme); |
|
fw.WriteLine(str); |
|
} |
|
catch (Exception ex) |
|
{ |
|
fw.WriteLine(ex.Message); |
|
} |
|
finally |
|
{ |
|
fw.Close(); |
|
fw.Dispose(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 操作类型 |
|
/// </summary> |
|
public enum OperationType |
|
{ |
|
PTZ, //倾斜+焦距 |
|
P, //水平运动 |
|
T, //上下运动 |
|
Z, //焦距 |
|
PT //倾斜运动 |
|
} |
|
}
|
|
|