YD_TrainingCompetition_Api/Services/HikvisionAlarmStore.cs
2026-07-02 10:05:51 +08:00

93 lines
2.7 KiB
C#

using Microsoft.Extensions.Options;
using System.Collections.Concurrent;
using YD_TrainingCompetition_Api.Models;
using YD_TrainingCompetition_Api.Options;
namespace YD_TrainingCompetition_Api.Services;
public sealed class HikvisionAlarmStore : IHikvisionAlarmStore
{
private readonly ConcurrentQueue<AlarmRecord> _alarms = new();
private readonly ConcurrentDictionary<string, HikvisionCameraStatus> _cameraStatuses = new(StringComparer.OrdinalIgnoreCase);
private readonly HikvisionOptions _options;
private readonly ILogger<HikvisionAlarmStore> _logger;
private int _alarmCount;
public HikvisionAlarmStore(IOptions<HikvisionOptions> options, ILogger<HikvisionAlarmStore> logger)
{
_options = options.Value;
_logger = logger;
}
public void Add(AlarmRecord record)
{
_alarms.Enqueue(record);
var newCount = Interlocked.Increment(ref _alarmCount);
// 超出上限则移除最旧的记录
while (newCount > _options.MaxAlarmRecords)
{
if (_alarms.TryDequeue(out _))
{
Interlocked.Decrement(ref _alarmCount);
newCount--;
}
}
_logger.LogInformation("Alarm stored: DeviceId={DeviceId}, Id={Id}, QueueSize={Size}",
record.DeviceId, record.Id, newCount);
}
public IReadOnlyCollection<AlarmRecord> GetAll()
{
return _alarms.Reverse().ToArray();
}
public IReadOnlyCollection<AlarmRecord> GetByDeviceId(string deviceId)
{
return _alarms
.Where(x => string.Equals(x.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase))
.Reverse()
.ToArray();
}
public AlarmRecord? GetLatest()
{
return _alarms.LastOrDefault();
}
public AlarmRecord? GetLatestByDevice(string deviceId)
{
return _alarms
.LastOrDefault(x => string.Equals(x.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase));
}
public void UpdateCameraStatus(HikvisionCameraStatus status)
{
status.LastSeen = DateTimeOffset.UtcNow;
_cameraStatuses[status.DeviceId] = status;
}
public IReadOnlyCollection<HikvisionCameraStatus> GetAllCameraStatuses()
{
return _cameraStatuses.Values
.OrderBy(x => x.DeviceId, StringComparer.OrdinalIgnoreCase)
.ToArray();
}
public HikvisionCameraStatus? GetCameraStatus(string deviceId)
{
return _cameraStatuses.TryGetValue(deviceId, out var status) ? status : null;
}
public void ClearAlarms()
{
while (_alarms.TryDequeue(out _))
{
Interlocked.Decrement(ref _alarmCount);
}
_logger.LogInformation("All alarms cleared");
}
}