SDK 的 Bug 修复
This commit is contained in:
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user