172 lines
6.2 KiB
C#
172 lines
6.2 KiB
C#
using AutoMapper;
|
|
using GreenHome.Application;
|
|
using GreenHome.Infrastructure.Data;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace GreenHome.Infrastructure.Services.Alert;
|
|
|
|
public sealed class AlertConditionService : IAlertConditionService
|
|
{
|
|
private readonly GreenHomeDbContext _dbContext;
|
|
private readonly IMapper _mapper;
|
|
|
|
public AlertConditionService(GreenHomeDbContext dbContext, IMapper mapper)
|
|
{
|
|
_dbContext = dbContext;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
public async Task<IReadOnlyList<AlertConditionDto>> GetByDeviceIdAsync(int deviceId, CancellationToken cancellationToken)
|
|
{
|
|
var conditions = await _dbContext.AlertConditions
|
|
.Include(x => x.Device)
|
|
.Include(x => x.Rules)
|
|
.Where(x => x.DeviceId == deviceId)
|
|
.OrderByDescending(x => x.CreatedAt)
|
|
.AsNoTracking()
|
|
.ToListAsync(cancellationToken);
|
|
|
|
return _mapper.Map<List<AlertConditionDto>>(conditions);
|
|
}
|
|
|
|
public async Task<AlertConditionDto?> GetByIdAsync(int id, CancellationToken cancellationToken)
|
|
{
|
|
var condition = await _dbContext.AlertConditions
|
|
.Include(x => x.Device)
|
|
.Include(x => x.Rules)
|
|
.AsNoTracking()
|
|
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
|
|
|
|
return condition != null ? _mapper.Map<AlertConditionDto>(condition) : null;
|
|
}
|
|
|
|
public async Task<int> CreateAsync(CreateAlertConditionRequest request, CancellationToken cancellationToken)
|
|
{
|
|
var condition = new Domain.AlertCondition
|
|
{
|
|
DeviceId = request.DeviceId,
|
|
NotificationType = request.NotificationType,
|
|
TimeType = request.TimeType,
|
|
CallCooldownMinutes = request.CallCooldownMinutes,
|
|
SmsCooldownMinutes = request.SmsCooldownMinutes,
|
|
IsEnabled = request.IsEnabled,
|
|
CreatedAt = DateTime.UtcNow,
|
|
UpdatedAt = DateTime.UtcNow
|
|
};
|
|
|
|
var rules = _mapper.Map<List<Domain.AlertRule>>(request.Rules);
|
|
foreach (var rule in rules)
|
|
{
|
|
condition.Rules.Add(rule);
|
|
}
|
|
|
|
_dbContext.AlertConditions.Add(condition);
|
|
await _dbContext.SaveChangesAsync(cancellationToken);
|
|
|
|
return condition.Id;
|
|
}
|
|
|
|
public async Task UpdateAsync(UpdateAlertConditionRequest request, CancellationToken cancellationToken)
|
|
{
|
|
var condition = await _dbContext.AlertConditions
|
|
.Include(x => x.Rules)
|
|
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken);
|
|
|
|
if (condition == null)
|
|
throw new InvalidOperationException($"Alert condition not found: {request.Id}");
|
|
|
|
condition.NotificationType = request.NotificationType;
|
|
condition.TimeType = request.TimeType;
|
|
condition.CallCooldownMinutes = request.CallCooldownMinutes;
|
|
condition.SmsCooldownMinutes = request.SmsCooldownMinutes;
|
|
condition.IsEnabled = request.IsEnabled;
|
|
condition.UpdatedAt = DateTime.UtcNow;
|
|
|
|
_dbContext.AlertRules.RemoveRange(condition.Rules);
|
|
condition.Rules.Clear();
|
|
|
|
var newRules = _mapper.Map<List<Domain.AlertRule>>(request.Rules);
|
|
foreach (var rule in newRules)
|
|
{
|
|
condition.Rules.Add(rule);
|
|
}
|
|
|
|
await _dbContext.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task DeleteAsync(int id, CancellationToken cancellationToken)
|
|
{
|
|
var condition = await _dbContext.AlertConditions
|
|
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
|
|
|
|
if (condition == null)
|
|
throw new InvalidOperationException($"Alert condition not found: {id}");
|
|
|
|
_dbContext.AlertConditions.Remove(condition);
|
|
await _dbContext.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<bool> ToggleEnabledAsync(int id, bool isEnabled, CancellationToken cancellationToken)
|
|
{
|
|
var condition = await _dbContext.AlertConditions
|
|
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
|
|
|
|
if (condition == null)
|
|
return false;
|
|
|
|
condition.IsEnabled = isEnabled;
|
|
condition.UpdatedAt = DateTime.UtcNow;
|
|
|
|
await _dbContext.SaveChangesAsync(cancellationToken);
|
|
return true;
|
|
}
|
|
|
|
public async Task<IReadOnlyList<RelayConditionDto>> GetRelayConditionsAsync(int deviceId, CancellationToken cancellationToken)
|
|
{
|
|
var conditions = await _dbContext.AlertConditions
|
|
.Include(x => x.Rules)
|
|
.Where(x => x.DeviceId == deviceId && (int)x.NotificationType > 0)
|
|
.OrderByDescending(x => x.CreatedAt)
|
|
.AsNoTracking()
|
|
.ToListAsync(cancellationToken);
|
|
|
|
var result = conditions.Select(c => new RelayConditionDto
|
|
{
|
|
Enabled = c.IsEnabled ? 1 : 0,
|
|
TimeType = (int)c.TimeType,
|
|
Relay = "R" + (int)c.NotificationType,
|
|
Rules = c.Rules.OrderBy(r => r.Order).Select(r => new RelayRuleDto
|
|
{
|
|
Sensor = ((int)r.SensorType).ToString(),
|
|
Op = ((int)r.ComparisonType).ToString(),
|
|
V1 = r.Value1,
|
|
V2 = r.Value2
|
|
}).ToList()
|
|
}).ToList();
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<IReadOnlyList<RelayConditionDto>> GetUpdatedRelayConditionsAsync(int deviceId, DateTime? lastUpdateDate, CancellationToken cancellationToken)
|
|
{
|
|
if (lastUpdateDate == null)
|
|
return await GetRelayConditionsAsync(deviceId, cancellationToken);
|
|
|
|
var hasUpdates = await _dbContext.AlertConditions
|
|
.AnyAsync(x => x.DeviceId == deviceId && (int)x.NotificationType > 0 && x.UpdatedAt > lastUpdateDate, cancellationToken);
|
|
|
|
if (!hasUpdates)
|
|
return Array.Empty<RelayConditionDto>();
|
|
|
|
return await GetRelayConditionsAsync(deviceId, cancellationToken);
|
|
}
|
|
|
|
public async Task<bool> HasUpdatedConditionsAsync(int deviceId, DateTime? lastUpdateDate, CancellationToken cancellationToken)
|
|
{
|
|
if (lastUpdateDate == null) return true;
|
|
|
|
return await _dbContext.AlertConditions
|
|
.AnyAsync(x => x.DeviceId == deviceId && (int)x.NotificationType > 0 && x.UpdatedAt > lastUpdateDate, cancellationToken);
|
|
}
|
|
}
|