Esempio n. 1
0
 /// <summary>
 /// 发送小车任务,行:1.打标  2.坡口短缓存架  3.坡口长缓存架 4.坡口短缓存架  5.坡口机   6.组队输送架
 /// </summary>
 /// <param name="car"></param>
 /// <param name="plc"></param>
 /// <param name="task"></param>
 /// <returns></returns>
 public BllResult SendTaskToCar(Equipment car, CarTask task, IPLC plc)
 {
     try
     {
         List <EquipmentProp> propsToWriter = new List <EquipmentProp>();
         var props = car.EquipmentProps;
         var wcsConfirmTaskFinish = props.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsConfirmTaskFinish.ToString());
         wcsConfirmTaskFinish.Value = "0";
         var wcsActionType = props.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsActionType.ToString());
         wcsActionType.Value = task.Type.ToString();
         var wcsStartRow = props.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsStartRow.ToString());
         wcsStartRow.Value = task.FromLocation.ToString();
         var wcsDestinationRow = props.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsDestinationRow.ToString());
         wcsDestinationRow.Value = task.ToLocation.ToString();
         var wcsTaskHeaderId = props.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsTaskHeaderId.ToString());
         wcsTaskHeaderId.Value = task.StepTraceId.ToString();
         var wcsTaskCarId = props.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsTaskCarId.ToString());
         wcsTaskCarId.Value = task.Id.ToString();
         var wcsSwitch = props.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsSwitch.ToString());
         wcsSwitch.Value = "1";
         propsToWriter.AddRange(new List <EquipmentProp>()
         {
             wcsConfirmTaskFinish, wcsStartRow, wcsDestinationRow, wcsTaskHeaderId, wcsTaskCarId, wcsActionType, wcsSwitch
         });
         //return S7Helper.PlcSplitWrite(plc, propsToWriter, 20);
         return(plc.Writes(propsToWriter));
     }
     catch (Exception ex)
     {
         return(BllResultFactory.Error(ex.Message));
     }
 }
        /// <summary>
        /// 中船项目发送定长切割处理
        /// </summary>
        /// <param name="machine">切割机</param>
        /// <param name="plc">目标plc</param>
        /// <param name="WCSCutMaterialID">原材料ID</param>
        /// <param name="WCSCutMaterialLength">原材料长度</param>
        /// <param name="WCSCutDiameter">原材料直径</param>
        /// <param name="WCSCutThickness">原材料壁厚</param>
        /// <param name="WCSCutLength">切断长</param>
        /// <param name="WCSCutPipeEnd">管端</param>
        /// <param name="WCSCutAssemblyStation">下料工位</param>
        /// <returns></returns>
        protected BllResult SendCutToPlcZC(Equipment machine, IPLC plc, int i, int WCSCutMaterialID, int WCSCutMaterialLength, int WCSCutDiameter, int WCSCutThickness, int WCSCutLength, int WCSCutPipeEnd, int WCSCutAssemblyStation)
        {
            List <EquipmentProp> props = null;
            var prop1 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSCutMaterialID_" + i.ToString());

            prop1.Value = WCSCutMaterialID.ToString();
            var prop2 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSCutMaterialLength_" + i.ToString());

            prop2.Value = WCSCutMaterialLength.ToString();
            var prop3 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSCutDiameter_" + i.ToString());

            prop3.Value = (WCSCutDiameter * 10).ToString();
            var prop4 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSCutThickness_" + i.ToString());

            prop4.Value = (WCSCutThickness * 10).ToString();
            var prop5 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSCutLength_" + i.ToString());

            prop5.Value = WCSCutLength.ToString();
            var prop6 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSCutPipeEnd_" + i.ToString());

            prop6.Value = WCSCutPipeEnd.ToString();
            var prop7 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSCutAssemblyStation_" + i.ToString());

            prop7.Value = WCSCutAssemblyStation.ToString();

            props = new List <EquipmentProp> {
                prop1, prop2, prop3, prop4, prop5, prop6, prop7
            };
            BllResult plcResult = plc.Writes(props);

            return(plcResult);
        }
Esempio n. 3
0
 /// <summary>
 /// 发送穿梭车的信息
 /// </summary>
 /// <param name="car">穿梭车</param>
 /// <param name="plc">plc</param>
 /// <param name="carActionType">小车执行的动作类型</param>
 /// <param name="carRow">行</param>
 /// <param name="carColumn">列</param>
 /// <param name="carLayer">层</param>
 /// <param name="taskHeaderId">任务-关联WCS的TaskHeader表格</param>
 /// <param name="taskCarId">子任务</param>
 /// <returns></returns>
 public BllResult SendTaskToCar(Equipment car, IPLC plc, CarActionType carActionType, string carRow, string carColumn, string carLayer, string taskHeaderId, string taskCarId)
 {
     try
     {
         List <EquipmentProp> propsToWriter = new List <EquipmentProp>();
         var props  = car.EquipmentProps;
         var action = props.Find(t => t.EquipmentTypeTemplateCode == "wcsActionType");
         action.Value = carActionType.GetIndexString();
         var taskRow = props.Find(t => t.EquipmentTypeTemplateCode == "wcsRow");
         taskRow.Value = carRow;
         var taskLine = props.Find(t => t.EquipmentTypeTemplateCode == "wcsLine");
         taskLine.Value = carColumn;
         var taskLayer = props.Find(t => t.EquipmentTypeTemplateCode == "wcsLayer");
         taskLayer.Value = carLayer;
         var taskHeader = props.Find(t => t.EquipmentTypeTemplateCode == "wcsTaskHeaderId");
         taskHeader.Value = taskHeaderId;
         var taskCar = props.Find(t => t.EquipmentTypeTemplateCode == "wcsTaskCarId");
         taskCar.Value = taskCarId;
         var switchEnable = props.Find(t => t.EquipmentTypeTemplateCode == "wcsSwitch");
         switchEnable.Value = "1";
         propsToWriter.AddRange(new List <EquipmentProp>()
         {
             action, taskHeader, taskCar, taskRow, taskLine, taskLayer, switchEnable
         });
         //return S7Helper.PlcSplitWrite(plc, propsToWriter, 20);
         return(plc.Writes(propsToWriter));
     }
     catch (Exception ex)
     {
         return(BllResultFactory.Error(ex.Message));
     }
 }
Esempio n. 4
0
        /// <summary>
        /// 心跳
        /// </summary>
        /// <param name="srm"></param>
        /// <param name="plc"></param>
        public BllResult Heartbeat(Equipment srm, IPLC plc)
        {
            var prop = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSHeartBeat.ToString());

            if (prop.Value == "1")
            {
                prop.Value = "0";
            }
            else
            {
                prop.Value = "1";
            }
            var result = plc.Writes(new List <EquipmentProp>()
            {
                prop
            });

            if (result.Success)
            {
                return(BllResultFactory.Sucess());
            }
            else
            {
                Logger.Log($"发送桁车{srm.Name}心跳数据失败:{result.Msg}", LogLevel.Error);
                return(BllResultFactory.Error());
            }
        }
Esempio n. 5
0
        /// <summary>
        /// 写入或清除 ECS允许上料信号,True为写入,False为清除
        /// </summary>
        /// <param name="plc"></param>
        /// <param name="robot"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        protected BllResult SendLoadReadyToPlc(bool load_Ready, Equipment robot, IPLC plc, int pipeMaterial, int pipeLength, decimal pipeDiameter, decimal pipeThickness)
        {
            var operate       = load_Ready ? "写入" : "清除";
            var status        = load_Ready ? MachineMessageFlag.WCS回复允许上料.GetIndexString() : MachineMessageFlag.默认.GetIndexString();
            var WCSACKMessage = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMessage.ToString());

            var WCS_Pipe_Material  = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMaterial.ToString());
            var WCS_Pipe_Length    = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKLength.ToString());
            var WCS_Pipe_Diameter  = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKDiameter.ToString());
            var WCS_Pipe_Thickness = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKThickness.ToString());

            WCS_Pipe_Material.Value  = pipeMaterial.ToString();
            WCS_Pipe_Length.Value    = pipeLength.ToString();
            WCS_Pipe_Diameter.Value  = pipeDiameter.ToString();
            WCS_Pipe_Thickness.Value = pipeThickness.ToString();
            WCSACKMessage.Value      = status.ToString();
            var propsToWriter = new List <EquipmentProp> {
                WCSACKMessage, WCS_Pipe_Material, WCS_Pipe_Length, WCS_Pipe_Diameter, WCS_Pipe_Thickness
            };

            BllResult plcResult = plc.Writes(propsToWriter);

            if (plcResult.Success)
            {
                Logger.Log($"{operate}设备【{robot.Name}】上料准备完成 信号成功", LogLevel.Success);
            }
            else
            {
                Logger.Log($"{operate}设备【{robot.Name}】上料准备完成 信号失败,写入PLC失败:原因:{plcResult.Msg}", LogLevel.Error);
            }
            return(plcResult);
        }
Esempio n. 6
0
 /// <summary>
 /// 下发数据到桁车
 /// </summary>
 /// <param name="truss"></param>
 /// <param name="plc"></param>
 /// <param name="taskFlag"></param>
 /// <param name="productId"></param>
 /// <param name="position"></param>
 /// <param name="taskNo"></param>
 /// <returns></returns>
 public BllResult SendTaskToTruss(Equipment truss, IPLC plc, TrussTaskFlag taskFlag, string productId, string stationId, string wcsLine, string wcsLayer, string taskNo)
 {
     try
     {
         List <EquipmentProp> propsToWriter = new List <EquipmentProp>();
         var props        = truss.EquipmentProps;
         var WCSProductId = props.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSProductId.ToString());
         WCSProductId.Value = productId;
         var WCSStationId = props.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSStationId.ToString());
         WCSStationId.Value = stationId;
         var WCSLine = props.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSLine.ToString());
         WCSLine.Value = wcsLine;
         var WCSLayer = props.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSLayer.ToString());
         WCSLayer.Value = wcsLayer;
         var WCSTaskNo = props.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSTaskNo.ToString());
         WCSTaskNo.Value = taskNo;
         var WCSForkAction = props.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSForkAction.ToString());
         WCSForkAction.Value = TrussForkAction.一号机械手.GetIndexString();
         var WCSTaskFlag = props.Find(t => t.EquipmentTypeTemplateCode == TrussNormalProps.WCSTaskFlag.ToString());
         WCSTaskFlag.Value = taskFlag.GetIndexString();
         propsToWriter.AddRange(new List <EquipmentProp>()
         {
             WCSProductId, WCSStationId, WCSLine, WCSLayer, WCSTaskNo, WCSForkAction, WCSTaskFlag
         });
         return(plc.Writes(propsToWriter));
     }
     catch (Exception ex)
     {
         return(BllResultFactory.Error($"写入plc失败,下发任务出现异常:{ex.Message}"));
     }
 }
Esempio n. 7
0
 /// <summary>
 /// 下发数据到WCS交换区
 /// </summary>
 /// <param name="stocker"></param>
 /// <param name="plc"></param>
 /// <param name="forkAction"></param>
 /// <param name="forkTaskFlag"></param>
 /// <param name="forkRow"></param>
 /// <param name="forkColumn"></param>
 /// <param name="forkLayer"></param>
 /// <param name="forkStation"></param>
 /// <param name="taskNo"></param>
 /// <returns></returns>
 public BllResult SendTaskToStocker(Equipment stocker, IPLC plc, SRMForkAction forkAction, SRMForkTaskFlag forkTaskFlag, string forkRow, string forkColumn, string forkLayer, string forkStation, string taskNo)
 {
     try
     {
         List <EquipmentProp> propsToWriter = new List <EquipmentProp>();
         var props  = stocker.EquipmentProps;
         var action = props.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSForkAction.ToString());
         action.Value = forkAction.GetIndexString();
         var taskFlag = props.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
         taskFlag.Value = forkTaskFlag.GetIndexString();
         var row = props.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1Row.ToString());
         row.Value = forkRow;
         var column = props.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1Column.ToString());
         column.Value = forkColumn;
         var layer = props.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1Layer.ToString());
         layer.Value = forkLayer;
         var station = props.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1Station.ToString());
         station.Value = forkStation;
         var task = props.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1Task.ToString());
         task.Value = taskNo;
         propsToWriter.AddRange(new List <EquipmentProp>()
         {
             action, taskFlag, row, column, layer, station, task
         });
         return(plc.Writes(propsToWriter));
     }
     catch (Exception ex)
     {
         return(BllResultFactory.Error($"下发任务出现异常:{ex.Message}"));
     }
 }
Esempio n. 8
0
 public BllResult SendCleanTaskToCar(Equipment car, CarTask task, IPLC plc)
 {
     try
     {
         List <EquipmentProp> propsToWriter = new List <EquipmentProp>();
         var props  = car.EquipmentProps;
         var action = props.Find(t => t.EquipmentTypeTemplateCode == "wcsActionType");
         action.Value = "0";
         var taskRow = props.Find(t => t.EquipmentTypeTemplateCode == "wcsTaskRow");
         taskRow.Value = "0";
         //var taskLine = props.Find(t => t.EquipmentTypeTemplateCode == "wcsTaskLine");
         //taskLine.Value = "0";
         //var taskLayer = props.Find(t => t.EquipmentTypeTemplateCode == "wcsTaskLayer");
         //taskLayer.Value = "0";
         var taskHeader = props.Find(t => t.EquipmentTypeTemplateCode == "wcsTaskHeaderId");
         taskHeader.Value = "0";
         var taskCar = props.Find(t => t.EquipmentTypeTemplateCode == "wcsTaskCarId");
         taskCar.Value = "0";
         var switchEnable = props.Find(t => t.EquipmentTypeTemplateCode == "wcsSwitch");
         switchEnable.Value = "0";
         var hasPallet = props.Find(t => t.EquipmentTypeTemplateCode == "hasPallet");
         hasPallet.Value = "1";
         propsToWriter.AddRange(new List <EquipmentProp>()
         {
             action, taskRow, taskHeader, taskCar, switchEnable, hasPallet
         });
         //return S7Helper.PlcSplitWrite(plc, propsToWriter, 20);
         return(plc.Writes(propsToWriter));
     }
     catch (Exception ex)
     {
         return(BllResultFactory.Error(ex.Message));
     }
 }
        /// <summary>
        /// 写入或清除 任务信息
        /// 到达处理
        /// </summary>
        /// <param name="plc"></param>
        /// <param name="cutter"></param>
        /// <param name="product">是否生产,true为生产,false为清除</param>
        /// <param name="result"></param>
        /// <returns></returns>
        protected BllResult SendStepTraceToPlc(IPLC plc, Equipment cutter, bool allow, string wcsStepTraceId, int pipeMaterial, int pipeLength, int pipeDiameter, int pipeThickness)
        {
            var operate            = allow ? "写入" : "清除";
            var status             = allow ? StationMessageFlag.地址回复.GetIndexString() : StationMessageFlag.默认.GetIndexString();
            var WCSReplyMessage    = cutter.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSReplyMessage.ToString());
            var WCS_Allow_Load     = cutter.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMessage.ToString());
            var WCSACKTaskId       = cutter.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKTaskId.ToString());
            var WCS_Pipe_Material  = cutter.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMaterial.ToString());
            var WCS_Pipe_Length    = cutter.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKLength.ToString());
            var WCS_Pipe_Diameter  = cutter.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKDiameter.ToString());
            var WCS_Pipe_Thickness = cutter.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKThickness.ToString());

            WCS_Pipe_Material.Value  = pipeMaterial.ToString();
            WCS_Pipe_Length.Value    = pipeLength.ToString();
            WCS_Pipe_Diameter.Value  = pipeDiameter.ToString();
            WCS_Pipe_Thickness.Value = pipeThickness.ToString();

            WCSReplyMessage.Value = status.ToString();
            WCSACKTaskId.Value    = wcsStepTraceId;
            var propsToWriter = new List <EquipmentProp> {
                WCS_Allow_Load, WCSACKTaskId, WCS_Pipe_Material, WCS_Pipe_Length, WCS_Pipe_Diameter, WCS_Pipe_Thickness
            };

            return(plc.Writes(propsToWriter));
        }
Esempio n. 10
0
        /// <summary>
        /// 位置到达回复
        /// </summary>
        /// <param name="machine"></param>
        /// <param name="plc"></param>
        /// <param name="message"></param>
        /// <param name="loadStatus"></param>
        /// <param name="number"></param>
        /// <param name="backup"></param>
        /// <returns></returns>
        public BllResult SendAckToPlc(Equipment machine, IPLC plc, MachineMessageFlag messageFlag, string number, string taskId, string barcode, string requestProductId, string pipeMaterial, string pipeLength, string pipeDiameter, string pipeThickness, string address)
        {
            pipeDiameter  = (Convert.ToInt32(decimal.Parse(pipeDiameter) * 10)).ToString();
            pipeThickness = (Convert.ToInt32(decimal.Parse(pipeThickness) * 10)).ToString();

            List <EquipmentProp> props = null;
            var prop1 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMessage.ToString());

            prop1.Value = messageFlag.GetIndexString();
            var prop2 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKNumber.ToString());

            prop2.Value = number;
            var prop3 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKTaskId.ToString());

            prop3.Value = taskId;
            var prop4 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKBarcode.ToString());

            prop4.Value = barcode;
            var prop5 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKProductId.ToString());

            prop5.Value = requestProductId;
            var prop6 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMaterial.ToString());

            prop6.Value = pipeMaterial;
            var prop7 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKLength.ToString());

            prop7.Value = pipeLength;
            var prop8 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKDiameter.ToString());

            prop8.Value = pipeDiameter;
            var prop9 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKThickness.ToString());

            prop9.Value = pipeThickness;
            var prop10 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSReplyAddress.ToString());

            prop10.Value = address;
            if (messageFlag == MachineMessageFlag.默认)
            {
                props = new List <EquipmentProp>()
                {
                    prop1, prop2, prop3, prop4, prop5, prop6, prop7, prop8, prop9, prop10
                };
            }
            else
            {
                props = new List <EquipmentProp>()
                {
                    prop2, prop3, prop4, prop5, prop6, prop7, prop8, prop9, prop10, prop1
                };
            }
            return(plc.Writes(props));
        }
Esempio n. 11
0
        /// <summary>
        /// 写入或清除 任务信息
        /// </summary>
        /// <param name="plc"></param>
        /// <param name="robot"></param>
        /// <param name="product">是否生产,true为生产,false为清除</param>
        /// <param name="result"></param>
        /// <returns></returns>
        protected BllResult SendStepTraceToPlc(IPLC plc, Equipment machineTool, bool wcsAllowLoad, string wcsStepTraceId)
        {
            var WCS_Allow_Load    = machineTool.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == EcsToMachineToolPorps.WCS_Allow_Load.ToString());
            var WCS_Step_Trace_Id = machineTool.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == EcsToMachineToolPorps.WCS_Step_Trace_Id.ToString());

            WCS_Allow_Load.Value    = wcsAllowLoad.ToString();
            WCS_Step_Trace_Id.Value = wcsStepTraceId;
            var propsToWriter = new List <EquipmentProp> {
                WCS_Allow_Load, WCS_Step_Trace_Id
            };

            return(plc.Writes(propsToWriter));
        }
Esempio n. 12
0
        /// <summary>
        /// 地址请求回复
        /// </summary>
        /// <param name="pipeLine"></param>
        /// <param name="plc"></param>
        /// <param name="message"></param>
        /// <param name="loadStatus"></param>
        /// <param name="number"></param>
        /// <param name="barcode"></param>
        /// <param name="weight"></param>
        /// <param name="lenght"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="address"></param>
        /// <param name="backup"></param>
        /// <returns></returns>
        public BllResult SendAddressReplyToPlc(Equipment pipeLine, IPLC plc, StationMessageFlag messageFlag, StationLoadStatus loadStatus, string number, string taskId, string barcode, string pipeMaterial, string pipeLength, string pipeDiameter, string pipeThickness, string address)
        {
            pipeDiameter  = (Convert.ToInt32(decimal.Parse(pipeDiameter) * 10)).ToString();
            pipeThickness = (Convert.ToInt32(decimal.Parse(pipeThickness) * 10)).ToString();

            List <EquipmentProp> props = null;
            var prop1 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyMessage.ToString());

            prop1.Value = messageFlag.GetIndexString();
            var prop2 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyLoadStatus.ToString());

            prop2.Value = loadStatus.GetIndexString();
            var prop3 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyNumber.ToString());

            prop3.Value = number;
            var prop4 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyTaskId.ToString());

            prop4.Value = taskId;
            var prop5 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyBarcode.ToString());

            prop5.Value = barcode;
            var prop6 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyMaterial.ToString());

            prop6.Value = pipeMaterial;
            var prop7 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyLength.ToString());

            prop7.Value = pipeLength;
            var prop8 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyDiameter.ToString());

            prop8.Value = pipeDiameter;
            var prop9 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyThickness.ToString());

            prop9.Value = pipeThickness;
            var prop10 = pipeLine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PipeLineProps.WCSReplyAddress.ToString());

            prop10.Value = address;
            if (messageFlag == StationMessageFlag.默认)
            {
                props = new List <EquipmentProp> {
                    prop1, prop2, prop3, prop4, prop5, prop6, prop7, prop8, prop9, prop10
                };
            }
            else
            {
                props = new List <EquipmentProp> {
                    prop2, prop3, prop4, prop5, prop6, prop7, prop8, prop9, prop10, prop1
                };
            }
            return(plc.Writes(props));
        }
Esempio n. 13
0
 /// <summary>
 /// 高速堆垛机的下发给PLC的调用函数
 /// 由于只有一个叉,动作类型暂时保留固定写单叉动作。
 /// </summary>
 /// <param name="stocker">堆垛机编码</param>
 /// <param name="plc">对应写入PLC的OPC连接</param>
 /// <param name="taskMode">任务模型</param>
 /// <param name="forkTaskFlag">取货任务的任务类型</param>
 /// <param name="forkRow">取货的行(2,1,3,4)</param>
 /// <param name="forkColumn">取货的列</param>
 /// <param name="forkLayer">取货的层</param>
 /// <param name="forkStation">取货的站台</param>
 /// <param name="forkTaskFlag2">放货的任务类型</param>
 /// <param name="forkRow2">放货的行(2,1,3,4)</param>
 /// <param name="forkColumn2">放货的列</param>
 /// <param name="forkLayer2">放货的层</param>
 /// <param name="forkStation2">放货的站台</param>
 /// <param name="taskNo">任务号</param>
 /// <param name="taskAccount">任务过账 </param>
 /// <returns></returns>
 public BllResult SendTaskToStocker(Equipment stocker, IPLC plc, SuperSRMTaskMode taskMode,
                                    SRMForkTaskFlag forkTaskFlag, string forkRow, string forkColumn, string forkLayer, string forkStation,
                                    SRMForkTaskFlag forkTaskFlag2, string forkRow2, string forkColumn2, string forkLayer2, string forkStation2,
                                    string taskNo, TaskAccount taskAccount)
 {
     try
     {
         List <EquipmentProp> propsToWriter = new List <EquipmentProp>();
         var props  = stocker.EquipmentProps;
         var action = props.Find(t => t.EquipmentTypeTemplateCode == "WCSForkTaskMode");
         action.Value = taskMode.GetIndexString();
         var taskFlag = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1TaskFlag");
         taskFlag.Value = forkTaskFlag.GetIndexString();
         var row = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Row");
         row.Value = forkRow;
         var column = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Column");
         column.Value = forkColumn;
         var layer = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Layer");
         layer.Value = forkLayer;
         var station = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Station");
         station.Value = forkStation;
         var taskFlag2 = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1TaskFlag2");
         taskFlag2.Value = forkTaskFlag2.GetIndexString();
         var row2 = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Row2");
         row2.Value = forkRow2;
         var column2 = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Column2");
         column2.Value = forkColumn2;
         var layer2 = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Layer2");
         layer2.Value = forkLayer2;
         var station2 = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Station2");
         station2.Value = forkStation2;
         var task = props.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1Task");
         task.Value = taskNo;
         var account = props.Find(t => t.EquipmentTypeTemplateCode == "WCSTaskAccount");
         account.Value = taskAccount.GetIndexString();
         propsToWriter.AddRange(new List <EquipmentProp>()
         {
             action, taskFlag, row, column, layer, station, taskFlag2, row2, column2, layer2, station2, task, account
         });
         return(plc.Writes(propsToWriter));
     }
     catch (Exception ex)
     {
         Logger.Log($"PLC写入信息错误:" + ex.Message, LogLevel.Exception);
         return(BllResultFactory.Error($"下发任务出现异常:{ex.Message}"));
     }
 }
Esempio n. 14
0
        /// <summary>
        /// 写入或清除  任务信息
        /// </summary>
        /// <param name="robot"></param>
        /// <param name="plc"></param>
        /// <param name="stepTraceId"></param>
        /// <param name="type"></param>
        /// <param name="number"></param>
        /// <returns></returns>
        protected BllResult SendStepTraceToPlc(string stepTraceId, string type, string number, bool wcsAllowLoad, Equipment robot, IPLC plc)
        {
            var Step_Trace_Id = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PcRobotStation.Step_Trace_Id.ToString());

            Step_Trace_Id.Value = stepTraceId;
            var TYPE = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PcRobotStation.TYPE.ToString());

            TYPE.Value = type;
            var Number = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PcRobotStation.Number.ToString());

            Number.Value = number;
            var WCS_Allow_Load = robot.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == PcRobotStation.WCS_Allow_Load.ToString());

            WCS_Allow_Load.Value = wcsAllowLoad.ToString();
            var propsToWriter = new List <EquipmentProp> {
                Step_Trace_Id, TYPE, Number, WCS_Allow_Load
            };

            return(plc.Writes(propsToWriter));
        }
Esempio n. 15
0
        public BllResult SendAckToPlcForInOrOut(Equipment station, IPLC plc, StationMessageFlag messageFlag, StationLoadStatus loadStatus, string number, string backup)
        {
            var prop1 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSACKMessage.ToString());

            prop1.Value = messageFlag.GetIndexString();
            var prop2 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSACKLoadStatus.ToString());

            prop2.Value = loadStatus.GetIndexString();
            var prop3 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSACKNumber.ToString());

            prop3.Value = number;
            //var prop4 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSACKBackup.ToString());
            //prop4.Value = backup;
            List <EquipmentProp> props = new List <EquipmentProp>()
            {
                prop2, prop3, prop1
            };

            return(plc.Writes(props));
        }
Esempio n. 16
0
        /// <summary>
        /// 切割请求处理
        /// </summary>
        /// <param name="machine">切割机</param>
        /// <param name="cutFlag">是否允许切割</param>
        /// <param name="wcsCutTaskId">管段任务号</param>
        /// <param name="wcsCutMaterial">管段材料</param>
        /// <param name="wcsCutLength">管段长度</param>
        /// <param name="wcsCutDiameter">管段直径</param>
        /// <param name="wcsCutThickness">管段壁厚</param>
        /// <param name="plc"></param>
        /// <returns></returns>
        protected BllResult SendCutToPlc(Equipment machine, IPLC plc, CutFlag cutFlag, string wcsCutTaskId, string wcsCutMaterial, string wcsCutLength, string wcsCutDiameter, string wcsCutThickness)
        {
            wcsCutDiameter  = (Convert.ToInt32(decimal.Parse(wcsCutDiameter) * 10)).ToString();
            wcsCutThickness = (Convert.ToInt32(decimal.Parse(wcsCutThickness) * 10)).ToString();

            List <EquipmentProp> props = null;
            var prop1 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSAllowCut.ToString());

            prop1.Value = cutFlag.GetIndexString();
            var prop2 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSCutTaskId.ToString());

            prop2.Value = wcsCutTaskId;
            var prop3 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSCutMaterial.ToString());

            prop3.Value = wcsCutMaterial;
            var prop4 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSCutLength.ToString());

            prop4.Value = wcsCutLength;
            var prop5 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSCutDiameter.ToString());

            prop5.Value = wcsCutDiameter;
            var prop6 = machine.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSCutThickness.ToString());

            prop6.Value = wcsCutThickness;

            if (cutFlag == CutFlag.默认)
            {
                props = new List <EquipmentProp> {
                    prop1, prop2, prop3, prop4, prop5, prop6
                };
            }
            else
            {
                props = new List <EquipmentProp> {
                    prop2, prop3, prop4, prop5, prop6, prop1
                };
            }
            BllResult plcResult = plc.Writes(props);

            return(plcResult);
        }
Esempio n. 17
0
 /// <summary>
 /// 输入开启信号
 /// </summary>
 /// <param name="car"></param>
 /// <param name="plc"></param>
 public BllResult sendWcsSwitch(Equipment car, IPLC plc, string wcsSwitchValue)
 {
     try
     {
         var wcsSwitch = car.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == CarProps.wcsSwitch.ToString());
         if (wcsSwitch.Value != wcsSwitchValue)
         {
             wcsSwitch.Value = wcsSwitchValue;
             var result = plc.Writes(new List <EquipmentProp>()
             {
                 wcsSwitch
             });
             return(result);
         }
     }
     catch (Exception ex)
     {
         return(BllResultFactory.Error(ex.Message));
     }
     return(BllResultFactory.Sucess());
 }
Esempio n. 18
0
        /// <summary>
        /// 位置到达回复
        /// </summary>
        /// <param name="bevel"></param>
        /// <param name="plc"></param>
        /// <param name="message"></param>
        /// <param name="loadStatus"></param>
        /// <param name="number"></param>
        /// <param name="backup"></param>
        /// <returns></returns>
        public BllResult SendAckToPlc(Equipment bevel, IPLC plc, MachineMessageFlag messageFlag, string number, string taskId, string barcode, string requestProductId, string pipeMaterial, string pipeLength, string pipeDiameter, string pipeThickness, string address)
        {
            var prop1 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMessage.ToString());

            prop1.Value = messageFlag.GetIndexString();
            var prop2 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKNumber.ToString());

            prop2.Value = number;
            var prop3 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKTaskId.ToString());

            prop3.Value = taskId;
            var prop4 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKBarcode.ToString());

            prop4.Value = barcode;
            var prop5 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKProductId.ToString());

            prop5.Value = requestProductId;
            var prop6 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKMaterial.ToString());

            prop6.Value = pipeMaterial;
            var prop7 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKLength.ToString());

            prop7.Value = pipeLength;
            var prop8 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKDiameter.ToString());

            prop8.Value = pipeDiameter;
            var prop9 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSACKThickness.ToString());

            prop9.Value = pipeThickness;
            var prop10 = bevel.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == MachineProps.WCSReplyAddress.ToString());

            prop10.Value = address;
            List <EquipmentProp> props = new List <EquipmentProp>()
            {
                prop2, prop3, prop4, prop5, prop6, prop7, prop8, prop9, prop10, prop1
            };

            return(plc.Writes(props));
        }
Esempio n. 19
0
        /// <summary>
        /// 心跳
        /// </summary>
        /// <param name="stocker"></param>
        /// <param name="plc"></param>
        public void Heartbeat(Equipment stocker, IPLC plc)
        {
            var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSHeartBeat.ToString());

            if (prop.Value == "1")
            {
                prop.Value = "0";
            }
            else
            {
                prop.Value = "1";
            }
            var result = plc.Writes(new List <EquipmentProp>()
            {
                prop
            });

            if (!result.Success)
            {
                Logger.Log($"发送堆垛机{stocker.Name}心跳数据失败:{result.Msg}", LogLevel.Error);
            }
        }
Esempio n. 20
0
 /// <summary>
 /// 心跳
 /// </summary>
 /// <param name="car"></param>
 /// <param name="plc"></param>
 public BllResult Heartbeat(Equipment car, IPLC plc)
 {
     try
     {
         var prop = car.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSHeartBeat");
         if (prop.Value == "1")
         {
             prop.Value = "0";
         }
         else
         {
             prop.Value = "1";
         }
         return(plc.Writes(new List <EquipmentProp>()
         {
             prop
         }));
     }
     catch (Exception ex)
     {
         return(BllResultFactory.Error(ex.Message));
     }
 }
Esempio n. 21
0
        /// <summary>
        /// 实现地址回复
        /// </summary>
        /// <param name="station"></param>
        /// <param name="plc"></param>
        /// <param name="message"></param>
        /// <param name="loadStatus"></param>
        /// <param name="number"></param>
        /// <param name="barcode"></param>
        /// <param name="weight"></param>
        /// <param name="lenght"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="address"></param>
        /// <param name="backup"></param>
        /// <returns></returns>
        public BllResult SendAddressReplyToPlc(Equipment station, IPLC plc, StationMessageFlag messageFlag, StationLoadStatus loadStatus, string number, string barcode, string weight, string lenght, string width, string height, string address, string backup)
        {
            var prop1 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyMessage.ToString());

            prop1.Value = messageFlag.GetIndexString();
            var prop2 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyLoadStatus.ToString());

            prop2.Value = loadStatus.GetIndexString();
            var prop3 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyNumber.ToString());

            prop3.Value = number;
            var prop4 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyBarcode.ToString());

            prop4.Value = barcode;
            var prop5 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyWeight.ToString());

            prop5.Value = weight;
            var prop6 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyLength.ToString());

            prop6.Value = lenght;
            var prop7 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyWidth.ToString());

            prop7.Value = width;
            var prop8 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyHeight.ToString());

            prop8.Value = height;
            var prop9 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyAddress.ToString());

            prop9.Value = address;
            //var prop10 = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.WCSReplyBackup.ToString());
            //prop10.Value = backup;
            List <EquipmentProp> props = new List <EquipmentProp> {
                prop2, prop3, prop4, prop5, prop6, prop7, prop8, prop9, prop1
            };

            return(plc.Writes(props));
        }
Esempio n. 22
0
        private void Write()
        {
            Stopwatch stopwatch = new Stopwatch();

            for (int i = 0; i < 1000000; i++)
            {
                stopwatch.Restart();
                var prop7 = Equipments.SelectMany(t => t.EquipmentProps).Where(t => t.EquipmentTypeTemplateCode == "Prop7").ToList();
                var prop8 = Equipments.SelectMany(t => t.EquipmentProps).Where(t => t.EquipmentTypeTemplateCode == "Prop8").ToList();
                var prop9 = Equipments.SelectMany(t => t.EquipmentProps).Where(t => t.EquipmentTypeTemplateCode == "Prop9").ToList();
                prop7.ForEach(t => t.Value = i.ToString());
                prop8.ForEach(t =>
                {
                    if (t.Value == "True")
                    {
                        t.Value = "False";
                    }
                    else
                    {
                        t.Value = "True";
                    }
                });
                prop9.ForEach(t => t.Value = "HelloWorld");
                var a = plc.Writes(Equipments.SelectMany(t => t.EquipmentProps).ToList());
                stopwatch.Stop();
                if (a.Success)
                {
                    Console.WriteLine($"线程:{Thread.CurrentThread.ManagedThreadId},写入次数:{i},耗时:{stopwatch.ElapsedMilliseconds.ToString()},{string.Join("||", Equipments.Select(t => t.EquipmentProps).Select(t => $"设备:{t[0].Equipment.Code},写入值:{string.Join(",", t.Select(n => n.Value))}").ToList())}");
                }
                else
                {
                    MessageBox.Show(a.Msg);
                    return;
                }
            }
        }
Esempio n. 23
0
        /// <summary>
        /// 以堆垛机状态驱动,重写堆垛机控制逻辑
        /// hack:1.注意此处改动:堆垛机任务完成不再以状态去查找任务,以堆垛机携带的任务号为准;
        /// 2.标准实现中不支持跨巷道移库
        /// </summary>
        /// <param name="srm"></param>
        /// <param name="plc"></param>
        /// <returns></returns>
        public BllResult ExcuteSingle(Equipment srm, List <Equipment> allEquipments, IPLC plc)
        {
            //联机、无故障
            if (Validate(srm).Success)
            {
                #region 对于单叉堆垛机,判断这个货叉有误故障

                if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TotalError.ToString()).Value == "True")
                {
                    //如果报有故障,则返回
                    return(BllResultFactory.Error("货叉1故障"));
                }

                #endregion

                #region 堆垛机任务执行判断
                if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务执行中.GetIndexString())
                {
                    //任务执行中就return
                    return(BllResultFactory.Sucess());
                }
                if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务中断_出错.GetIndexString())
                {
                    //由人工处理,一般为空出和重入
                    return(BllResultFactory.Sucess());
                }
                if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.发任务错误.GetIndexString())
                {
                    //由人工处理,需要重新下发任务
                    return(BllResultFactory.Sucess());
                }
                #endregion

                #region 任务,货位和本巷道的其他设备

                //找出所有未完成的任务
                var tasksResult = AppSession.Dal.GetCommonModelByConditionWithZero <TaskEntity>($"where taskStatus < {TaskEntityStatus.任务完成.GetIndexInt()} " +
                                                                                                $"and taskStatus>={TaskEntityStatus.下发任务.GetIndexInt()} and deleted = 0 and warehouseCode='{AppSession.WarehouseCode}'");
                if (!tasksResult.Success)
                {
                    //如果查找发生错误
                    return(BllResultFactory.Error(tasksResult.Msg));
                }
                //找出同巷道的库位,考虑到可能多个巷道移库,这里分别查询出所有库位和当前堆垛机所在巷道的库位
                var locationsResult = AppSession.LocationService.GetAllLocations(null, null, null, null, null, null, null, srm.WarehouseCode);
                if (!locationsResult.Success)
                {
                    return(BllResultFactory.Error(locationsResult.Msg));
                }
                //所有库位
                var allLocations = locationsResult.Data;
                //本巷道库位
                var locationsRoadWay = allLocations.Where(t => t.RoadWay == srm.RoadWay).ToList();
                //找出本巷道的所有设备
                var equipmentsRoadWay = allEquipments.Where(t => t.RoadWay == srm.RoadWay && t.WarehouseCode == srm.WarehouseCode).ToList();

                //获取当前堆垛机可以到达的列
                var minProp   = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.ManageSmallColumn.ToString());
                var maxProp   = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.ManageBigColumn.ToString());
                int minColumn = Convert.ToInt32(minProp.Value);
                int maxColumn = Convert.ToInt32(maxProp.Value);
                //可用的可出站台
                //hack:注意,此处针对每个巷道均需要配置StationStatusMonitor!如果没有配置,则可出站台为空集合;
                var stationOutStatusMonitor = equipmentsRoadWay.Find(a => a.EquipmentType.Code == "StationStatusMonitor");
                var availableOutStation     = stationOutStatusMonitor == null ? new List <Equipment>() : equipmentsRoadWay.Where(t => t.EquipmentType.Code.Contains("Station") &&
                                                                                                                                 stationOutStatusMonitor.EquipmentProps.
                                                                                                                                 Count(b => b.EquipmentTypeTemplateCode == t.StationIndex.ToString() && b.Value == StationTaskLimit.可出.GetIndexString()) > 0).ToList();
                //筛选可出站台,可出站台得在堆垛机的最大列和最小列之间且目标区域与堆垛机
                //hack:这里按需选择是否判断站台的区域与堆垛机的区域是否相同
                availableOutStation = availableOutStation.Where(t => t.ColumnIndex >= minColumn && t.ColumnIndex <= maxColumn).ToList();

                //筛选任务,任务的范围得在堆垛机的最大列和最小列之间
                var tasks = tasksResult.Data.Where(t =>
                {
                    if (t.TaskType != (int)TaskType.换站)
                    {
                        //hack:这里筛选本巷道或关联到本巷道的任务,规则为起始或目标库位,所以,当将来出现跨巷道移库时,需要特别处理跨巷道移库任务
                        //兼容转轨,这里需要对两个库位是否在当前堆垛机可以到达的列做个判断,如果超出,则不执行
                        var tempLocations = locationsRoadWay.Where(a => a.Code == t.FromLocationCode || a.Code == t.ToLocationCode).ToList();
                        if (tempLocations.Count > 0)
                        {
                            return(tempLocations.Exists(a =>
                            {
                                return a.RoadWay == srm.RoadWay && (a.Line >= minColumn && a.Line <= maxColumn);
                            }));
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        //如果是换站,则toPort必须在本巷道中
                        var temp = AppSession.ExcuteService.GetOutStationByPort(srm.DestinationArea, t.ToPort, App.WarehouseCode);
                        if (temp.Success)
                        {
                            if (temp.Data.Exists(a => a.RoadWay != srm.RoadWay))
                            {
                                return(false);
                            }
                            else
                            {
                                return(true);
                            }
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }).ToList();

                //筛选任务,任务的前置任务如果存在,则其前置任务需要大于完成状态
                tasks = tasks.Where(t =>
                {
                    if (t.PreTaskId != 0)
                    {
                        var tempResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where id = {t.PreTaskId}");
                        if (tempResult.Success)
                        {
                            var innerTask = tempResult.Data[0];
                            if (innerTask.TaskStatus >= (int)TaskEntityStatus.任务完成)
                            {
                                return(true);
                            }
                            else
                            {
                                return(false);
                            }
                        }
                        else
                        {
                            Logger.Log($"未找到任务{t.Id},远程任务号:{t.RemoteTaskNo}的前置远程任务:{t.PreRemoteTaskNo},前置内部任务号:{t.PreTaskId},该任务不允许执行。如果要执行,请取消其前置任务号", LogLevel.Warning);
                            return(false);
                        }
                    }
                    else
                    {
                        return(true);
                    }
                }).ToList();

                #endregion

                //货叉1待机情况下
                if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.待机.GetIndexString())
                {
                    //货叉任务待机时,可执行放和取任务,同时当执行完成时,交互后货叉1会从任务完成更新为待机
                    EquipmentProp fork1TaskFlag = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                    if (fork1TaskFlag.Value == SRMForkTaskFlag.任务完成.GetIndexString())
                    {
                        return(ClearWCSData(srm, plc));
                    }
                    else if (fork1TaskFlag.Value == SRMForkTaskFlag.除任务.GetIndexString())
                    {
                        return(ClearWCSData(srm, plc));
                    }
                    //货叉无任务且货叉在中心
                    else if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString()).Value == SRMForkTaskFlag.无任务.GetIndexString() && srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1Center.ToString()).Value == "True")
                    {
                        #region 优先处理重新下发的任务,此处可按需去除有货无货的校验

                        //库内取,要求货叉1无货
                        var taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库内取货.GetIndexInt() && locationsRoadWay.Count(a => a.Code == t.FromLocationCode) > 0 && t.SendAgain == 1);
                        if (taskForResend != null && srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1HasPallet.ToString()).Value == "False")
                        {
                            var locationForResend = locationsRoadWay.Find(t => t.Code == taskForResend.FromLocationCode);
                            return(ReSendTask(srm, plc, locationForResend.SrmCode == srm.Code ? locationForResend.RowIndex1.ToString() : locationForResend.RowIndex2.ToString(), locationForResend.Line.ToString(), locationForResend.Layer.ToString(), "0", taskForResend, SRMForkTaskFlag.库内取货));
                        }

                        //库内放货时,任务标记已在当前堆垛机上,校验之,要求货叉有货
                        taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库内放货.GetIndexInt() && locationsRoadWay.Count(a => a.Code == t.ToLocationCode) > 0 && t.SendAgain == 1 && t.Gateway == srm.Code);
                        if (taskForResend != null && srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1HasPallet.ToString()).Value == "True")
                        {
                            var locationForResend = locationsRoadWay.Find(t => t.Code == taskForResend.ToLocationCode);
                            return(ReSendTask(srm, plc, locationForResend.SrmCode == srm.Code ? locationForResend.RowIndex1.ToString() : locationForResend.RowIndex2.ToString(), locationForResend.Line.ToString(), locationForResend.Layer.ToString(), "0", taskForResend, SRMForkTaskFlag.库内放货));
                        }

                        //库外取货时,此站台得在本巷道内,要求货叉无货
                        //hack:一般情况下不存在同个巷道多个重新下发的任务,如果存在,此处需要特别处理
                        taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库外取货.GetIndexInt() &&
                                                             equipmentsRoadWay.Count(a => a.Code == t.Gateway) > 0 &&
                                                             t.SendAgain == 1);
                        if (taskForResend != null && srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1HasPallet.ToString()).Value == "False")
                        {
                            //使用task的ArrivaEquipmentCode来记录task对应托盘当前或上一次所在的口,则此处通过ArrivaEquipmentCode来查找当前task所在的口
                            var stationResult = equipmentsRoadWay.First(t => t.Code == taskForResend.Gateway);
                            return(ReSendTask(srm, plc, stationResult.RowIndex1.ToString(), stationResult.RowIndex1.ToString(), "0", stationResult.StationIndex.ToString(), taskForResend, SRMForkTaskFlag.库外取货));
                        }
                        //库外放货,要求货叉有货,要求站台可出
                        taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库外放货.GetIndexInt() && t.Gateway == srm.Code && t.SendAgain == 1);
                        if (taskForResend != null && srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1HasPallet.ToString()).Value == "True")
                        {
                            var stationsResult = AppSession.ExcuteService.GetOutStationByPort(srm.DestinationArea, taskForResend.ToPort, App.WarehouseCode);
                            if (!stationsResult.Success)
                            {
                                return(BllResultFactory.Error($"重新下发任务出错:{stationsResult.Msg}"));
                            }
                            //这些站台要在可用的站台列表中并选取离堆垛机最近的一个站台
                            var station = stationsResult.Data.Where(t => availableOutStation.Exists(a => a.Code == t.Code)).OrderBy(t => CurrentColumn - t.ColumnIndex).FirstOrDefault();
                            if (station == null)
                            {
                                Logger.Log($"堆垛机{srm.Name}当前没有可用的站台可以放货,任务:{taskForResend.Id}", LogLevel.Warning);
                                return(BllResultFactory.Error());
                            }
                            else
                            {
                                return(ReSendTask(srm, plc, station.RowIndex1.ToString(), "0", "0", station.StationIndex.ToString(), taskForResend, SRMForkTaskFlag.库外放货));
                            }
                        }

                        #endregion

                        //判断堆垛机货叉上是不是有货,有货就只能接受放货任务,无货就可以接受取货任务
                        if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1HasPallet.ToString()).Value == "True")
                        {
                            //有货,则查找同巷道的取货任务完成状态的任务,同一个堆垛机,单叉情况下最多一条
                            #region 判断是否超出一条
                            if (tasks.Count(t => (t.TaskStatus == TaskEntityStatus.响应堆垛机库内取货完成.GetIndexInt() || t.TaskStatus == TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt()) && t.Gateway == srm.Code) > 1)
                            {
                                Logger.Log($"堆垛机{srm.Name}显示货叉上有货,但是对应的任务超过1条,请检查状态为{TaskEntityStatus.响应堆垛机库内取货完成}" +
                                           $"和{TaskEntityStatus.响应堆垛机库外取货完成}的任务", LogLevel.Error);
                                return(BllResultFactory.Error());
                            }
                            #endregion

                            //添加任务号进行判断
                            int taskNo = int.Parse(srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskNo.ToString()).Value);
                            //先找库内取货完成的任务
                            var task = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.响应堆垛机库内取货完成.GetIndexInt() && t.Gateway == srm.Code);
                            if (task == null)
                            {
                                //如果没有就找库外取货完成的任务,此任务以ArrivaEquipmentCode去查找堆垛机任务
                                task = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt() && t.Gateway == srm.Code);
                            }
                            if (task == null)
                            {
                                //如果还是没有找到任务,那就说明的确没有这条任务,或是人为原因导致的,但此时又显示货叉有货,所以这里是有问题的,做个日志
                                Logger.Log($"堆垛机{srm.Name}显示货叉上有货,但是没有对应的任务", LogLevel.Error);
                                return(BllResultFactory.Error());
                            }
                            else
                            {
                                if (task.Id != taskNo)
                                {
                                    Logger.Log($"堆垛机{srm.Name}显示货叉上有货,并且找到对应的任务:{task.Id},但是和堆垛机对应的任务号:{taskNo},出现偏差请核对", LogLevel.Error);
                                    return(BllResultFactory.Error());
                                }
                                //判断任务类型
                                //移库
                                if (task.TaskType == TaskType.移库.GetIndexInt())
                                {
                                    //是否同巷道
                                    var tempLocation = locationsRoadWay.FirstOrDefault(t => t.Code == task.ToLocationCode);
                                    if (tempLocation != null)
                                    {
                                        //同一个巷道,则直接下发库内放货
                                        return(SendTaskToLocation(srm, plc, task, tempLocation, TaskEntityStatus.发堆垛机库内放货, SRMForkTaskFlag.库内放货, task.TaskStatus));
                                    }
                                    else
                                    {
                                        //hack:默认不支持巷道间的移库,如需要则请按实际情况自行实现
                                        Logger.Log($"任务:{task.Id}对应去向货位{task.ToLocationCode}不在本巷道中,请检查任务数据", LogLevel.Error);
                                        return(BllResultFactory.Error());
                                    }
                                }
                                else if (task.TaskType == TaskType.整盘出库.GetIndexInt() || task.TaskType == TaskType.空容器出库.GetIndexInt() || task.TaskType == TaskType.换站.GetIndexInt())
                                {
                                    //整出任务,空盘出库和换站,都是奔着port去的:
                                    var stationsResult = AppSession.ExcuteService.GetOutStationByPort(srm.DestinationArea, task.ToPort, App.WarehouseCode);
                                    if (!stationsResult.Success)
                                    {
                                        Logger.Log($"未找到可出站台:" + stationsResult.Msg, LogLevel.Error);
                                        return(BllResultFactory.Error(stationsResult.Msg));
                                    }
                                    var station = stationsResult.Data.Where(t => availableOutStation.Exists(a => a.Code == t.Code)).OrderBy(t => CurrentColumn - t.ColumnIndex).FirstOrDefault();
                                    if (station == null)
                                    {
                                        Logger.Log($"堆垛机{srm.Name}当前没有可用的站台可以放货,任务:{task.Id}", LogLevel.Warning);
                                        return(BllResultFactory.Error());
                                    }
                                    else
                                    {
                                        return(SendTaskToStation(srm, plc, task, TaskEntityStatus.发堆垛机库外放货, SRMForkTaskFlag.库外放货, station, task.TaskStatus));
                                    }
                                }
                                else if (task.TaskType == TaskType.整盘入库.GetIndexInt() || task.TaskType == TaskType.空容器入库.GetIndexInt())
                                {
                                    //整盘入库、空盘入库:当前目的货位与堆垛机是否在同一个巷道,在,则下发库内放货任务;不在,报错;
                                    var tempLocation = locationsRoadWay.FirstOrDefault(t => t.Code == task.ToLocationCode);
                                    if (tempLocation != null)
                                    {
                                        //同一个巷道,则直接下发库内放货
                                        return(SendTaskToLocation(srm, plc, task, tempLocation, TaskEntityStatus.发堆垛机库内放货, SRMForkTaskFlag.库内放货, task.TaskStatus));
                                    }
                                    else
                                    {
                                        Logger.Log($"任务:{task.Id}对应去向货位{task.ToLocationCode}不在本巷道中,请检查任务数据", LogLevel.Error);
                                        return(BllResultFactory.Error());
                                    }
                                }
                                else if (task.TaskType == TaskType.出库查看.GetIndexInt() || task.TaskType == TaskType.分拣出库.GetIndexInt() ||
                                         task.TaskType == TaskType.盘点.GetIndexInt() || task.TaskType == TaskType.补充入库.GetIndexInt())
                                {
                                    //补充入库、分拣出库、盘点、出库查看:需要判断任务阶段来决定是出还是入
                                    //判断任务阶段
                                    if (task.Stage == TaskStageFlag.入.GetIndexInt())
                                    {
                                        //判断目标货位是否在当前巷道
                                        var tempLocation = locationsRoadWay.FirstOrDefault(t => t.Code == task.ToLocationCode);
                                        if (tempLocation != null)
                                        {
                                            //同一个巷道,则直接下发库内放货
                                            return(SendTaskToLocation(srm, plc, task, tempLocation, TaskEntityStatus.发堆垛机库内放货, SRMForkTaskFlag.库内放货, task.TaskStatus));
                                        }
                                        else
                                        {
                                            Logger.Log($"任务:{task.Id}对应去向货位{task.ToLocationCode}不在本巷道中,请检查任务数据", LogLevel.Error);
                                            return(BllResultFactory.Error());
                                        }
                                    }
                                    else
                                    {
                                        //出
                                        var stationsResult = AppSession.ExcuteService.GetOutStationByPort(srm.DestinationArea, task.ToPort, App.WarehouseCode);
                                        if (!stationsResult.Success)
                                        {
                                            return(BllResultFactory.Error(stationsResult.Msg));
                                        }
                                        var station = stationsResult.Data.Where(t => availableOutStation.Exists(a => a.Code == t.Code)).OrderBy(t => CurrentColumn - t.ColumnIndex).FirstOrDefault();
                                        if (station == null)
                                        {
                                            Logger.Log($"堆垛机{srm.Name}当前没有可用的站台可以放货,任务:{task.Id}", LogLevel.Warning);
                                            return(BllResultFactory.Error());
                                        }
                                        else
                                        {
                                            return(SendTaskToStation(srm, plc, task, TaskEntityStatus.发堆垛机库外放货, SRMForkTaskFlag.库外放货, station, task.TaskStatus));
                                        }
                                    }
                                }
                                else
                                {
                                    //报警,未知的任务类型
                                    Logger.Log($"堆垛机{srm.Name}对应的任务{task.Id}为未知的任务类型", LogLevel.Error);
                                    return(BllResultFactory.Error());
                                }
                            }
                        }
                        else
                        {
                            //无货,说明完全处在空闲状态
                            var tempTasks = tasks;
                            if (tempTasks.Count == 0)
                            {
                                return(BllResultFactory.Error());
                            }
                            else
                            {
                                //完全空闲的堆垛机实际只执行取货任务,则为库外取与库内取两种
                                //找出下发状态的待取的离堆垛机最近的任务,并且对应站台口需要可用
                                var task1s = tempTasks.Where(t => t.TaskStatus == TaskEntityStatus.发任务.GetIndexInt() &&
                                                             (t.TaskType == TaskType.出库查看.GetIndexInt() ||
                                                              t.TaskType == TaskType.分拣出库.GetIndexInt() ||
                                                              t.TaskType == TaskType.整盘出库.GetIndexInt() ||
                                                              t.TaskType == TaskType.盘点.GetIndexInt() ||
                                                              t.TaskType == TaskType.空容器出库.GetIndexInt() ||
                                                              t.TaskType == TaskType.补充入库.GetIndexInt() ||
                                                              t.TaskType == TaskType.移库.GetIndexInt()) &&
                                                             locationsRoadWay.Exists(a => a.Code == t.FromLocationCode)).ToList();
                                task1s.ForEach(t =>
                                {
                                    t.FromLocation    = locationsRoadWay.First(a => a.Code == t.FromLocationCode);
                                    t.ToPortEquipment = equipmentsRoadWay.FirstOrDefault(a => a.Code == t.ToPort);
                                });
                                //任务过滤条件,任务port对应的station要可用
                                task1s = task1s.Where(t => t.TaskType == (int)TaskType.移库 || (availableOutStation.Exists(a => AppSession.ExcuteService.GetOutStationByPort(srm.DestinationArea, t.ToPort, App.WarehouseCode).Data?.Exists(b => b.Code == a.Code) == true))).ToList();


                                //库内取货的任务
                                var task1 = task1s.OrderByDescending(t => t.Priority).ThenBy(t => Math.Abs((int)t.FromLocation.Line - CurrentColumn)).FirstOrDefault();

                                //本巷道接入口的任务
                                var task2s = tempTasks.Where(t => t.TaskStatus == TaskEntityStatus.响应接入站台到达.GetIndexInt() && equipmentsRoadWay.Exists(a => a.Code == t.Gateway)).ToList();
                                task2s.ForEach(t => t.ArrivaEquipment = equipmentsRoadWay.Find(a => a.Code == t.Gateway));
                                //按优先级以及站台与现有堆垛机的距离优先做调度,注意,接入的站台必须要在堆垛机可以到达的列之间
                                var task2 = task2s.Where(t => t.ArrivaEquipment.ColumnIndex >= minColumn && t.ArrivaEquipment.ColumnIndex <= maxColumn).OrderByDescending(t => t.Priority).ThenBy(t => Math.Abs(t.ArrivaEquipment.ColumnIndex - CurrentColumn)).FirstOrDefault();
                                if (task1 == null && task2 == null)
                                {
                                    //说明当前没有可以被执行的任务
                                    return(BllResultFactory.Sucess());
                                }
                                if (task2 != null)
                                {
                                    //说明库外取货任务不为空,则下发接入任务
                                    return(SendTaskToStation(srm, plc, task2, TaskEntityStatus.发堆垛机库外取货, SRMForkTaskFlag.库外取货, equipmentsRoadWay.Find(t => t.Code == task2.Gateway), task2.TaskStatus));
                                }
                                if (task1 != null)
                                {
                                    //说明库内取货任务不为空
                                    return(SendTaskToLocation(srm, plc, task1, task1.FromLocation, TaskEntityStatus.发堆垛机库内取货, SRMForkTaskFlag.库内取货, task1.TaskStatus));
                                }

                                //当两种任务均存在时,此处设置两种模式,出库优先与均衡模式(按堆垛机位置进行)
                                var configResult = AppSession.BllService.GetAllConfig();
                                var config       = configResult.Data?.FirstOrDefault(t => t.Code == ConfigStrings.OutFirst.ToString());
                                if (config == null || config.Value != "1")
                                {
                                    //均衡模式
                                    var dis1 = Math.Abs((int)task1.FromLocation.Line - CurrentColumn);
                                    var dis2 = Math.Abs(task2.ArrivaEquipment.RowIndex1 - CurrentColumn);
                                    if (dis1 <= dis2)
                                    {
                                        return(SendTaskToLocation(srm, plc, task1, task1.FromLocation, TaskEntityStatus.发堆垛机库内取货, SRMForkTaskFlag.库内取货, task1.TaskStatus));
                                    }
                                    else
                                    {
                                        return(SendTaskToStation(srm, plc, task2, TaskEntityStatus.发堆垛机库外取货, SRMForkTaskFlag.库外取货, equipmentsRoadWay.First(t => t.Code == task2.Gateway), task2.TaskStatus));
                                    }
                                }
                                else
                                {
                                    //出库优先模式
                                    return(SendTaskToLocation(srm, plc, task1, task1.FromLocation, TaskEntityStatus.发堆垛机库内取货, SRMForkTaskFlag.库内取货, task1.TaskStatus));
                                }
                            }
                        }
                    }
                    else
                    {
                        //hack:其他情况1-库内取货,2-库内放货,3-库外入库,4库外出库, 5重新分配入库地址,暂时不做处理,这里也应不需要处理这些情况
                    }
                }
                else if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务完成.GetIndexString() &&
                         srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString()).Value != SRMForkTaskFlag.任务完成.GetIndexString())
                {
                    //一共4种完成情况
                    //根据任务号和货叉类型进行任务完成处理
                    int taskNo     = int.Parse(srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskNo.ToString()).Value);
                    int forkType   = int.Parse(srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskType.ToString()).Value);
                    var taskResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where id = {taskNo}");
                    if (!taskResult.Success)
                    {
                        Logger.Log($"根据堆垛机任务号{taskNo}未找到任务:{taskResult.Msg}", LogLevel.Error);
                        return(BllResultFactory.Error());
                    }
                    var task        = taskResult.Data[0];
                    var tempStatus  = task.TaskStatus;
                    var tempGateWay = task.Gateway;
                    //库内取货完成
                    if (forkType == SRMForkTaskFlag.库内取货.GetIndexInt())
                    {
                        //更新任务状态
                        task.TaskStatus = TaskEntityStatus.响应堆垛机库内取货完成.GetIndexInt();
                        task.Gateway    = srm.Code; //标记当前堆垛机到任务
                        var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                        if (tempResult.Success)
                        {
                            //标记交换区地址,任务完成10
                            var prop = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库内取货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库内取货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                task.TaskStatus = tempStatus;
                                task.Gateway    = tempGateWay;
                                AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                return(BllResultFactory.Error());
                            }
                        }
                        else
                        {
                            Logger.Log($"完成堆垛机{srm.Name}库内取货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{srm.Name}库内取货时,更新任务{task.Id}状态失败:{tempResult.Msg}"));
                        }
                    }

                    //库内放货完成
                    else if (forkType == SRMForkTaskFlag.库内放货.GetIndexInt())
                    {
                        //本地完成任务,然后进行回传
                        var tempResult = AppSession.TaskService.CompleteTask(task.Id.Value, App.User.UserCode);
                        if (!tempResult.Success)
                        {
                            Logger.Log($"完成堆垛机{srm.Name}库内放货失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{srm.Name}库内放货失败:{tempResult.Msg}"));
                        }
                        else
                        {
                            //标记交换区地址,任务完成10
                            var prop = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库内放货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库内放货失败,请人工处理任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                return(BllResultFactory.Error());
                            }
                        }
                    }
                    //库外取货完成时
                    else if (forkType == SRMForkTaskFlag.库外取货.GetIndexInt())
                    {
                        //更新任务状态
                        task.TaskStatus = TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt();
                        task.Gateway    = srm.Code; //标记当前堆垛机到任务
                        var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                        if (tempResult.Success)
                        {
                            //标记交换区地址,任务完成10
                            var prop = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库外取货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库外取货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                task.TaskStatus = tempStatus;
                                task.Gateway    = tempGateWay;
                                AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                return(BllResultFactory.Error());
                            }
                        }
                        else
                        {
                            Logger.Log($"完成堆垛机{srm.Name}库外取货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{srm.Name}库外取货时,更新任务{task.Id}状态失败:{tempResult.Msg}"));
                        }
                    }
                    //库外放货完成时
                    else if (forkType == SRMForkTaskFlag.库外放货.GetIndexInt())
                    {
                        //库外放货时,堆垛机会携带站台Index,找到放货站台并更新到任务;
                        var currentStation = srm.EquipmentProps.FirstOrDefault(t => t.EquipmentTypeTemplateCode == SRMProps.CurrentStation.ToString());
                        if (currentStation == null)
                        {
                            Logger.Log($"未找到堆垛机{srm.Name}对应的出入口属性", LogLevel.Error);
                            return(BllResultFactory.Error());
                        }
                        var station = equipmentsRoadWay.FirstOrDefault(t => t.StationIndex?.ToString() == currentStation.Value && t.WarehouseCode == srm.WarehouseCode && t.DestinationArea == srm.DestinationArea);
                        if (station == null)
                        {
                            Logger.Log($"未找到堆垛机{srm.Name}对应的出入口{currentStation.Value}", LogLevel.Error);
                            return(BllResultFactory.Error());
                        }

                        //更新任务状态
                        task.TaskStatus = TaskEntityStatus.响应堆垛机库外放货完成.GetIndexInt();
                        //注意此处对应放货的具体接出站台
                        task.Gateway = station.Code;
                        var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                        if (tempResult.Success)
                        {
                            //标记交换区地址,任务完成10
                            var prop = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库外放货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{srm.Name}完成库外放货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                task.TaskStatus = tempStatus;
                                task.Gateway    = tempGateWay;
                                AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                return(BllResultFactory.Error());
                            }
                        }
                        else
                        {
                            Logger.Log($"完成堆垛机{srm.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{srm.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}"));
                        }
                    }
                    return(BllResultFactory.Sucess());
                }
                else
                {
                    //未知情况
                    Logger.Log($"堆垛机{srm.Name}执行中,执行状态为:{srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value};可能由于WCS还未处理造成", LogLevel.Warning);
                    return(BllResultFactory.Sucess());
                }
            }
            return(BllResultFactory.Sucess());
        }
Esempio n. 24
0
        /// <summary>
        /// 单叉整任务下发
        /// </summary>
        /// <param name="srm"></param>
        /// <param name="plc"></param>
        /// <param name="newTaskFlag"></param>
        /// <param name="getForkTaskFlag"></param>
        /// <param name="getForkRow"></param>
        /// <param name="getForkColumn"></param>
        /// <param name="getForkLayer"></param>
        /// <param name="getForkStation"></param>
        /// <param name="putForkTaskFlag"></param>
        /// <param name="putForkRow"></param>
        /// <param name="putForkColumn"></param>
        /// <param name="putForkLayer"></param>
        /// <param name="putForkStation"></param>
        /// <param name="taskNo"></param>
        /// <param name="forkTaskFlag"></param>
        /// <returns></returns>
        public BllResult SendTaskToSRM(Equipment srm, IPLC plc, SSRMNewTaskFlag newTaskFlag,
                                       SRMForkTaskFlag getForkTaskFlag, string getForkRow, string getForkColumn, string getForkLayer, string getForkStation,
                                       SRMForkTaskFlag putForkTaskFlag, string putForkRow, string putForkColumn, string putForkLayer, string putForkStation,
                                       string taskNo, SSRMTaskCompleteFlag completeFlag)
        {
            try
            {
                List <EquipmentProp> propsToWriter = new List <EquipmentProp>();
                var props = srm.EquipmentProps;

                var action = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSNewTask.ToString());
                action.Value = newTaskFlag.GetIndexString();

                //--

                var getTaskFlag = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSGetFork1TaskFlag.ToString());
                getTaskFlag.Value = getForkTaskFlag.GetIndexString();

                var getRow = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSGetRow.ToString());
                getRow.Value = getForkRow;

                var getStation = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSGetPort.ToString());
                getStation.Value = getForkStation;

                var getColumn = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSGetColumn.ToString());
                getColumn.Value = getForkColumn;

                var getLayer = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSGetLayer.ToString());
                getLayer.Value = getForkLayer;

                //--

                var putTaskFlag = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSPutFork1TaskFlag.ToString());
                putTaskFlag.Value = putForkTaskFlag.GetIndexString();

                var putRow = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSPutRow.ToString());
                putRow.Value = putForkRow;

                var putStation = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSPutPort.ToString());
                putStation.Value = putForkStation;

                var putColumn = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSPutColumn.ToString());
                putColumn.Value = putForkColumn;

                var putLayer = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSPutLayer.ToString());
                putLayer.Value = putForkLayer;

                // -
                var taskNoProp = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSTaskNo.ToString());
                taskNoProp.Value = taskNo;

                // -
                var taskFlagProp = props.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSTaskCompleteFlag.ToString());
                taskFlagProp.Value = completeFlag.GetIndexString();


                propsToWriter.AddRange(new List <EquipmentProp>()
                {
                    action, getTaskFlag, getRow, getColumn, getLayer, getStation, putTaskFlag, putRow, putStation, putColumn, putLayer, taskNoProp, taskFlagProp
                });
                return(plc.Writes(propsToWriter));
            }
            catch (Exception ex)
            {
                Logger.Log($"PLC写入信息错误:" + ex.Message, LogLevel.Exception);
                return(BllResultFactory.Error($"下发任务出现异常:{ex.Message}"));
            }
        }
        /// <summary>
        /// 以堆垛机状态驱动,重写堆垛机控制逻辑
        /// hack:1.注意此处改动:堆垛机任务完成不再以状态去查找任务,以堆垛机携带的任务号为准;2.标准实现中不支持跨巷道移库
        /// </summary>
        /// <param name="stocker"></param>
        /// <param name="plc"></param>
        /// <returns></returns>
        public BllResult ExcuteSingle(Equipment stocker, List <Equipment> allEquipments, IPLC plc)
        {
            //联机、无故障
            if (Validate(stocker).Success)
            {
                #region 堆垛机任务执行判断
                if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务执行中.GetIndexString())
                {
                    //任务执行中就return
                    return(BllResultFactory.Sucess());
                }
                if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务中断_出错.GetIndexString())
                {
                    //由人工处理,一般为空出和重入
                    return(BllResultFactory.Sucess());
                }
                if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.发任务错误.GetIndexString())
                {
                    //由人工处理,需要重新下发任务
                    return(BllResultFactory.Sucess());
                }
                #endregion

                #region 任务,货位和本巷道的其他设备

                //找出所有未完成的任务
                var tasksResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where taskStatus < {TaskEntityStatus.任务完成.GetIndexInt()} " +
                                                                                        $"and taskStatus>={TaskEntityStatus.下发任务.GetIndexInt()} and deleted = 0 and warehouseCode={AppSession.WarehouseCode}");
                if (!tasksResult.Success)
                {
                    //如果没有找到任务就直接返回
                    return(BllResultFactory.Error(tasksResult.Msg));
                }
                //找出同巷道的库位,考虑到可能多个巷道移库,这里分别查询出所有库位和当前堆垛机所在的库位
                var locationsResult = AppSession.LocationService.GetAllLocations(null, null, null, null, null, null, null, stocker.WarehouseCode);
                if (!locationsResult.Success)
                {
                    return(BllResultFactory.Error(locationsResult.Msg));
                }
                var locations        = locationsResult.Data;
                var locationsRoadWay = locationsResult.Data.Where(t => t.RoadWay == stocker.RoadWay).ToList();
                //找出本巷道的所有设备
                var tempEquipments = allEquipments.Where(t => t.RoadWay == stocker.RoadWay && t.WarehouseCode == stocker.WarehouseCode).ToList();
                //可用站台
                //var availableStation = AppSession.ExcuteService.GetAvailableStation(tempEquipments);
                //hack:注意,此处需要配置StationStatusMonitor!
                var availableStation = tempEquipments.Where(t => t.EquipmentType.Code.Contains("Station") &&
                                                            tempEquipments.First(a => a.EquipmentType.Code == "StationStatusMonitor").EquipmentProps.
                                                            Count(b => b.EquipmentTypeTemplateCode == t.StationIndex.ToString() && b.Value == StationTaskLimit.可出.GetIndexString()) > 0).ToList();

                //hack:这里筛选本巷道或关联到本巷道的任务,规则为起始或目标库位,所以,当将来出现跨巷道移库时,需要特别处理跨巷道移库任务
                var tasks = tasksResult.Data.Where(t => locationsRoadWay.Count(a => a.Code == t.FromLocationCode || a.Code == t.ToLocationCode) > 0).ToList();

                #endregion

                //堆垛机待机情况下
                if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.待机.GetIndexString())
                {
                    //货叉任务待机时,可执行放和取任务,同时当执行完成时,交互后堆垛机会从任务完成更新为待机
                    if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString()).Value == SRMForkTaskFlag.任务完成.GetIndexString())
                    {
                        return(ClearWCSData(stocker, plc));
                    }
                    else if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString()).Value == SRMForkTaskFlag.无任务.GetIndexString())
                    {
                        #region 优先处理重新下发的任务

                        var taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库内取货.GetIndexInt() && locationsRoadWay.Count(a => a.Code == t.FromLocationCode) > 0 && t.SendAgain == 1);
                        if (taskForResend != null)
                        {
                            var locationForResend = locationsRoadWay.Find(t => t.Code == taskForResend.FromLocationCode);
                            return(ReSendTask(stocker, plc, locationForResend.RowIndex1.ToString(), locationForResend.Line.ToString(), locationForResend.Layer.ToString(), "0", taskForResend, SRMForkTaskFlag.库内取货));
                        }

                        taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库内放货.GetIndexInt() && locationsRoadWay.Count(a => a.Code == t.ToLocationCode) > 0 && t.SendAgain == 1);
                        if (taskForResend != null)
                        {
                            var locationForResend = locationsRoadWay.Find(t => t.Code == taskForResend.ToLocationCode);
                            return(ReSendTask(stocker, plc, locationForResend.RowIndex1.ToString(), locationForResend.Line.ToString(), locationForResend.Layer.ToString(), "0", taskForResend, SRMForkTaskFlag.库内放货));
                        }

                        //取货时,此站台得在本巷道内
                        //hack:一般情况下不存在同个巷道多个重新下发的任务,如果存在,此处需要特别处理
                        taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库外取货.GetIndexInt() &&
                                                             tempEquipments.Count(a => a.Code == t.Gateway) > 0 &&
                                                             t.SendAgain == 1);
                        if (taskForResend != null)
                        {
                            //使用task的ArrivaEquipmentCode来记录task对应托盘当前或上一次所在的口,则此处通过ArrivaEquipmentCode来查找当前task所在的口
                            var stationResult = tempEquipments.First(t => t.Code == taskForResend.Gateway);
                            return(ReSendTask(stocker, plc, stationResult.RowIndex1.ToString(), stationResult.RowIndex1.ToString(), "0", stationResult.StationIndex.ToString(), taskForResend, SRMForkTaskFlag.库外取货));
                        }

                        taskForResend = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.发堆垛机库外放货.GetIndexInt() && t.Gateway == stocker.Code && t.SendAgain == 1);
                        if (taskForResend != null)
                        {
                            var stationsResult = AppSession.ExcuteService.GetOutStationByPort(stocker.DestinationArea, taskForResend.ToPort, App.WarehouseCode);
                            if (!stationsResult.Success)
                            {
                                return(BllResultFactory.Error($"重新下发任务出错:{stationsResult.Msg}"));
                            }
                            //这些站台要在可用的站台列表中并选取离堆垛机最近的一个站台
                            //var station = stationsResult.Data.Where(t => availableStation.Count(a => a.Code == t.Code) > 0).OrderBy(t => CurrentColumn - t.ColumnIndex).FirstOrDefault();
                            var station = availableStation.Find(t => t.Code == stationsResult.Data[0].Code);
                            if (station == null)
                            {
                                Logger.Log($"堆垛机{stocker.Name}当前没有可用的站台可以放货,任务:{taskForResend.Id}", LogLevel.Warning);
                                return(BllResultFactory.Error());
                            }
                            else
                            {
                                return(ReSendTask(stocker, plc, station.RowIndex1.ToString(), "0", "0", station.StationIndex.ToString(), taskForResend, SRMForkTaskFlag.库外放货));
                            }
                        }

                        #endregion

                        //判断堆垛机货叉上是不是有货,有货就只能接受放货任务,无货就可以接受取货任务
                        if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1ForkHasPallet.ToString()).Value == "True")
                        {
                            //有货,则查找同巷道的取货任务完成状态的任务,同一个堆垛机,单叉情况下最多一条
                            #region 判断是否超出一条
                            if (tasks.Count(t => (t.TaskStatus == TaskEntityStatus.响应堆垛机库内取货完成.GetIndexInt() ||
                                                  t.TaskStatus == TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt()) &&
                                            t.Gateway == stocker.Code) > 1)
                            {
                                Logger.Log($"堆垛机{stocker.Name}显示货叉上有货,但是对应的任务超过1条,请检查状态为{TaskEntityStatus.响应堆垛机库内取货完成}" +
                                           $"和{TaskEntityStatus.响应堆垛机库外取货完成}的任务", LogLevel.Error);
                                return(BllResultFactory.Error());
                            }
                            #endregion
                            //添加任务号进行判断
                            int taskNo = int.Parse(stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskNo.ToString()).Value);
                            //先找库内取货完成的任务
                            var task = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.响应堆垛机库内取货完成.GetIndexInt() && t.Gateway == stocker.Code);
                            if (task == null)
                            {
                                //如果没有就找库外取货完成的任务,此任务以ArrivaEquipmentCode去查找堆垛机任务
                                task = tasks.FirstOrDefault(t => t.TaskStatus == TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt() && t.Gateway == stocker.Code);
                            }
                            if (task == null)
                            {
                                //如果还是没有找到任务,那就说明的确没有这条任务,或是人为原因导致的,但此时又显示货叉有货,所以这里是有问题的,做个日志
                                Logger.Log($"堆垛机{stocker.Name}显示货叉上有货,但是没有对应的任务", LogLevel.Error);
                                return(BllResultFactory.Error());
                            }
                            else
                            {
                                if (task.Id != taskNo)
                                {
                                    Logger.Log($"堆垛机{stocker.Name}显示货叉上有货,并且找到对应的任务:{task.Id},但是和堆垛机对应的任务号:{taskNo},出现偏差请核对", LogLevel.Error);
                                    return(BllResultFactory.Error());
                                }
                                //判断任务类型
                                //移库
                                if (task.TaskType == TaskType.移库.GetIndexInt())
                                {
                                    //是否同巷道
                                    var tempLocation = locationsRoadWay.FirstOrDefault(t => t.Code == task.ToLocationCode);
                                    if (tempLocation != null)
                                    {
                                        //同一个巷道,则直接下发库内放货
                                        return(SendTaskToLocation(stocker, plc, task, tempLocation, TaskEntityStatus.发堆垛机库内放货, SRMForkTaskFlag.库内放货, task.TaskStatus));
                                    }
                                    else
                                    {
                                        //hack:默认不支持巷道间的移库,如需要则请按实际情况自行实现
                                        Logger.Log($"任务:{task.Id}对应去向货位{task.ToLocationCode}不在本巷道中,请检查任务数据", LogLevel.Error);
                                        return(BllResultFactory.Error());
                                    }
                                }
                                else if (task.TaskType == TaskType.整盘出库.GetIndexInt() || task.TaskType == TaskType.空容器出库.GetIndexInt() || task.TaskType == TaskType.换站.GetIndexInt())
                                {
                                    //整出任务,空盘出库和换站,都是奔着port去的:
                                    var stationsResult = AppSession.ExcuteService.GetOutStationByPort(stocker.DestinationArea, taskForResend.ToPort, App.WarehouseCode);
                                    if (!stationsResult.Success)
                                    {
                                        Logger.Log(stationsResult.Msg, LogLevel.Error);
                                        return(BllResultFactory.Error(stationsResult.Msg));
                                    }
                                    // var station = stationsResult.Data.Where(t => availableStation.Count(a => a.Code == t.Code) > 0).OrderBy(t => CurrentColumn - t.ColumnIndex).FirstOrDefault();
                                    var station = availableStation.Find(t => t.Code == stationsResult.Data[0].Code);
                                    if (station == null)
                                    {
                                        Logger.Log($"堆垛机{stocker.Name}当前没有可用的站台可以放货,任务:{task.Id}", LogLevel.Warning);
                                        return(BllResultFactory.Error());
                                    }
                                    else
                                    {
                                        return(SendTaskToStation(stocker, plc, task, TaskEntityStatus.发堆垛机库外放货, SRMForkTaskFlag.库外放货, station, task.TaskStatus));
                                    }
                                }
                                else if (task.TaskType == TaskType.整盘入库.GetIndexInt() || task.TaskType == TaskType.空容器入库.GetIndexInt())
                                {
                                    //整盘入库、空盘入库:当前目的货位与堆垛机是否在同一个巷道,在,则下发库内放货任务;不在,报错;
                                    var tempLocation = locationsRoadWay.FirstOrDefault(t => t.Code == task.ToLocationCode);
                                    if (tempLocation != null)
                                    {
                                        //同一个巷道,则直接下发库内放货
                                        return(SendTaskToLocation(stocker, plc, task, tempLocation, TaskEntityStatus.发堆垛机库内放货, SRMForkTaskFlag.库内放货, task.TaskStatus));
                                    }
                                    else
                                    {
                                        Logger.Log($"任务:{task.Id}对应去向货位{task.ToLocationCode}不在本巷道中,请检查任务数据", LogLevel.Error);
                                        return(BllResultFactory.Error());
                                    }
                                }
                                else if (task.TaskType == TaskType.出库查看.GetIndexInt() || task.TaskType == TaskType.分拣出库.GetIndexInt() ||
                                         task.TaskType == TaskType.盘点.GetIndexInt() || task.TaskType == TaskType.补充入库.GetIndexInt())
                                {
                                    //补充入库、分拣出库、盘点、出库查看:需要判断任务阶段来决定是出还是入
                                    //判断任务阶段
                                    if (task.Stage == TaskStageFlag.入.GetIndexInt())
                                    {
                                        //判断目标货位是否在当前巷道
                                        var tempLocation = locationsRoadWay.FirstOrDefault(t => t.Code == task.ToLocationCode);
                                        if (tempLocation != null)
                                        {
                                            //同一个巷道,则直接下发库内放货
                                            return(SendTaskToLocation(stocker, plc, task, tempLocation, TaskEntityStatus.发堆垛机库内放货, SRMForkTaskFlag.库内放货, task.TaskStatus));
                                        }
                                        else
                                        {
                                            Logger.Log($"任务:{task.Id}对应去向货位{task.ToLocationCode}不在本巷道中,请检查任务数据", LogLevel.Error);
                                            return(BllResultFactory.Error());
                                        }
                                    }
                                    else
                                    {
                                        //出
                                        var stationsResult = AppSession.ExcuteService.GetOutStationByPort(stocker.DestinationArea, taskForResend.ToPort, App.WarehouseCode);
                                        if (!stationsResult.Success)
                                        {
                                            return(BllResultFactory.Error(stationsResult.Msg));
                                        }
                                        //var station = stationsResult.Data.Where(t => availableStation.Count(a => a.Code == t.Code) > 0).OrderBy(t => CurrentColumn - t.ColumnIndex).FirstOrDefault();
                                        var station = availableStation.Find(t => t.Code == stationsResult.Data[0].Code);
                                        if (station == null)
                                        {
                                            Logger.Log($"堆垛机{stocker.Name}当前没有可用的站台可以放货,任务:{task.Id}", LogLevel.Warning);
                                            return(BllResultFactory.Error());
                                        }
                                        else
                                        {
                                            return(SendTaskToStation(stocker, plc, task, TaskEntityStatus.发堆垛机库外放货, SRMForkTaskFlag.库外放货, station, task.TaskStatus));
                                        }
                                    }
                                }
                                else
                                {
                                    //报警,未知的任务类型
                                    Logger.Log($"堆垛机{stocker.Name}对应的任务{task.Id}为未知的任务类型", LogLevel.Error);
                                    return(BllResultFactory.Error());
                                }
                            }
                        }
                        else
                        {
                            //无货,说明完全处在空闲状态
                            var tempTasks = tasks;
                            if (tempTasks.Count == 0)
                            {
                                return(BllResultFactory.Error());
                            }
                            else
                            {
                                //完全空闲的堆垛机实际只执行取货任务,则为库外取与库内取两种
                                //找出下发状态的待取的离堆垛机最近的任务,并且对应站台口需要可用
                                var task1s = tempTasks.Where(t => t.TaskStatus == TaskEntityStatus.发任务.GetIndexInt() &&
                                                             (t.TaskType == TaskType.出库查看.GetIndexInt() ||
                                                              t.TaskType == TaskType.分拣出库.GetIndexInt() ||
                                                              t.TaskType == TaskType.整盘出库.GetIndexInt() ||
                                                              t.TaskType == TaskType.盘点.GetIndexInt() ||
                                                              t.TaskType == TaskType.空容器出库.GetIndexInt() ||
                                                              t.TaskType == TaskType.补充入库.GetIndexInt() ||
                                                              t.TaskType == TaskType.移库.GetIndexInt()) &&
                                                             locationsRoadWay.Exists(a => a.Code == t.FromLocationCode)).ToList();
                                task1s.ForEach(t =>
                                {
                                    t.FromLocation    = locationsRoadWay.First(a => a.Code == t.FromLocationCode);
                                    t.ToPortEquipment = tempEquipments.FirstOrDefault(a => a.Code == t.ToPort);
                                });
                                //任务过滤条件,任务port对应的station要可用
                                task1s = task1s.Where(t => availableStation.Exists(a => AppSession.ExcuteService.GetOutStationByPort(stocker.DestinationArea, t.ToPort, App.WarehouseCode).Data?.Exists(b => b.Code == a.Code) == true)).ToList();

                                //库内取货的任务
                                var task1 = task1s.OrderByDescending(t => t.Priority).ThenBy(t => Math.Abs((int)t.FromLocation.Line - CurrentColumn)).FirstOrDefault();

                                //本巷道接入口的任务
                                var task2 = tempTasks.Where(t => t.TaskStatus == TaskEntityStatus.响应接入站台到达.GetIndexInt() && tempEquipments.Exists(a => a.Code == t.Gateway)).OrderByDescending(t => t.Priority).ThenBy(t => Math.Abs((int)t.FromLocation.Line - CurrentColumn)).FirstOrDefault();
                                if (task1 == null && task2 == null)
                                {
                                    //说明当前没有可以被执行的任务
                                    return(BllResultFactory.Error());
                                }
                                if (task1 == null)
                                {
                                    //说明库外取货任务不为空,则下发接入任务
                                    return(SendTaskToStation(stocker, plc, task2, TaskEntityStatus.发堆垛机库外取货, SRMForkTaskFlag.库外取货, tempEquipments.First(t => t.Code == task2.Gateway), task2.TaskStatus));
                                }
                                if (task2 == null)
                                {
                                    //说明库内取货任务不为空
                                    return(SendTaskToLocation(stocker, plc, task1, task1.FromLocation, TaskEntityStatus.发堆垛机库内取货, SRMForkTaskFlag.库内取货, task1.TaskStatus));
                                }

                                //当两种任务均存在时,此处设置两种模式,出库优先与均衡模式(按堆垛机位置进行)
                                var configResult = AppSession.BllService.GetAllConfig();
                                var config       = configResult.Data?.FirstOrDefault(t => t.Code == ConfigStrings.OutFirst.ToString());
                                if (config == null || config.Value != "1")
                                {
                                    //均衡模式
                                    var dis1 = Math.Abs((int)task1.FromLocation.Line - CurrentColumn);
                                    var dis2 = Math.Abs(task2.ArrivaEquipment.RowIndex1 - CurrentColumn);
                                    if (dis1 <= dis2)
                                    {
                                        return(SendTaskToLocation(stocker, plc, task1, task1.FromLocation, TaskEntityStatus.发堆垛机库内取货, SRMForkTaskFlag.库内取货, task1.TaskStatus));
                                    }
                                    else
                                    {
                                        return(SendTaskToStation(stocker, plc, task2, TaskEntityStatus.发堆垛机库外取货, SRMForkTaskFlag.库外取货, tempEquipments.First(t => t.Code == task2.Gateway), task2.TaskStatus));
                                    }
                                }
                                else
                                {
                                    //出库优先模式
                                    return(SendTaskToLocation(stocker, plc, task1, task1.FromLocation, TaskEntityStatus.发堆垛机库内取货, SRMForkTaskFlag.库内取货, task1.TaskStatus));
                                }
                            }
                        }
                    }
                    else if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1TaskFlag").Value == SRMForkTaskFlag.除任务.GetIndexString())
                    {
                        return(ClearWCSData(stocker, plc));
                    }
                    else
                    {
                        //hack:其他情况1-库内取货,2-库内放货,3-库外入库,4库外出库, 5重新分配入库地址,暂时不做处理,这里也应不需要处理这些情况
                    }
                }
                else if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务完成.GetIndexString() &&
                         stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString()).Value != SRMForkTaskFlag.任务完成.GetIndexString())
                {
                    //一共4种完成情况
                    //根据任务号和货叉类型进行任务完成处理
                    int taskNo     = int.Parse(stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskNo.ToString()).Value);
                    int forkType   = int.Parse(stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskType.ToString()).Value);
                    var taskResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where id = {taskNo}");
                    if (!taskResult.Success)
                    {
                        Logger.Log($"根据堆垛机任务号{taskNo}未找到任务:{taskResult.Msg}", LogLevel.Error);
                        return(BllResultFactory.Error());
                    }
                    var task        = taskResult.Data[0];
                    var tempStatus  = task.TaskStatus;
                    var tempGateWay = task.Gateway;
                    //库内取货完成
                    if (forkType == SRMForkTaskFlag.库内取货.GetIndexInt())
                    {
                        //更新任务状态
                        task.TaskStatus = TaskEntityStatus.响应堆垛机库内取货完成.GetIndexInt();
                        task.Gateway    = stocker.Code;
                        var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                        if (tempResult.Success)
                        {
                            //标记交换区地址,任务完成10
                            var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库内取货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库内取货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                task.TaskStatus = tempStatus;
                                task.Gateway    = tempGateWay;
                                AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                return(BllResultFactory.Error());
                            }
                        }
                        else
                        {
                            Logger.Log($"完成堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{tempResult.Msg}"));
                        }
                    }

                    //库内放货完成
                    else if (forkType == SRMForkTaskFlag.库内放货.GetIndexInt())
                    {
                        //本地完成任务,然后进行回传
                        var tempResult = AppSession.TaskService.CompleteTask(task.Id.Value, App.User.UserCode);
                        if (!tempResult.Success)
                        {
                            Logger.Log($"完成堆垛机{stocker.Name}库内放货失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{stocker.Name}库内放货失败:{tempResult.Msg}"));
                        }
                        else
                        {
                            //标记交换区地址,任务完成10
                            var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库内放货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库内放货失败,请人工处理任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                return(BllResultFactory.Error());
                            }
                        }
                    }
                    //库外取货完成时
                    else if (forkType == SRMForkTaskFlag.库外取货.GetIndexInt())
                    {
                        //更新任务状态
                        task.TaskStatus = TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt();
                        task.Gateway    = stocker.Code;
                        var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                        if (tempResult.Success)
                        {
                            //标记交换区地址,任务完成10
                            var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库外取货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库外取货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                task.TaskStatus = tempStatus;
                                task.Gateway    = tempGateWay;
                                AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                return(BllResultFactory.Error());
                            }
                        }
                        else
                        {
                            Logger.Log($"完成堆垛机{stocker.Name}库外取货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{stocker.Name}库外取货时,更新任务{task.Id}状态失败:{tempResult.Msg}"));
                        }
                    }
                    //库外放货完成时
                    else if (forkType == SRMForkTaskFlag.库外放货.GetIndexInt())
                    {
                        //库外放货时,堆垛机会携带站台Index,找到放货站台并更新到任务;
                        var currentStation = stocker.EquipmentProps.FirstOrDefault(t => t.EquipmentTypeTemplateCode == SRMProps.CurrentStation.ToString());
                        if (currentStation == null)
                        {
                            Logger.Log($"未找到堆垛机{stocker.Name}对应的出入口属性", LogLevel.Error);
                            return(BllResultFactory.Error());
                        }
                        var station = tempEquipments.FirstOrDefault(t => t.StationIndex?.ToString() == currentStation.Value);
                        if (station == null)
                        {
                            Logger.Log($"未找到堆垛机{stocker.Name}对应的出入口{currentStation.Value}", LogLevel.Error);
                            return(BllResultFactory.Error());
                        }

                        //更新任务状态
                        task.TaskStatus = TaskEntityStatus.响应堆垛机库外放货完成.GetIndexInt();
                        //注意此处对应放货的具体接出站台
                        task.Gateway = station.Code;
                        var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                        if (tempResult.Success)
                        {
                            //标记交换区地址,任务完成10
                            var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString());
                            prop.Value = SRMForkTaskFlag.任务完成.GetIndexString();
                            var sendResult = plc.Writes(new List <EquipmentProp> {
                                prop
                            });
                            if (sendResult.Success)
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库外放货成功,任务:{task.Id}", LogLevel.Success);
                                return(BllResultFactory.Sucess());
                            }
                            else
                            {
                                Logger.Log($"堆垛机{stocker.Name}完成库外放货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                task.TaskStatus = tempStatus;
                                task.Gateway    = tempGateWay;
                                AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                return(BllResultFactory.Error());
                            }
                        }
                        else
                        {
                            Logger.Log($"完成堆垛机{stocker.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error);
                            return(BllResultFactory.Error($"完成堆垛机{stocker.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}"));
                        }
                    }
                    return(BllResultFactory.Sucess());
                }
                else
                {
                    //未知情况
                    Logger.Log($"堆垛机{stocker.Name}出现了未知的执行状态:{stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value}", LogLevel.Warning);
                    return(BllResultFactory.Sucess());
                }
            }
            return(BllResultFactory.Sucess());
        }
Esempio n. 26
0
        /// <summary>
        /// 以任务号为依据,对堆垛机进行重新编写控制逻辑
        /// 1.
        /// </summary>
        /// <param name="stocker"></param>
        /// <param name="plc"></param>
        /// <returns></returns>
        public BllResult ExcuteSingle(Equipment stocker, IPLC plc)
        {
            //联机、无故障
            if (Validate(stocker).Success)
            {
                #region 第一步:任务执行判断,用于手动情况或异常的处理
                if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务执行中.GetIndexString())
                {
                    //任务执行中就return
                    return(BllResultFactory.Sucess());
                }
                if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务中断_出错.GetIndexString())
                {
                    //由人工处理,一般为空出和重入
                    return(BllResultFactory.Sucess());
                }
                if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.发任务错误.GetIndexString())
                {
                    //由人工处理,需要重新下发任务
                    return(BllResultFactory.Sucess());
                }
                #endregion
                #region 任务和货位

                //找出所有下发未完成的任务
                var tasksResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where taskStatus < {TaskEntityStatus.任务完成.GetIndexInt()} " +
                                                                                        $"and taskStatus>={TaskEntityStatus.下发任务.GetIndexInt()} and deleted = 0 and warehouseCode={AppSession.WarehouseCode}");
                if (!tasksResult.Success)
                {
                    //如果没有找到任务就直接返回
                    return(BllResultFactory.Error(tasksResult.Msg));
                }
                //找出同巷道的库位
                //找出同巷道的库位,考虑到可能多个巷道移库,这里分别查询出所有库位和当前堆垛机所在的库位
                var locationsResult = AppSession.LocationService.GetAllLocations(null, null, null, null, null, null, null, stocker.WarehouseCode);
                if (!locationsResult.Success)
                {
                    return(BllResultFactory.Error(locationsResult.Msg));
                }
                var locations        = locationsResult.Data;
                var locationsRoadWay = locationsResult.Data.Where(t => t.RoadWay == stocker.RoadWay).ToList();

                //hack:这里筛选本巷道的任务,规则为起始或目标库位在本巷道中,所以,当将来出现跨巷道移库时,需要特别处理跨巷道移库任务
                var tasks = tasksResult.Data.Where(t => locationsRoadWay.Count(a => a.Code == t.FromLocationCode || a.Code == t.ToLocationCode) > 0).ToList();
                #endregion
                string Fork1TaskExecuteStatus = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1TaskExcuteStatus.ToString()).Value;
                //堆垛机待机情况下
                if (Fork1TaskExecuteStatus == SRMTaskExcuteStatus.待机.GetIndexString())
                {
                    //货叉任务待机时,可执行放和取任务,同时当执行完成时,交互后堆垛机会从任务完成更新为待机
                    //TODO:WCSFork1TaskFlag  WCSTaskAccount 用于高速堆垛机
                    string WcsFork1TaskFlag = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSFork1TaskFlag.ToString()).Value;
                    if (WcsFork1TaskFlag == SRMForkTaskFlag.除任务.GetIndexString())
                    {
                        return(ClearWCSData(stocker, plc, TaskAccount.New));
                    }
                    else if (WcsFork1TaskFlag == SRMForkTaskFlag.任务完成.GetIndexString())
                    {
                        return(ClearWCSData(stocker, plc, TaskAccount.New));
                    }
                    string WcsTaskAccount = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.WCSTaskAccount.ToString()).Value;
                    if (WcsTaskAccount == SRMForkTaskFlag.任务完成.GetIndexString())
                    {
                        return(ClearWCSData(stocker, plc, TaskAccount.New));
                    }
                    else if (WcsTaskAccount == SRMForkTaskFlag.无任务.GetIndexString())
                    {
                        #region 优先处理重新下发的任务
                        //todo://任务重发逻辑待完成
                        #endregion
                        //获取需要下发给堆垛机的任务
                        if (stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.Fork1ForkHasPallet.ToString()).Value == "True")
                        {
                            Logger.Log($"堆垛机{stocker.Name}显示货叉上有货,高速堆垛机不应该出现有托盘的时候还出现待机无任务的情况", LogLevel.Error);
                            return(BllResultFactory.Error());
                        }
                        else
                        {
                            //判断任务限制情况
                            var tempTasks = tasks;
                            //hack:关于拣选的限制暂时没有做
                            string taskLimit = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SRMProps.TaskLimit.ToString()).Value;
                            if (taskLimit == SRMTaskLimit.限制出库.GetIndexString())
                            {
                                //限制出库,则不能执行下发状态的出库性质任务
                                var temp = tasks.Where(t => t.TaskStatus == TaskEntityStatus.发任务.GetIndexInt())
                                           .Where(t => t.TaskType != TaskType.整盘出库.GetIndexInt() && t.TaskType != TaskType.空容器出库.GetIndexInt() && t.TaskType != TaskType.换站.GetIndexInt() &&
                                                  t.TaskType != TaskType.盘点.GetIndexInt() && t.TaskType != TaskType.出库查看.GetIndexInt() && t.TaskType != TaskType.分拣出库.GetIndexInt()).ToList();
                                tempTasks = tasks.Where(t => temp.Count(a => a.Id == t.Id) == 0).ToList();
                            }
                            else if (taskLimit == SRMTaskLimit.限制入库.GetIndexString())
                            {
                                //限制入库,则不能响应待入状态的入库性质任务
                                tempTasks = tasks.Where(t => t.TaskStatus != TaskEntityStatus.响应接入站台到达.GetIndexInt()).ToList();
                            }
                            if (tempTasks.Count == 0)
                            {
                                return(BllResultFactory.Error());
                            }
                            else
                            {
                                // 这里不需要判断高速堆垛机的位置[一个入口,一个出口,循环]  根据任务依次执行即可
                                TaskEntity task = tempTasks.Where(t => t.TaskStatus == TaskEntityStatus.发任务.GetIndexInt() ||
                                                                  t.TaskStatus == TaskEntityStatus.响应接入站台到达.GetIndexInt()).FirstOrDefault();
                                if (task != null)
                                {
                                    //出库性质的任务
                                    if (task.TaskStatus == TaskEntityStatus.发任务.GetIndexInt() &&
                                        (task.TaskType == TaskType.整盘出库.GetIndexInt() || task.TaskType == TaskType.空容器出库.GetIndexInt() ||
                                         task.TaskType == TaskType.补充入库.GetIndexInt() || task.TaskType == TaskType.分拣出库.GetIndexInt() ||
                                         task.TaskType == TaskType.盘点.GetIndexInt() || task.TaskType == TaskType.出库查看.GetIndexInt() ||
                                         task.TaskType == TaskType.移库.GetIndexInt() || task.TaskType == TaskType.移位.GetIndexInt()))
                                    {
                                        //TODO:判断该出库口是否有任务未完成

                                        //解析任务并下发
                                        if (task.TaskType != TaskType.移库.GetIndexInt() || task.TaskType != TaskType.移位.GetIndexInt())  //不是移库、移位的任务,都需要解析出库站台
                                        {
                                            Location  from    = locations.FirstOrDefault(t => t.Code == task.FromLocationCode);
                                            Equipment station = Stations.FirstOrDefault(t => t.Code == task.ToPort);
                                            if (from != null && station != null)
                                            {
                                                task.TaskStatus = TaskEntityStatus.发堆垛机库内取货.GetIndexInt();

                                                var res = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                                if (res.Success)
                                                {
                                                    var result = SendTaskToStocker(stocker, plc, SuperSRMTaskMode.完整任务,
                                                                                   SRMForkTaskFlag.库内取货, from.RowIndex1.ToString(), from.Line.ToString(), from.Layer.ToString(), "0",
                                                                                   SRMForkTaskFlag.库外放货, station.RowIndex1.ToString(), station.ColumnIndex.ToString(), station.LayerIndex.ToString(), station.StationIndex.ToString(),
                                                                                   task.Id.ToString(), TaskAccount.New);
                                                    if (result.Success)
                                                    {
                                                        Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}成功,库位:{from.Code},出库口:{task.ToPort}", LogLevel.Info);
                                                        return(BllResultFactory.Sucess());
                                                    }
                                                    else
                                                    {
                                                        Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}失败:{result.Msg};回滚任务{task.Id}状态。", LogLevel.Error);
                                                        task.TaskStatus = TaskEntityStatus.发任务.GetIndexInt();
                                                        AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                                        return(BllResultFactory.Error());
                                                    }
                                                }
                                                else
                                                {
                                                    Logger.Log($"下发堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{res.Msg}", LogLevel.Error);
                                                    return(BllResultFactory.Error($"下发堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{res.Msg}"));
                                                }
                                            }
                                            return(BllResultFactory.Error($"任务:{task.Id}对应的来源库位:{task.FromLocationCode}和去向站台:{task.ToPort}出现的了问题"));
                                        }
                                        else
                                        {
                                            Location from = locations.Where(t => t.Code == task.FromLocationCode).FirstOrDefault();
                                            Location to   = locations.Where(t => t.Code == task.ToLocationCode).FirstOrDefault();
                                            if (from != null && to != null)
                                            {
                                                task.TaskStatus = TaskEntityStatus.发堆垛机库内取货.GetIndexInt();

                                                var res = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                                if (res.Success)
                                                {
                                                    BllResult result;
                                                    if (task.TaskType == TaskType.移库.GetIndexInt())
                                                    {
                                                        result = SendTaskToStocker(stocker, plc, SuperSRMTaskMode.完整任务,
                                                                                   SRMForkTaskFlag.库内取货, from.RowIndex1.ToString(), from.Line.ToString(), from.Layer.ToString(), "0",
                                                                                   SRMForkTaskFlag.库内放货, to.RowIndex1.ToString(), to.Line.ToString(), to.Layer.ToString(), "0",
                                                                                   task.Id.ToString(), TaskAccount.New);
                                                    }
                                                    else
                                                    {
                                                        result = SendTaskToStocker(stocker, plc, SuperSRMTaskMode.无,
                                                                                   SRMForkTaskFlag.无任务, from.RowIndex1.ToString(), from.Line.ToString(), from.Layer.ToString(), "0",
                                                                                   SRMForkTaskFlag.无任务, to.RowIndex1.ToString(), to.Line.ToString(), to.Layer.ToString(), "0",
                                                                                   task.Id.ToString(), TaskAccount.New);
                                                    }
                                                    if (result.Success)
                                                    {
                                                        Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}成功,库位:{from.Code},出库口:{task.ToPort}", LogLevel.Info);
                                                        return(BllResultFactory.Sucess());
                                                    }
                                                    else
                                                    {
                                                        Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}失败:{result.Msg};回滚任务{task.Id}状态。", LogLevel.Error);
                                                        task.TaskStatus = TaskEntityStatus.发任务.GetIndexInt();
                                                        AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                                        return(BllResultFactory.Error());
                                                    }
                                                }
                                                else
                                                {
                                                    Logger.Log($"下发堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{res.Msg}", LogLevel.Error);
                                                    return(BllResultFactory.Error($"下发堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{res.Msg}"));
                                                }
                                            }
                                            return(BllResultFactory.Error($"任务类型:{task.TaskType}对应的来源库位:{task.FromLocationCode}和目标库位:{task.ToLocationCode}"));
                                        }
                                    }
                                    //入库性质的任务
                                    if (task.TaskStatus == TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt() &&
                                        (task.TaskType == TaskType.整盘入库.GetIndexInt() || task.TaskType == TaskType.空容器入库.GetIndexInt() ||
                                         task.TaskType == TaskType.补充入库.GetIndexInt() || task.TaskType == TaskType.分拣出库.GetIndexInt() ||
                                         task.TaskType == TaskType.盘点.GetIndexInt() || task.TaskType == TaskType.出库查看.GetIndexInt()))
                                    {
                                        Location  to      = locations.Where(t => t.Code == task.ToLocationCode).FirstOrDefault();
                                        Equipment station = Stations.Where(t => t.Code == task.Gateway).FirstOrDefault();
                                        if (station != null && to != null)
                                        {
                                            task.TaskStatus = TaskEntityStatus.发堆垛机库外取货.GetIndexInt();

                                            var res = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                            if (res.Success)
                                            {
                                                var result = SendTaskToStocker(stocker, plc, SuperSRMTaskMode.完整任务,
                                                                               SRMForkTaskFlag.库外取货, station.RowIndex1.ToString(), station.ColumnIndex.ToString(), station.LayerIndex.ToString(), station.StationIndex.ToString(),
                                                                               SRMForkTaskFlag.库内放货, to.RowIndex1.ToString(), to.Line.ToString(), to.Layer.ToString(), "0",
                                                                               task.Id.ToString(), TaskAccount.New);
                                                if (result.Success)
                                                {
                                                    Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}成功,库位:{to.Code},入库站台:{task.Gateway}", LogLevel.Info);
                                                    return(BllResultFactory.Sucess());
                                                }
                                                else
                                                {
                                                    Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}失败:{result.Msg};回滚任务{task.Id}状态。", LogLevel.Error);
                                                    task.TaskStatus = TaskEntityStatus.响应接入站台到达.GetIndexInt();
                                                    AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                                    return(BllResultFactory.Error());
                                                }
                                            }
                                            else
                                            {
                                                Logger.Log($"下发堆垛机{stocker.Name}库外取货时,更新任务{task.Id}状态失败:{res.Msg}", LogLevel.Error);
                                                return(BllResultFactory.Error($"下发堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{res.Msg}"));
                                            }
                                        }

                                        return(BllResultFactory.Error($"任务:{task.Id}对应的库位:{task.FromLocationCode},{task.ToLocationCode}和接入站台:{task.Gateway},{task.ToPort}出现的了问题"));
                                    }

                                    //入库性质的换站任务
                                    if (task.TaskStatus == TaskEntityStatus.响应堆垛机库外取货完成.GetIndexInt() && task.TaskType == TaskType.换站.GetIndexInt())
                                    {
                                        Equipment station = Stations.Where(t => t.Code == task.Gateway).FirstOrDefault();
                                        Equipment to      = Stations.Where(t => t.Code == task.ToPort).FirstOrDefault();
                                        if (station != null && to != null)
                                        {
                                            task.TaskStatus = TaskEntityStatus.发堆垛机库外取货.GetIndexInt();

                                            var res = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                            if (res.Success)
                                            {
                                                var result = SendTaskToStocker(stocker, plc, SuperSRMTaskMode.完整任务,
                                                                               SRMForkTaskFlag.库外取货, station.RowIndex1.ToString(), station.ColumnIndex.ToString(), station.LayerIndex.ToString(), station.StationIndex.ToString(),
                                                                               SRMForkTaskFlag.库外放货, to.RowIndex1.ToString(), to.ColumnIndex.ToString(), to.LayerIndex.ToString(), to.StationIndex.ToString(),
                                                                               task.Id.ToString(), TaskAccount.New);
                                                if (result.Success)
                                                {
                                                    Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}成功,库位:{to.Code},入库站台:{task.Gateway}", LogLevel.Info);
                                                    return(BllResultFactory.Sucess());
                                                }
                                                else
                                                {
                                                    Logger.Log($"下发堆垛机{stocker.Name},任务:{task.Id},任务类型:{task.TaskType},货叉类型:{SRMForkTaskFlag.库内取货}失败:{result.Msg};回滚任务{task.Id}状态。", LogLevel.Error);
                                                    task.TaskStatus = TaskEntityStatus.响应接入站台到达.GetIndexInt();
                                                    AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                                    return(BllResultFactory.Error());
                                                }
                                            }
                                            else
                                            {
                                                Logger.Log($"下发堆垛机{stocker.Name}库外取货时,更新任务{task.Id}状态失败:{res.Msg}", LogLevel.Error);
                                                return(BllResultFactory.Error($"下发堆垛机{stocker.Name}库内取货时,更新任务{task.Id}状态失败:{res.Msg}"));
                                            }
                                        }

                                        return(BllResultFactory.Error($"任务:{task.Id}对应的接入站台:{task.Gateway},{task.ToPort}出现的了问题"));
                                    }
                                    {
                                        Logger.Log($"堆垛机{stocker.Name}待机空闲,出现有任务需要执行,但是任务状态{task.TaskStatus}和任务类型{task.TaskTypeDesc}不匹配", LogLevel.Error);
                                        return(BllResultFactory.Error());
                                    }
                                }
                                else
                                {
                                    var tmpTsk = tempTasks.Where(t => t.TaskStatus > TaskEntityStatus.发任务.GetIndexInt());
                                    if (tmpTsk != null)
                                    {
                                        Logger.Log($"堆垛机{stocker.Name}待机空闲,出现有任务需要执行,但是根据条件没刷选出任何任务", LogLevel.Error);
                                        return(BllResultFactory.Error());
                                    }
                                    return(BllResultFactory.Sucess());
                                }
                            }
                        }
                    }

                    else
                    {
                        //hack:其他情况1-库内取货,2-库内放货,3-库外入库,4库外出库, 5重新分配入库地址,暂时不做处理,这里也应不需要处理这些情况
                    }
                }
                else if (Fork1TaskExecuteStatus == SRMTaskExcuteStatus.任务完成.GetIndexString())
                {
                    //todo:响应任务完成
                    //一共4种完成情况  高速堆垛机只有2中情况会有完成信号  库外出库和库内放货
                    //根据任务号和货叉类型进行任务完成处理
                    int taskNo   = int.Parse(stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "Fork1TaskNo").Value);
                    int forkType = int.Parse(stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "Fork1TaskType").Value);

                    //库内放货完成
                    if (forkType == SRMForkTaskFlag.库内放货.GetIndexInt())
                    {
                        var task = tasks.FirstOrDefault(t => t.Id == taskNo && t.TaskStatus < TaskEntityStatus.任务完成.GetIndexInt() && t.TaskStatus >= TaskEntityStatus.发堆垛机库内取货.GetIndexInt() &&
                                                        locations.Count(a => a.Code == t.ToLocationCode) > 0);
                        if (task != null)
                        {
                            //调用WMS任务完成接口  ---- TODO:huhai20190416先注解

                            //var tempResult = AppSession.Dal.CompleteTask(task.Id.ToString(), AppSession.Client, AppSession.Urls);
                            //if (!tempResult.Success)
                            //{
                            //    Logger.Log($"任务{task.Id}状态修改失败!!", LogLevel.Error);
                            //}
                            task.TaskStatus = TaskEntityStatus.任务完成.GetIndexInt();
                            var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                            if (tempResult.Success)
                            {
                                //标记交换区地址,任务完成10
                                //var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1TaskFlag");
                                //prop.Value = "10";
                                var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSTaskAccount");
                                prop.Value = TaskAccount.OK.GetIndexString();
                                //var sendResult = S7Helper.PlcSplitWrite(plc, new List<EquipmentProp> { prop }, 20);
                                var sendResult = plc.Writes(new List <EquipmentProp> {
                                    prop
                                });
                                if (sendResult.Success)
                                {
                                    Logger.Log($"堆垛机{stocker.Name}完成库内放货成功,任务:{task.Id}", LogLevel.Success);
                                    return(BllResultFactory.Sucess());
                                }
                                else
                                {
                                    //hack:这里如果更新PLC地址失败,WMS端并不会回滚,此时应考虑如何人工处理;
                                    Logger.Log($"堆垛机{stocker.Name}完成库内放货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                    return(BllResultFactory.Error());
                                }
                            }
                            else
                            {
                                Logger.Log($"完成堆垛机{stocker.Name}库内放货失败,任务{task.Id}请求WMS接口失败:{tempResult.Msg}", LogLevel.Error);
                                return(BllResultFactory.Error($"完成堆垛机{stocker.Name}库内放货失败,任务{task.Id}请求WMS接口失败:{tempResult.Msg}"));
                            }
                        }
                    }
                    //库外放货完成时
                    else if (forkType == SRMForkTaskFlag.库外放货.GetIndexInt())
                    {
                        var task = tasks.FirstOrDefault(t => t.Id == taskNo && t.TaskStatus <TaskEntityStatus.发堆垛机库外放货.GetIndexInt() && t.TaskStatus> TaskEntityStatus.发任务.GetIndexInt() &&
                                                        locations.Count(a => a.Code == t.FromLocationCode) > 0);
                        if (task != null)
                        {
                            //更新任务状态
                            int preStatus = task.TaskStatus;
                            task.TaskStatus = TaskEntityStatus.响应堆垛机库外放货完成.GetIndexInt();
                            var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                            if (tempResult.Success)
                            {
                                //标记交换区地址,任务完成10
                                //var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSFork1TaskFlag");
                                //prop.Value = "10";
                                var prop = stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "WCSTaskAccount");
                                prop.Value = "10";
                                //var sendResult = S7Helper.PlcSplitWrite(plc, new List<EquipmentProp> { prop }, 20);
                                var sendResult = plc.Writes(new List <EquipmentProp> {
                                    prop
                                });
                                if (sendResult.Success)
                                {
                                    Logger.Log($"堆垛机{stocker.Name}完成库外放货成功,任务:{task.Id}", LogLevel.Success);
                                    return(BllResultFactory.Sucess());
                                }
                                else
                                {
                                    Logger.Log($"堆垛机{stocker.Name}完成库外放货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error);
                                    task.TaskStatus = preStatus;
                                    AppSession.Dal.UpdateCommonModel <TaskEntity>(task);
                                    return(BllResultFactory.Error());
                                }
                            }
                            else
                            {
                                Logger.Log($"完成堆垛机{stocker.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error);
                                return(BllResultFactory.Error($"完成堆垛机{stocker.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}"));
                            }
                        }
                    }
                    //未知情况
                    Logger.Log($"堆垛机{stocker.Name}的任务完成时候和系统对应的任务出现了异常:PLC:{taskNo}或 货叉的任务类型:{forkType} ", LogLevel.Warning);
                    return(BllResultFactory.Error($"堆垛机{stocker.Name}的任务完成时候和系统对应的任务出现了异常:PLC:{taskNo}或 货叉的任务类型:{forkType} "));
                }
                else
                {
                    //Logger.Log($"堆垛机{stocker.Name}的任务完成时候和系统对应的任务出现了异常:PLC:{taskNo}或 货叉的任务类型:{forkType} ", LogLevel.Warning);
                    //未知情况
                    Logger.Log($"堆垛机{stocker.Name}出现了未知的执行状态:{stocker.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "Fork1TaskExcuteStatus").Value}", LogLevel.Warning);
                    return(BllResultFactory.Sucess());
                }
            }
            return(BllResultFactory.Sucess());
        }