namespace SHH.CameraSdk; /// /// 增强型设备元数据中心 (V3.3.1 修复版) /// 核心职责: /// 1. 封装设备的硬件参数、通道能力、功能集,提供能力自发现 /// 2. 支持元数据同步与差异对比,指导上层模块执行差异化处理 /// 3. 存储运维指标与 SDK 原生句柄,支撑故障诊断与性能调优 /// 设计特性:只读优先,通过版本号标记同步状态,避免并发修改冲突 /// public class DeviceMetadata { #region --- 1. 设备级身份信息 (Identity) --- /// 设备型号名称(如 DS-2CD3T47G2-LIU) public string ModelName { get; init; } = "Unknown"; /// 设备唯一序列号(全局唯一,用于设备溯源) public string SerialNumber { get; init; } = string.Empty; /// 固件/系统版本号(用于判断 SDK 兼容性) public string FirmwareVersion { get; init; } = string.Empty; /// 所属厂商/品牌(决定驱动适配逻辑) public DeviceBrand Brand { get; init; } = DeviceBrand.Unknown; /// 元数据版本号(本地刷新计数,每次同步自增) public long Version { get; private set; } /// 最后同步时间(标记元数据的最新有效时刻) public DateTime LastSyncedAt { get; private set; } #endregion #region --- 2. 级联能力模型 (Cascaded Capabilities) --- private readonly ReadOnlyCollection _channels; /// 通道元数据集合(只读,防止外部篡改) public ReadOnlyCollection Channels { get => _channels; init => _channels = value ?? new ReadOnlyCollection(new List()); } /// 设备总通道数量(IPC 通常为 1,NVR 为接入路数) public int ChannelCount => Channels.Count; /// 索引器:通过通道号快速获取对应通道的能力描述 /// 物理通道号 /// 通道元数据 / 不存在则返回 null public ChannelMetadata? this[int channelIndex] => Channels.FirstOrDefault(c => c.ChannelIndex == channelIndex); #endregion #region --- 3. 运维指标与非托管句柄 --- /// 设备实时健康度字典(如 CPU 使用率、温度、内存占用等) public Dictionary HealthMetrics { get; init; } = new(); /// /// 厂商 SDK 原始句柄/结构体快照 /// 注意事项: /// 1. 标记 [JsonIgnore] 防止序列化非托管指针导致程序崩溃 /// 2. 仅用于驱动层与 SDK 交互,上层业务禁止直接操作 /// [JsonIgnore] public object? NativeHandle { get; init; } /// 厂商扩展标签(如设备位置、安装时间、责任人等自定义信息) public Dictionary Tags { get; init; } = new(); #endregion #region --- 4. 构造与同步 (Constructor & Sync) --- /// /// 默认构造函数(用于 BaseVideoSource 初始状态,无通道数据) /// public DeviceMetadata() : this(Enumerable.Empty()) { } /// /// 完整构造函数(初始化通道元数据集合) /// /// 通道元数据列表 public DeviceMetadata(IEnumerable channels) { // 转换为只读集合,确保通道数据不可变 _channels = new ReadOnlyCollection(channels?.ToList() ?? new List()); // 标记初始同步状态 MarkSynced(); } /// /// 标记元数据同步完成 /// 作用:更新版本号与同步时间,用于差异对比的基准判断 /// public void MarkSynced() { Version++; LastSyncedAt = DateTime.Now; } #endregion #region --- 5. 业务逻辑辅助方法 (Business Helpers) --- /// /// 校验动态流配置的合法性(基于设备能力) /// /// 待校验的动态配置项 /// 校验失败时的详细原因 /// 合法返回 true,非法返回 false 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; } /// /// 元数据差异比对逻辑(用于 BaseVideoSource.RefreshMetadataAsync 方法) /// /// 最新拉取的设备元数据 /// 元数据差异描述符 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 }