93 lines
2.7 KiB
C#
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");
|
||
|
|
}
|
||
|
|
}
|