双钱-需求变更:增加了两个搬送流程,增加了两个库区,主要是修改对空托上线脱皮机的逻辑
| | |
| | | tasks.Add(GetTask(WCSCore.Dispatch)); |
| | | |
| | | //添加自定义线程 |
| | | tasks.Add(GetTask(Monitor.CheckEmptyCnt));//检测空托盘 |
| | | tasks.Add(GetTask(Monitor.CheckEmptyCnt));//检测空托盘,空托堆叠入库 |
| | | |
| | | tasks.Add(GetTask(Monitor.CheckEmptyLoc_YclOutLineArea));//检测原材料产线下线附近是否有空位 |
| | | |
| | | tasks.Add(GetTask(Monitor.CheckCntAndBoard));//同步 TN_Container 均要实时显示 |
| | | |
| | |
| | | |
| | | tasks.Add(GetTask(Monitor.CGOkCheck));// 在复检区检测物品合格,合格的物品自动回库 |
| | | |
| | | tasks.Add(GetTask(Monitor.XBChekcFull));//线边满托货位自动解绑 |
| | | //tasks.Add(GetTask(Monitor.XBChekcFull));//线边满托货位自动解绑 |
| | | |
| | | Task.WaitAll(tasks.ToArray()); |
| | | } |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 线边空托到空托堆叠区 |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | internal static SimpleResult EmptyLineToEmptyMax(EmptyLineToEmptyMaxInfo model) |
| | | { |
| | | LogHelper.Info("触发API:线边空托到空托堆叠区" + JsonConvert.SerializeObject(model), "API"); |
| | | var result = new SimpleResult();//返回结果 |
| | | try |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | |
| | | if (model.cntCount<=0) |
| | | { |
| | | result.resultCode = 1; |
| | | result.resultMsg = $"参数cntCount必须大于0,即最少要有一个空托"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | | |
| | | var startLoc = db.Queryable<TN_Location>().First(it => it.S_CODE == model.startLoc); |
| | | |
| | | if (startLoc == null) |
| | | { |
| | | result.resultCode = 2; |
| | | result.resultMsg = $"未找到该起点{model.startLoc}"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | | |
| | | var settingArea = Settings.Areas[13]; |
| | | if (startLoc.S_AREA_CODE != settingArea) |
| | | { |
| | | result.resultCode = 3; |
| | | result.resultMsg = $"该起点{model.startLoc}必须在此库区内{settingArea}"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | | |
| | | if (startLoc.N_LOCK_STATE != 0 || startLoc.S_LOCK_STATE != "无") |
| | | { |
| | | result.resultCode = 4; |
| | | result.resultMsg = $"该起点{model.startLoc}已锁定,任务正在搬送"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | | |
| | | //查询符合的未锁定已启用指定货区的当前数量合计后最接近容量的货位,终点 |
| | | var endLoc = db.Queryable<TN_Location>(). |
| | | Where(a => a.N_CURRENT_NUM + model.cntCount <= a.N_CAPACITY && a.S_AREA_CODE == Settings.Areas[3] && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y"). |
| | | ToList().OrderByDescending(a => a.N_CURRENT_NUM + model.cntCount - a.N_CAPACITY).ThenBy(a => a.N_ROW).ThenBy(a => a.N_COL).ToList().First(); |
| | | |
| | | using (var trans = db.Ado.UseTran()) |
| | | { |
| | | startLoc.N_CURRENT_NUM = model.cntCount; |
| | | startLoc.N_LOCK_STATE = 2; |
| | | startLoc.S_LOCK_STATE = "出库锁"; |
| | | |
| | | endLoc.N_LOCK_STATE = 1; |
| | | endLoc.S_LOCK_STATE = "入库锁"; |
| | | |
| | | string cntStr = ""; |
| | | for (int i = 0; i < model.cntCount; i++) |
| | | { |
| | | cntStr += Guid.NewGuid().ToString("D")+","; |
| | | } |
| | | cntStr.Trim(','); |
| | | var locCnt = new TN_Loc_Container() |
| | | { |
| | | S_LOC_CODE = startLoc.S_CODE, |
| | | S_CNTR_CODE = cntStr, |
| | | }; |
| | | |
| | | var task = new TN_Task() |
| | | { |
| | | S_CODE = WCSHelper.GenerateTaskNo(), |
| | | S_START_AREA = startLoc.S_AREA_CODE, |
| | | S_END_AREA = endLoc.S_AREA_CODE, |
| | | S_START_LOC = startLoc.S_CODE, |
| | | S_END_LOC = endLoc.S_CODE, |
| | | S_TYPE = "空托下线堆叠", |
| | | N_PRIORITY = 3, |
| | | N_SCHEDULE_TYPE = 1, |
| | | N_B_STATE = 0, |
| | | S_B_STATE = "等待", |
| | | S_CNTR_CODE = locCnt.S_CNTR_CODE, |
| | | }; |
| | | |
| | | if ( |
| | | db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new { it.N_CURRENT_NUM, it.N_LOCK_STATE, it.S_LOCK_STATE }).ExecuteCommand() == 1 && |
| | | db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE }).ExecuteCommand() == 1 && |
| | | db.Insertable<TN_Loc_Container>(locCnt).ExecuteCommand() == 1 && |
| | | db.Insertable<TN_Task>(task).ExecuteCommand() == 1 |
| | | ) |
| | | { |
| | | Task task1 = Task.Run(() => |
| | | { |
| | | WMSHelper.InsertOpInfo(model.staff, "点对点", locCnt.S_CNTR_CODE); |
| | | }); |
| | | |
| | | trans.CommitTran(); |
| | | result.resultCode = 0; |
| | | result.resultMsg = $"创建 空托下线堆叠 任务成功,起点:{startLoc.S_CODE},终点:{endLoc.S_CODE}"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | | else |
| | | { |
| | | trans.RollbackTran(); |
| | | result.resultCode = 12; |
| | | result.resultMsg = $"创建 空托下线堆叠 任务失败,起点:{startLoc.S_CODE},终点:{endLoc.S_CODE}"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | result.resultCode = -1; |
| | | result.resultMsg = $"PDA满托复检判断,发生了异常:{ex.Message}"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 线边空托到原材料输送线 |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | |
| | | if (endLoc.S_AREA_CODE != endLocArea) |
| | | { |
| | | result.resultCode = 8; |
| | | result.resultMsg = $"此货位:{endLoc.S_CODE},不属于原材料产线空托区{endLocArea}"; |
| | | result.resultMsg = $"此货位:{endLoc.S_CODE},不属于原材料产线空托上线口库区{endLocArea}"; |
| | | LogHelper.Info(result.resultMsg); |
| | | return result; |
| | | } |
| | |
| | | Settings.LineSorting = 0; |
| | | } |
| | | |
| | | Task task1 = Task.Run(() => |
| | | { |
| | | WMSHelper.InsertOpInfo(model.staff, "点对点", Cnt); |
| | | }); |
| | | |
| | | |
| | | trans.CommitTran(); |
| | | result.resultCode = 0; |
| | |
| | | public class EmptyLineToLineInfo |
| | | { |
| | | public string startLoc { get; set; }//起点 |
| | | |
| | | public string staff { get; set; } = "None";//操作人 |
| | | } |
| | | |
| | | public class EmptyLineToEmptyMaxInfo |
| | | { |
| | | public string startLoc { get; set; }//起点 |
| | | public int cntCount { get; set; }//容器数量 |
| | | public string staff { get; set; } = "None";//操作人 |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 线边空托到原材料输送线 |
| | | /// 线边空托到原材料产线 |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | |
| | | { |
| | | return ApiHelper.EmptyLineToLine(model); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 线边空托到空托堆叠区 |
| | | /// </summary> |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | [HttpPost] |
| | | [Route("EmptyLineToEmptyMax")] |
| | | public SimpleResult EmptyLineToEmptyMax(EmptyLineToEmptyMaxInfo model) |
| | | { |
| | | return ApiHelper.EmptyLineToEmptyMax(model); |
| | | } |
| | | } |
| | | } |
| | |
| | | "SqlServer": "Data Source=127.0.0.1;Initial Catalog=DoubleCoinTest;User ID=sa;Password=123456;", |
| | | "TCPServerIP": "127.0.0.1", |
| | | "TCPServerPort": 8085, |
| | | "Areas": [ "SQKQ0", "SQKQ1", "SQKQ2", "SQKQ3", "SQKQ4", "SQKQ5", "SQKQ6", "SQKQ7", "SQKQ8", "SQKQ9", "SQKQ10", "SQKQ11", "SQKQ12", "线边空托区编码", "原材料产线空托区编码" ], |
| | | "Areas": [ "SQKQ0", "SQKQ1", "SQKQ2", "SQKQ3", "SQKQ4", "SQKQ5", "SQKQ6", "SQKQ7", "SQKQ8", "SQKQ9", "SQKQ10", "SQKQ11", "SQKQ12", "线边空托区编码13", "原材料产线空托区编码14", "原材料产线附近空托库区15", "空托货架库区16" ], |
| | | "S7TestMoni": true, |
| | | "IsOpenScanCode": true, |
| | | "ProductionLine": [ |
| | |
| | | "HostToAgvServerUrl": "http://127.0.0.1:9988/HostToAGV.cgi",//连接AGV管理系统的地址 |
| | | "TCPServerIP": "127.0.0.1",//Socket服务端地址,用于连接AGV读卡器并通讯 |
| | | "TCPServerPort": 8085,//Socket服务端端口,用于连接AGV读卡器并通讯 |
| | | "Areas": [ "SQKQ0", "SQKQ1", "SQKQ2", "SQKQ3", "SQKQ4" , "SQKQ5", "SQKQ6", "SQKQ7", "SQKQ8", "SQKQ9" , "SQKQ10", "SQKQ11" , "SQKQ12", "SQKQ13", "SQKQ14" ], |
| | | "Areas": [ "SQKQ0", "SQKQ1", "SQKQ2", "SQKQ3", "SQKQ4" , "SQKQ5", "SQKQ6", "SQKQ7", "SQKQ8", "SQKQ9" , "SQKQ10", "SQKQ11" , "SQKQ12", "SQKQ13", "SQKQ14" , "SQKQ15", "SQKQ16" ], |
| | | // 原材料产线库区SQKQ0——》满托缓存库区SQKQ1——》加工线线边区SQKQ2——》空托堆叠区SQKQ3——》空托缓存库区SQKQ4——》 |
| | | //人工拆盘区SQKQ5——》人工空托区SQKQ6——》人工抽检区SQKQ7——》拆盘不合格区SQKQ8——》称重区SQKQ9 |
| | | //——》余料起点区SQKQ10——》次品回炉区SQKQ11 ——》过期暂存区SQKQ12 ——》线边空托区SQKQ13 ——》原材料产线空托库区SQKQ14 |
| | | //——》余料起点区SQKQ10——》次品回炉区SQKQ11 ——》过期暂存区SQKQ12 ——》线边空托区SQKQ13 ——》原材料产线空托上线口库区SQKQ14 |
| | | //——》原材料产线附近空托库区SQKQ15——》空托货架库区SQKQ16 |
| | | |
| | | "S7TestMoni": true,//如果为true,跳过S7通讯测试,只能使用PDA |
| | | "IsOpenScanCode": true,//如果为true,开启读卡器扫码功能,如果为false,不开启 |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 检测原材料产线下线附近是否有空位 |
| | | /// </summary> |
| | | internal static void CheckEmptyLoc_YclOutLineArea() |
| | | { |
| | | try |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | |
| | | var endLoc = db.Queryable<TN_Location>(). |
| | | Where(o => o.S_AREA_CODE == Settings.Areas[15] |
| | | && o.N_LOCK_STATE == 0 |
| | | && o.S_LOCK_STATE == "无" |
| | | && o.C_ENABLE == "Y" |
| | | && o.N_CURRENT_NUM == 0 |
| | | && SqlFunc.Subqueryable<TN_Loc_Container>().Where(b => b.S_LOC_CODE == o.S_CODE).NotAny() |
| | | ).//原材料产线附近空托库区 |
| | | First(); |
| | | |
| | | if (endLoc == null) |
| | | { |
| | | LogHelper.Info($"原材料产线附近空托库区{Settings.Areas[15]},已满,无需再入空托"); |
| | | return; |
| | | } |
| | | |
| | | var startLoc = db.Queryable<TN_Location>(). |
| | | Where(o => o.S_AREA_CODE == Settings.Areas[3] |
| | | && o.N_LOCK_STATE == 0 |
| | | && o.S_LOCK_STATE == "无" |
| | | && o.C_ENABLE == "Y" |
| | | && o.N_CURRENT_NUM > 0 |
| | | && SqlFunc.Subqueryable<TN_Loc_Container>().Where(b => b.S_LOC_CODE == o.S_CODE).Any() |
| | | ).ToList().//空托堆叠库区 |
| | | OrderByDescending(o => o.N_CURRENT_NUM). |
| | | First(); |
| | | |
| | | if (startLoc == null) |
| | | { |
| | | startLoc = db.Queryable<TN_Location>(). |
| | | Where(o => o.S_AREA_CODE == Settings.Areas[16] |
| | | && o.N_LOCK_STATE == 0 |
| | | && o.S_LOCK_STATE == "无" |
| | | && o.C_ENABLE == "Y" |
| | | && o.N_CURRENT_NUM > 0 |
| | | && SqlFunc.Subqueryable<TN_Loc_Container>().Where(b => b.S_LOC_CODE == o.S_CODE).Any() |
| | | ).ToList().//空托货架库区 |
| | | OrderByDescending(o => o.N_CURRENT_NUM). |
| | | First(); |
| | | } |
| | | |
| | | if (startLoc == null) |
| | | { |
| | | LogHelper.Info($"起点没有找到合适的空托货位,要求有货"); |
| | | return; |
| | | } |
| | | |
| | | var cntrList = db.Queryable<TN_Loc_Container>().Where(a => a.S_LOC_CODE == startLoc.S_CODE).OrderBy(a => a.T_CREATE, OrderByType.Asc).ToList(); |
| | | |
| | | if (cntrList.Count < 1) |
| | | { |
| | | LogHelper.Info($"起点{startLoc.S_CODE}未找到货位容器关系信息"); |
| | | return; |
| | | } |
| | | |
| | | string cntrString = ""; |
| | | for (int i = 0; i < cntrList.Count; i++) |
| | | { |
| | | if (i == cntrList.Count - 1)//最后一个字符串连接不加逗号 |
| | | { |
| | | cntrString += cntrList[i].S_CNTR_CODE; |
| | | } |
| | | else |
| | | { |
| | | cntrString += cntrList[i].S_CNTR_CODE + ","; |
| | | } |
| | | } |
| | | |
| | | if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "空托自动上线", 3, cntrString))//创建搬送任务,起点终点容器 |
| | | { |
| | | LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁, |
| | | LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁 |
| | | |
| | | LogHelper.Info($"生成空托自动上线任务成功,容器:{cntrString},起点:{startLoc.S_CODE}"); |
| | | } |
| | | else |
| | | { |
| | | LogHelper.Info($"生成空托自动上线任务失败,容器:{cntrString},起点:{startLoc.S_CODE}"); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 线边满托货位自动解绑 |
| | | /// </summary> |
| | | internal static void XBChekcFull() |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | try |
| | | { |
| | | |
| | |
| | | } |
| | | |
| | | var endLoc = db.Queryable<TN_Location>(). |
| | | Where(a => a.S_AREA_CODE == Settings.Areas[15] && a.N_LOCK_STATE == 0 |
| | | && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 |
| | | && SqlFunc.Subqueryable<TN_Loc_Container>().Where(b => b.S_LOC_CODE == a.S_CODE).NotAny() |
| | | ).First();//先找 原材料产线附近空托库区 |
| | | |
| | | if (endLoc == null) |
| | | { |
| | | endLoc = db.Queryable<TN_Location>(). |
| | | Where(a => a.S_AREA_CODE == Settings.Areas[16] && a.N_LOCK_STATE == 0 |
| | | && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 |
| | | && SqlFunc.Subqueryable<TN_Loc_Container>().Where(b => b.S_LOC_CODE == a.S_CODE).NotAny() |
| | | ).First(); |
| | | }// 再找 空托货架库区 |
| | | |
| | | if (endLoc == null) |
| | | { |
| | | endLoc = db.Queryable<TN_Location>(). |
| | | Where(a => a.S_AREA_CODE == Settings.Areas[4] && a.N_LOCK_STATE == 0 |
| | | && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0 |
| | | && SqlFunc.Subqueryable<TN_Loc_Container>().Where(b => b.S_LOC_CODE == a.S_CODE).NotAny() |
| | | ). |
| | | OrderBy(a => a.N_CURRENT_NUM, OrderByType.Asc). |
| | | First(); |
| | | ).First(); |
| | | }// 最后找 空托缓存库区 |
| | | |
| | | |
| | | if (endLoc == null) |
| | | { |
| | |
| | | |
| | | Task task3 = Task.Run(() => |
| | | { |
| | | EmptyInStackArea(tN_Task); |
| | | EmptyInStackArea(tN_Task);//空托下线堆叠 |
| | | }); |
| | | |
| | | Task task1 = Task.Run(() => |
| | |
| | | } |
| | | }); |
| | | |
| | | |
| | | Task task12 = Task.Run(() => |
| | | { |
| | | if (tN_Task.S_TYPE == "PDA满托下线入库" || tN_Task.S_TYPE == "PLC满托下线入库") |
| | |
| | | else |
| | | { |
| | | //安全请求等 |
| | | TaskProcess.OperateReq(model.task_no, model.state, model.forklift_no, model.ext_data); |
| | | //TaskProcess.OperateReq(model.task_no, model.state, model.forklift_no, model.ext_data); |
| | | } |
| | | |
| | | } |
| | | else |
| | | { |
| | |
| | | //查询符合的未锁定已启用指定货区的当前数量合计后最接近容量的货位,终点 |
| | | var endLoc = db.Queryable<TN_Location>(). |
| | | Where(a => a.N_CURRENT_NUM + item.N_CURRENT_NUM <= a.N_CAPACITY && a.S_AREA_CODE == Settings.Areas[3] && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y"). |
| | | OrderBy(a => a.N_CURRENT_NUM + item.N_CURRENT_NUM - a.N_CAPACITY, OrderByType.Desc).First(); |
| | | ToList().OrderByDescending(a => a.N_CURRENT_NUM + item.N_CURRENT_NUM - a.N_CAPACITY).ThenBy(a=>a.N_ROW).ThenBy(a => a.N_COL).ToList().First(); |
| | | |
| | | if (endLoc == null) |
| | | { |
| | |
| | | public string S_AGV_SITE { get; set; } |
| | | public int N_CURRENT_NUM { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 层 |
| | | /// </summary> |
| | | public int N_LAYER { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 行\排 |
| | | /// </summary> |
| | | public int N_ROW { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 列 |
| | | /// </summary> |
| | | public int N_COL { get; set; } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 0无 1入库锁 2出库锁 3其它锁 |
| | |
| | | start = LocationHelper.GetAgvSite(mst.S_START_LOC); |
| | | end = LocationHelper.GetAgvSite(mst.S_END_LOC); |
| | | |
| | | if (mst.S_TYPE == "空托下线堆叠") |
| | | if (mst.S_TYPE.Contains("空托下线堆叠")) |
| | | { |
| | | end = LocationHelper.GetAgvSite(mst.S_END_LOC,true); |
| | | } |