SDK 的 Bug 修复

This commit is contained in:
2026-01-17 00:03:16 +08:00
parent 97a322960a
commit 2a331d769f
10 changed files with 131 additions and 38 deletions

View File

@@ -69,7 +69,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
#region --- 2. (Internal States & Infrastructure) ---
/// <summary> 设备在线状态标志volatile 确保多线程可见性) </summary>
private volatile bool _isOnline;
private volatile bool _isActived;
/// <summary> 视频源核心状态(受 _stateSyncRoot 保护) </summary>
private VideoSourceStatus _status = VideoSourceStatus.Disconnected;
@@ -119,7 +119,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
public bool IsRunning { get; set; }
/// <summary> 设备在线状态 </summary>
public bool IsOnline => _isOnline;
public bool IsActived => _isActived;
/// <summary> 设备元数据(能力集、通道信息等) </summary>
public DeviceMetadata Metadata { get; protected set; } = new();
@@ -223,7 +223,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
_config = newConfig.DeepCopy();
// 写入审计日志
AddAuditLog($"配置已更新 [IP:{_config.IpAddress}],生效时机:{(_isOnline ? "" : "")}");
AddAuditLog($"配置已更新 [IP:{_config.IpAddress}],生效时机:{(_isActived ? "" : "")}");
Debug.WriteLine($"[ConfigUpdated] 设备 {Id} 配置落地完成");
}
finally
@@ -280,7 +280,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
await _pendingLifecycleTask.ConfigureAwait(false);
// 幂等性检查:已在线则直接返回
if (_isOnline) return;
if (_isActived) return;
// 更新状态为连接中
UpdateStatus(VideoSourceStatus.Connecting, $"正在启动 {_config.Brand} 设备...");
@@ -297,7 +297,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
Interlocked.Exchange(ref _lastFrameTick, Environment.TickCount64 + 5000);
// 标记运行状态
_isOnline = true;
_isActived = true;
IsRunning = true;
// 更新状态为播放中,并刷新元数据
@@ -307,7 +307,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
catch (Exception ex)
{
// 异常回滚:标记离线并更新状态
_isOnline = false;
_isActived = false;
UpdateStatus(VideoSourceStatus.Disconnected, $"启动失败: {ex.Message}");
throw; // 向上抛出异常,由上层处理
}
@@ -326,7 +326,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
try
{
// 标记离线,阻断后续数据处理
_isOnline = false;
_isActived = false;
// 执行驱动层停止逻辑
await OnStopAsync().ConfigureAwait(false);
@@ -346,7 +346,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
public async Task<MetadataDiff> RefreshMetadataAsync()
{
// 离线状态不刷新元数据
if (!_isOnline) return MetadataDiff.None;
if (!_isActived) return MetadataDiff.None;
try
{
@@ -379,7 +379,7 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
public void ApplyOptions(DynamicStreamOptions options)
{
// 离线或参数为空时,忽略请求
if (options == null || !_isOnline)
if (options == null || !_isActived)
{
AddAuditLog("动态参数应用失败:设备离线或参数为空");
return;
@@ -437,10 +437,10 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
/// <param name="ex">相机统一异常</param>
protected void ReportError(CameraException ex)
{
if (!_isOnline) return;
if (!_isActived) return;
// 标记离线并更新状态为重连中
_isOnline = false;
_isActived = false;
UpdateStatus(VideoSourceStatus.Reconnecting, $"SDK异常: {ex.Message}", ex);
}
@@ -709,6 +709,46 @@ public abstract class BaseVideoSource : IVideoSource, IAsyncDisposable, IDeviceC
#endregion
#region --- 14. (Resilience Helpers) ---
/// <summary>
/// 认证类致命错误标记(如密码错、用户锁定)
/// 作用:触发 15 分钟长冷冻期,防止 IP 被相机锁定
/// </summary>
public bool IsAuthFailed { get; set; }
/// <summary>
/// 上次尝试执行 StartAsync 的系统 Tick 时间 (单调时钟)
/// </summary>
private long _lastStartAttemptTick = 0;
public long LastStartAttemptTick => Interlocked.Read(ref _lastStartAttemptTick);
/// <summary>
/// 更新最后一次启动尝试的时间戳为当前时间
/// </summary>
public void MarkStartAttempt()
{
Interlocked.Exchange(ref _lastStartAttemptTick, Environment.TickCount64);
}
/// <summary>
/// 强制重置自愈相关的冷却与错误标记
/// 用于用户手动干预(如修改密码)后,使协调器能立即触发下一次尝试
/// </summary>
public void ResetResilience()
{
// 1. 清除认证失败标记
IsAuthFailed = false;
// 2. 将尝试时间戳归零
// 这样在 Coordinator 中计算 elapsed = now - 0结果会远大于 30s
Interlocked.Exchange(ref _lastStartAttemptTick, 0);
_sdkLog.Debug($"[Sdk] 设备 {Id} 自愈状态已人工重置");
}
#endregion
// 自动从 SmartFrame 中提取
public int Width { get; protected set; }
public int Height { get; protected set; }