SingleSRMAnalysis.cs 11.1 KB
using FreeSql;
using HHECS.DAQHandle.Common.Enums;
using HHECS.DAQHandle.Common.Utils;
using HHECS.DAQHandle.Models;
using HHECS.EquipmentModel;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace HHECS.DAQHandle.EquipmentHandle
{
    internal class SingleSRMAnalysis : BaseAnalysis
    {
        public override void Execute(IEnumerable<EquipmentDataRecord> records)
        {
            try
            {
                base.Execute(records);
                if (records.Any()) return;
                foreach (var item in records.GroupBy(x => x.EquipmentCode))
                {
                    var equipmentSN = item.Key;
                    var isSetValueSuccess = UpdateTagValue(item.OrderByDescending(x => x.Timestamp).Last());
                    if (!isSetValueSuccess)
                    {
                        foreach (var item1 in item)
                        {
                            //更新数据状态为设置数值报错
                            item1.HandleStage = (byte)(item1.HandleStage ^ item1.SET_VALUE_ERROR);
                        }
                    }  

                    var alarmCodes = new List<SingleSRMProp>();
                    UpdateEquipmentAlarm(equipmentSN, alarmCodes, [.. item]);
                    
                    var statusCodes = new List<SingleSRMProp>();
                    UpdateEquipmentStatus(equipmentSN, statusCodes, [.. item]);

                  
                    //更新状态到数据库
                    Context.UpdateRange(item);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[{nameof(SingleSRMAnalysis)}]解析异常:{ex.Message}");
            }
        }



        protected override void UpdateEquipmentAlarm<T>(string equipmentSN, IList<T> alarmCodes, IList<EquipmentDataRecord> records)
        {
            base.UpdateEquipmentAlarm(equipmentSN, alarmCodes, records);
            if (records.Any()) return;
            try
            {

                /* 1.获取历史状态信息(可能需要一次性获取所有设备,后续从内存中查找)
               2.根据数据判断当前设备的状态
               3.与历史状态进行比较
                  有匹配的历史数据
                      如果状态相同
                          判断当前数据的时间是否最新
                              是最新 更新时间
                               不是最新 判断是否存在异常的持续期间
                                    是 丢弃
                                    不是 
                                        判断与前后同类型异常是否超过超时时间 
                                            不是 添加新异常
                                            是  延长上一个异常的时间 、 更新后一个异常的开始时间、连接前后两个异常? //对数据改动较大可能不执行
                      不同,结束上一个状态,并插入新数据
                  无匹配的历史数据
                      根据超时时间进行状态更新结束异常状态,由于设备状态与设备报警不同,一直会有一种状态,所以如果是空闲状态则不更新数据,或者加入断开连接状态
            */
                var equipment = Context.Equipment.Where(x => x.Code == equipmentSN).First();
                if (equipment == null)
                {
                    SystemLog.PrintError($"设备{equipmentSN}不存在");
                    return;
                }
                foreach (var equipmentInfo in records)
                {
                    try
                    {
                        var alarmRecords = Context.EquipmentAlarmRecords.Where(x => x.EquipmentCode == equipmentInfo.EquipmentCode && x.IsEnd == false).ToList();
                        var alarms = EquipmentTypePropTemps.FindAll(x => x.PropType == EquipmentPropType.PLCMonitorAddress && equipmentInfo.Props[x.Code] != x.MonitorCompareValue);
                        //如果alarms考虑直接结束报警,目前是隔五秒刷新
                        if (alarms.Count > 0)
                        {

                            foreach (var alarm in alarms)
                            {
                                //匹配数据库中已有记录,如果当前的时间戳小于已记录的异常,不做处理
                                var record = alarmRecords.Find(t => t.PropCode == alarm.Code);
                                if (record == null)
                                {
                                    //说明记录中没有,或者超过5秒,则直接新增这个报警;
                                    EquipmentAlarmRecord equipmentAlarm = new EquipmentAlarmRecord
                                    {
                                        EquipmentCode = equipmentInfo.EquipmentCode,
                                        EquipmentName = equipment.Name,
                                        PropCode = alarm.Code,
                                        AlarmMessage = alarm.MonitorFailure,
                                        CreateTime = DateTime.Now,
                                        UpdateTime = DateTime.Now,//确保不为null 
                                    };
                                    Context.EquipmentAlarmRecords.Add(equipmentAlarm);
                                    Context.SaveChanges();
                                }
                                else
                                {
                                    //更新这个报警
                                    record.UpdateTime = DateTime.Now;
                                    Context.EquipmentAlarmRecords.Update(record);
                                }
                            }
                            
                        }
                    }
                    catch (Exception ex)
                    {
                        equipmentInfo.HandleStage = (byte)(equipmentInfo.HandleStage ^ equipmentInfo.SET_ALARM_ERROR);
                        SystemLog.PrintError($"记录{equipmentInfo.Id}设置报警信息异常:{ex}");
                    }
                }

            }
            catch (Exception ex)
            {
                SystemLog.PrintError($"{ex}");
            }

        }

        protected override void UpdateEquipmentStatus<T>(string equipmentSN, IList<T> statusCodes, IList<EquipmentDataRecord> records)
        {
            base.UpdateEquipmentStatus(equipmentSN, statusCodes, records);

            /* 1.获取历史状态信息(可能需要一次性获取所有设备,后续从内存中查找)
               2.根据数据判断当前设备的状态
               3.与历史状态进行比较
                  有匹配的历史数据
                      如果状态相同
                          判断当前数据的时间是否最新
                              是最新 更新时间
                               不是最新 判断是否存在同类型状态的持续期间
                                    是 丢弃
                                    不是  //暂不实现
                                        截断在此区间的状态 
                                            
                      不同,结束上一个状态,并插入新数据
                  无匹配的历史数据
                      根据超时时间进行状态更新结束异常状态,由于设备状态与设备报警不同,一直会有一种状态,所以如果是空闲状态则不更新数据,或者加入断开连接状态
            */


            foreach (var srm in records)
            {
                try
                {
                    //与此设备相关的所有状态记录
                    var statusRecords = Context.EquipmentStatusRecords.Where(t => t.EquipmentCode == srm.EquipmentCode && t.IsEnd == false).ToList();
                    if (statusRecords.Count > 1)
                    {
                        SystemLog.PrintError($"设备{srm.EquipmentCode}同时存在多条未结束的状态;{string.Join(",", statusRecords.Select(x => x.Status))}");
                    }
                    //记录过期处理
                    if (srm.UpdateTime < statusRecords.First().UpdateTime)
                    {
                        SystemLog.PrintWarn($"记录{srm.Id}已过期");
                    }


                    //故障
                    if (srm.Props[SRMProps.TotalError.ToString()] == "True")
                    {
                        RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Error);
                    }
                    else
                    {
                        //空闲等
                        if (srm.Props[SRMProps.OperationModel.ToString()] == SRMOperationModel.Maintain.GetIndexString())
                        {
                            //维修
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Maintain);
                        }
                        else if (srm.Props[SRMProps.OperationModel.ToString()] == SRMOperationModel.Manual.GetIndexString()
                        || srm.Props[SRMProps.OperationModel.ToString()] == SRMOperationModel.StandAlone.GetIndexString()
                        || srm.Props[SRMProps.OperationModel.ToString()] == SRMOperationModel.Airborne.GetIndexString())
                        {
                            //手动
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Manual);
                        }
                        else if (srm.Props[SRMProps.OperationModel.ToString()] == SRMOperationModel.Online.GetIndexString()
                        && srm.Props[SRMProps.Fork1TaskExcuteStatus.ToString()] == SRMTaskExcuteStatus.TaskExecuting.GetIndexString())
                        {
                            //运行中
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Running);
                        }
                        else if (srm.Props[SRMProps.OperationModel.ToString()] == SRMOperationModel.Online.GetIndexString()
                        && srm.Props[SRMProps.Fork1TaskExcuteStatus.ToString()] == SRMTaskExcuteStatus.Standby.GetIndexString())
                        {
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Free);
                        }
                        else if (srm.Props[SRMProps.OperationModel.ToString()] == SRMOperationModel.Online.GetIndexString()
                        && (srm.Props[SRMProps.Fork1TaskExcuteStatus.ToString()] == SRMTaskExcuteStatus.TaskInterruptError.GetIndexString()
                            || srm.Props[SRMProps.Fork1TaskExcuteStatus.ToString()] == SRMTaskExcuteStatus.TaskSendError.GetIndexString()))
                        {
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.TaskExcuteError);
                        }

                    }
                }
                catch (Exception ex)
                {
                    SystemLog.PrintError($"记录{srm.Id}状态记录处理失败:{ex}");
                }
            }

        }

    }
}