SingleSRMAnalysis.cs 11.7 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))
                {
                    Context.AttachRange(item);

                    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);
                    Context.SaveChanges();
                }
            }
            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
            {


                foreach (var equipmentInfo in records)
                {
                    try
                    {
                        var lastAlarm = Context.EquipmentAlarmRecords.Where(x => x.EquipmentCode == equipmentInfo.EquipmentCode)
                            .OrderByDescending(x => x.UpdateTime)
                            .Take(1).First();
                        if (lastAlarm != null)
                        {
                            DateTime acceptTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local).AddSeconds(equipmentInfo.Timestamp);
                            //记录过期处理
                            if (acceptTime < lastAlarm.UpdateTime)
                            {
                                SystemLog.PrintWarn($"记录{equipmentInfo.Id}已过期");
                                continue;
                            }
                        }
                        var alarmRecords = Context.EquipmentAlarmRecords.Where(x => x.EquipmentCode == equipmentInfo.EquipmentCode && x.IsEnd == false).ToList();
                        var alarms = EquipmentTypePropTemps.FindAll(x =>
                        {
                            return
                               //x.PropType == EquipmentPropType.PLCMonitorAddress
                               equipmentInfo.Props[x.Address] != x.MonitorCompareValue;
                        });
                        //如果alarms考虑直接结束报警,目前是隔五秒刷新
                        if (alarms.Count > 0)
                        {

                            foreach (var alarm in alarms)
                            {
                                //匹配数据库中已有记录,如果当前的时间戳小于已记录的异常,不做处理
                                var record = alarmRecords.Find(t => t.PropCode == alarm.Address);

                                if (record == null)
                                {
                                    //说明记录中没有,或者超过5秒,则直接新增这个报警;
                                    EquipmentAlarmRecord equipmentAlarm = new EquipmentAlarmRecord
                                    {
                                        EquipmentCode = equipmentInfo.EquipmentCode,
                                        EquipmentName = equipmentInfo.EquipmentName,
                                        PropCode = alarm.Code,
                                        AlarmMessage = string.IsNullOrWhiteSpace(equipmentInfo.Props[alarm.Address]) ? "值为空" :"值不正常"+ alarm.MonitorFailure,
                                        CreateTime = DateTime.Now,
                                        UpdateTime = DateTime.Now,//确保不为null 
                                    };
                                    Context.EquipmentAlarmRecords.Add(equipmentAlarm);

                                }
                                else
                                {
                                    //更新这个报警
                                    record.UpdateTime = DateTime.Now;
                                    Context.EquipmentAlarmRecords.Update(record);
                                }
                                Context.SaveChanges();
                            }

                        }
                    }
                    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))}");
                    }

                    DateTime acceptTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local).AddSeconds(srm.Timestamp);
                    //记录过期处理
                    if (statusRecords.Count != 0 && acceptTime < statusRecords.First().UpdateTime)
                    {
                        SystemLog.PrintWarn($"记录{srm.Id}已过期");
                    }

                    var totalError = EquipmentTypePropTemps.Where(x => x.Code == SRMProps.TotalError.ToString()).First().Address;
                    //故障
                    if (string.IsNullOrWhiteSpace(srm.Props[totalError]))
                    {
                        SystemLog.PrintError($"记录{srm.Id}的totalError属性无有效数据");
                    }
                    else if (srm.Props[totalError] == "True")
                    {
                        RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Error);
                    }
                    else
                    {
                        var operationModel = EquipmentTypePropTemps.Where(x => x.Code == SRMProps.OperationModel.ToString()).First().Address;
                        var fork1TaskExcuteStatus = EquipmentTypePropTemps.Where(x => x.Code == SRMProps.Fork1TaskExcuteStatus.ToString()).First().Address;

                        if (string.IsNullOrWhiteSpace(srm.Props[operationModel]) || string.IsNullOrWhiteSpace(fork1TaskExcuteStatus))
                        {
                            SystemLog.PrintError($"记录{srm.Id}的operationModel属性无有效数据{srm.Props[operationModel]}或fork1TaskExcuteStatus 无有效数据{srm.Props[fork1TaskExcuteStatus]}");
                        }
                        //空闲等
                        if (srm.Props[operationModel] == SRMOperationModel.Maintain.GetIndexString())
                        {
                            //维修
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Maintain);
                        }
                        else if (srm.Props[operationModel] == SRMOperationModel.Manual.GetIndexString()
                        || srm.Props[operationModel] == SRMOperationModel.StandAlone.GetIndexString()
                        || srm.Props[operationModel] == SRMOperationModel.Airborne.GetIndexString())
                        {
                            //手动
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Manual);
                        }
                        else if (srm.Props[operationModel] == SRMOperationModel.Online.GetIndexString()
                        && srm.Props[fork1TaskExcuteStatus] == SRMTaskExcuteStatus.TaskExecuting.GetIndexString())
                        {
                            //运行中
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Running);
                        }
                        else if (srm.Props[operationModel] == SRMOperationModel.Online.GetIndexString()
                        && srm.Props[fork1TaskExcuteStatus] == SRMTaskExcuteStatus.Standby.GetIndexString())
                        {
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.Free);
                        }
                        else if (srm.Props[operationModel] == SRMOperationModel.Online.GetIndexString()
                        && (srm.Props[fork1TaskExcuteStatus] == SRMTaskExcuteStatus.TaskInterruptError.GetIndexString()
                            || srm.Props[fork1TaskExcuteStatus] == SRMTaskExcuteStatus.TaskSendError.GetIndexString()))
                        {
                            RecordEquipmentStatus(srm, statusRecords, EquipmentStatusRecordStatus.TaskExcuteError);
                        }

                    }
                }
                catch (Exception ex)
                {
                    SystemLog.PrintError($"记录{srm.Id}状态记录处理失败:{ex}");
                }
                finally
                {
                    srm.IsHandle = true;
                    srm.UpdateTime = DateTime.Now;
                }
            }

        }

    }
}