| | |
| | | using static HH.WCS.Mobox3.YNJT_BZP.api.AgvController; |
| | | using static HH.WCS.Mobox3.YNJT_BZP.api.ApiModel; |
| | | using static HH.WCS.Mobox3.YNJT_BZP.dispatch.GtDispatch; |
| | | using static HH.WCS.Mobox3.YNJT_BZP.util.Settings; |
| | | |
| | | namespace HH.WCS.Mobox3.YNJT_BZP.core { |
| | | internal class WCSCore { |
| | | public static void OperateAgvTaskStatus(AgvTaskState model) { |
| | | LogHelper.Info($"AGV任务状态反馈,入参:{JsonConvert.SerializeObject(model)}", "AGV"); |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(model.No)) |
| | |
| | | var TN_Task = WCSHelper.GetTask(model.No); |
| | | if (TN_Task != null) |
| | | { |
| | | bool isExist = WCSHelper.CheckActionRecordExist(TN_Task.S_CODE, model.State); |
| | | if (!isExist) |
| | | var wmsTask = WMSHelper.GetWmsTask(TN_Task.S_OP_CODE); |
| | | if (wmsTask != null && wmsTask.N_B_STATE < 2) |
| | | { |
| | | WCSHelper.AddActionRecord(model.No, model.State, model.ForkliftNo, model.ExtData); |
| | | if (model.State <= 7) |
| | | { |
| | | //有任务号请求 |
| | | switch (model.State) |
| | | { |
| | | case 1: |
| | | TN_Task.S_EQ_NO = model.ForkliftNo; |
| | | WCSHelper.Begin(TN_Task); |
| | | break; |
| | | #region MyRegion |
| | |
| | | case 6: |
| | | TaskProcess.OperateStatus(TN_Task, 6); |
| | | WCSHelper.UpdateStatus(TN_Task, "卸货完成"); |
| | | |
| | | // AGV卸货输送线,触发入库任务 |
| | | if (TN_Task.S_END_LOC != wmsTask.S_END_LOC) |
| | | { |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV卸货输送线,触发WCS入库任务", "AGV"); |
| | | Container container = ContainerHelper.GetCntr(TN_Task.S_CNTR_CODE); |
| | | if (container != null) |
| | | { |
| | | WCSCore.createLastTask(TN_Task.S_END_LOC, wmsTask, 1); |
| | | } |
| | | } |
| | | break; |
| | | #endregion |
| | | case 2: |
| | | WCSHelper.End(TN_Task); |
| | | |
| | | var cntrItemRels = ContainerHelper.GetCntrItemRel(TN_Task.S_CNTR_CODE); |
| | | if (cntrItemRels.Count > 0) |
| | | if (cntrItemRels.Count > 0) |
| | | { |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV任务完成,任务信息回报GT", "AGV"); |
| | | string shift = ApiHelper.getShift(DateTime.Now.TimeOfDay); |
| | | string ydate_shiftName = ""; |
| | | if (shift == "III") |
| | | { |
| | | ydate_shiftName = DateTime.Now.AddDays(-1).ToString("yy/MM/dd") + "-" + shift; |
| | | } |
| | | else |
| | | else |
| | | { |
| | | ydate_shiftName = DateTime.Now.ToString("yy/MM/dd") + "-" + shift; |
| | | } |
| | |
| | | } |
| | | break; |
| | | case 7: |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV任务取消", "AGV"); |
| | | //判断是否收到过强制取消,有就不做任何处理 |
| | | if (!WCSHelper.CheckActionRecordExist(TN_Task.S_CODE, 17)) |
| | | { |
| | |
| | | break; |
| | | } |
| | | } |
| | | else if (model.State == 2001) |
| | | else if (model.State == 1003) |
| | | { |
| | | //申请新终点 |
| | | string endLoc = AGVApplyEndLoc(model.No); |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV小车进入等待位:{TN_Task.S_END_LOC}", "AGV"); |
| | | // 卸货前等待 |
| | | // 查询当前终点是等待区,则查询入库agv接驳位 |
| | | var waitLoc = Settings.getAgvWaitLoc(TN_Task.S_END_LOC); |
| | | if (waitLoc != null) |
| | | { |
| | | if (TN_Task.S_TYPE.Contains("入库")) |
| | | { |
| | | var endLoc = AGVApplyEndLoc(model.No); |
| | | if (endLoc != null) |
| | | { |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV小车变更终点:{endLoc.S_CODE}", "AGV"); |
| | | // 通知AGV更改终点 |
| | | ChangeParamModel paramModel = new ChangeParamModel() |
| | | { |
| | | task_no = model.No, |
| | | param_no = 0, |
| | | param = $"{model.No};{TN_Task.S_START_LOC};{TN_Task.S_END_LOC};0;400;0;2" |
| | | }; |
| | | LogHelper.Info($"通知AGV更改终点,参数:{paramModel}", "AGV"); |
| | | /* NDCApi.ChangeOrderParam(paramModel);*/ |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else if (model.State == 1004) |
| | | { |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV小车卸货后在接驳位:{TN_Task.S_END_LOC}等待", "AGV"); |
| | | // 卸货后等待 |
| | | // 查询终点货位是否是入库接驳位 |
| | | var agvJBLoc = Settings.getAgvJBLoc(TN_Task.S_END_LOC); |
| | | if (agvJBLoc != null && agvJBLoc.action == 1) |
| | | { |
| | | //是则查询WCS的任务执行情况 |
| | | var wcsTask = WCSHelper.GetTaskBySrcNoAndScheduleType(TN_Task.S_OP_CODE, "WCS" , wmsTask.S_TYPE); |
| | | if (wcsTask != null) |
| | | { |
| | | bool existAction = WCSHelper.CheckActionRecordExist(wcsTask.S_CODE, 7); |
| | | if (existAction) |
| | | { |
| | | LogHelper.Info($"下游任务:{wcsTask.S_CODE}取消入库,rfid校验失败,生成新任务到异常区", "AGV"); |
| | | //如果WCS反馈7取消任务,则rfid校验失败,生成新任务到异常区,并变更agv任务号、起点、终点 |
| | | var mst = WMSHelper.GetWmsTask(TN_Task.S_OP_CODE); |
| | | var endLoc = WMSHelper.getErrorBufferAreaLoc(); |
| | | if (endLoc != null) |
| | | { |
| | | LocationHelper.UnLockLoc(mst.S_END_LOC); |
| | | mst.S_END_LOC = endLoc.S_CODE; |
| | | mst.S_END_AREA = endLoc.S_AREA_CODE; |
| | | |
| | | var newWcsTask = WCSCore.createLastTask(TN_Task.S_END_LOC, mst, 2, "出库异常区任务"); |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV小车改道终点:{newWcsTask.S_END_LOC}", "AGV"); |
| | | if (newWcsTask != null) |
| | | { |
| | | WCSHelper.End(TN_Task); |
| | | |
| | | // 通知AGV更改终点 |
| | | ChangeParamModel paramModel = new ChangeParamModel() |
| | | { |
| | | task_no = model.No, |
| | | param_no = 0, |
| | | param = $"{model.No};{newWcsTask.S_START_LOC};{newWcsTask.S_END_LOC};0;0;0;1" |
| | | }; |
| | | LogHelper.Info($"通知AGV更改终点,参数:{paramModel}", "AGV"); |
| | | /*NDCApi.ChangeOrderParam(paramModel);*/ |
| | | } |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info("异常区没有空货位,无法入库异常区", "AGV"); |
| | | } |
| | | } |
| | | |
| | | existAction = WCSHelper.CheckActionRecordExist(wcsTask.S_CODE, 3); |
| | | if (existAction) |
| | | { |
| | | LogHelper.Info($"任务号:{TN_Task.S_CODE},RFID检测通过,AGV任务正常完成", "AGV"); |
| | | //WCS反馈3已取货,则agv任务正常结束 ,通知AGV完成任务 |
| | | ChangeParamModel paramModel = new ChangeParamModel() |
| | | { |
| | | task_no = model.No, |
| | | param_no = 0, |
| | | param = $"{model.No};{TN_Task.S_START_LOC};{TN_Task.S_END_LOC};0;0;0;1" |
| | | }; |
| | | LogHelper.Info($"通知AGV完成任务,参数:{paramModel}", "AGV"); |
| | | /*NDCApi.ChangeOrderParam(paramModel);*/ |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //安全请求等 |
| | | TaskProcess.OperateReq(model.No, model.State, model.ForkliftNo, model.ExtData); |
| | | } |
| | | |
| | | WCSHelper.AddActionRecord(model.No, model.State, model.ForkliftNo, model.ExtData); |
| | | } |
| | | } |
| | | } |
| | |
| | | /// <param name="mst"></param> |
| | | /// <param name="actType">1.入库 2.出库</param> |
| | | /// <returns></returns> |
| | | public static bool createLastTask(string startLocCode , WMSTask mst ,int actType) |
| | | public static WCSTask createLastTask(string startLocCode , WMSTask mst ,int actType ,string typeName = null) |
| | | { |
| | | LogHelper.Info("创建下一段任务", "WMS"); |
| | | var startLoc = LocationHelper.GetLoc(startLocCode); |
| | | if (startLoc != null) |
| | | LogHelper.Info($"作业号:{mst.S_CODE},创建下一段任务", "WMS"); |
| | | var existTask = WCSHelper.GetTaskByStart(startLocCode); |
| | | if (existTask == null) |
| | | { |
| | | string cntrCode = ""; |
| | | string scheduleType = ""; |
| | | if (actType == 1) |
| | | var startLoc = LocationHelper.GetLoc(startLocCode); |
| | | if (startLoc != null) |
| | | { |
| | | var locCntrRels = LocationHelper.GetLocCntr(startLocCode); |
| | | if (locCntrRels.Count > 0) |
| | | string cntrCode = ""; |
| | | string scheduleType = ""; |
| | | if (actType == 1) |
| | | { |
| | | foreach (var cntr in locCntrRels) |
| | | var locCntrRels = LocationHelper.GetLocCntr(startLocCode); |
| | | if (locCntrRels.Count > 0) |
| | | { |
| | | cntrCode = cntrCode + ","+ cntr.S_CNTR_CODE; |
| | | foreach (var cntr in locCntrRels) |
| | | { |
| | | cntrCode = cntrCode + "," + cntr.S_CNTR_CODE; |
| | | } |
| | | cntrCode = cntrCode.Substring(1, cntrCode.Length - 1); |
| | | } |
| | | cntrCode = cntrCode.Substring(1, cntrCode.Length-1); |
| | | scheduleType = "WCS"; |
| | | } |
| | | scheduleType = "WCS"; |
| | | } |
| | | |
| | | if (actType == 2) |
| | | { |
| | | cntrCode = mst.S_CNTR_CODE; |
| | | scheduleType = "AGV"; |
| | | } |
| | | if (actType == 2) |
| | | { |
| | | cntrCode = mst.S_CNTR_CODE; |
| | | scheduleType = "AGV"; |
| | | } |
| | | string type = ""; |
| | | if (typeName == null) |
| | | { |
| | | type = mst.S_TYPE + "-2"; |
| | | } |
| | | else |
| | | { |
| | | type = typeName; |
| | | } |
| | | |
| | | // 创建一段入库任务 |
| | | WCSTask wcsTask = new WCSTask() |
| | | { |
| | | S_OP_NAME = mst.S_OP_DEF_NAME, |
| | | S_OP_CODE = mst.S_CODE, |
| | | S_CODE = WCSHelper.GenerateTaskNo(), |
| | | S_CNTR_CODE = cntrCode, |
| | | S_TYPE = mst.S_TYPE + "-2", |
| | | S_START_LOC = startLoc.S_CODE, |
| | | S_START_AREA = startLoc.S_AREA_CODE, |
| | | S_END_LOC = mst.S_END_LOC, |
| | | S_END_AREA = mst.S_END_AREA, |
| | | S_SCHEDULE_TYPE = scheduleType, |
| | | N_PRIORITY = mst.N_PRIORITY, |
| | | T_START_TIME = DateTime.Now, |
| | | }; |
| | | // 创建一段入库任务 |
| | | WCSTask wcsTask = new WCSTask() |
| | | { |
| | | S_OP_NAME = mst.S_OP_DEF_NAME, |
| | | S_OP_CODE = mst.S_CODE, |
| | | S_CODE = WCSHelper.GenerateTaskNo(), |
| | | S_CNTR_CODE = cntrCode, |
| | | S_TYPE = type, |
| | | S_START_LOC = startLoc.S_CODE, |
| | | S_START_AREA = startLoc.S_AREA_CODE, |
| | | S_END_LOC = mst.S_END_LOC, |
| | | S_END_AREA = mst.S_END_AREA, |
| | | S_SCHEDULE_TYPE = scheduleType, |
| | | N_PRIORITY = mst.N_PRIORITY, |
| | | T_START_TIME = DateTime.Now, |
| | | }; |
| | | |
| | | if (WCSHelper.CreateTask(wcsTask)) |
| | | { |
| | | // 起点、接驳点、终点加锁 |
| | | LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); |
| | | LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); |
| | | if (WCSHelper.CreateTask(wcsTask)) |
| | | { |
| | | // 起点、接驳点、终点加锁 |
| | | LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); |
| | | LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); |
| | | |
| | | WMSHelper.UpdateTaskEnd(mst); |
| | | return true; |
| | | WMSHelper.UpdateTaskEnd(mst); |
| | | return wcsTask; |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | return null; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | private static readonly object emptyTrayInLock = new object(); // 静态锁对象 |
| | | |
| | | /// <summary> |
| | | /// agv申请终点 |
| | | /// </summary> |
| | | /// <param name="taskNo"></param> |
| | | public static string AGVApplyEndLoc(string taskNo) |
| | | public static Location AGVApplyEndLoc(string taskNo) |
| | | { |
| | | LogHelper.Info("【agv申请终点】", "AGV"); |
| | | string endLocCode = null; |
| | | LogHelper.Info($"任务号:{taskNo},AGV等待区申请终点", "AGV"); |
| | | var cst = WCSHelper.GetTask(taskNo); |
| | | if (cst != null && cst.N_B_STATE < 3) |
| | | if (cst != null && cst.N_B_STATE < 3) |
| | | { |
| | | var mst = WMSHelper.GetWmsTask(cst.S_OP_CODE); |
| | | if (mst != null && mst.N_B_STATE < 2 && mst.S_END_LOC == "虚拟货位") |
| | | if (mst != null && mst.N_B_STATE < 2 && mst.S_END_LOC == "虚拟货位") |
| | | { |
| | | var container = ContainerHelper.GetCntr(cst.S_CNTR_CODE); |
| | | if (container != null) |
| | | if (container != null) |
| | | { |
| | | var endLoc = WMSHelper.GetInstockEndLoc(container.N_TYPE); |
| | | if (endLoc != null) |
| | | string itemCode = null; |
| | | var cntrItemRels = ContainerHelper.GetCntrItemRel(cst.S_CNTR_CODE); |
| | | if (cntrItemRels.Count > 0) |
| | | { |
| | | Location agvLoc = null; |
| | | var locCodes = Settings.getAgvJBLocList(1, endLoc.N_ROADWAY, 1); |
| | | if (locCodes.Count > 0) |
| | | // 满料托盘入库 |
| | | itemCode = cntrItemRels[0].S_ITEM_CODE; |
| | | var endLoc = WMSHelper.GetInstockEndLoc(container.N_TYPE, null, 1, itemCode); |
| | | if (endLoc != null) |
| | | { |
| | | agvLoc = LocationHelper.GetLoc(locCodes[0]); |
| | | } |
| | | |
| | | if (agvLoc != null && agvLoc.C_ENABLE == "Y") |
| | | { |
| | | var wcsTask = WCSHelper.GetTaskByStartAndEnd(agvLoc.S_CODE); |
| | | if (wcsTask == null && agvLoc.N_LOCK_STATE == 0) |
| | | Location agvLoc = null; |
| | | var locCodes = Settings.getAgvJBLocList( endLoc.N_ROADWAY, 1); |
| | | if (locCodes.Count > 0) |
| | | { |
| | | // 胎圈入库,下发母拖出库任务 \ 帘布、内衬入库,下发托盘回库任务 |
| | | if (mst.S_TYPE.Contains("入库")) |
| | | foreach (var locCode in locCodes) |
| | | { |
| | | if (agvLoc.N_CURRENT_NUM == 1) |
| | | agvLoc = LocationHelper.GetLoc(locCode); |
| | | if (agvLoc != null && agvLoc.C_ENABLE == "Y") |
| | | { |
| | | var locCntrRels = LocationHelper.GetLocCntr(agvLoc.S_CODE); |
| | | if (locCntrRels.Count > 0) |
| | | { |
| | | var container1 = ContainerHelper.GetCntr(locCntrRels[0].S_CNTR_CODE); |
| | | if (container1.N_TYPE == 0) |
| | | { |
| | | if (container.N_TYPE == 4 || container.N_TYPE == 5) |
| | | { |
| | | ApiHelper.baseTrayInStockAgv(agvLoc.S_CODE, mst.S_CODE); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info($"接驳位:{agvLoc.S_CODE},存在非母拖容器", "AGV"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info($"接驳位:{agvLoc.S_CODE}的当前数量与容器数量不匹配", "AGV"); |
| | | } |
| | | } |
| | | else if (agvLoc.N_CURRENT_NUM == 0) |
| | | { |
| | | if (container.N_TYPE == 6) |
| | | { |
| | | ApiHelper.baseTrayOutStockAgv(agvLoc.S_CODE, mst.S_CODE); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | return endLocCode; |
| | | cst.S_END_LOC = agvLoc.S_CODE; |
| | | cst.S_END_AREA = agvLoc.S_AREA_CODE; |
| | | WCSHelper.UpdateTaskEnd(cst); |
| | | |
| | | mst.S_END_LOC = endLoc.S_CODE; |
| | | mst.S_END_AREA = endLoc.S_AREA_CODE; |
| | | WMSHelper.UpdateTaskEnd(mst); |
| | | LocationHelper.LockLoc(endLoc.S_CODE, 1); |
| | | |
| | | LogHelper.Info($"任务号:{taskNo},AGV申请的终点:{agvLoc.S_CODE}", "AGV"); |
| | | return agvLoc; |
| | | } |
| | | } |
| | | cst.S_END_LOC = agvLoc.S_CODE; |
| | | cst.S_END_AREA = agvLoc.S_AREA_CODE; |
| | | WCSHelper.UpdateTaskEnd(cst); |
| | | |
| | | mst.S_END_LOC = endLoc.S_CODE; |
| | | mst.S_END_AREA = endLoc.S_AREA_CODE; |
| | | WMSHelper.UpdateTaskEnd(mst); |
| | | |
| | | LocationHelper.LockLoc(agvLoc.S_CODE, 1); |
| | | LocationHelper.LockLoc(endLoc.S_CODE, 1); |
| | | endLocCode = agvLoc.S_CODE; |
| | | LogHelper.Info($"任务号:{taskNo},入库接驳位货位都已禁用", "AGV"); |
| | | } |
| | | else |
| | | else |
| | | { |
| | | LogHelper.Info("接驳位当前有任务未完成,请稍等", "AGV"); |
| | | LogHelper.Info($"任务号:{taskNo},没有配置立库接驳位", "AGV"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info("没有可用的入库接驳位", "AGV"); |
| | | LogHelper.Info($"任务号:{taskNo},立库没有满足条件的空货位", "AGV"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info("没有空余的货位", "AGV"); |
| | | // 空托盘回库 |
| | | lock (emptyTrayInLock) |
| | | { |
| | | var emptyTrayBuffers = WMSHelper.getEmptyTrayBufferList(); |
| | | if (emptyTrayBuffers.Count > 0) |
| | | { |
| | | var emptyTray = emptyTrayBuffers.Where(a => a.TRAY_TYPE == container.N_TYPE).OrderBy(a => a.T_CREATE).FirstOrDefault(); |
| | | if (emptyTray != null) |
| | | { |
| | | var endLoc = LocationHelper.GetLoc(emptyTray.END_LOC); |
| | | cst.S_END_LOC = endLoc.S_CODE; |
| | | cst.S_END_AREA = endLoc.S_AREA_CODE; |
| | | WCSHelper.UpdateTaskEnd(cst); |
| | | |
| | | mst.S_END_LOC = endLoc.S_CODE; |
| | | mst.S_END_AREA = endLoc.S_AREA_CODE; |
| | | WMSHelper.UpdateTaskEnd(mst); |
| | | LocationHelper.LockLoc(endLoc.S_CODE, 1); |
| | | |
| | | emptyTray.IS_CREATED = "Y"; |
| | | WMSHelper.updateEmptyTrayBuffer(emptyTray); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var endLoc = WMSHelper.GetInstockEndLoc(container.N_TYPE, null, 1); |
| | | if (endLoc != null) |
| | | { |
| | | Location agvLoc = null; |
| | | var locCodes = Settings.getAgvJBLocList(endLoc.N_ROADWAY, 1); |
| | | if (locCodes.Count > 0) |
| | | { |
| | | foreach (var locCode in locCodes) |
| | | { |
| | | agvLoc = LocationHelper.GetLoc(locCode); |
| | | if (agvLoc != null && agvLoc.C_ENABLE == "Y") |
| | | { |
| | | cst.S_END_LOC = agvLoc.S_CODE; |
| | | cst.S_END_AREA = agvLoc.S_AREA_CODE; |
| | | WCSHelper.UpdateTaskEnd(cst); |
| | | |
| | | mst.S_END_LOC = endLoc.S_CODE; |
| | | mst.S_END_AREA = endLoc.S_AREA_CODE; |
| | | WMSHelper.UpdateTaskEnd(mst); |
| | | LocationHelper.LockLoc(endLoc.S_CODE, 1); |
| | | |
| | | LogHelper.Info($"任务号:{taskNo},AGV申请的终点:{agvLoc.S_CODE}", "AGV"); |
| | | return agvLoc; |
| | | } |
| | | } |
| | | |
| | | LogHelper.Info($"任务号:{taskNo},入库接驳位货位都已禁用", "AGV"); |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info($"任务号:{taskNo},没有配置立库接驳位", "AGV"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info($"任务号:{taskNo},立库没有满足条件的空货位", "AGV"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info($"任务号:{taskNo},AGV任务的容器:{cst.S_CNTR_CODE}不存在", "AGV"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info($"任务号:{taskNo},AGV任务已申请终点,请勿重复申请", "AGV"); |
| | | } |
| | | } |
| | | return endLocCode; |
| | | else |
| | | { |
| | | LogHelper.Info($"任务号:{taskNo},AGV任务已完成或取消", "AGV"); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |