Files
Ayay/SHH.CameraSdk/Abstractions/Models/DeviceMetadata.cs

176 lines
6.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace SHH.CameraSdk;
/// <summary>
/// 增强型设备元数据中心 (V3.3.1 修复版)
/// 核心职责:
/// <para>1. 封装设备的硬件参数、通道能力、功能集,提供能力自发现</para>
/// <para>2. 支持元数据同步与差异对比,指导上层模块执行差异化处理</para>
/// <para>3. 存储运维指标与 SDK 原生句柄,支撑故障诊断与性能调优</para>
/// 设计特性:只读优先,通过版本号标记同步状态,避免并发修改冲突
/// </summary>
public class DeviceMetadata
{
#region --- 1. (Identity) ---
/// <summary> 设备型号名称(如 DS-2CD3T47G2-LIU </summary>
public string ModelName { get; init; } = "Unknown";
/// <summary> 设备唯一序列号(全局唯一,用于设备溯源) </summary>
public string SerialNumber { get; init; } = string.Empty;
/// <summary> 固件/系统版本号(用于判断 SDK 兼容性) </summary>
public string FirmwareVersion { get; init; } = string.Empty;
/// <summary> 所属厂商/品牌(决定驱动适配逻辑) </summary>
public DeviceBrand Brand { get; init; } = DeviceBrand.Unknown;
/// <summary> 元数据版本号(本地刷新计数,每次同步自增) </summary>
public long Version { get; private set; }
/// <summary> 最后同步时间(标记元数据的最新有效时刻) </summary>
public DateTime LastSyncedAt { get; private set; }
#endregion
#region --- 2. (Cascaded Capabilities) ---
private readonly ReadOnlyCollection<ChannelMetadata> _channels;
/// <summary> 通道元数据集合(只读,防止外部篡改) </summary>
public ReadOnlyCollection<ChannelMetadata> Channels
{
get => _channels;
init => _channels = value ?? new ReadOnlyCollection<ChannelMetadata>(new List<ChannelMetadata>());
}
/// <summary> 设备总通道数量IPC 通常为 1NVR 为接入路数) </summary>
public int ChannelCount => Channels.Count;
/// <summary> 索引器:通过通道号快速获取对应通道的能力描述 </summary>
/// <param name="channelIndex">物理通道号</param>
/// <returns>通道元数据 / 不存在则返回 null</returns>
public ChannelMetadata? this[int channelIndex] =>
Channels.FirstOrDefault(c => c.ChannelIndex == channelIndex);
#endregion
#region --- 3. ---
/// <summary> 设备实时健康度字典(如 CPU 使用率、温度、内存占用等) </summary>
public Dictionary<string, object> HealthMetrics { get; init; } = new();
/// <summary>
/// 厂商 SDK 原始句柄/结构体快照
/// <para>注意事项:</para>
/// <para>1. 标记 [JsonIgnore] 防止序列化非托管指针导致程序崩溃</para>
/// <para>2. 仅用于驱动层与 SDK 交互,上层业务禁止直接操作</para>
/// </summary>
[JsonIgnore]
public object? NativeHandle { get; init; }
/// <summary> 厂商扩展标签(如设备位置、安装时间、责任人等自定义信息) </summary>
public Dictionary<string, string> Tags { get; init; } = new();
#endregion
#region --- 4. (Constructor & Sync) ---
/// <summary>
/// 默认构造函数(用于 BaseVideoSource 初始状态,无通道数据)
/// </summary>
public DeviceMetadata() : this(Enumerable.Empty<ChannelMetadata>()) { }
/// <summary>
/// 完整构造函数(初始化通道元数据集合)
/// </summary>
/// <param name="channels">通道元数据列表</param>
public DeviceMetadata(IEnumerable<ChannelMetadata> channels)
{
// 转换为只读集合,确保通道数据不可变
_channels = new ReadOnlyCollection<ChannelMetadata>(channels?.ToList() ?? new List<ChannelMetadata>());
// 标记初始同步状态
MarkSynced();
}
/// <summary>
/// 标记元数据同步完成
/// <para>作用:更新版本号与同步时间,用于差异对比的基准判断</para>
/// </summary>
public void MarkSynced()
{
Version++;
LastSyncedAt = DateTime.Now;
}
#endregion
#region --- 5. (Business Helpers) ---
/// <summary>
/// 校验动态流配置的合法性(基于设备能力)
/// </summary>
/// <param name="options">待校验的动态配置项</param>
/// <param name="errorMessage">校验失败时的详细原因</param>
/// <returns>合法返回 true非法返回 false</returns>
public bool ValidateOptions(DynamicStreamOptions options, out string errorMessage)
{
errorMessage = string.Empty;
if (options == null) return true;
// 示例校验规则:云台控制权限校验
if (options.VendorExtensions?.ContainsKey("PtzAction") == true
&& !Channels.Any(c => c.SupportPtz))
{
errorMessage = "该设备物理硬件不支持云台控制功能";
return false;
}
// 可扩展其他校验规则:如分辨率合法性、码流类型支持性等
return true;
}
/// <summary>
/// 元数据差异比对逻辑(用于 BaseVideoSource.RefreshMetadataAsync 方法)
/// </summary>
/// <param name="other">最新拉取的设备元数据</param>
/// <returns>元数据差异描述符</returns>
public MetadataDiff CompareWith(DeviceMetadata other)
{
// 入参防护:对比对象为空则返回无差异
if (other == null) return MetadataDiff.None;
return new MetadataDiff
{
// 1. 基础信息变更:任意通道名称变化则标记
NameChanged = this.Channels.Any(c =>
{
var targetChannel = other[c.ChannelIndex];
return targetChannel != null && targetChannel.Name != c.Name;
}),
// 2. 能力集变更PTZ/音频/AI 功能支持状态变化则标记
CapabilityChanged = this.Channels.Any(c =>
{
var targetChannel = other[c.ChannelIndex];
if (targetChannel == null) return false;
return targetChannel.SupportPtz != c.SupportPtz
|| targetChannel.SupportAudioIn != c.SupportAudioIn
|| targetChannel.SupportAiAnalysis != c.SupportAiAnalysis;
}),
// 3. 致命变更:品牌不一致或通道数量变化(设备更换/替换场景)
IsMajorChange = this.Brand != other.Brand || this.ChannelCount != other.ChannelCount,
// 4. 分辨率配置变更:任意通道的分辨率档位数量变化则标记
ResolutionProfilesChanged = this.Channels.Any(c =>
{
var targetChannel = other[c.ChannelIndex];
return targetChannel != null
&& targetChannel.SupportedResolutions.Count != c.SupportedResolutions.Count;
})
};
}
#endregion
}