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.

244 lines
9.4 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;
namespace Haoliang.Core.Services
{
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 class AlarmRuleService : IAlarmRuleService
{
private readonly IAlarmRuleRepository _alarmRuleRepository;
private readonly IDeviceRepository _deviceRepository;
private readonly IAlarmRepository _alarmRepository;
private readonly ILoggingService _loggingService;
public AlarmRuleService(
IAlarmRuleRepository alarmRuleRepository,
IDeviceRepository deviceRepository,
IAlarmRepository alarmRepository,
ILoggingService loggingService)
{
_alarmRuleRepository = alarmRuleRepository;
_deviceRepository = deviceRepository;
_alarmRepository = alarmRepository;
_loggingService = loggingService;
}
public async Task<AlarmRule> CreateAlarmRuleAsync(AlarmRule rule)
{
// Validate rule
if (string.IsNullOrWhiteSpace(rule.RuleName))
throw new ArgumentException("Rule name is required");
if (string.IsNullOrWhiteSpace(rule.Condition))
throw new ArgumentException("Condition is required");
rule.RuleId = 0; // Ensure new rule
rule.CreatedAt = DateTime.Now;
rule.UpdatedAt = DateTime.Now;
await _alarmRuleRepository.AddAsync(rule);
await _alarmRuleRepository.SaveAsync();
await _loggingService.LogInfoAsync($"Created alarm rule: {rule.RuleName}");
return rule;
}
public async Task<AlarmRule> UpdateAlarmRuleAsync(int ruleId, AlarmRule rule)
{
var existingRule = await _alarmRuleRepository.GetByIdAsync(ruleId);
if (existingRule == null)
throw new KeyNotFoundException($"Alarm rule with ID {ruleId} not found");
existingRule.RuleName = rule.RuleName;
existingRule.Condition = rule.Condition;
existingRule.AlarmType = rule.AlarmType;
existingRule.AlarmSeverity = rule.AlarmSeverity;
existingRule.IsActive = rule.IsActive;
existingRule.DeviceId = rule.DeviceId;
existingRule.UpdatedAt = DateTime.Now;
await _alarmRuleRepository.UpdateAsync(existingRule);
await _alarmRuleRepository.SaveAsync();
await _loggingService.LogInfoAsync($"Updated alarm rule: {existingRule.RuleName}");
return existingRule;
}
public async Task<bool> DeleteAlarmRuleAsync(int ruleId)
{
var rule = await _alarmRuleRepository.GetByIdAsync(ruleId);
if (rule == null)
return false;
await _alarmRuleRepository.DeleteAsync(rule);
await _alarmRuleRepository.SaveAsync();
await _loggingService.LogInfoAsync($"Deleted alarm rule: {rule.RuleName}");
return true;
}
public async Task<AlarmRule> GetAlarmRuleByIdAsync(int ruleId)
{
return await _alarmRuleRepository.GetByIdAsync(ruleId);
}
public async Task<IEnumerable<AlarmRule>> GetAllAlarmRulesAsync()
{
return await _alarmRuleRepository.GetAllAsync();
}
public async Task<IEnumerable<AlarmRule>> GetActiveAlarmRulesAsync()
{
return await _alarmRuleRepository.GetActiveRulesAsync();
}
public async Task<IEnumerable<AlarmRule>> GetRulesByDeviceAsync(int deviceId)
{
return await _alarmRuleRepository.GetRulesByDeviceAsync(deviceId);
}
public async Task<bool> EvaluateAlarmRuleAsync(AlarmRule rule, DeviceCurrentStatus status)
{
if (!rule.IsActive)
return false;
try
{
// Simple condition evaluation (in real implementation, use expression parser)
var condition = rule.Condition.ToLower();
if (condition.Contains("device_offline") && !status.IsOnline)
return true;
if (condition.Contains("device_error") && status.Status == "Error")
return true;
if (condition.Contains("high_temperature") &&
status.Tags?.Any(t => t.Id == "temperature" && Convert.ToDouble(t.Value) > 80) == true)
return true;
if (condition.Contains("low_production") &&
status.CumulativeCount < 10)
return true;
// Custom condition evaluation
if (condition.Contains("running_time") &&
status.IsRunning &&
(DateTime.Now - status.RecordTime).TotalMinutes > 120)
return true;
return false;
}
catch (Exception ex)
{
await _loggingService.LogErrorAsync($"Error evaluating alarm rule {rule.RuleName}: {ex.Message}", ex);
return false;
}
}
public async Task<Alarm> GenerateAlarmFromRuleAsync(AlarmRule rule, DeviceCurrentStatus status)
{
var device = await _deviceRepository.GetByIdAsync(status.DeviceId);
if (device == null)
throw new InvalidOperationException("Device not found");
var alarm = new Alarm
{
DeviceId = status.DeviceId,
DeviceCode = device.DeviceCode,
DeviceName = device.DeviceName,
AlarmType = rule.AlarmType.ToString(),
AlarmSeverity = rule.AlarmSeverity,
Title = $"Alarm triggered by rule: {rule.RuleName}",
Description = $"Condition: {rule.Condition}",
AlarmStatus = AlarmStatus.Active,
CreateTime = DateTime.Now,
IsActive = true
};
await _alarmRepository.AddAsync(alarm);
await _alarmRepository.SaveAsync();
await _loggingService.LogWarningAsync($"Generated alarm: {alarm.Title} for device {device.DeviceCode}");
return alarm;
}
public async Task TestAlarmRuleAsync(int ruleId)
{
var rule = await _alarmRuleRepository.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();
var sampleDevice = devices.FirstOrDefault();
if (sampleDevice == null)
{
await _loggingService.LogWarningAsync($"No devices available to test alarm rule {rule.RuleName}");
return;
}
var sampleStatus = new DeviceCurrentStatus
{
DeviceId = sampleDevice.Id,
DeviceCode = sampleDevice.DeviceCode,
DeviceName = sampleDevice.DeviceName,
IsOnline = true,
IsAvailable = true,
Status = "Running",
IsRunning = true,
NCProgram = "TEST_PROGRAM",
CumulativeCount = 50,
OperatingMode = "Auto",
RecordTime = DateTime.Now,
Tags = new List<TagData>
{
new TagData { Id = "temperature", Value = 85.0, Time = DateTime.Now },
new TagData { Id = "pressure", Value = 120, Time = DateTime.Now }
}
};
var shouldTrigger = await EvaluateAlarmRuleAsync(rule, sampleStatus);
if (shouldTrigger)
{
await GenerateAlarmFromRuleAsync(rule, sampleStatus);
await _loggingService.LogInformationAsync($"Alarm rule test: {rule.RuleName} would trigger an alarm");
}
else
{
await _loggingService.LogInformationAsync($"Alarm rule test: {rule.RuleName} would not trigger an alarm");
}
}
}
// Additional repository interface for alarm rules
public interface IAlarmRuleRepository : IRepository<AlarmRule>
{
Task<IEnumerable<AlarmRule>> GetActiveRulesAsync();
Task<IEnumerable<AlarmRule>> GetRulesByDeviceAsync(int deviceId);
Task<IEnumerable<AlarmRule>> GetRulesByAlarmTypeAsync(AlarmType alarmType);
Task<bool> RuleExistsAsync(string ruleName);
Task<IEnumerable<AlarmRule>> GetEnabledRulesAsync();
}
}