Files
GreenHomeBack/src/GreenHome.Infrastructure/Services/Alert/AlertConditionService.cs

177 lines
6.4 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 relays = await _dbContext.DeviceRelays
.Include(x => x.Rules)
.Where(x => x.DeviceSettings.DeviceId == deviceId && x.IsEnabled)
.OrderBy(x => x.RelayIndex)
.AsNoTracking()
.ToListAsync(cancellationToken);
var result = relays.Select(relay => new RelayConditionDto
{
Enabled = relay.IsEnabled ? 1 : 0,
TimeType = relay.Rules.Any()
? (int)relay.Rules.OrderBy(r => r.Order).First().TimeType
: (int)Domain.AlertTimeType.Always,
Relay = "R" + relay.RelayIndex,
Name = relay.Name,
Rules = relay.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,
Action = (int)r.Action,
TimeType = (int)r.TimeType
}).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.DeviceRelays
.AnyAsync(x => x.DeviceSettings.DeviceId == deviceId && 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.DeviceRelays
.AnyAsync(x => x.DeviceSettings.DeviceId == deviceId && x.UpdatedAt > lastUpdateDate, cancellationToken);
}
}