2025-12-26 03:18:21 +08:00
|
|
|
|
namespace SHH.CameraSdk;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 视频源基础配置对象 (V3.3.1 修复版)
|
|
|
|
|
|
/// 核心职责:定义建立相机物理连接所需的所有标准化参数与厂商扩展参数
|
|
|
|
|
|
/// 关键修复:
|
|
|
|
|
|
/// <para>1. [Fix Bug U: 配置漂移] 驱动层接收配置时需创建副本,防止外部修改导致的连接异常</para>
|
|
|
|
|
|
/// <para>2. 强化配置有效性校验,提前拦截非法参数</para>
|
|
|
|
|
|
/// 注意事项:此类为引用类型,传递时建议使用深拷贝
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class VideoSourceConfig
|
|
|
|
|
|
{
|
|
|
|
|
|
#region --- 1. 核心连接配置 (Core Connection Configurations) ---
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 业务系统唯一标识(对应数据库自增ID,全局唯一) </summary>
|
|
|
|
|
|
public long Id { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 设备显示名称(如:北大门-枪机01,用于前端展示) </summary>
|
|
|
|
|
|
public string Name { get; set; } = string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 设备品牌(决定加载对应的驱动实现类) </summary>
|
|
|
|
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
|
|
|
|
public DeviceBrand Brand { get; set; } = DeviceBrand.Unknown;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 设备 IP 地址或域名(如 192.168.1.100 或 camera.example.com) </summary>
|
|
|
|
|
|
public string IpAddress { get; set; } = string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 设备端口号(厂商默认值:海康8000、大华37777、RTSP 554) </summary>
|
|
|
|
|
|
public ushort Port { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 设备登录用户名(默认值:admin) </summary>
|
|
|
|
|
|
public string Username { get; set; } = "admin";
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 设备登录密码(默认空字符串,需根据实际设备配置) </summary>
|
|
|
|
|
|
public string Password { get; set; } = string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 渲染句柄(可选):用于硬解码时直接绑定显示窗口,提升渲染性能 </summary>
|
2025-12-28 08:07:55 +08:00
|
|
|
|
public long RenderHandle { get; set; }
|
2025-12-26 03:18:21 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary> 物理通道号(IPC 通常为 1;NVR 对应接入的摄像头通道索引) </summary>
|
|
|
|
|
|
public int ChannelIndex { get; set; } = 1;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 默认码流类型(0 = 主码流(高清),1 = 子码流(低带宽)) </summary>
|
|
|
|
|
|
public int StreamType { get; set; } = 0;
|
|
|
|
|
|
|
2025-12-28 08:07:55 +08:00
|
|
|
|
/// <summary> 关联的主板IP </summary>
|
|
|
|
|
|
public string MainboardIp { get; set; }
|
|
|
|
|
|
= string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>关联的主板端口</summary>
|
|
|
|
|
|
public int MainboardPort { get; set; }
|
|
|
|
|
|
|
2025-12-26 12:15:10 +08:00
|
|
|
|
/// <summary> Rtsp 播放路径 </summary>
|
|
|
|
|
|
public string RtspPath { get; set; } = string.Empty;
|
|
|
|
|
|
|
2025-12-26 03:18:21 +08:00
|
|
|
|
/// <summary> 传输协议(TCP/UDP/Multicast,默认 TCP 保证可靠性) </summary>
|
|
|
|
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
|
|
|
|
public TransportProtocol Transport { get; set; } = TransportProtocol.Tcp;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 连接超时时间(毫秒,默认 5000ms = 5秒) </summary>
|
|
|
|
|
|
public int ConnectionTimeoutMs { get; set; } = 5000;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-01-12 18:27:58 +08:00
|
|
|
|
|
2025-12-26 03:18:21 +08:00
|
|
|
|
#region --- 2. 厂商扩展配置 (Vendor-Specific Extensions) ---
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 厂商扩展参数字典
|
|
|
|
|
|
/// 用途:存储无法标准化的品牌专属参数
|
|
|
|
|
|
/// 示例:
|
|
|
|
|
|
/// <code>
|
|
|
|
|
|
/// {
|
|
|
|
|
|
/// "RtspPath": "/h264/ch1/main/av_stream",
|
|
|
|
|
|
/// "HikLoginMode": "ISAPI",
|
|
|
|
|
|
/// "DaHuaStreamProtocol": "HTTP"
|
|
|
|
|
|
/// }
|
|
|
|
|
|
/// </code>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Dictionary<string, string> VendorArguments { get; set; } = new();
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region --- 3. 配置工具方法 (Configuration Utility Methods) ---
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 配置有效性校验:检查核心参数是否合法,非法则抛出异常
|
|
|
|
|
|
/// 作用:提前拦截无效配置,避免驱动层连接时出现未知错误
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <exception cref="ArgumentException">核心参数非法时抛出</exception>
|
|
|
|
|
|
public void Validate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Id <= 0)
|
|
|
|
|
|
throw new ArgumentException("配置ID必须为正整数", nameof(Id));
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(IpAddress))
|
|
|
|
|
|
throw new ArgumentException("IP地址不能为空", nameof(IpAddress));
|
|
|
|
|
|
if (Port == 0)
|
|
|
|
|
|
throw new ArgumentException("端口号必须为有效数值", nameof(Port));
|
|
|
|
|
|
if (Brand == DeviceBrand.Unknown)
|
|
|
|
|
|
throw new ArgumentException("必须指定设备品牌", nameof(Brand));
|
|
|
|
|
|
if (ChannelIndex <= 0)
|
|
|
|
|
|
throw new ArgumentException("通道号必须为正整数", nameof(ChannelIndex));
|
|
|
|
|
|
if (ConnectionTimeoutMs <= 0)
|
|
|
|
|
|
throw new ArgumentException("连接超时时间必须大于0", nameof(ConnectionTimeoutMs));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成设备唯一连接指纹
|
|
|
|
|
|
/// 用途:用于连接池去重、缓存键、日志标识等场景
|
|
|
|
|
|
/// 格式:{Brand}://{Username}@{IpAddress}:{Port}/{ChannelIndex}
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>唯一连接指纹字符串</returns>
|
|
|
|
|
|
public string GetConnectionKey()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 使用 StringBuilder 提升拼接性能,避免频繁创建字符串
|
|
|
|
|
|
return new StringBuilder()
|
|
|
|
|
|
.Append(Brand)
|
|
|
|
|
|
.Append("://")
|
|
|
|
|
|
.Append(Username)
|
|
|
|
|
|
.Append('@')
|
|
|
|
|
|
.Append(IpAddress)
|
|
|
|
|
|
.Append(':')
|
|
|
|
|
|
.Append(Port)
|
|
|
|
|
|
.Append('/')
|
|
|
|
|
|
.Append(ChannelIndex)
|
|
|
|
|
|
.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建配置对象的深拷贝(防止外部修改导致配置漂移)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>新的配置副本</returns>
|
|
|
|
|
|
public VideoSourceConfig DeepCopy()
|
|
|
|
|
|
{
|
|
|
|
|
|
var copy = new VideoSourceConfig
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = this.Id,
|
|
|
|
|
|
Name = this.Name,
|
|
|
|
|
|
Brand = this.Brand,
|
|
|
|
|
|
IpAddress = this.IpAddress,
|
|
|
|
|
|
Port = this.Port,
|
|
|
|
|
|
Username = this.Username,
|
|
|
|
|
|
Password = this.Password,
|
|
|
|
|
|
RenderHandle = this.RenderHandle,
|
|
|
|
|
|
ChannelIndex = this.ChannelIndex,
|
2025-12-28 08:07:55 +08:00
|
|
|
|
MainboardIp = this.MainboardIp,
|
|
|
|
|
|
MainboardPort = this.MainboardPort,
|
2025-12-26 12:15:10 +08:00
|
|
|
|
RtspPath = this.RtspPath,
|
2025-12-26 03:18:21 +08:00
|
|
|
|
StreamType = this.StreamType,
|
|
|
|
|
|
Transport = this.Transport,
|
|
|
|
|
|
ConnectionTimeoutMs = this.ConnectionTimeoutMs
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 深拷贝扩展参数字典
|
|
|
|
|
|
foreach (var kvp in this.VendorArguments)
|
|
|
|
|
|
{
|
|
|
|
|
|
copy.VendorArguments.Add(kvp.Key, kvp.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|