唐山轨道机控制端TCP服务
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

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 //倾斜运动
}
}