using HH.WCS.JunzhouNongfu.device; using HH.WCS.Mobox3.YNJT_BZP.api; using HH.WCS.Mobox3.YNJT_BZP.dispatch; using HH.WCS.Mobox3.YNJT_BZP.models; using HH.WCS.Mobox3.YNJT_BZP.process; using HH.WCS.Mobox3.YNJT_BZP.util; using HH.WCS.Mobox3.YNJT_BZP.wms; using Newtonsoft.Json; using Org.BouncyCastle.Asn1.X509; using S7.Net; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Runtime.Remoting.Metadata.W3cXsd2001; using System.Threading.Tasks; 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)) { LogHelper.Info("任务号为空", "AGV"); } else { var TN_Task = WCSHelper.GetTask(model.No); if (TN_Task != null) { var wmsTask = WMSHelper.GetWmsTask(TN_Task.S_OP_CODE); if (wmsTask != null && wmsTask.N_B_STATE < 2) { if (model.State <= 7) { //有任务号请求 switch (model.State) { case 1: TN_Task.S_EQ_NO = model.ForkliftNo; WCSHelper.Begin(TN_Task); break; #region MyRegion case 3: WCSHelper.UpdateStatus(TN_Task, "开始取货"); break; case 4: WCSHelper.UpdateStatus(TN_Task, "取货完成"); TaskProcess.OperateStatus(TN_Task, 4); break; case 5: WCSHelper.UpdateStatus(TN_Task, "开始卸货"); break; 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) { LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV任务完成,任务信息回报GT", "AGV"); string shift = ApiHelper.getShift(DateTime.Now.TimeOfDay); string ydate= ""; if (shift == "III") { ydate = DateTime.Now.AddDays(-1).ToString("dd/MM/yy"); } else { ydate = DateTime.Now.ToString("dd/MM/yy"); } Trfloc trfloc = new Trfloc() { recid = 1, ydate = ydate, shift = shift, bc_entried = cntrItemRels[0].S_CG_ID, loc_from = TN_Task.S_START_LOC, loc_to = TN_Task.S_END_LOC, qty = cntrItemRels[0].F_QTY, lot = 1, scantime = TN_Task.T_CREATE.ToString("yyyy-MM-dd HH:mm:ss"), pic = model.ForkliftNo, last_modify_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") }; } break; case 7: LogHelper.Info($"任务号:{TN_Task.S_CODE},AGV任务取消", "AGV"); //判断是否收到过强制取消,有就不做任何处理 if (!WCSHelper.CheckActionRecordExist(TN_Task.S_CODE, 17)) { TaskProcess.OperateStatus(TN_Task, 7); WCSHelper.Cancel(TN_Task); } break; } } else if (model.State == 1003) { 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); } } } } catch (Exception ex) { LogHelper.Info($"agv回报错误,错误原因:{ex.Message}", "AGV"); } } /// /// 创建最后一个任务 /// /// /// /// 1.入库 2.出库 /// public static WCSTask createLastTask(string startLocCode , WMSTask mst ,int actType ,string typeName = null) { LogHelper.Info($"作业号:{mst.S_CODE},创建下一段任务", "WMS"); var existTask = WCSHelper.GetTaskByStart(startLocCode); if (existTask == null) { var startLoc = LocationHelper.GetLoc(startLocCode); if (startLoc != null) { string cntrCode = ""; string scheduleType = ""; if (actType == 1) { var locCntrRels = LocationHelper.GetLocCntr(startLocCode); if (locCntrRels.Count > 0) { foreach (var cntr in locCntrRels) { cntrCode = cntrCode + "," + cntr.S_CNTR_CODE; } cntrCode = cntrCode.Substring(1, cntrCode.Length - 1); } scheduleType = "WCS"; } 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 = 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); WMSHelper.UpdateTaskEnd(mst); return wcsTask; } } } return null; } /// /// 任务分发,根据调度类型发给不同的调度系统 /// internal static void Dispatch() { var db = new SqlHelper().GetInstance(); //查询任务 //获取所有等待的任务 var list = WCSHelper.GetWaitingTaskList(); if (list.Count > 0) { foreach (var task in list) { if (!TaskProcess.Intercept(task)) { //使用自定义任务推送 TaskProcess.SendTask(task); } } } } private static readonly object emptyTrayInLock = new object(); // 静态锁对象 /// /// agv申请终点 /// /// public static Location AGVApplyEndLoc(string taskNo) { LogHelper.Info($"任务号:{taskNo},AGV等待区申请终点", "AGV"); var cst = WCSHelper.GetTask(taskNo); 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 == "虚拟货位") { var container = ContainerHelper.GetCntr(cst.S_CNTR_CODE); if (container != null) { string itemCode = null; var cntrItemRels = ContainerHelper.GetCntrItemRel(cst.S_CNTR_CODE); if (cntrItemRels.Count > 0) { // 满料托盘入库 itemCode = cntrItemRels[0].S_ITEM_CODE; int itemType = cntrItemRels[0].N_PRODUCT_TYPE_CODE; var endLoc = WMSHelper.GetInstockEndLoc(container.N_TYPE, null, 1, itemCode); 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 { // 空托盘回库 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"); } } else { LogHelper.Info($"任务号:{taskNo},AGV任务已完成或取消", "AGV"); } return null; } } }