You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
648 lines
24 KiB
C#
648 lines
24 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Haoliang.Models.System;
|
|
using Haoliang.Models.Device;
|
|
using Haoliang.Models.DataCollection;
|
|
using Haoliang.Data.Repositories;
|
|
using Haoliang.Core.Services;
|
|
|
|
namespace Haoliang.Core.Services
|
|
{
|
|
public interface IAlarmService
|
|
{
|
|
Task<Alarm> CreateAlarmAsync(Alarm alarm);
|
|
Task<Alarm> UpdateAlarmAsync(int alarmId, Alarm alarm);
|
|
Task<bool> DeleteAlarmAsync(int alarmId);
|
|
Task<Alarm> GetAlarmByIdAsync(int alarmId);
|
|
Task<IEnumerable<Alarm>> GetAllAlarmsAsync();
|
|
Task<IEnumerable<Alarm>> GetAlarmsByDeviceAsync(int deviceId);
|
|
Task<IEnumerable<Alarm>> GetAlarmsByTypeAsync(AlarmType type);
|
|
Task<IEnumerable<Alarm>> GetActiveAlarmsAsync();
|
|
Task<IEnumerable<Alarm>> GetAlarmsByDateRangeAsync(DateTime startDate, DateTime endDate);
|
|
Task<bool> ResolveAlarmAsync(int alarmId, string resolutionNote);
|
|
Task<bool> AcknowledgeAlarmAsync(int alarmId, string acknowledgeNote);
|
|
Task<AlarmStatistics> GetAlarmStatisticsAsync(DateTime date);
|
|
Task<IEnumerable<Alarm>> GetCriticalAlarmsAsync();
|
|
Task<IEnumerable<Alarm>> GetDeviceAlarmsAsync(int deviceId, int days = 7);
|
|
}
|
|
|
|
public interface IAlarmRuleService
|
|
{
|
|
Task<AlarmRule> CreateAlarmRuleAsync(AlarmRule rule);
|
|
Task<AlarmRule> UpdateAlarmRuleAsync(int ruleId, AlarmRule rule);
|
|
Task<bool> DeleteAlarmRuleAsync(int ruleId);
|
|
Task<AlarmRule> GetAlarmRuleByIdAsync(int ruleId);
|
|
Task<IEnumerable<AlarmRule>> GetAllAlarmRulesAsync();
|
|
Task<IEnumerable<AlarmRule>> GetActiveAlarmRulesAsync();
|
|
Task<IEnumerable<AlarmRule>> GetRulesByDeviceAsync(int deviceId);
|
|
Task<bool> EvaluateAlarmRuleAsync(AlarmRule rule, DeviceCurrentStatus status);
|
|
Task<Alarm> GenerateAlarmFromRuleAsync(AlarmRule rule, DeviceCurrentStatus status);
|
|
Task TestAlarmRuleAsync(int ruleId);
|
|
}
|
|
|
|
public interface IAlarmNotificationService
|
|
{
|
|
Task SendAlarmNotificationAsync(Alarm alarm);
|
|
Task SendBulkAlarmNotificationsAsync(IEnumerable<Alarm> alarms);
|
|
Task<bool> SendSmsNotificationAsync(string phoneNumber, string message);
|
|
Task<bool> SendEmailNotificationAsync(string email, string subject, string message);
|
|
Task<bool> SendWechatNotificationAsync(string openId, string message);
|
|
Task<IEnumerable<AlarmNotification>> GetNotificationHistoryAsync(DateTime startDate, DateTime endDate);
|
|
Task<bool> ConfigureNotificationChannelAsync(NotificationChannel channel);
|
|
Task<IEnumerable<NotificationChannel>> GetAvailableChannelsAsync();
|
|
}
|
|
|
|
public class AlarmManager : IAlarmService
|
|
{
|
|
private readonly IAlarmRepository _alarmRepository;
|
|
private readonly IAlarmRuleService _alarmRuleService;
|
|
private readonly IAlarmNotificationService _notificationService;
|
|
|
|
public AlarmManager(
|
|
IAlarmRepository alarmRepository,
|
|
IAlarmRuleService alarmRuleService,
|
|
IAlarmNotificationService notificationService)
|
|
{
|
|
_alarmRepository = alarmRepository;
|
|
_alarmRuleService = alarmRuleService;
|
|
_notificationService = notificationService;
|
|
}
|
|
|
|
public async Task<Alarm> CreateAlarmAsync(Alarm alarm)
|
|
{
|
|
// 设置初始状态
|
|
alarm.AlarmStatus = AlarmStatus.Active;
|
|
alarm.CreateTime = DateTime.Now;
|
|
alarm.UpdateTime = DateTime.Now;
|
|
|
|
var createdAlarm = await _alarmRepository.AddAsync(alarm);
|
|
|
|
// 发送告警通知
|
|
await _notificationService.SendAlarmNotificationAsync(createdAlarm);
|
|
|
|
return createdAlarm;
|
|
}
|
|
|
|
public async Task<Alarm> UpdateAlarmAsync(int alarmId, Alarm alarm)
|
|
{
|
|
var existingAlarm = await _alarmRepository.GetByIdAsync(alarmId);
|
|
if (existingAlarm == null)
|
|
{
|
|
throw new KeyNotFoundException($"Alarm with ID {alarmId} not found");
|
|
}
|
|
|
|
// 更新字段
|
|
alarm.AlarmId = alarmId;
|
|
alarm.UpdateTime = DateTime.Now;
|
|
|
|
var updatedAlarm = await _alarmRepository.UpdateAsync(alarm);
|
|
return updatedAlarm;
|
|
}
|
|
|
|
public async Task<bool> DeleteAlarmAsync(int alarmId)
|
|
{
|
|
return await _alarmRepository.DeleteAsync(alarmId);
|
|
}
|
|
|
|
public async Task<Alarm> GetAlarmByIdAsync(int alarmId)
|
|
{
|
|
return await _alarmRepository.GetByIdAsync(alarmId);
|
|
}
|
|
|
|
public async Task<IEnumerable<Alarm>> GetAllAlarmsAsync()
|
|
{
|
|
return await _alarmRepository.GetAllAsync();
|
|
}
|
|
|
|
public async Task<IEnumerable<Alarm>> GetAlarmsByDeviceAsync(int deviceId)
|
|
{
|
|
return await _alarmRepository.GetByDeviceIdAsync(deviceId);
|
|
}
|
|
|
|
public async Task<IEnumerable<Alarm>> GetAlarmsByTypeAsync(AlarmType type)
|
|
{
|
|
return await _alarmRepository.GetByAlarmTypeAsync(type);
|
|
}
|
|
|
|
public async Task<IEnumerable<Alarm>> GetActiveAlarmsAsync()
|
|
{
|
|
return await _alarmRepository.GetByStatusAsync(AlarmStatus.Active);
|
|
}
|
|
|
|
public async Task<IEnumerable<Alarm>> GetAlarmsByDateRangeAsync(DateTime startDate, DateTime endDate)
|
|
{
|
|
return await _alarmRepository.GetByDateRangeAsync(startDate, endDate);
|
|
}
|
|
|
|
public async Task<bool> ResolveAlarmAsync(int alarmId, string resolutionNote)
|
|
{
|
|
var alarm = await _alarmRepository.GetByIdAsync(alarmId);
|
|
if (alarm == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
alarm.AlarmStatus = AlarmStatus.Resolved;
|
|
alarm.ResolutionNote = resolutionNote;
|
|
alarm.ResolvedTime = DateTime.Now;
|
|
alarm.UpdateTime = DateTime.Now;
|
|
|
|
return await _alarmRepository.UpdateAsync(alarm) != null;
|
|
}
|
|
|
|
public async Task<bool> AcknowledgeAlarmAsync(int alarmId, string acknowledgeNote)
|
|
{
|
|
var alarm = await _alarmRepository.GetByIdAsync(alarmId);
|
|
if (alarm == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
alarm.AlarmStatus = AlarmStatus.Acknowledged;
|
|
alarm.AcknowledgeNote = acknowledgeNote;
|
|
alarm.AcknowledgedTime = DateTime.Now;
|
|
alarm.UpdateTime = DateTime.Now;
|
|
|
|
return await _alarmRepository.UpdateAsync(alarm) != null;
|
|
}
|
|
|
|
public async Task<AlarmStatistics> GetAlarmStatisticsAsync(DateTime date)
|
|
{
|
|
return await _alarmRepository.GetAlarmStatisticsAsync(date);
|
|
}
|
|
|
|
public async Task<IEnumerable<Alarm>> GetCriticalAlarmsAsync()
|
|
{
|
|
return await _alarmRepository.GetBySeverityAsync(AlarmSeverity.Critical);
|
|
}
|
|
|
|
public async Task<IEnumerable<Alarm>> GetDeviceAlarmsAsync(int deviceId, int days = 7)
|
|
{
|
|
var startDate = DateTime.Now.AddDays(-days);
|
|
var endDate = DateTime.Now;
|
|
return await _alarmRepository.GetByDeviceAndDateRangeAsync(deviceId, startDate, endDate);
|
|
}
|
|
}
|
|
|
|
public class AlarmRuleService : IAlarmRuleService
|
|
{
|
|
private readonly IAlarmRuleRepository _ruleRepository;
|
|
private readonly IAlarmRepository _alarmRepository;
|
|
private readonly IDeviceRepository _deviceRepository;
|
|
private readonly ILoggerService _logger;
|
|
|
|
public AlarmRuleService(
|
|
IAlarmRuleRepository ruleRepository,
|
|
IAlarmRepository alarmRepository,
|
|
IDeviceRepository deviceRepository,
|
|
ILoggerService logger)
|
|
{
|
|
_ruleRepository = ruleRepository;
|
|
_alarmRepository = alarmRepository;
|
|
_deviceRepository = deviceRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<AlarmRule> CreateAlarmRuleAsync(AlarmRule rule)
|
|
{
|
|
rule.IsActive = true;
|
|
rule.CreateTime = DateTime.Now;
|
|
rule.UpdateTime = DateTime.Now;
|
|
|
|
return await _ruleRepository.AddAsync(rule);
|
|
}
|
|
|
|
public async Task<AlarmRule> UpdateAlarmRuleAsync(int ruleId, AlarmRule rule)
|
|
{
|
|
var existingRule = await _ruleRepository.GetByIdAsync(ruleId);
|
|
if (existingRule == null)
|
|
{
|
|
throw new KeyNotFoundException($"Alarm rule with ID {ruleId} not found");
|
|
}
|
|
|
|
rule.RuleId = ruleId;
|
|
rule.UpdateTime = DateTime.Now;
|
|
|
|
return await _ruleRepository.UpdateAsync(rule);
|
|
}
|
|
|
|
public async Task<bool> DeleteAlarmRuleAsync(int ruleId)
|
|
{
|
|
return await _ruleRepository.DeleteAsync(ruleId);
|
|
}
|
|
|
|
public async Task<AlarmRule> GetAlarmRuleByIdAsync(int ruleId)
|
|
{
|
|
return await _ruleRepository.GetByIdAsync(ruleId);
|
|
}
|
|
|
|
public async Task<IEnumerable<AlarmRule>> GetAllAlarmRulesAsync()
|
|
{
|
|
return await _ruleRepository.GetAllAsync();
|
|
}
|
|
|
|
public async Task<IEnumerable<AlarmRule>> GetActiveAlarmRulesAsync()
|
|
{
|
|
return await _ruleRepository.GetByStatusAsync(true);
|
|
}
|
|
|
|
public async Task<IEnumerable<AlarmRule>> GetRulesByDeviceAsync(int deviceId)
|
|
{
|
|
return await _ruleRepository.GetByDeviceIdAsync(deviceId);
|
|
}
|
|
|
|
public async Task<bool> EvaluateAlarmRuleAsync(AlarmRule rule, DeviceCurrentStatus status)
|
|
{
|
|
if (!rule.IsActive || status == null)
|
|
return false;
|
|
|
|
try
|
|
{
|
|
switch (rule.RuleType)
|
|
{
|
|
case AlarmRuleType.DeviceOffline:
|
|
return EvaluateDeviceOfflineRule(rule, status);
|
|
|
|
case AlarmRuleType.TemperatureHigh:
|
|
return EvaluateTemperatureRule(rule, status);
|
|
|
|
case AlarmRuleType.PressureHigh:
|
|
return EvaluatePressureRule(rule, status);
|
|
|
|
case AlarmRuleType.ProductionStop:
|
|
return EvaluateProductionStopRule(rule, status);
|
|
|
|
case AlarmRuleType.NetworkError:
|
|
return EvaluateNetworkErrorRule(rule, status);
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to evaluate alarm rule {rule.RuleId}: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<Alarm> GenerateAlarmFromRuleAsync(AlarmRule rule, DeviceCurrentStatus status)
|
|
{
|
|
var alarm = new Alarm
|
|
{
|
|
DeviceId = status.DeviceId,
|
|
DeviceCode = "", // Will be populated from device
|
|
AlarmType = rule.AlarmType,
|
|
Severity = rule.Severity,
|
|
Title = rule.AlarmTitle,
|
|
Description = rule.AlarmDescription,
|
|
AlarmStatus = AlarmStatus.Active,
|
|
RuleId = rule.RuleId,
|
|
CreateTime = DateTime.Now,
|
|
UpdateTime = DateTime.Now
|
|
};
|
|
|
|
// Get device code
|
|
var device = await _deviceRepository.GetByIdAsync(status.DeviceId);
|
|
if (device != null)
|
|
{
|
|
alarm.DeviceCode = device.DeviceCode;
|
|
}
|
|
|
|
return alarm;
|
|
}
|
|
|
|
public async Task TestAlarmRuleAsync(int ruleId)
|
|
{
|
|
var rule = await _ruleRepository.GetByIdAsync(ruleId);
|
|
if (rule == null)
|
|
throw new KeyNotFoundException($"Alarm rule with ID {ruleId} not found");
|
|
|
|
// Get a sample device status for testing
|
|
var devices = await _deviceRepository.GetAllAsync();
|
|
if (!devices.Any())
|
|
throw new Exception("No devices available for testing");
|
|
|
|
var sampleDevice = devices.First();
|
|
var deviceStatus = new DeviceCurrentStatus
|
|
{
|
|
DeviceId = sampleDevice.Id,
|
|
Status = "Running",
|
|
IsRunning = true,
|
|
NCProgram = "O1234",
|
|
CumulativeCount = 1000,
|
|
RecordTime = DateTime.Now
|
|
};
|
|
|
|
// Evaluate the rule
|
|
var shouldTrigger = await EvaluateAlarmRuleAsync(rule, deviceStatus);
|
|
|
|
if (shouldTrigger)
|
|
{
|
|
var alarm = await GenerateAlarmFromRuleAsync(rule, deviceStatus);
|
|
alarm.Title = $"Test Alarm: {rule.AlarmTitle}";
|
|
alarm.Description = $"This is a test alarm for rule '{rule.RuleName}'.";
|
|
|
|
await _alarmRepository.AddAsync(alarm);
|
|
await _alarmRepository.SaveAsync();
|
|
|
|
await _logger.LogInformationAsync($"Test alarm created for rule {rule.RuleId}");
|
|
}
|
|
else
|
|
{
|
|
await _logger.LogInformationAsync($"Rule {rule.RuleId} did not trigger alarm during test");
|
|
}
|
|
}
|
|
|
|
private bool EvaluateDeviceOfflineRule(AlarmRule rule, DeviceCurrentStatus status)
|
|
{
|
|
// Check if device status indicates offline
|
|
return status.Status?.ToLower() == "offline" ||
|
|
!status.IsRunning ||
|
|
string.IsNullOrEmpty(status.NCProgram);
|
|
}
|
|
|
|
private bool EvaluateTemperatureRule(AlarmRule rule, DeviceCurrentStatus status)
|
|
{
|
|
// Find temperature tag
|
|
var temperatureTag = status.Tags?.FirstOrDefault(t => t.Id?.Contains("temp") == true || t.Id?.Contains("温度") == true);
|
|
if (temperatureTag == null || temperatureTag.Value == null)
|
|
return false;
|
|
|
|
if (decimal.TryParse(temperatureTag.Value.ToString(), out decimal temperature))
|
|
{
|
|
return temperature > rule.ThresholdValue;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool EvaluatePressureRule(AlarmRule rule, DeviceCurrentStatus status)
|
|
{
|
|
// Find pressure tag
|
|
var pressureTag = status.Tags?.FirstOrDefault(t => t.Id?.Contains("pressure") == true || t.Id?.Contains("压力") == true);
|
|
if (pressureTag == null || pressureTag.Value == null)
|
|
return false;
|
|
|
|
if (decimal.TryParse(pressureTag.Value.ToString(), out decimal pressure))
|
|
{
|
|
return pressure > rule.ThresholdValue;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool EvaluateProductionStopRule(AlarmRule rule, DeviceCurrentStatus status)
|
|
{
|
|
// Check if device has been stopped for specified duration
|
|
var stopDuration = TimeSpan.FromMinutes(rule.ThresholdValue);
|
|
return !status.IsRunning &&
|
|
status.RecordTime < DateTime.Now.Subtract(stopDuration);
|
|
}
|
|
|
|
private bool EvaluateNetworkErrorRule(AlarmRule rule, DeviceCurrentStatus status)
|
|
{
|
|
// Check for network-related errors in status
|
|
return status.Tags?.Any(t => t.Id?.Contains("error") == true && t.Value?.ToString() == "1") == true;
|
|
}
|
|
}
|
|
|
|
public class AlarmNotificationService : IAlarmNotificationService
|
|
{
|
|
private readonly IAlarmNotificationRepository _notificationRepository;
|
|
private readonly IEmailService _emailService;
|
|
private readonly ISmsService _smsService;
|
|
private readonly IWechatService _wechatService;
|
|
private readonly ILoggerService _logger;
|
|
private readonly IDeviceRepository _deviceRepository;
|
|
|
|
public AlarmNotificationService(
|
|
IAlarmNotificationRepository notificationRepository,
|
|
IEmailService emailService,
|
|
ISmsService smsService,
|
|
IWechatService wechatService,
|
|
ILoggerService logger,
|
|
IDeviceRepository deviceRepository)
|
|
{
|
|
_notificationRepository = notificationRepository;
|
|
_emailService = emailService;
|
|
_smsService = smsService;
|
|
_wechatService = wechatService;
|
|
_logger = logger;
|
|
_deviceRepository = deviceRepository;
|
|
}
|
|
|
|
public async Task SendAlarmNotificationAsync(Alarm alarm)
|
|
{
|
|
try
|
|
{
|
|
var device = await _deviceRepository.GetByIdAsync(alarm.DeviceId);
|
|
var notificationChannels = await GetNotificationChannelsForDevice(alarm.DeviceId);
|
|
|
|
foreach (var channel in notificationChannels)
|
|
{
|
|
if (channel.IsEnabled)
|
|
{
|
|
await SendNotificationViaChannel(alarm, channel, device);
|
|
}
|
|
}
|
|
|
|
// Log the notification
|
|
await LogNotificationSent(alarm, notificationChannels.Count());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to send alarm notification for alarm {alarm.AlarmId}: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public async Task SendBulkAlarmNotificationsAsync(IEnumerable<Alarm> alarms)
|
|
{
|
|
foreach (var alarm in alarms)
|
|
{
|
|
await SendAlarmNotificationAsync(alarm);
|
|
}
|
|
}
|
|
|
|
public async Task<bool> SendSmsNotificationAsync(string phoneNumber, string message)
|
|
{
|
|
try
|
|
{
|
|
return await _smsService.SendSmsAsync(phoneNumber, message);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to send SMS to {phoneNumber}: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> SendEmailNotificationAsync(string email, string subject, string message)
|
|
{
|
|
try
|
|
{
|
|
return await _emailService.SendEmailAsync(email, subject, message);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to send email to {email}: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> SendWechatNotificationAsync(string openId, string message)
|
|
{
|
|
try
|
|
{
|
|
return await _wechatService.SendMessageAsync(openId, message);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to send WeChat message to {openId}: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<IEnumerable<AlarmNotification>> GetNotificationHistoryAsync(DateTime startDate, DateTime endDate)
|
|
{
|
|
return await _notificationRepository.GetByDateRangeAsync(startDate, endDate);
|
|
}
|
|
|
|
public async Task<bool> ConfigureNotificationChannelAsync(NotificationChannel channel)
|
|
{
|
|
// Validate channel configuration
|
|
if (!ValidateChannelConfiguration(channel))
|
|
return false;
|
|
|
|
// Save channel configuration
|
|
return await _notificationRepository.SaveChannelAsync(channel);
|
|
}
|
|
|
|
public async Task<IEnumerable<NotificationChannel>> GetAvailableChannelsAsync()
|
|
{
|
|
return await _notificationRepository.GetAllChannelsAsync();
|
|
}
|
|
|
|
private async Task<List<NotificationChannel>> GetNotificationChannelsForDevice(int deviceId)
|
|
{
|
|
// This would typically query the database for device-specific notification settings
|
|
// For now, return a default set of channels
|
|
return new List<NotificationChannel>
|
|
{
|
|
new NotificationChannel { ChannelType = NotificationChannelType.Email, IsEnabled = true },
|
|
new NotificationChannel { ChannelType = NotificationChannelType.Sms, IsEnabled = false },
|
|
new NotificationChannel { ChannelType = NotificationChannelType.WeChat, IsEnabled = false }
|
|
};
|
|
}
|
|
|
|
private async Task SendNotificationViaChannel(Alarm alarm, NotificationChannel channel, Device device)
|
|
{
|
|
var message = FormatAlarmMessage(alarm, device);
|
|
var subject = $"Alarm: {alarm.AlarmType} - {device?.DeviceCode}";
|
|
|
|
switch (channel.ChannelType)
|
|
{
|
|
case NotificationChannelType.Email:
|
|
if (!string.IsNullOrEmpty(channel.Recipient))
|
|
{
|
|
await SendEmailNotificationAsync(channel.Recipient, subject, message);
|
|
}
|
|
break;
|
|
|
|
case NotificationChannelType.Sms:
|
|
if (!string.IsNullOrEmpty(channel.Recipient))
|
|
{
|
|
await SendSmsNotificationAsync(channel.Recipient, message);
|
|
}
|
|
break;
|
|
|
|
case NotificationChannelType.WeChat:
|
|
if (!string.IsNullOrEmpty(channel.Recipient))
|
|
{
|
|
await SendWechatNotificationAsync(channel.Recipient, message);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private string FormatAlarmMessage(Alarm alarm, Device device)
|
|
{
|
|
return $"🚨 Alarm Alert\n\n" +
|
|
$"Device: {device?.DeviceCode} ({device?.DeviceName})\n" +
|
|
$"Type: {alarm.AlarmType}\n" +
|
|
$"Severity: {alarm.Severity}\n" +
|
|
$"Title: {alarm.Title}\n" +
|
|
$"Description: {alarm.Description}\n" +
|
|
$"Time: {alarm.CreateTime:yyyy-MM-dd HH:mm:ss}\n" +
|
|
$"Device ID: {alarm.DeviceId}";
|
|
}
|
|
|
|
private bool ValidateChannelConfiguration(NotificationChannel channel)
|
|
{
|
|
switch (channel.ChannelType)
|
|
{
|
|
case NotificationChannelType.Email:
|
|
return !string.IsNullOrEmpty(channel.Recipient) && channel.Recipient.Contains("@");
|
|
|
|
case NotificationChannelType.Sms:
|
|
return !string.IsNullOrEmpty(channel.Recipient) && channel.Recipient.All(char.IsDigit);
|
|
|
|
case NotificationChannelType.WeChat:
|
|
return !string.IsNullOrEmpty(channel.Recipient);
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private async Task LogNotificationSent(Alarm alarm, int channelCount)
|
|
{
|
|
var notification = new AlarmNotification
|
|
{
|
|
AlarmId = alarm.AlarmId,
|
|
NotificationTime = DateTime.Now,
|
|
ChannelsUsed = channelCount,
|
|
Success = true
|
|
};
|
|
|
|
await _notificationRepository.AddNotificationAsync(notification);
|
|
}
|
|
}
|
|
|
|
// Additional supporting classes and interfaces
|
|
public interface IEmailService
|
|
{
|
|
Task<bool> SendEmailAsync(string email, string subject, string message);
|
|
}
|
|
|
|
public interface ISmsService
|
|
{
|
|
Task<bool> SendSmsAsync(string phoneNumber, string message);
|
|
}
|
|
|
|
public interface IWechatService
|
|
{
|
|
Task<bool> SendMessageAsync(string openId, string message);
|
|
}
|
|
|
|
public interface IAlarmRuleRepository
|
|
{
|
|
Task<AlarmRule> AddAsync(AlarmRule rule);
|
|
Task<AlarmRule> UpdateAsync(AlarmRule rule);
|
|
Task<bool> DeleteAsync(int ruleId);
|
|
Task<AlarmRule> GetByIdAsync(int ruleId);
|
|
Task<IEnumerable<AlarmRule>> GetAllAsync();
|
|
Task<IEnumerable<AlarmRule>> GetByStatusAsync(bool isActive);
|
|
Task<IEnumerable<AlarmRule>> GetByDeviceIdAsync(int deviceId);
|
|
}
|
|
|
|
public interface IAlarmNotificationRepository
|
|
{
|
|
Task<AlarmNotification> AddNotificationAsync(AlarmNotification notification);
|
|
Task<IEnumerable<AlarmNotification>> GetByDateRangeAsync(DateTime startDate, DateTime endDate);
|
|
Task<bool> SaveChannelAsync(NotificationChannel channel);
|
|
Task<IEnumerable<NotificationChannel>> GetAllChannelsAsync();
|
|
}
|
|
} |