OEM初版

This commit is contained in:
2025-10-10 17:54:53 +08:00
parent ccbe0f626f
commit 9036f967fc
16 changed files with 1736 additions and 237 deletions

View File

@@ -1,13 +1,11 @@
using FATrace.HKNetLib.Common;
using FATrace.HKNetLib.Common;
using FATrace.HKNetLib.Hardware;
using System;
using System.Collections.Generic;
using System.Linq;
using FATrace.Model;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static FATrace.HKNetLib.Hardware.CHCNetSDK;
using System.Threading;
using System.Threading.Tasks;
namespace FATrace.HKNetLib.Wrapper
{
@@ -93,8 +91,73 @@ namespace FATrace.HKNetLib.Wrapper
}
}
#region NVR信息
/// <summary>
/// NVR IP
/// </summary>
public string NVR_IP { get; set; }
/// <summary>
/// NVR Port
/// </summary>
public ushort NVR_Port { get; set; }
/// <summary>
/// NVR UserName
/// </summary>
public string NVR_UserName { get; set; }
/// <summary>
/// NVR Pw
/// </summary>
public string NVR_Pw { get; set; }
/// <summary>
/// NVR VideoSavePath 保存的地址信息
/// </summary>
public string NVRVideoSavePath { get; set; }
#endregion
#region
/// <summary>
/// 事件发布的消息
/// </summary>
public event EventHandler<VideoAction> VideoActionEventHandler;
/// <summary>
/// 下发视频进度过程的Handler
/// </summary>
public event EventHandler<short> NVRLoadVideoProcessEventHandler;
/// <summary>
/// 下发视频完成的Handler
/// </summary>
public event EventHandler<string> NVRLoadVideoCompleteEventHandler;
/// <summary>
/// 当前NVR登录信息
/// </summary>
public CameraLoginInfo NVRLoginInfo { get; set; } = new CameraLoginInfo();
/// <summary>
/// NVR登录状态
/// </summary>
public bool NVRLoginState { get; set; }
#endregion
#region NVR开发
/// <summary>
/// NVRCamera 集合数据
/// </summary>
public List<NVRCamera> ListNVRCamera { get; set; } = new List<NVRCamera>();
/// <summary>
/// NVR设备信息 DVR_DEVICEINFO_V30
/// </summary>
@@ -105,7 +168,14 @@ namespace FATrace.HKNetLib.Wrapper
/// </summary>
public CHCNetSDK.NET_DVR_IPPARACFG_V40 DVR_IPPARACFG_V40 { get; set; }
/// <summary>
/// 模拟通道个数
/// </summary>
private uint dwAChanTotalNum { get; set; } = 0;
/// <summary>
/// 数字通道个数
/// </summary>
private uint dwDChanTotalNum { get; set; } = 0;
public NET_DVR_GET_STREAM_UNION DVR_GET_STREAM_UNION { get; set; }
@@ -153,6 +223,7 @@ namespace FATrace.HKNetLib.Wrapper
{
LastMsgErr = GetLastError();
//MessageBox.Show(str1);
NVRLoginState = false;
return false;
}
else
@@ -161,6 +232,12 @@ namespace FATrace.HKNetLib.Wrapper
//MessageBox.Show("Login Success!");
//btnLogin.Text = "Logout";
NVRLoginInfo.IP = DVRIPAddress;
NVRLoginInfo.Port = (ushort)DVRPortNumber;
NVRLoginInfo.Password = DVRPassword;
NVRLoginInfo.UserName = DVRUserName;
NVRLoginState = true;
dwAChanTotalNum = (uint)DVRDeviceInfoV30.byChanNum;
dwDChanTotalNum = (uint)DVRDeviceInfoV30.byIPChanNum + 256 * (uint)DVRDeviceInfoV30.byHighDChanNum;
@@ -236,6 +313,14 @@ namespace FATrace.HKNetLib.Wrapper
Marshal.StructureToPtr(DVR_GET_STREAM_UNION, ptrChanInfo, false);
DVR_IPCHANINFO = (CHCNetSDK.NET_DVR_IPCHANINFO)Marshal.PtrToStructure(ptrChanInfo, typeof(CHCNetSDK.NET_DVR_IPCHANINFO));
ListNVRCamera.Add(new NVRCamera()
{
//ChNo = DVR_IPCHANINFO.byChannel,
ChNo = (i + 1),
IPID = DVR_IPCHANINFO.byIPID,
IsOnline = DVR_IPCHANINFO.byEnable
});
//列出IP通道
//ListIPChannel(i + 1, DVR_IPCHANINFO.byEnable, DVR_IPCHANINFO.byIPID);
Marshal.FreeHGlobal(ptrChanInfo);
@@ -250,20 +335,19 @@ namespace FATrace.HKNetLib.Wrapper
}
/// <summary>
/// 根据时间获取DVR统计信息
/// 根据时间获取DVR 视频数据信息
/// </summary>
public (bool Result, string Msg) Sdk_NET_DVR_GetFileByTime_V40(DateTime startTime, DateTime endTime, string SaveVideFilePath)
{
if (m_lDownHandle >= 0)
{
//MessageBox.Show("Downloading, please stop firstly!");//正在下载,请先停止下载
return (Result: false, Msg: "正在下载,请先停止下载");
}
NET_DVR_PLAYCOND struDownPara = new NET_DVR_PLAYCOND();
struDownPara.dwChannel = (uint)iChannelNum[(int)iSelIndex]; //通道号 Channel number
struDownPara.dwChannel = (uint)iChannelNum[(int)iSelIndex];
//设置下载的开始时间 Set the starting time
// 设置下载的开始时间
struDownPara.struStartTime.dwYear = startTime.Year;
struDownPara.struStartTime.dwMonth = startTime.Month;
struDownPara.struStartTime.dwDay = startTime.Day;
@@ -271,7 +355,7 @@ namespace FATrace.HKNetLib.Wrapper
struDownPara.struStartTime.dwMinute = startTime.Minute;
struDownPara.struStartTime.dwSecond = startTime.Second;
//设置下载的结束时间 Set the stopping time
// 设置下载的结束时间
struDownPara.struStopTime.dwYear = endTime.Year;
struDownPara.struStopTime.dwMonth = endTime.Month;
struDownPara.struStopTime.dwDay = endTime.Day;
@@ -279,10 +363,7 @@ namespace FATrace.HKNetLib.Wrapper
struDownPara.struStopTime.dwMinute = endTime.Minute;
struDownPara.struStopTime.dwSecond = endTime.Second;
//string sVideoFileName; //录像文件保存路径和文件名 the path and file name to save
//sVideoFileName = "D:\\Downtest_Channel" + struDownPara.dwChannel + ".mp4";
//按时间下载 Download by time
// 按时间下载
m_lDownHandle = CHCNetSDK.NET_DVR_GetFileByTime_V40(m_lUserID, SaveVideFilePath, ref struDownPara);
if (m_lDownHandle < 0)
{
@@ -291,30 +372,153 @@ namespace FATrace.HKNetLib.Wrapper
}
uint iOutValue = 0;
//该接口指定了当前要下载的录像文件调用成功后还需要调用NET_DVR_PlayBackControl_V40接口的开始播放控制命令NET_DVR_PLAYSTART才能实现下载。
//V5.0.3.2或以后版本通过该接口保存录像保存的录像文件数据超过文件最大限制字节数默认为1024MBSDK会自动切片即新建文件进行保存文件名命名规则为“在接口传入的文件名基础上增加数字标识(例如:*_1.mp4、*_2.mp4)”。
//可以调用NET_DVR_GetSDKLocalCfg、NET_DVR_SetSDKLocalCfg(配置类型NET_DVR_LOCAL_CFG_TYPE_GENERAL)获取和设置切片模式和文件最大限制字节数。
// 该接口指定了当前要下载的录像文件,调用成功后,还需要调用 NET_DVR_PlayBackControl_V40 接口的开始播放控制命令NET_DVR_PLAYSTART才能实现下载。
if (!CHCNetSDK.NET_DVR_PlayBackControl_V40(m_lDownHandle, CHCNetSDK.NET_DVR_PLAYSTART, IntPtr.Zero, 0, IntPtr.Zero, ref iOutValue))
{
LastMsgErr = GetLastError();
try { CHCNetSDK.NET_DVR_StopGetFile(m_lDownHandle); } catch { }
m_lDownHandle = -1;
return (Result: false, Msg: $"[NET_DVR_PlayBackControl_V40] 执行下载控制失败:{LastMsgErr}");
}
return (Result: true, Msg: "下载成功!");
}
/// <summary>
/// 获取下载的进度
/// </summary>
/// <param name="downHandle"></param>
/// <returns></returns>
public int Sdk_NET_DVR_GetDownloadPos(Int32 downHandle)
{
return CHCNetSDK.NET_DVR_GetDownloadPos(downHandle);
StartDownloadProgressMonitor();
return (Result: true, Msg: "下载OK!");
}
#endregion
#region
private CancellationTokenSource _downloadCts;
private const int _downloadPollIntervalMs = 500;
/// <summary>
/// 启动下载进度轮询,定期发布 NVRLoadVideoProcessEventHandler 事件
/// </summary>
public void StartDownloadProgressMonitor()
{
// 先确保没有旧的轮询任务
StopDownloadProgressMonitor();
_downloadCts = new CancellationTokenSource();
var token = _downloadCts.Token;
Task.Run(async () =>
{
try
{
while (!token.IsCancellationRequested && m_lDownHandle >= 0)
{
int progress = -1;
try
{
progress = CHCNetSDK.NET_DVR_GetDownloadPos(m_lDownHandle);
}
catch
{
progress = -1;
}
if (progress >= 0)
{
short percent = (short)Math.Min(100, progress);
try
{
NVRLoadVideoProcessEventHandler?.Invoke(this, percent);
}
catch
{
// 事件订阅者异常不应中断轮询
}
if (progress >= 100)
{
// 完成:停止下载,退出轮询
Sdk_NET_DVR_StopGetFile();
NVRLoadVideoCompleteEventHandler?.Invoke(this, "下载完成");
break;
}
}
else
{
// 发生错误,尝试停止下载并退出
Sdk_NET_DVR_StopGetFile();
break;
}
try { await Task.Delay(_downloadPollIntervalMs, token); } catch { /* ignore */ }
}
}
catch
{
// 轮询线程异常吞掉,避免影响上层逻辑
}
}, token);
}
/// <summary>
/// 停止下载进度轮询
/// </summary>
private void StopDownloadProgressMonitor()
{
try
{
if (_downloadCts != null)
{
if (!_downloadCts.IsCancellationRequested)
{
_downloadCts.Cancel();
}
_downloadCts.Dispose();
_downloadCts = null;
}
}
catch
{
// 忽略取消中的异常
}
}
/// <summary>
/// 停止当前下载并清理资源
/// </summary>
/// <returns></returns>
public (bool Result, string Msg) Sdk_NET_DVR_StopGetFile()
{
try
{
// 停止轮询
StopDownloadProgressMonitor();
if (m_lDownHandle >= 0)
{
bool stopOk = CHCNetSDK.NET_DVR_StopGetFile(m_lDownHandle);
m_lDownHandle = -1;
if (!stopOk)
{
LastMsgErr = GetLastError();
return (false, $"[NET_DVR_StopGetFile] 停止下载失败:{LastMsgErr}");
}
}
return (true, "停止下载成功");
}
catch (Exception)
{
return (false, "停止下载异常");
}
}
#endregion
public bool IsOnline()
{
try