GetShelfJob.cs 12.4 KB
using Common;

namespace DeviceLibrary
{
    /// <summary>
    /// 取料串
    /// </summary>
    public class GetShelfJob : Job
    {
        /// <summary>
        ///取料串
        /// </summary>
        /// <param name="agvPlae">agv当前位置</param>
        /// <param name="tarPlace">目的地</param>
        /// <param name="RFID">RFID</param>
        /// <param name="fullShelf">是否是满料串</param>
        public GetShelfJob(string agvPlae, string tarPlace, string RFID = "", bool fullShelf = false)
        {
            this.agvPlace = agvPlae;
            TargetPlace = tarPlace;
            this.isFullShelf = fullShelf;
            this.RFID = RFID;
        }


        /// <summary>
        /// 接收任务时,agv的位置
        /// </summary>
        private string agvPlace = "";
        /// <summary>
        /// 是否是满料串
        /// </summary>
        private bool isFullShelf = false;
        /// <summary>
        /// 目的地
        /// </summary>
        public string TargetPlace { get; private set; }
        private string runInfo = "";
        private string RFID = "";
        /// <summary>
        /// 运行信息
        /// </summary>
        public override string RunInfo
        {
            get
            {
                int t1 = Context.nodeInfo.FindIndex(s => s.Name.Equals(agvPlace));
                string from = "";
                if (t1 > -1)
                    from = Context.nodeInfo[t1].AliceName;
                else
                    from = agvPlace;
                int t2 = Context.nodeInfo.FindIndex(s => s.Name.Equals(TargetPlace));
                string to = "";
                if (t2 > -1)
                    to = Context.nodeInfo[t2].AliceName;
                else
                    to = TargetPlace;
                return string.Format("取{5}料串任务[RFID={4}]: {0}[目的地={1}][任务名称={2}][任务状态={3}]", runInfo, to, CurTaskName, CurTaskState, RFID, isFullShelf ? "满" : "空");
            }
        }

        private JobStep<EXECUTE_STEP> curJobStep = new JobStep<EXECUTE_STEP>(EXECUTE_STEP.P1_NONE);

        private string GetShowInfo()
        {
            int t1 = Context.nodeInfo.FindIndex(s => s.Name.Equals(agvPlace));
            string from = "";
            if (t1 > -1)
                from = Context.nodeInfo[t1].AliceName;
            else
                from = agvPlace;
            int t2 = Context.nodeInfo.FindIndex(s => s.Name.Equals(TargetPlace));
            string to = "";
            if (t2 > -1)
                to = Context.nodeInfo[t2].AliceName;
            else
                to = TargetPlace;
            return string.Format("取料串任务: {0} [{1}->{2}]", runInfo, from, to); ;
        }
        /// <summary>
        /// 任务执行
        /// </summary>
        /// <param name="agv"></param>
        public override Job Execute(Agv_Info agv)
        {
            string msg = agv.Name + " ";
            bool rtn = false;
            agv.Msg = GetShowInfo();
            agv.RFID = RFID;
            CurTaskState = Context.GetTakJobState(agv);
            if (curJobStep.IsStep(EXECUTE_STEP.P1_NONE))
            {

                if ((agvPlace.Equals(SettingString.Standby) || agvPlace.Equals(SettingString.AutoCharge)))
                {
                    curJobStep.ToNextStep(EXECUTE_STEP.P2_WAIT_REACH_SHELF_PLACE);
                    runInfo = "待机位/充电位收到任务,开始执行";
                    msg += runInfo;
                    curJobStep.Msg = msg;
                    Context.MoveToNode(agv, TargetPlace);
                    UpdateJobTaskInfo(agv);
                }
                else
                {
                    curJobStep.ToNextStep(EXECUTE_STEP.P2_WAIT_REACH_SHELF_PLACE);
                    runInfo = "默认位置收到任务,开始执行";
                    msg += runInfo;
                    curJobStep.Msg = msg;

                    Context.MoveToNode(agv, TargetPlace);
                    UpdateJobTaskInfo(agv);
                }
            }
            else if (curJobStep.IsStep(EXECUTE_STEP.P2_WAIT_REACH_SHELF_PLACE))
            {
                if (Context.CheckTaskMoveFinished(agv, TargetPlace, CurTaskState))
                {
                    curJobStep.ToNextStep(EXECUTE_STEP.P4_WAIT_LINE_RESPONSE);
                    runInfo = "到达料架处" + TargetPlace + ",并向线体发送出料请求";
                    msg += runInfo;
                    curJobStep.Msg = msg;

                    Context.server.Ready(TargetPlace, "");

                }
            }
            else if (curJobStep.IsStep(EXECUTE_STEP.P4_WAIT_LINE_RESPONSE))
            {
                int i = Context.nodeInfo.FindIndex(s => s.Name.Equals(TargetPlace));//&& s.StateEquals(eNodeStatus.MayLeave)
                if (i > -1)
                {
                    curJobStep.ToNextStep(EXECUTE_STEP.P5_WAIT_SHELF_IN_AGV);
                    runInfo = "线体" + TargetPlace + "出料,链条运行";
                    msg += runInfo;
                    curJobStep.Msg = msg;
                    rtn = agv.AssignTask(Common.SettingString.Enter);
                    UpdateJobTaskInfo(agv);
                }
                if (curJobStep.IsTimeOut(15000, out double timeOutTime))
                {
                    if (TargetPlace.Equals(SettingString.D3) || TargetPlace.Equals(SettingString.D4))
                    {
                        runInfo = string.Format("线体[{0}]允许出料信号[{1}]超时{2}秒,该处料串可能被手动干预,回待机位", TargetPlace, Agv.ClientAction.MayLeave, timeOutTime.ToString("f2"));
                        msg += string.Format("线体[{0}]允许出料信号[{1}]超时15S,该处料串可能被手动干预,回待机位", TargetPlace, Agv.ClientAction.MayLeave);
                        curJobStep.Msg = msg;
                        return new ChargeJob(TargetPlace);
                    }
                    else
                    {
                        curJobStep.ToNextStep(EXECUTE_STEP.P2_WAIT_REACH_SHELF_PLACE);
                        runInfo = string.Format("线体[{0}]允许出料信号[{1}]超时{2}秒,重发出料请求", TargetPlace, Agv.ClientAction.MayLeave, timeOutTime.ToString("f2"));
                        msg += string.Format("线体[{0}]允许出料信号[{1}]超时15S,重发出料请求", TargetPlace, Agv.ClientAction.MayLeave);
                        curJobStep.Msg = msg;
                        //去待机位
                    }
                }
            }
            else if (curJobStep.IsStep(EXECUTE_STEP.P5_WAIT_SHELF_IN_AGV))
            {
                if (Context.CheckEnterOrLeaveFinished(agv, SettingString.Enter, CurTaskState))
                {
                    //Context.server.CloseDoor(TargetPlace);
                    if (FindShelfTarget(agv, out string tarNodeName))
                    {
                        runInfo = "料串进入小车完成,任务结束";
                        msg += runInfo;
                        curJobStep.Msg = msg;
                        return new SendShelfJob(TargetPlace, tarNodeName, RFID);
                    }
                    else
                    {
                        curJobStep.ToNextStep(EXECUTE_STEP.P6_WAIT_REACH_STANDBY);
                        runInfo = "料串进入小车完成,当前无节点需要料串,去待机位";
                        msg += runInfo;
                        curJobStep.Msg = msg;

                        Context.MoveToNode(agv, SettingString.Standby);
                        UpdateJobTaskInfo(agv);
                    }

                }
                else if (curJobStep.IsTimeOut(60000, out double timeOutTime))
                {
                    runInfo = string.Format("线体[{0}]出料超时{1}秒,请检查出料情况", TargetPlace, timeOutTime.ToString("f2"));
                    msg += string.Format("线体[{0}]出料超时,请检查出料情况", TargetPlace);
                    curJobStep.Msg = msg;
                    //去待机位
                }
            }
            else if (curJobStep.IsStep(EXECUTE_STEP.P6_WAIT_REACH_STANDBY))
            {
                if (Context.CheckTaskMoveFinished(agv, SettingString.Standby, CurTaskState))
                {
                    runInfo = "到达待机位并搜索任务";
                    msg += runInfo;
                    curJobStep.Msg = msg;
                    if (FindShelfTarget(agv, out string tarNodeName))
                    {
                        runInfo = "搜索到料串目的地,任务结束";
                        msg += runInfo;
                        curJobStep.Msg = msg;
                        return new SendShelfJob(SettingString.Standby, tarNodeName, RFID);
                    }

                }
            }
            else if (curJobStep.IsStep(EXECUTE_STEP.P8_END))
            {
                return null;
            }
            return this;
        }

        private bool FindShelfTarget(Agv_Info currentAgv, out string tarPlace)
        {
            tarPlace = "";
            if (isFullShelf)
            {
                //检查云仓入口是否需要满料串入库
                if (IsPlace(SettingString.A3))
                {
                    if (JobType.FindNeedEnterMission(currentAgv, SettingString.D1,false))
                    {
                        if(!BoxInJobType.IsMixString(RFID))
                        {
                            tarPlace = SettingString.D1;
                            return true;
                        }
                    }
                    if (JobType.FindNeedEnterMission(currentAgv, SettingString.D3, false))
                    {
                        tarPlace = SettingString.D3;
                        return true;
                    }
                    if (JobType.FindNeedEnterMission(currentAgv, SettingString.A4, true))
                    {
                        tarPlace = SettingString.A4;
                        return true;
                    }
                }
            }
            else//空料串
            {

                //检查云仓是否需要空料架
                if (IsPlace(SettingString.A1)|| IsPlace(SettingString.D2) || IsPlace(SettingString.D4))
                {
                    if (JobType.FindNeedEnterMission(currentAgv, SettingString.D1, true))
                    {
                        tarPlace = SettingString.D1;
                        return true;
                    }
                    if (JobType.FindNeedEnterMission(currentAgv, SettingString.D3, true))
                    {
                        tarPlace = SettingString.D3;
                        return true;
                    }
                    if (JobType.FindNeedEnterMission(currentAgv, SettingString.A4, true))
                    {
                        tarPlace = SettingString.A4;
                        return true;
                    }
                    if (JobType.FindNeedEnterMission(currentAgv, SettingString.A2, true))
                    {
                        tarPlace = SettingString.A2;
                        return true;
                    }
                }
            }


            return false;
        }

        private bool IsPlace(string place)
        {
            return TargetPlace.Equals(place);
        }
        /// <summary>
        /// 执行流程
        /// </summary>
        private enum EXECUTE_STEP
        {
            /// <summary>
            /// 接收到任务
            /// </summary>
            P1_NONE,
            /// <summary>
            /// 等待到达包装料架处
            /// </summary>
            P2_WAIT_REACH_SHELF_PLACE,
            /// <summary>
            /// 等待到达4D
            /// </summary>
            P3_WAIT_REACH_4D_DOOR,
            /// <summary>
            /// 等待到达4C
            /// </summary>
            P3_WAIT_REACH_4C_DOOR,
            /// <summary>
            /// 等待线体回复
            /// </summary>
            P4_WAIT_LINE_RESPONSE,
            /// <summary>
            /// 等待料架进入AGV
            /// </summary>
            P5_WAIT_SHELF_IN_AGV,
            /// <summary>
            /// 等待到达待机位
            /// </summary>
            P6_WAIT_REACH_STANDBY,
            /// <summary>
            /// 等待到达4D
            /// </summary>
            P7_WAIT_REACH_4D_DOOR,
            /// <summary>
            /// 任务结束
            /// </summary>
            P8_END
        }
    }

}