BoardController.cs 20.2 KB
using DataAcquisition.Common.Enums;
using DataAcquisition.DataAccess;
using DataAcquisition.Models;
using DataAcquisition.Services;
using DataAcquisition.ViewModels.Board;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;

namespace DataAcquisition.ApiControllers
{
    /// <summary>
    /// 看板接口
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class BoardController : ControllerBase
    {
        private readonly IDbContextFactory<DataContext> _dbContextFactory;
        private readonly DataCacheService _dataCacheService;
        private readonly IMemoryCache _memoryCache;
        private readonly TimeSpan _absoluteExpirationRelativeToNow;

        public BoardController(IDbContextFactory<DataContext> dbContextFactory, DataCacheService dataCacheService, IMemoryCache memoryCache)
        {
            _dbContextFactory = dbContextFactory;
            _dataCacheService = dataCacheService;
            _memoryCache = memoryCache;
            _absoluteExpirationRelativeToNow = TimeSpan.FromSeconds(2);
        }

        /// <summary>
        /// 焊接看板1
        /// </summary>
        /// <remarks>1号厂房</remarks>
        /// <returns></returns>
        [HttpGet]
        public BoardResult<dynamic> GetWeldBoardData()
        {
            var result = new BoardResult<dynamic>();
            try
            {
                var key = nameof(GetWeldBoardData);
                var cacheData = _memoryCache.Get<BoardResult<dynamic>>(key);
                if (cacheData != null)
                {
                    return cacheData;
                }

                //本月开始时间
                var monthStartTime = DateTime.Today.AddDays(1 - DateTime.Today.Day).Date;
                using var context = _dbContextFactory.CreateDbContext();
                var robotEquipment = _dataCacheService.Equipments.Find(x => x.Code == EquipmentConst.Fanuc_1.ToString())!;

                _ = double.TryParse(robotEquipment[RobotProps.Pos_X.ToString()].Value, out var pos_X);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_Y.ToString()].Value, out var pos_Y);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_Z.ToString()].Value, out var pos_Z);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_A.ToString()].Value, out var pos_A);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_B.ToString()].Value, out var pos_B);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_C.ToString()].Value, out var pos_C);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_E1.ToString()].Value, out var pos_E1);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_E2.ToString()].Value, out var pos_E2);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_E3.ToString()].Value, out var pos_E3);
                _ = double.TryParse(robotEquipment[RobotProps.Pos_E4.ToString()].Value, out var pos_E4);

                //_ = bool.TryParse(robotEquipment[RobotProps.Weld_CleanGun.ToString()].Value, out var weld_CleanGun);
                _ = bool.TryParse(robotEquipment[RobotProps.WeldFlag.ToString()].Value, out var weldFlag);
                _ = bool.TryParse(robotEquipment[RobotProps.Weld_Gas.ToString()].Value, out var weld_Gas);
                _ = bool.TryParse(robotEquipment[RobotProps.WeldCompleteFlag.ToString()].Value, out var weldCompleteFlag);
                _ = bool.TryParse(robotEquipment[RobotProps.BootFlag.ToString()].Value, out var bootFalgValue);
                _ = bool.TryParse(robotEquipment[RobotProps.Alarm.ToString()].Value, out var alarmValue);
                _ = bool.TryParse(robotEquipment[RobotProps.WorkFlag.ToString()].Value, out var workFlagValue);
                _ = bool.TryParse(robotEquipment[RobotProps.Work_Time.ToString()].Value, out var workTime);
                _ = bool.TryParse(robotEquipment[RobotProps.Weld_Type.ToString()].Value, out var weldType);
                _ = bool.TryParse(robotEquipment[RobotProps.ArcVoltageTracking.ToString()].Value, out var arcVoltageTracking);

                _ = float.TryParse(robotEquipment[RobotProps.Weld_V.ToString()].Value, out var weld_V);
                _ = float.TryParse(robotEquipment[RobotProps.Weld_I.ToString()].Value, out var weld_I);
                _ = float.TryParse(robotEquipment[RobotProps.Weld_Speed.ToString()].Value, out var weld_Speed);
                _ = int.TryParse(robotEquipment[RobotProps.Work_Mode.ToString()].Value, out var work_Mode);
                _ = int.TryParse(robotEquipment[RobotProps.Program_No.ToString()].Value, out var program_no);
                //_ = int.TryParse(robotEquipment[RobotProps.Type.ToString()].Value, out var type);
                _ = int.TryParse(robotEquipment[RobotProps.Station.ToString()].Value, out var station);
                _ = int.TryParse(robotEquipment[RobotProps.WireFeeder.ToString()].Value, out var wireFeeder);

                var type = robotEquipment[RobotProps.Type.ToString()].Value;

                var equipmentState = "在线";
                if (!bootFalgValue)
                {
                    equipmentState = "离线";
                }
                //仅自动模式显示
                else if (alarmValue && work_Mode >= 3)
                {
                    equipmentState = "报警";
                }
                else if (workFlagValue)
                {
                    equipmentState = "工作";
                }

                //加工状态
                var productStateName = "空闲";
                var timeSum = 0d;
                if (workTime)
                {
                    productStateName = weldFlag ? "焊接" : "加工";
                    timeSum = Math.Round(TimeSpan.FromTicks(context.WorkpieceProductions.Where(x => x.EquipmentCode == robotEquipment.Code && x.WorkpieceCode == $"{type}").OrderByDescending(x => x.CreateTime).Select(x => x.UpdateTime.Ticks - x.CreateTime.Ticks).FirstOrDefault()).TotalMinutes, 2);
                }

                var lastProductionId = context.WorkpieceProductions.Where(x => x.EquipmentCode == robotEquipment.Code).OrderBy(x => x.IsEnd).ThenByDescending(x => x.CreateTime).Select(x => x.Id).FirstOrDefault();
                var days = 7;//显示最近N天的数据
                var xAxisData = Enumerable.Range(0, days).Select(x => DateTime.Today.AddDays(-x)).OrderBy(x => x).ToList();
                var bootFalgTicks = context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.BootFlag.ToString()).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks);
                var vm = new Board1VM
                {
                    NowDayCountLeft = new NowDayCountLeft
                    {
                        WorkTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WorkFlag.ToString() && x.CreateTime >= DateTime.Today).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),

                        ArcingTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WeldFlag.ToString() && x.CreateTime >= DateTime.Today).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),

                        FinishCount = context.WorkpieceProductions.Where(x => x.EquipmentCode == robotEquipment.Code && x.CreateTime >= DateTime.Today && x.IsEnd).Count(),

                        PowerTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.BootFlag.ToString() && x.CreateTime >= DateTime.Today).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2)
                    },
                    EqCenter = new EquipmentStatusVM
                    {
                        EqCode = robotEquipment.Code,
                        EqName = robotEquipment.Name,
                        EqState = equipmentState,
                        Station = station switch
                        {
                            1 => "工位1",
                            2 => "工位2",
                            _ => "无数据",
                        },
                        WeldType = weldType ? "焊接" : "模拟",
                        ArcVoltageTracking = arcVoltageTracking ? "开启" : "关闭",
                        Eqmode = work_Mode switch
                        {
                            1 => "T1模式",
                            2 => "T2模式",
                            3 => "自动模式",
                            4 => "外部自动模式",
                            _ => "无数据"
                        },
                        MonthDaoDian = context.WorkpieceProductions.Where(x => x.EquipmentCode == robotEquipment.Code && x.CreateTime >= monthStartTime && x.IsEnd).Count(),

                        MonthWeld = Math.Round(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.Weld_Speed.ToString() && x.CreateTime >= monthStartTime).Select(x => x.Value).AsEnumerable().Sum(Convert.ToSingle), 2),
                    },
                    MonthCountRight = new MonthCountRight
                    {
                        WorkTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WorkFlag.ToString() && x.CreateTime >= monthStartTime).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),

                        ArcingTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WeldFlag.ToString() && x.CreateTime >= monthStartTime).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),

                        PowerTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.BootFlag.ToString() && x.CreateTime >= monthStartTime).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),

                        AlarmTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.Alarm.ToString() && x.CreateTime >= monthStartTime).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),
                    },

                    EqInfoLeft = new EquipmentInfoLeftVM
                    {
                        ClearSpearState = wireFeeder switch
                        {
                            1 => "1#",
                            2 => "2#",
                            _ => "无数据"
                        },
                        ArcingState = weldFlag,
                        //NowProject = type == 0 ? "无" : $"程序{type}",
                        ProjectRow = program_no,
                        X = Math.Round(pos_X, 1),
                        Y = Math.Round(pos_Y, 1),
                        Z = Math.Round(pos_Z, 1),
                        A = Math.Round(pos_A, 1),
                        B = Math.Round(pos_B, 1),
                        C = Math.Round(pos_C, 1),
                        E1 = Math.Round(pos_E1, 1),
                        E2 = Math.Round(pos_E2, 1),
                        E3 = Math.Round(pos_E3, 1),
                        E4 = Math.Round(pos_E4, 1),
                        SsSpeed = Math.Round(weld_Speed, 1),
                        Current = Math.Round(weld_I, 1),
                        Voltage = GetVoltageVal(weld_I, weld_V, robotEquipment),
                    },
                    EqInfoRight = new EquipmentInfoRight
                    {
                        EfficiencyList = new Efficiency
                        {
                            Arcing = xAxisData.Select(x => Convert.ToInt32(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(r => r.EquipmentCode == robotEquipment.Code && r.EquipmentPropertyCode == RobotProps.WeldFlag.ToString() && r.CreateTime.Date == x).Sum(r => r.UpdateTime.Ticks - r.CreateTime.Ticks)).TotalMinutes)).ToList(),

                            PowerOn = xAxisData.Select(x => Convert.ToInt32(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(r => r.EquipmentCode == robotEquipment.Code && r.EquipmentPropertyCode == RobotProps.BootFlag.ToString() && r.CreateTime.Date == x).Sum(r => r.UpdateTime.Ticks - r.CreateTime.Ticks)).TotalMinutes)).ToList(),

                            Work = xAxisData.Select(x => Convert.ToInt32(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(r => r.EquipmentCode == robotEquipment.Code && r.EquipmentPropertyCode == RobotProps.Work_Time.ToString() && r.CreateTime.Date == x).Sum(r => r.UpdateTime.Ticks - r.CreateTime.Ticks)).TotalMinutes)).ToList(),
                            XAxisData = xAxisData.Select(x => x.ToString("M")).ToList(),
                        },
                        WeldFlagData = xAxisData.Select(dateTime => new BoardChart
                        {
                            Name = dateTime.ToString("M"),
                            Value = GetWeldFlagRate(context, robotEquipment, dateTime),
                            WorkTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WorkFlag.ToString() && x.CreateTime.Date == dateTime.Date).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),
                            ArcingTime = Math.Round(TimeSpan.FromTicks(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WeldFlag.ToString() && x.CreateTime.Date == dateTime.Date).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks)).TotalHours, 2),
                        }).ToList(),
                        ProductInfo = type ?? "无数据",
                        ProductState = productStateName,
                        TimeSum = timeSum,
                        YieldList = new YieldListVM
                        {
                            XAxisData = xAxisData.Select(x => x.ToString("M")).ToList(),
                            Yield = xAxisData.Select(x => context.WorkpieceProductions.Where(w => w.EquipmentCode == robotEquipment.Code && w.CreateTime.Date == x.Date && w.IsEnd).Count()).ToList(),
                        }
                    },

                    CurrentList = context.WeldProcessRecords.Where(x => x.ProductionId == lastProductionId && x.Code == RobotProps.Weld_I.ToString()).OrderBy(x => x.CreateTime).Select(x => x.Value).AsEnumerable().Select(x =>
                    {
                        _ = double.TryParse(x, out var val);
                        return Math.Round(val, 1);
                    }).ToList(),
                    EqEfficiencyCenter = new EquipmentEfficiency
                    {
                        AlarmRate = GetAlarmRate(context, robotEquipment),
                        AutoRate = GetAutoRate(context, robotEquipment),
                        OnLineRate = GetOnLineRate(context, robotEquipment),
                        UtilizeRate = UtilizeRate(context, robotEquipment),
                    },
                    VoltagetList = context.WeldProcessRecords.Where(x => x.ProductionId == lastProductionId && x.Code == RobotProps.Weld_V.ToString()).OrderBy(x => x.CreateTime).Select(x => x.Value).AsEnumerable().Select(x =>
                    {
                        _ = double.TryParse(x, out var val);
                        return Math.Round(val, 1);
                    }).ToList(),
                };

                //获取电压值
                double GetVoltageVal(float weld_I, float weld_V, Equipment robot)
                {
                    //Kuka C2设备数值有误差,电流值为0时,电压应显示0
                    //var codes = new List<EquipmentConst>
                    //{
                    //    EquipmentConst.KukaC2_1,
                    //    EquipmentConst.KukaC2_2,
                    //}.Select(x => x.ToString()).ToList();
                    //if (codes.Contains(robot.Code) && weld_I <= 0)
                    //{
                    //    return 0;
                    //}
                    return Math.Round(weld_V, 1);
                }

                //故障率
                int GetAlarmRate(DataContext context, Equipment robotEquipment)
                {
                    if (bootFalgTicks == 0) return 0;
                    return Convert.ToInt32(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.Alarm.ToString()).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks) * 100 / bootFalgTicks);
                }

                int UtilizeRate(DataContext context, Equipment robotEquipment)
                {
                    if (bootFalgTicks == 0) return 0;
                    return Convert.ToInt32(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WorkFlag.ToString()).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks) * 100 / bootFalgTicks);
                }

                int GetAutoRate(DataContext context, Equipment robotEquipment)
                {
                    if (bootFalgTicks == 0) return 0;
                    return Convert.ToInt32(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.WeldFlag.ToString()).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks) * 100 / bootFalgTicks);
                }

                //在线率
                int GetOnLineRate(DataContext context, Equipment robotEquipment)
                {
                    var bootFlagStartDay = context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.BootFlag.ToString()).OrderBy(x => x.CreateTime).Select(x => x.CreateTime).FirstOrDefault();
                    if (bootFlagStartDay == default) return 0;
                    if (bootFlagStartDay <= DateTime.Today.AddMonths(-1))
                    {
                        bootFlagStartDay = DateTime.Today.AddMonths(-1);
                    }
                    return Convert.ToInt32(context.EquipmentPropertyRecords.Where(x => x.EquipmentCode == robotEquipment.Code && x.EquipmentPropertyCode == RobotProps.BootFlag.ToString()).Sum(x => x.UpdateTime.Ticks - x.CreateTime.Ticks) * 100 / (DateTime.Now - bootFlagStartDay).Ticks);
                }

                result.Data = new
                {
                    Head = new
                    {
                        vm.NowDayCountLeft,
                        vm.EqCenter,
                        vm.MonthCountRight,
                    },
                    Center = new
                    {
                        vm.EqInfoLeft,
                        vm.EqInfoRight,
                    },
                    Footer = new
                    {
                        vm.CurrentList,
                        vm.EqEfficiencyCenter,
                        vm.VoltagetList,
                    }
                };
                _memoryCache.Set(key, result, _absoluteExpirationRelativeToNow);
            }
            catch (Exception ex)
            {
                result.Code = 500;
                result.Message = ex.Message;
            }
            return result;
        }

        //燃弧率
        private static int GetWeldFlagRate(DataContext context, Equipment robotEquipment, DateTime date)
        {
            var runTicks = context.EquipmentPropertyRecords.Where(p => p.EquipmentCode == robotEquipment.Code && p.EquipmentPropertyCode == RobotProps.BootFlag.ToString() && p.CreateTime.Date == date).Sum(s => s.UpdateTime.Ticks - s.CreateTime.Ticks);
            if (runTicks == 0) return 0;
            var weldTicks = context.EquipmentPropertyRecords.Where(p => p.EquipmentCode == robotEquipment.Code && p.EquipmentPropertyCode == RobotProps.WeldFlag.ToString() && p.CreateTime.Date == date).Sum(s => s.UpdateTime.Ticks - s.CreateTime.Ticks);
            return Convert.ToInt32(weldTicks * 100 / runTicks);
        }
    }
}