需求:通过接入设备后,获取现场实时记录。
实现:通过配置NVR,设置间隔时间定时抓拍摄像头画面,通过SDK定时获取NVR对应通道的设备抓拍图片数据。
离线、上线、下载进度回调。
//初始化SDK接口
m_DisConnectCallBack += new fDisConnectCallBack(DisConnectCallBack);
m_ReConnectCallBack += new fHaveReConnectCallBack(ReConnectCallBack);
m_DownloadPosCallBack += new fTimeDownLoadPosCallBack(DownLoadPosCallBack);
建立NVR通道实体类型
private class nvr_data
{
public int index { get; set; }//数据序列号
public IntPtr m_LoginID { get; set; }//
public IntPtr m_DownloadID { get; set; }
public string filepath { get; set; }//抓拍图片路径
public DateTime catchtime { get; set; }//抓拍时间
public string devicecontent { get; set; }//设备信息
public NET_DEVICEINFO_Ex m_DeviceInfo { get; set; }
public string ip { get; set; }
public string username { get; set; }
public string password { get; set; }
public bool download_flag { get; set; }//检测下载状态
public int time { get; set; }//抓拍时间间隔
public string channelanme { get; set; }//通道名称
}
通过配置XML文件读取通道信息
登录设备开启图片下载线程
//初始化抓拍路径
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
//初始化SDK接口
m_DisConnectCallBack += new fDisConnectCallBack(DisConnectCallBack);
m_ReConnectCallBack += new fHaveReConnectCallBack(ReConnectCallBack);
m_DownloadPosCallBack += new fTimeDownLoadPosCallBack(DownLoadPosCallBack);
try
{
NETClient.Init(m_DisConnectCallBack, IntPtr.Zero, null);
NETClient.SetAutoReconnect(m_ReConnectCallBack, IntPtr.Zero);
}
catch (Exception ex)
{
this.BeginInvoke((Action<string>)setText, ex.Message);
}
this.BeginInvoke((Action<string>)setText, "初始化成功");
//开始初始化接口
UploadFileOss.StartUpload();
//查询NVR配置
XmlDocument NRVconfig = new XmlDocument();
NRVconfig.Load(Application.StartupPath + "\\NRVconfig.xml");
XmlNodeList configration = NRVconfig.SelectNodes("configration");
if (configration != null && configration[0].HasChildNodes)
{
for (int i = 0; i < configration[0].ChildNodes.Count; i++)
{
XmlNode nvr = configration[0].ChildNodes[i];
//初始化数据
nvr_datas[i] = new nvr_data();
nvr_datas[i].index = i;
nvr_datas[i].ip = nvr.Attributes["ip"].Value;
nvr_datas[i].username = nvr.Attributes["username"].Value;
nvr_datas[i].password = nvr.Attributes["password"].Value;
nvr_datas[i].time = Convert.ToInt32(nvr.Attributes["time"].Value);
nvr_datas[i].catchtime = DateTime.Now.AddMinutes(nvr_datas[i].time * -2 - 1);
nvr_datas[i].m_LoginID = IntPtr.Zero;
nvr_datas[i].m_DownloadID = IntPtr.Zero;
//登录
NET_DEVICEINFO_Ex m_DeviceInfo = new NET_DEVICEINFO_Ex();
nvr_datas[i].m_LoginID = NETClient.Login(nvr_datas[i].ip, 37777, nvr_datas[i].username, nvr_datas[i].password, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref m_DeviceInfo);
if (IntPtr.Zero == nvr_datas[i].m_LoginID)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[i].ip + NETClient.GetLastError());
}
else
{
string channelname = "通道1";
bool ret = NETClient.QueryChannelName(nvr_datas[i].m_LoginID, ref channelname);
if (ret)
{
nvr_datas[i].channelanme = channelname;
}
else
{
this.BeginInvoke((Action<string>)setText, nvr_datas[i].ip + NETClient.GetLastError());
}
this.BeginInvoke((Action<string>)setText, "LoginID" + nvr_datas[i].m_LoginID + nvr_datas[i].ip + ",37777," + nvr_datas[i].username + "," + nvr_datas[i].password + "--登录成功");
}
nvr_datas[i].m_DeviceInfo = m_DeviceInfo;
IntPtr pStream = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
NETClient.SetDeviceMode(nvr_datas[i].m_LoginID, EM_USEDEV_MODE.RECORD_STREAM_TYPE, pStream);
}
if (configration[0].ChildNodes.Count > 0)
{
//开始下载
ThreadPool.SetMaxThreads(2, 2);
//从NVR数据零开始下载
th_getpic1 = new Thread(download);
th_getpic1.IsBackground = true;
th_getpic1.Start(0);
isdownload = true;
ISCatch = true;
this.BeginInvoke((Action<string>)setText, "开始下载");
}
}
根据NVR设置的抓拍时间间隔下载数据,防止下载到重复数据,所有通道在一个线程中,轮循下载。
/// <summary>
/// 下载抓拍图片方法
/// </summary>
/// <param name="o"></param>
public void download(object o)
{
try
{
int index = Convert.ToInt32(o);
while (isdownload)
{
DateTime now = DateTime.Now;
//计算一分钟误差,防止方法执行的过程超过一分钟,数据获取不全
//time*2 ,因为DateTime end = now.AddMinutes(time * -1);nvr_datas[index].catchtime = end;
//相当于nvr_datas[index].time <= ((now.AddMinutes(time * -1) - nvr_datas[index].catchtime).Minutes - 1)
if ((nvr_datas[index].time * 2) <= ((now - nvr_datas[index].catchtime).Minutes - 1))
{
if (upload_flag)
{
IntPtr m_LoginID = nvr_datas[index].m_LoginID;
//IntPtr m_DownloadID = nvr_datas[index].m_DownloadID;
string filepath = path.TrimEnd(new char[] { '\\' }) + "\\" + nvr_datas[index].ip + now.Ticks.ToString() + ".jpg";
DateTime end = now.AddMinutes(nvr_datas[index].time * -1);//取当前时间之前time分钟的数据
DateTime start = end.AddMinutes(nvr_datas[index].time * -1);//取结束时间之前的time分钟数据
//停止下载
if (nvr_datas[index].m_DownloadID != IntPtr.Zero)
{
bool ret = NETClient.StopDownload(nvr_datas[index].m_DownloadID);
nvr_datas[index].m_DownloadID = IntPtr.Zero;
}
Thread.Sleep(1000);
nvr_datas[index].catchtime = end;//抓拍时间为SDK中的结束时间
nvr_datas[index].filepath = @filepath;
nvr_datas[index].devicecontent = nvr_datas[index].channelanme;//目前只取通道名称
//开始新的下载
nvr_datas[index].m_DownloadID = NETClient.DownloadByTime(m_LoginID, 0, EM_QUERY_RECORD_TYPE.PICTURE, start, end, filepath, m_DownloadPosCallBack, IntPtr.Zero, null, IntPtr.Zero, IntPtr.Zero);
this.BeginInvoke((Action<string>)setText, "开始新的查找 ip:" + nvr_datas[index].ip + " start:" + start.ToString("yyyy-MM-dd HH:mm:ss") + " end:" + end.ToString("yyyy-MM-dd HH:mm:ss") + "DownloadID" + nvr_datas[index].m_DownloadID);
if (IntPtr.Zero == nvr_datas[index].m_DownloadID)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
nvr_datas[index].download_flag = false;
//延时五秒校验
Thread.Sleep(1000 * 5);
ThreadPool.QueueUserWorkItem(ISCatchPIC, index);
}
}
Thread.Sleep(1000 * 60);//一分钟循环一次,默认最大下载时间为1分钟
index = nvr_datas[index + 1] == null ? 0 : index + 1;
}
}
catch (Exception ex)
{
this.BeginInvoke((Action<string>)setText, ex.ToString() + ex.StackTrace.ToString());
}
}
nvr储存的图片有时几百K,有时几M,有时则是有图片参数正确,但是却不能下载,为了防止影响之后的数据下载,进行了超时校验。
/// <summary>
/// 检测下载状态是否异常,异常需要重新下载
/// </summary>
/// <param name="o"></param>
private void ISCatchPIC(object o)
{
try
{
int index = Convert.ToInt32(o);
while (!nvr_datas[index].download_flag && ISCatch)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + "重新查找图片");
IntPtr m_LoginID = nvr_datas[index].m_LoginID;
//停止下载
if (nvr_datas[index].m_DownloadID != IntPtr.Zero)
{
bool ret = NETClient.StopDownload(nvr_datas[index].m_DownloadID);
if (!ret)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
nvr_datas[index].m_DownloadID = IntPtr.Zero;
}
bool result = NETClient.Logout(m_LoginID);
if (!result)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
Thread.Sleep(1000 * 1);
NET_DEVICEINFO_Ex m_DeviceInfo = new NET_DEVICEINFO_Ex();
nvr_datas[index].m_LoginID = NETClient.Login(nvr_datas[index].ip, 37777, nvr_datas[index].username, nvr_datas[index].password, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref m_DeviceInfo);
nvr_datas[index].m_DeviceInfo = m_DeviceInfo;
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + " 登录成功 LoginID" + nvr_datas[index].m_LoginID);
//重新开始下载
Thread.Sleep(1000);
DateTime now = DateTime.Now;
string filepath = path.TrimEnd(new char[] { '\\' }) + "\\" + now.Ticks.ToString() + ".jpg";
DateTime end = now.AddMinutes(nvr_datas[index].time * -1);//取当前时间之前time分钟的数据
DateTime start = end.AddMinutes(nvr_datas[index].time * -1);//取结束时间之前的time分钟数据
nvr_datas[index].catchtime = end;//抓拍时间为SDK中的结束时间
nvr_datas[index].filepath = filepath;
nvr_datas[index].m_DownloadID = NETClient.DownloadByTime(m_LoginID, 0, EM_QUERY_RECORD_TYPE.PICTURE, start, end, filepath, m_DownloadPosCallBack, IntPtr.Zero, null, IntPtr.Zero, IntPtr.Zero);
//开始新的下载
this.BeginInvoke((Action<string>)setText, "开始新的查找 ip:" + nvr_datas[index].ip + " start:" + start.ToString("yyyy-MM-dd HH:mm:ss") + " end:" + end.ToString("yyyy-MM-dd HH:mm:ss") + "DownloadID" + nvr_datas[index].m_DownloadID);
if (IntPtr.Zero == nvr_datas[index].m_DownloadID)
{
this.BeginInvoke((Action<string>)setText, nvr_datas[index].ip + NETClient.GetLastError());
}
nvr_datas[index].download_flag = false;
//延时5秒校验
Thread.Sleep(1000 * 5);
//getpic_timer = new System.Threading.Timer(new TimerCallback(download), drs[0], 1000 * 1, 1000 * 60 * time);
}
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
this.BeginInvoke((Action<string>)setText, "ThreadAbortException ");
}
catch (Exception ex)
{
this.BeginInvoke((Action<string>)setText, ex.ToString() + ex.StackTrace.ToString());
}
}
下载进度为实时监视下载过程使用,dwDownLoadSize---当次数据长度,dwDownLoadSize--数据总长度
private void DownLoadPosCallBack(IntPtr lPlayHandle, uint dwTotalSize, uint dwDownLoadSize, int index_, NET_RECORDFILE_INFO recordfileinfo, IntPtr dwUser)