海康威视SDK通过NVR获取视频设备的状态
前言
项目现场是通过NVR对多路摄像头设备进行集中管理,包括实时画面的预览和视频信号的存储、回放。
现在要实现这样一个功能:定期查询摄像头的状态,以确保摄像头都处于在线状态。
1 问题分析
功能的需求是获取摄像头的状态,那么通过注册(login)设备的方式肯定可行,login成功即表示设备在线,否则即为离线。
但是由于整个园区的视频设备多大几百个,这样的势必会造成批量的注册和登出操作,挺麻烦的,而且遇到多个设备无法注册的情况下会造成整个查询的过程时间很长,效率很慢。
因此,既然NVR是视频设备的集成管理设备,那么我们还是从NVR入手,相比NVR的接口中一定有相关的说明。
2 解决过程
2.1 找到接口
从官网下载的SDK中的《设备网络SDK使用手册.chm》中搜索关键字【通道】,找到了接口【NET_DVR_GetDVRConfig】,通过查阅,判断该接口即为所求。命令:NET_DVR_GET_IPPARACFG_V40;结果结构体:NET_DVR_IPPARACFG_V40;子结构体;NET_DVR_IPDEVINFO_V31,NVR中的视频信号的状态便包含于这个结构体中。
2.2 配置参数
根据参数说明,声明一下参数:
CHCNetSDK.NET_DVR_IPPARACFG_V40 IPParacfg = new CHCNetSDK.NET_DVR_IPPARACFG_V40();//结果
uint dwOutBufferSize = (uint)Marshal.SizeOf(IPParacfg);//输出大小
IntPtr pOutBuf = Marshal.AllocHGlobal((int)dwOutBufferSize);//输出结果的指针
uint lpBytesReturned = 0;
int lChannel = 0;
if (!CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40,lChannel, pOutBuf, dwOutBufferSize,ref lpBytesReturned))
{
IPParacfg = (CHCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(pOutBuf, typeof(CHCNetSDK.NET_DVR_IPPARACFG_V40));
}
这里面第三个参数lChannel我存有疑问。因为《设备网络SDK编程指南(DVR&NVR).pdf》中说的是【无效】参数,即填写“-1”,而《设备网络SDK使用手册.chm》中说的是说从0开始。而下面的解释也没看明白什么意思,到底是填组号还是通道号 搞不清楚,注册返回的消息里也没有组号啊,难不成要是根据通道号一个一个查的?!。
通道号是指设备视频通道号,通过注册设备(NET_DVR_Login_V30)返回的设备信息(NET_DVR_DEVICEINFO_V30)获取模拟通道个数(byChanNum)、模拟通道起始通道号(byStartChan)和设备支持的最大IP通道数(byIPChanNum+ byHighDChanNum*256)、数字通道起始通道号(byStartDChan)。
我心想,那就先测试一下 看看什么结果吧。
直接上结果:
- lChannel=0,返回false,结果失败;
- lChannel=1,返回true,结果有误,显示通道数、组数上万;
- lChannel=2/3/4/5/…,结果同lChannel=1;
- lChannel=-1,结果同lChannel=1。
其实我最开始觉得是将输出结果转换为目标格式的时候出现了问题。我开始尝试用其他版本的SDk去测试,但是并没有结果。
我又回归到最初的版本。当我调整参数测试的时候偶然发现这样一个问题:
当我先用lChannel=0测试的时候确实会出现 返回结果确实是false,但是我在设置lChannel=1,就可以获得正确的结果。
事实上我并不知道原因(手动狗头)。
最后代码如下:
public struct ChannelInfo
{
/// <summary>
/// 设备是否启用
/// </summary>
public int IsEnable { get; set; }
/// <summary>
/// 通道是否启用
/// </summary>
public bool IsChannleEnable { get; set; }
/// <summary>
/// IP地址
/// </summary>
public string IPAddress { get; set; }
public int CameraID { get; set; }
}
public List<ChannelInfo> NET_DVR_GetDVRConfig()
{
List<ChannelInfo> results =new List<ChannelInfo>();
CHCNetSDK.NET_DVR_IPPARACFG_V40 IPParacfg = new CHCNetSDK.NET_DVR_IPPARACFG_V40();
uint dwOutBufferSize = (uint)Marshal.SizeOf(IPParacfg);
IntPtr pOutBuf = Marshal.AllocHGlobal((int)dwOutBufferSize);
uint lpBytesReturned = 0;
int lChannel =0;
CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, lChannel, pOutBuf, dwOutBufferSize, ref lpBytesReturned);
lChannel = 1;
if (!CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, lChannel, pOutBuf, dwOutBufferSize,ref lpBytesReturned))
{
IPParacfg = (CHCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(pOutBuf, typeof(CHCNetSDK.NET_DVR_IPPARACFG_V40));
if (IPParacfg.dwGroupNum==1&&IPParacfg.dwDChanNum<=64&&IPParacfg.dwDChanNum>0)
{
NET_DVR_IPDEVINFO_V31[] IPDeviceInfos = IPParacfg.struIPDevInfo;
for(int i=0;i< IPDeviceInfos.Length; i++)
{
if (IPDeviceInfos[i].byEnable == 1)
{
ChannelInfo channelInfo = new ChannelInfo();
channelInfo.IPAddress = IPDeviceInfos[i].struIP.sIpV4;
channelInfo.IsEnable = IPDeviceInfos[i].byEnable;
results.Add(channelInfo);
}
}
}
}
return results;
}