Program.cs 14.9 KB
using HHECS.BllModel;
using HHECS.DAQHandle;
using HHECS.DAQHandle.Common.Enums;
using HHECS.DAQHandle.Common.Utils;
using HHECS.DAQHandle.Dto;
using HHECS.DAQHandle.EquipmentHandle;
using HHECS.DAQHandle.Models;
using System.Configuration;
using System.Diagnostics;

internal class Program
{
    private static void Main(string[] args)
    {
        try
        {
            var appConfigResult = LoadAppConfig();
            if (!appConfigResult.Success)
            {
                SystemLog.PrintError($"加载配置文件信息失败:{appConfigResult.Msg}");
                return;
            }
            var appConfig = appConfigResult.Data;

            var result = ValidationConfig(appConfig);
            if (!result.Success)
            {
                SystemLog.PrintError($"配置信息校验失败:{result.Msg}");
                return;
            }

            var connectionString = ConfigurationManager.ConnectionStrings[appConfig.IsProductionEnvironment ? "Production" : "Development"].ConnectionString;
            GlobalVar.SetConnectionString(connectionString);
            UpdateClientStatus();
            Startup(appConfig);
        }
        catch (Exception ex)
        {
            SystemLog.PrintWarn($"程序启动出现异常:{ex.Message}");
        }
    }

    private static void Startup(AppConfig config)
    {
        var equipments = new List<EquipmentExtend>();
        var equipmentTypes = new List<EquipmentTypeExtend>();
        var equipmentTypeCodes = config.EquipmentTypeCodes;
        SystemLog.PrintInfo($"正在初始化数据...");
        while (true)
        {
            try
            {
                var result = InitialData(equipmentTypeCodes, ref equipments, ref equipmentTypes);
                if (!result.Success)
                {
                    SystemLog.PrintError($"初始化数据失败:{result.Msg}");
                    continue;
                }
                if (equipmentTypes.Count == 0)
                {
                    SystemLog.PrintError($"获取设备类型[{string.Join(',', equipmentTypeCodes)}]数据失败,数据为空!");
                    continue;
                }
                Stopwatch stopwatch = Stopwatch.StartNew();
                var tasks = new List<Task>();
                foreach (var currentEquipmentType in equipmentTypes)
                {
                    tasks.Add(Task.Run(() =>
                    {
                        Stopwatch stopwatch = Stopwatch.StartNew();
                        _ = Enum.TryParse<EquipmentTypeConst>(currentEquipmentType.Code, out var equipmentTypeCode);
                        var parameter = new AnalysisParameter
                        {
                            Equipments = equipments.Where(x => x.EquipmentTypeId == currentEquipmentType.Id).ToList(),
                            EquipmentType = currentEquipmentType,
                            AppConfig = config,
                            EquipmentTotalAlarmCode = equipmentTypeCode switch
                            {
                                EquipmentTypeConst.SingleForkSRM => SRMProps.TotalError.ToString(),
                                EquipmentTypeConst.DoubleForkSRM => SRMProps.TotalError.ToString(),
                                EquipmentTypeConst.SingleForkSSRM => SRMProps.TotalError.ToString(),
                                EquipmentTypeConst.SingleForkSSRMV132 => SRMProps.TotalError.ToString(),
                                EquipmentTypeConst.WeldRobot => RobotProp.Alarm.ToString(),
                                EquipmentTypeConst.AGVForklift => "",//待完善
                                EquipmentTypeConst.RGVStation => RGVProps.Fault.ToString(),
                                EquipmentTypeConst.StationMonitor => StationProps.StationError.ToString(),
                                EquipmentTypeConst.Hoist => HoistProps.HoistStatus.ToString(),
                                _ => string.Empty,
                            }
                        };
                        IAnalysis handle = equipmentTypeCode switch
                        {
                            EquipmentTypeConst.SingleForkSRM => new SingleForkSRMAnalysis(parameter),
                            EquipmentTypeConst.DoubleForkSRM => new DoubleForkSRMAnalysis(parameter),
                            EquipmentTypeConst.SingleForkSSRM => new SingleForkSSRMAnalysis(parameter),
                            EquipmentTypeConst.SingleForkSSRMV132 => new SingleForkSSRMV132Analysis(parameter),
                            EquipmentTypeConst.WeldRobot => new WeldRobotAnalysis(parameter),
                            EquipmentTypeConst.AGVForklift => new AGVAnalysis(parameter),
                            EquipmentTypeConst.RGVStation => new RGVStationAnalysis(parameter),
                            EquipmentTypeConst.StationMonitor => new StationMonitorAnalysis(parameter),
                            EquipmentTypeConst.Hoist => new HoistAnalysis(parameter),
                            _ => null
                        };
                        //未知类型,则跳过
                        if (handle is null)
                        {
                            SystemLog.PrintWarn($"未实现设备类型[{currentEquipmentType.Code}]对应的处理方法");
                            return;
                        }
                        try
                        {
                            var limit = config.ProcessingDataVolume;
                            if (equipmentTypeCode == EquipmentTypeConst.StationMonitor)
                            {
                                //站台数据量比较大,目前不处理站台状态和报警,所以每次多取一些数据
                                limit *= 5;
                            }

                            var freeSql = GlobalVar.FreeSql;
                            using var equipmentDataRecordRepository = freeSql.GetRepository<EquipmentDataRecord>();
                            var equipmentCodes = equipments.Where(x => x.EquipmentTypeId == currentEquipmentType.Id).Select(x => x.Code).ToList();
                            var equipmentDataRecords = equipmentDataRecordRepository
                                .Where(x => equipmentCodes.Contains(x.EquipmentCode) && !x.IsHandle && x.Version == config.Version)
                                .OrderBy(x => x.Timestamp).Take(limit).ToList();
                            if (equipmentDataRecords.Count == 0)
                            {
                                SystemLog.PrintInfo($"设备类型[{currentEquipmentType.Code}]记录数据为空,跳过解析,耗时:{stopwatch.ElapsedMilliseconds}ms");
                                return;
                            }

                            var result = handle.Execute(equipmentDataRecords);
                            if (!result.Success)
                            {
                                SystemLog.PrintError($"设备类型[{currentEquipmentType.Code}]解析失败,{result.Msg},数量{equipmentDataRecords.Count},耗时:{stopwatch.ElapsedMilliseconds}ms");
                                return;
                            }

                            var ids = equipmentDataRecords.Select(x => x.Id).ToList();
                            var minDateTime = equipmentDataRecords.Min(x => x.CreateTime);
                            var maxDateTime = equipmentDataRecords.Max(x => x.CreateTime);

                            freeSql.Delete<EquipmentDataRecord>().Where(x => ids.Contains(x.Id)
                            && x.CreateTime.Between(minDateTime, maxDateTime)).CommandTimeout(300).ExecuteAffrows();
                            SystemLog.PrintSuccess($"设备类型[{currentEquipmentType.Code}]解析完成,数量{equipmentDataRecords.Count},耗时:{stopwatch.ElapsedMilliseconds}ms");
                        }
                        catch (Exception ex)
                        {
                            SystemLog.PrintError($"[{handle.GetType().Name}]线程数据解析出现异常:{ex.Message}");
                        }
                    }));
                }
                Task.WaitAll(tasks.ToArray());
                Thread.Sleep(1000);
                const string tempString = "——————————————————";
                Console.WriteLine($"{tempString}[总耗时:{stopwatch.Elapsed}]{tempString}");
            }
            catch (Exception ex)
            {
                SystemLog.PrintError($"程序异常:{ex.Message}");
            }
        }
    }

    /// <summary>
    /// 加载配置文件信息
    /// </summary>
    /// <returns></returns>
    private static BllResult<AppConfig> LoadAppConfig()
    {
        try
        {
            _ = int.TryParse(ConfigurationManager.AppSettings["DataTimeOut"], out int dataTimeOutValue);
            _ = int.TryParse(ConfigurationManager.AppSettings["ProcessingDataVolume"], out int processingDataVolumeValue);
            _ = int.TryParse(ConfigurationManager.AppSettings["DataRetentionDays"], out int dataRetentionDaysValue);
            _ = int.TryParse(ConfigurationManager.AppSettings["Version"], out var version);
            _ = bool.TryParse(ConfigurationManager.AppSettings["IsProductionEnvironment"], out var isProductionEnvironmentValue);
            _ = Guid.TryParse((ConfigurationManager.AppSettings["ClientId"]), out var clientIdValue);
            var equipmentTypeCodes = ConfigurationManager.AppSettings["EquipmentType"];
            var warehouseCode = ConfigurationManager.AppSettings["WarehouseCode"];

            if (processingDataVolumeValue <= 0)
            {
                processingDataVolumeValue = 100;
            }

            if (isProductionEnvironmentValue)
            {
                Console.Title = "IOT数据处理端";
            }
            else
            {
                Console.Title = "IOT数据处理端(测试版)";
            }
            var appConfig = new AppConfig
            {
                ClientId = clientIdValue,
                WarehouseCode = warehouseCode,
                DataTimeOut = dataTimeOutValue,
                IsProductionEnvironment = isProductionEnvironmentValue,
                ProcessingDataVolume = processingDataVolumeValue,
                EquipmentTypeCodes = equipmentTypeCodes.Split(',').ToList(),
                Version = version
            };
            return BllResultFactory.Success(appConfig);
        }

        catch (Exception ex)
        {
            return BllResultFactory.Error<AppConfig>(ex.Message);
        }
    }

    /// <summary>
    /// 配置信息校验
    /// </summary>
    /// <param name="appConfig"></param>
    /// <returns></returns>
    private static BllResult ValidationConfig(AppConfig appConfig)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(appConfig.WarehouseCode))
            {
                return BllResultFactory.Error($"仓库编号[{nameof(appConfig.WarehouseCode)}]未配置!");
            }

            if (appConfig.EquipmentTypeCodes == null || appConfig.EquipmentTypeCodes.Count == 0)
            {
                return BllResultFactory.Error($"设备类型[{appConfig.EquipmentTypeCodes}]未配置!");
            }

            if (appConfig.Version == 0)
            {
                return BllResultFactory.Error($"程序版本[{appConfig.Version}]未配置!");
            }
            return BllResultFactory.Success();
        }
        catch (Exception ex)
        {
            return BllResultFactory.Error(ex.Message);
        }
    }

    /// <summary>
    /// 初始化数据
    /// </summary>
    /// <param name="equipmentTypeCodes">设备类型编号</param>
    /// <param name="equipments">设备集合</param>
    /// <param name="equipmentTypes">设备类型集合</param>
    /// <remarks>仅在设备或设备属性数据总数发生变化时加载</remarks>
    private static BllResult InitialData(List<string> equipmentTypeCodes, ref List<EquipmentExtend> equipments, ref List<EquipmentTypeExtend> equipmentTypes)
    {
        try
        {
            using var freeSql = GlobalVar.FreeSql;
            var equipmentRepository = freeSql.GetRepository<EquipmentExtend>();
            var equipmentPropRepository = freeSql.GetRepository<EquipmentPropExtend>();
            var equipmentTypeRepository = freeSql.GetRepository<EquipmentTypeExtend>();

            if (equipmentTypes.Count == 0)
            {
                equipmentTypes = equipmentTypeRepository.Where(x => equipmentTypeCodes.Contains(x.Code)).IncludeMany(x => x.EquipmentTypePropTemplates).ToList();
            }
            var equipmentTypeIds = equipmentTypes.Select(x => x.Id).ToList();
            var equipmentIds = equipmentRepository.Where(x => equipmentTypeIds.Contains(x.EquipmentTypeId)).ToList(x => x.Id);
            var equipmentTotal = equipmentIds.Count;
            var equipmentPropTotal = equipmentPropRepository.Where(x => equipmentIds.Contains(x.EquipmentId)).Count();
            if (equipments.Count != equipmentTotal || equipments.SelectMany(x => x.EquipmentProps).Count() != equipmentPropTotal)
            {
                equipments = equipmentRepository.Where(x => equipmentTypeIds.Contains(x.EquipmentTypeId)).IncludeMany(x => x.EquipmentProps).ToList();
                foreach (var item in equipments)
                {
                    var equipmentType = equipmentTypes.Find(x => x.Id == item.EquipmentTypeId);
                    item.EquipmentType = equipmentType;
                    item.EquipmentProps.ForEach(x => x.EquipmentTypePropTemplate = equipmentType.EquipmentTypePropTemplates.Find(t => t.Id == x.EquipmentTypePropTemplateId));
                }
            }
            return BllResultFactory.Success();
        }
        catch (Exception ex)
        {
            return BllResultFactory.Error(ex.Message);
        }
    }

    /// <summary>
    /// 更新客户端状态
    /// </summary>
    private static void UpdateClientStatus()
    {
        Task.Run(async () =>
        {
            while (true)
            {
                try
                {
                    await Task.Delay(5000);
                    using var clientStatusRepository = GlobalVar.FreeSql.GetRepository<ClientStatus>();
                    //更新客户端状态
                    _ = Guid.TryParse(ConfigurationManager.AppSettings["ClientId"], out var clientId);
                    if (clientId != Guid.Empty)
                    {
                        var client = clientStatusRepository.Where(x => x.ClientKeys == clientId).First();
                        if (client != null)
                        {
                            clientStatusRepository.Attach(client);
                            client.LastSeenDate = DateTime.Now;
                            clientStatusRepository.Update(client);
                        }
                    }
                }
                catch (Exception ex)
                {
                    SystemLog.PrintError($"客户端状态更新线程异常:{ex.Message}");
                }
            }
        });
    }
}