Program.cs 11.4 KB
using FreeSql;
using HHECS.DAQHandle.Common.Enums;
using HHECS.DAQHandle.Common.Utils;
using HHECS.DAQHandle.DataAccess;
using HHECS.DAQHandle.Dto;
using HHECS.DAQHandle.EquipmentHandle;
using HHECS.DAQHandle.Models;
using HHECS.EquipmentModel;
using System.Configuration;
using System.Diagnostics;
using System.Xml.Linq;
using static FreeSql.Internal.GlobalFilter;

internal class Program
{
    /// <summary>
    /// 单次处理的数据量
    /// </summary>
    private static int _limit = 100;
    private static long LastEquipmentCount = 0;
    private static long LastEquipmentPropTempCount = 0;
    private static List<EquipmentType> EquipmentTypes;
    //设备缓存数据
    public static Dictionary<string, EquipmentInfoDto> EquipmentInfos;
    protected static int DataRetentionDays = int.Parse(ConfigurationManager.AppSettings["DataRetentionDays"]);


    private static void Main(string[] args)
    {
        try
        {
            Console.Title = "IOT数据处理端";

            var warehouseCode = ConfigurationManager.AppSettings["WarehouseCode"];
            if (string.IsNullOrWhiteSpace(warehouseCode))
            {
                SystemLog.PrintWarn("仓库编号未配置!");
                return;
            }

            var equipmentTypeCodes = ConfigurationManager.AppSettings["EquipmentType"].Split(',').ToList();
            if (equipmentTypeCodes == null || equipmentTypeCodes.Count == 0)
            {
                SystemLog.PrintWarn("设备类型未配置!");
                return;
            }

            var limit = ConfigurationManager.AppSettings["ProcessingDataVolume"];
            if (!int.TryParse(limit, out _limit))
            {
                _limit = 100;
            }

            using var context = new DataContext();
            EquipmentTypes = context.EquipmentType.Where(x => equipmentTypeCodes.Contains(x.Code)).IncludeMany(x => x.EquipmentTypePropTemplates).ToList();

            //刷新模板数据
            InitData();
            Task.Run(async () =>
            {
                await Task.Delay(1000 * 60);
                while (true)
                {
                    try
                    {
                        if (IsDataChange())
                        {
                            InitData();
                        }
                        DeleteExpireData();
                        await Task.Delay(1000 * 60);
                    }
                    catch (Exception ex)
                    {
                        SystemLog.PrintError($"{ex}");
                    }

                }
            });


            Startup(EquipmentTypes);
        }
        catch (Exception ex)
        {
            SystemLog.PrintWarn($"程序启动出现异常:{ex}");
        }
    }

    private static void Startup(IEnumerable<EquipmentType> equipmentTypes)
    {
        while (true)
        {
            try
            {
                var tasks = new List<Task>();


                // using var context = new DataContext();
                foreach (var item in equipmentTypes)
                {
                  
                    //var equipmentCodes = context.Equipment.Where(x => x.EquipmentTypeId == item.Id).ToList(x => x.Code);
                    tasks.Add(Task.Run(() =>
                    {
                        Stopwatch stopwatch = Stopwatch.StartNew();
                        _ = Enum.TryParse<EquipmentTypeConst>(item.Code, out var equipmentTypeCode);
                        IAnalysis handle = equipmentTypeCode switch
                        {
                            EquipmentTypeConst.SingleForkSRM => new SingleForkSRMAnalysis(item),
                            EquipmentTypeConst.DoubleForkSRM => new DoubleForkSRMAnalysis(item),
                            EquipmentTypeConst.SingleForkSSRM => new SingleForkSSRMAnalysis(item),
                            EquipmentTypeConst.SingleForkSSRMV132 => new SingleForkSSRMV132Analysis(item),
                            EquipmentTypeConst.WeldRobot => new WeldRobotAnalysis(item),
                            EquipmentTypeConst.AGVForklift => new AGVAnalysis(item),
                            EquipmentTypeConst.RGVStation => new RGVAnalysis(item),
                            EquipmentTypeConst.StationMonitor => new StationMonitorAnalysis(item),
                            EquipmentTypeConst.Hoist => new HoistAnalysis(item),
                            _ => null
                        };
                        //未知类型,则跳过
                        if (handle is null)
                        {
                            SystemLog.PrintWarn($"未实现设备类型[{item.Code}]对应的处理方法");
                            return;
                        }
                        try
                        {
                            //using var context = new DataContext();
                            //var equipmentCodes = context.Equipment.Where(x => x.EquipmentTypeId == item.Id).ToList(x => x.Code);
                            //var equipmentDataRecords = context.EquipmentDataRecord.Where(x => equipmentCodes.Contains(x.EquipmentCode) && !x.IsHandle).OrderBy(x => x.Timestamp).Take(_limit).ToList();


                            //if (equipmentDataRecords.Count == 0)
                            //{
                            //    SystemLog.PrintInfo($"设备类型[{item.Code}]队列数据为空,跳过解析");
                            //    return;
                            //}
                            using var context = new DataContext();
                            var equipmentCodes = EquipmentInfos.Where(x => x.Value.EquipmentTypeId == item.Id).Select(x => x.Value.Code).ToList();
                            var equipmentDataRecords = context.EquipmentDataRecord.Where(x => equipmentCodes.Contains(x.EquipmentCode) && !x.IsHandle).OrderBy(x => x.Timestamp).Take(_limit).ToList();

                            var result = handle.Execute(equipmentDataRecords);
                            stopwatch.Stop();
                            if (!result.Success)
                            {
                                SystemLog.PrintError($"设备类型[{item.Code}]解析失败,{result.Msg},数量{equipmentDataRecords.Count},耗时{stopwatch.ElapsedMilliseconds}ms");
                                return;
                            }
                            SystemLog.PrintInfo($"设备类型[{item.Code}]解析完成,数量{equipmentDataRecords.Count},耗时{stopwatch.ElapsedMilliseconds}ms");
                        }
                        catch (Exception ex)
                        {
                            SystemLog.PrintError($"{ex}");
                        }
                    }));
                }
                Task.WaitAll(tasks.ToArray());
                Console.WriteLine($"————————————————————————————————————————————————————————");
            }
            catch (Exception ex)
            {
                SystemLog.PrintError($"程序异常:{ex}");
            }
        }
    }
    /// <summary>
    /// 初始化设备数据,并进行缓存
    /// </summary>
    private static void InitData()
    {
        SystemLog.PrintInfo("数据发生改变刷新设备数据");
        using var context = new DataContext();
        var equipments = context.Equipment.Where(x => EquipmentTypes.Any(y => y.Code == x.EquipmentType.Code)).IncludeMany(x => x.EquipmentProps).Include(x => x.EquipmentType).ToList();

        var equipmentPropTemps = context.EquipmentTypePropTemplate.Where(x => EquipmentTypes.Any(y => y.Id == x.EquipmentTypeId)).ToList();


        EquipmentInfos = equipments.Select(equipment => new EquipmentInfoDto()
        {
            Id = equipment.Id,
            Code = equipment.Code,
            Name = equipment.Name,
            EquipmentType = equipment.EquipmentType,
            EquipmentTypeId = equipment.EquipmentType.Id,
            //EquipmentPropTemps = x.EquipmentProps.Select(prop => new{prop.Address,Value=eq})
            EquipmentPropTemps =
            //equipment.EquipmentProps.ToDictionary(prop => prop.Address,
            //                               prop => equipmentPropTemps.Find(temp => temp.Code == prop.EquipmentTypePropTemplateCode)?.MonitorCompareValue)
            equipment.EquipmentProps.Select(prop =>
            {
                var temp = equipmentPropTemps.Find(temp => temp.Code == prop.EquipmentTypePropTemplateCode);
                if (temp == null)
                {
                    SystemLog.PrintError($"设备{equipment.Name}的属性{prop.EquipmentTypePropTemplateCode}在模板中不存在");
                    return (prop.Address, null, null, null, null);
                }
                return (prop.Address, temp?.MonitorCompareValue, temp?.PropType, temp?.MonitorFailure, temp.Code);
            }).ToList(),
        }).ToDictionary(x => x.Code, x => x);
    }

    /// <summary>
    /// 判断设备数据或者设备模板数据是否发生改变
    /// </summary>
    /// <returns></returns>
    private static bool IsDataChange()
    {
        var flag = false;

        using var context = new DataContext();
        var lastEquipmentCount = context.Equipment.Where(x => true).Count();
        var lastEquipmentPropTempCount = context.EquipmentProp.Where(x => true).Count();

        if (lastEquipmentCount != LastEquipmentCount || lastEquipmentPropTempCount != LastEquipmentPropTempCount)
        {
            flag = true;
        }
        LastEquipmentCount = lastEquipmentCount;
        LastEquipmentPropTempCount = lastEquipmentPropTempCount;

        return flag;
    }


    private static void DeleteExpireData()
    {
        try
        {
            using var context = new DataContext();
            var handleStage = EquipmentDataRecord.SET_ERROR_HANDLE | EquipmentDataRecord.SET_STATUS_HANDLE | EquipmentDataRecord.SET_VAULE_HANDLE;
            //删除已完成并且超过配置保留天数的数据
            var count = context.EquipmentDataRecord.Remove(x => x.IsHandle && x.HandleStage == handleStage && (DateTime.Now - (DateTime)x.CreateTime).TotalDays > DataRetentionDays);
            context.SaveChanges();


            SystemLog.PrintInfo($"清除了{count}条已处理数据");

        }
        catch (Exception ex)
        {
            SystemLog.PrintInfo($"清除已处理数据失败{ex}");
        }

        #region
        //EquipmentType = equipmentType;
        //EquipmentTypePropTemps = equipmentType.EquipmentTypePropTemplates;
        //var handleStage = EquipmentDataRecord.SET_ERROR_HANDLE | EquipmentDataRecord.SET_STATUS_HANDLE | EquipmentDataRecord.SET_VAULE_HANDLE;
        //var count = Context.EquipmentDataRecord.Where(x => x.IsHandle && x.HandleStage == handleStage).Count();
        ////保留9000-10000条数据
        //if (count < DataRetentionAmount) return;
        //var handleData = Context.EquipmentDataRecord.Where(x => x.IsHandle && x.HandleStage == handleStage).OrderBy(x => x.Timestamp).Take(1000).ToList();
        //if (handleData.Count > 0)
        //{
        //    try
        //    {
        //        Context.EquipmentDataRecord.RemoveRange(handleData);
        //        Context.SaveChanges();
        //        SystemLog.PrintInfo($"清除了{handleData.Count}条已处理数据");
        //    }
        //    catch (Exception ex)
        //    {
        //        SystemLog.PrintInfo($"清除已处理数据失败{ex}");
        //    }

        //}
        #endregion
    }
}