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#
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();
|
|
}
|
|
} |