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 CreateAlarmRuleAsync(AlarmRule rule); Task UpdateAlarmRuleAsync(int ruleId, AlarmRule rule); Task DeleteAlarmRuleAsync(int ruleId); Task GetAlarmRuleByIdAsync(int ruleId); Task> GetAllAlarmRulesAsync(); Task> GetActiveAlarmRulesAsync(); Task> GetRulesByDeviceAsync(int deviceId); Task EvaluateAlarmRuleAsync(AlarmRule rule, DeviceCurrentStatus status); Task 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 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 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 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 GetAlarmRuleByIdAsync(int ruleId) { return await _alarmRuleRepository.GetByIdAsync(ruleId); } public async Task> GetAllAlarmRulesAsync() { return await _alarmRuleRepository.GetAllAsync(); } public async Task> GetActiveAlarmRulesAsync() { return await _alarmRuleRepository.GetActiveRulesAsync(); } public async Task> GetRulesByDeviceAsync(int deviceId) { return await _alarmRuleRepository.GetRulesByDeviceAsync(deviceId); } public async Task 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 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 { 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 { Task> GetActiveRulesAsync(); Task> GetRulesByDeviceAsync(int deviceId); Task> GetRulesByAlarmTypeAsync(AlarmType alarmType); Task RuleExistsAsync(string ruleName); Task> GetEnabledRulesAsync(); } }