using HH.WCS.Mobox3.YNJT_BZP.core; using HH.WCS.Mobox3.YNJT_BZP.dispatch; using HH.WCS.Mobox3.YNJT_BZP.util; using HH.WCS.Mobox3.YNJT_BZP.wms; using HH.WCS.Mobox3.YNJT_BZP.api; using Newtonsoft.Json; using NLog.Fluent; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Security.Cryptography; using static HH.WCS.Mobox3.YNJT_BZP.util.Settings; namespace HH.WCS.Mobox3.YNJT_BZP.process { internal class TaskProcess { #region 任务相关 //--------------------------------------------------任务相关-------------------------------------------------- /// /// 取货卸货完成,缓存位状态更新 /// /// /// internal static void CacheBitUpdate(WCSTask mst, bool load) { if (load) { Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}"); LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}"); LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList()); } else { Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}"); LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,起点解绑容器{mst.S_CNTR_CODE}"); LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTR_CODE.Split(',').ToList()); } } /// /// 任务取消,缓存位状态更新 /// /// internal static void CacheBitCancelUpdate(WCSTask mst) { //任务取消,取货完成前的,起点的loadingCount和终点unLoadingCount都清除,取货完成的只处理终点 if (WCSHelper.CheckActionRecordExist(mst.S_CODE, 4) ) { //根据客户现场要求,如果取货完成任务失败人工拉到终点,我们就当卸货完成处理;如果是人工拉走到其它区域,我们就解锁终点,删除托盘。 //终点绑定 if (!WCSHelper.CheckActionRecordExist(mst.S_CODE, 5)) { CacheBitUpdate(mst, false); LocationHelper.UnLockLoc(mst.S_END_LOC); } } else { //起点终点解锁 LocationHelper.UnLockLoc(mst.S_START_LOC); LocationHelper.UnLockLoc(mst.S_END_LOC); //货位容器解绑 LocationHelper.UnBindingLoc(mst.S_START_LOC, new List { mst.S_CNTR_CODE }); } } /// /// 安全请求 /// /// /// /// /// internal static void OperateReq(string no, int state, string forkliftNo, string extData) { LogHelper.Info($"开始安全请求,任务号:{no},请求码:{state},小车号:{forkliftNo}", "AGV"); var cst = WCSHelper.GetTask(no); var mst = WMSHelper.GetWmsTask(cst.S_OP_CODE); var endLoc = LocationHelper.GetLoc(cst.S_END_LOC); var taskAction = WCSHelper.getActionRecord(no, state); if (taskAction != null) { LogHelper.Info($"再次安全请求,查询设备是否反馈", "AGV"); if (taskAction.N_S_STATUS == 1) { LogHelper.Info($"再次安全请求,设备已反馈", "AGV"); NDCApi.ChangeOrderParam(no, 8, "1"); } } else { LogHelper.Info($"首次进行安全请求,任务号:{no},请求码:{state},小车号:{forkliftNo}", "AGV"); bool result = false; if (state == 1101) { result = WCSDispatch.safetyInteraction(cst.S_CODE, cst.S_START_LOC, "1"); //请求取货, } if (state == 1102) { //请求卸货, var container = ContainerHelper.GetCntr(cst.S_CNTR_CODE); // 胎圈入库,下发母拖出库任务 \ 帘布、内衬入库,下发托盘回库任务 if (cst.S_TYPE.Contains("入库") && endLoc.N_LOCK_STATE == 0) { if (container.N_TYPE != 6 ) { if (endLoc.N_CURRENT_NUM == 1) { var locCntrRels = LocationHelper.GetLocCntr(endLoc.S_CODE); if (locCntrRels != null && locCntrRels.Count > 0) { var container1 = ContainerHelper.GetCntr(locCntrRels[0].S_CNTR_CODE); if (container1.N_TYPE == 0) { LogHelper.Info("非胎圈入库,接驳位存在母拖,下发母拖入库任务", "AGV"); ApiHelper.baseTrayInStockAgv(endLoc.S_CODE, mst.S_CODE); } } } else { result = true; } } // 胎圈入库 if (container.N_TYPE == 6 ) { if (endLoc.N_CURRENT_NUM == 0) { LogHelper.Info("胎圈入库,接驳位缺少母拖,下发母拖出库任务", "AGV"); ApiHelper.baseTrayOutStockAgv(endLoc.S_CODE, mst.S_CODE); } else if (endLoc.N_CURRENT_NUM == 1) { var locCntrRels = LocationHelper.GetLocCntr(endLoc.S_CODE); if (locCntrRels != null && locCntrRels.Count > 0) { var container1 = ContainerHelper.GetCntr(locCntrRels[0].S_CNTR_CODE); if (container1.N_TYPE == 0) { result = true; } } } } } // 请求WCS是否允许放货 if (result) { result = WCSDispatch.safetyInteraction(cst.S_CODE, cst.S_START_LOC, "2"); // 请求放货 } if (result) { //根据终点判断,是cb02的入口,判断内存中状态(要状态时间),允许卸货,通知agv改参数 var dic = new Dictionary(); //< Req >< Order No = 'TN2302020002' ParamNo = '18' Param1 = '12' /> dic.Add("No", no); dic.Add("ParamNo", "8"); dic.Add("Param1", "1"); NDC.ChangeOrder(dic); //改完参数车子就会自己卸货 } } if (state == 1103) { result = WCSDispatch.safetyInteraction(cst.S_CODE, cst.S_START_LOC, "3"); //取货完成允许离开 } if (state == 1104) { result = WCSDispatch.safetyInteraction(cst.S_CODE, cst.S_START_LOC, "4"); //放货完成允许离开 } // 安全请求发送成功,添加任务动作记录 if (result) { WCSHelper.AddActionRecord(no, state, forkliftNo, extData); LogHelper.Info($"首次进行安全请求成功", "AGV"); } } } /// /// 任务拦截 /// /// /// internal static bool Intercept(WCSTask mst) { var result = false; //出库任务是批量生成的,初始终点我们先给一个虚拟点,不推送。有单独的现场去判断出库缓存区光电,空了再给出库任务分配终点 if (mst.S_END_LOC == "出库虚拟点") { result = true; } return result; } /// /// 任务状态更新处理 /// /// /// internal static void OperateStatus(WCSTask mst, int state) { if (state == 4) { CacheBitUpdate(mst, true); } if (state == 6)//卸货完成 { CacheBitUpdate(mst, false); } if (state == 7) { CacheBitCancelUpdate(mst); } } private static object locLocker = new object(); /// /// 推送任务(此项目都是ndc系统) /// /// internal static bool SendTask(WCSTask mst) { var result = false; if (mst.N_B_STATE == 0) { var startLoc = LocationHelper.GetLocation(mst.S_START_LOC); var endLoc = LocationHelper.GetLocation(mst.S_END_LOC); if (mst.S_SCHEDULE_TYPE == "AGV") { AddOrderNewModel model = new AddOrderNewModel() { ts_no = 1, pri = 1, task_no = mst.S_CODE }; List paramList = new List(); var dic = new Dictionary(); dic.Add("From", startLoc.S_CODE); dic.Add("To", endLoc.S_CODE); foreach (var item in dic) { Param param = new Param { name = item.Key, value = item.Value, }; paramList.Add(param); } model.paramList = paramList; var res = NDCApi.AddOrderNew(model); if (res != null && res.err_code == 0 || true) { //推送成功,修改任务优先级 mst.N_B_STATE = 1; WCSHelper.UpdateStatus(mst); result = true; } } else if (mst.S_SCHEDULE_TYPE == "WCS") { if (true) { //推送成功,修改任务优先级 mst.N_B_STATE = 1; WCSHelper.UpdateStatus(mst); result = true; } } } return result; } private static List freeLineInfos = new List(); internal static freeLineBit GetFreeLineBit(string area, int row, int col) { if (freeLineInfos.Count == 0) { freeLineInfos = LocationHelper.GetAllFreeLineInfo(); } var res = freeLineInfos.Where(a => a.S_AREA_CODE == area && a.N_ROW == row && col >= a.START_COL && col <= a.END_COL).FirstOrDefault(); if (res != null) { return new freeLineBit { area = area, row = row, minCol = res.START_COL, maxCol = res.END_COL, bit1 = res.FIRST_POINT, bit2 = res.SECOND_POINT }; } return null; } public class freeLineBit { public string area { get; set; } public int row { get; set; } public int minCol { get; set; } public int maxCol { get; set; } public int bit1 { get; set; } public int bit2 { get; set; } } #endregion } }