using HH.WCS.JuShi.api; using HH.WCS.JuShi.core; using HH.WCS.JuShi.dispatch; using HH.WCS.JuShi.LISTA.process; using HH.WCS.JuShi.util; using HH.WCS.JuShi.wms; using HH.WCS.JuShi; using Newtonsoft.Json; using NLog.Fluent; using SqlSugar; using Swashbuckle.Swagger; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using static HH.WCS.JuShi.LISTA.process.HttpModel; using static System.Runtime.CompilerServices.RuntimeHelpers; using HH.WCS.JuShi.device; using Org.BouncyCastle.Utilities; using Opc.Ua; using System.Collections; using System.Xml.Linq; using System.Threading; using static HH.WCS.JuShi.dispatch.NDC; using static HH.WCS.JuShi.util.Settings; namespace HH.WCS.JuShi.process { internal class TaskProcess { #region 任务相关 //--------------------------------------------------任务相关-------------------------------------------------- /// /// 取货卸货完成,缓存位状态更新 /// /// /// internal static void CacheBitUpdate(WCSTask mst, bool load) { //var trayCarryCount = mst.N_CNTR_COUNT > 0 ? mst.N_CNTR_COUNT : 1; 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)) { //根据客户现场要求,如果取货完成任务失败人工拉到终点,我们就当卸货完成处理;如果是人工拉走到其它区域,我们就解锁终点,删除托盘。 //终点绑定 CacheBitUpdate(mst, false); LocationHelper.UnLockLoc(mst.S_END_LOC); } else { //起点终点解锁 LocationHelper.UnLockLoc(mst.S_START_LOC); LocationHelper.UnLockLoc(mst.S_END_LOC); } } /// /// 任务拦截 /// /// /// internal static bool Intercept(WCSTask mst) { var result = false; // if (mst.S_TYPE == "自动转运") { //判断人工卸货区开关 // result = true; // } return result; } /// /// 任务状态更新处理 /// /// /// internal static void OperateStatus(WCSTask mst, int state) { if (state == 4)//取货完成 { CacheBitUpdate(mst, true); //拆托机安全交互 ctjSafe(mst); } if (state == 6)//卸货完成 { CacheBitUpdate(mst, false); //rgv安全交互 rgvSafe(mst); //拆托机安全交互 ctjSafe(mst); } if (state == 7) { CacheBitCancelUpdate(mst); } } //rgv安全交互 private static void rgvSafe(WCSTask mst) { //rgv安全交互 根据终点货位找到是哪个rgv var reservoir = Settings.ReservoirAreas.Where(a => a.areaName == "RGV库区").FirstOrDefault(); if (mst.S_END_AREA.Equals(reservoir.areaCode)) { var safeInteractions = Settings.SafeInteractions.Where(a => a.location == mst.S_END_LOC).FirstOrDefault(); var safelists = JsonConvert.DeserializeObject>(DeviceProcess.rgvSafeInteraction); if (safelists.Any()) { var safelist = safelists.Where(s => s.ip == safeInteractions.ip).First(); LogHelper.Info($"RGV安全交互参数{safelist}"); //不等于 2卸货完成确认信号 就接着发 if (safelist.data != "2") { string datastr = "3F00102030400D0A"; // 返回信号 switch (safeInteractions.pointCode) { case "RGV1": datastr = datastr.Replace("10", "11"); break; case "RGV2": datastr = datastr.Replace("20", "21"); break; case "RGV3": datastr = datastr.Replace("30", "31"); break; case "RGV4": datastr = datastr.Replace("40", "41"); break; } LogHelper.Info($"RGV安全交互发送信号{safelist.ip},{datastr}"); PlcHelper.SendHex(safelist.ip, datastr); //休眠3秒再调 Thread.Sleep(3000); rgvSafe(mst); } else { LogHelper.Info($"RGV安全交互发送信号{safelist.ip},3F00102030400D0A"); //无状态信号 PlcHelper.SendHex(safelist.ip, "3F00102030400D0A"); } } } } //拆托机安全交互 private static void ctjSafe(WCSTask mst) { PlcDeviceTable plcDeviceTable = null; //找到线体 根据线体找内存里的状态 var rkreservoirs = Settings.ConveyorLinesInfos.Where(s => s.location == mst.S_END_LOC).FirstOrDefault(); var ckreservoirs = Settings.ConveyorLinesInfos.Where(s => s.location == mst.S_START_LOC).FirstOrDefault(); if (rkreservoirs != null) { plcDeviceTable = S7Helper.plcDeviceTables.Find(a => a.DeviceNo == rkreservoirs.code); } else if (ckreservoirs != null) { plcDeviceTable = S7Helper.plcDeviceTables.Find(a => a.DeviceNo == ckreservoirs.code); } LogHelper.Info($"拆托机安全交互写入参数{plcDeviceTable}"); if (plcDeviceTable != null) { //s7写入 double addr = 0; //偏移量 string deviceNo = null;//拆托机号 if (plcDeviceTable.DeviceNo == 1003) { addr = 90.1; deviceNo = "1"; } else if (plcDeviceTable.DeviceNo == 1006) { addr = 180.1; deviceNo = "2"; } else if (plcDeviceTable.DeviceNo == 1001) { addr = 30.0; deviceNo = "1"; } else if (plcDeviceTable.DeviceNo == 1004) { addr = 120.0; deviceNo = "2"; } LogHelper.Info($"拆托机安全交互写入{deviceNo},{addr}"); S7Helper.WriteDouble(deviceNo, 9, addr, 1); } } private static object locLocker = new object(); /// /// 堆叠库区出入库任务申请 /// /// /// /// /// /// /// /// /// internal static bool ApplyTN_Task(Location ls, ref List cntrs, string area, string itemCode, string itemBatch, string taskType, bool insStock = true) { var result = false; lock (locLocker) { try { if (insStock) { Console.WriteLine($"MoboxHelperCreateTask: {area}-{itemCode}-{itemBatch}-{taskType}"); var endTN_Location = GetLocation4In(area, itemCode, itemBatch, 3); if (endTN_Location != null) { var endLayer = endTN_Location.N_CURRENT_NUM == 0 ? 1 : 2; var taskNo = DateTime.Now.Ticks.ToString(); result = TaskProcess.CreateTransport(ls.S_CODE, endTN_Location.S_CODE, taskType, cntrs, 1, endLayer, 3, 70); } else { Console.WriteLine($"MoboxHelperCreateTask: 未找到终点货位"); } } else { var startTN_Location = GetLocation4Out(area, itemCode, itemBatch, 3); if (startTN_Location != null) { var startLayer = startTN_Location.N_CURRENT_NUM <= 3 ? 1 : 2; var taskNo = DateTime.Now.Ticks.ToString(); var carryCount = startTN_Location.N_CURRENT_NUM > 3 ? startTN_Location.N_CURRENT_NUM - 3 : startTN_Location.N_CURRENT_NUM; //出库要从起点获取托盘 var cntrList = LocationHelper.GetLocCntr(startTN_Location.S_CODE); if (cntrList.Count == startTN_Location.N_CURRENT_NUM) { cntrs = cntrList.OrderByDescending(a => a.T_CREATE).Take(carryCount).Select(a => a.S_CNTR_CODE.Trim()).ToList(); result = TaskProcess.CreateTransport(startTN_Location.S_CODE, ls.S_CODE, taskType, cntrs, startLayer, 1, carryCount, 65); } else { Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】"); } } } } catch (Exception ex) { Console.WriteLine("MoboxHelperCreateTask:" + ex.Message); LogHelper.Error("MoboxHelperCreateTask:" + ex.Message, ex); } } return result; } private static Location GetLocation4Out(string area, string itemCode, string itemBatch, int v) { throw new NotImplementedException(); } private static Location GetLocation4In(string area, string itemCode, string itemBatch, int v) { throw new NotImplementedException(); } /// /// 普通货架区的出入库申请 /// /// /// /// /// /// /// /// internal static bool ApplyNormalTN_Task(Location ls, ref List cntrs, string area, string taskType, string itemCode, bool insStock = true) { var result = false; lock (locLocker) { try { if (insStock) { Console.WriteLine($"MoboxHelperCreateTask: {area}-{taskType}"); var endTN_Location = new Location(); if (endTN_Location != null) { var taskNo = DateTime.Now.Ticks.ToString(); result = TaskProcess.CreateTransport(ls.S_CODE, endTN_Location.S_CODE, taskType, cntrs, 70); } else { Console.WriteLine($"MoboxHelperCreateTask: 未找到终点货位"); } } else { var startTN_Location = new Location(); if (startTN_Location != null) { //出库要从起点获取托盘 var cntrList = LocationHelper.GetLocCntr(startTN_Location.S_CODE); if (cntrList.Count == startTN_Location.N_CURRENT_NUM) { result = TaskProcess.CreateTransport(startTN_Location.S_CODE, ls.S_CODE, taskType, new List { cntrList[0].S_CNTR_CODE }, 65); } else { Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】"); } } } } catch (Exception ex) { Console.WriteLine("MoboxHelperCreateTask:" + ex.Message); LogHelper.Error("MoboxHelperCreateTask:" + ex.Message, ex); } } return result; } /// /// 推送任务 /// /// internal static bool SendTask(WCSTask mst) { var result = false; var start = "0"; var end = "0"; var taskType = mst.S_TYPE.Trim(); // if (mst.N_B_STATE == 0) { if (mst.N_SCHEDULE_TYPE == 1) { start = LocationHelper.GetAgvSite(mst.S_START_LOC); end = LocationHelper.GetAgvSite(mst.S_END_LOC); Console.WriteLine($"SendTask {mst.S_CODE}"); Console.WriteLine("start=" + start); Console.WriteLine("end= " + end); var dic = new Dictionary(); dic.Add("Pri", mst.N_PRIORITY.ToString()); dic.Add("From", start.ToString()); dic.Add("To", end.ToString()); dic.Add("No", mst.S_CODE.Trim());// dic.Add("Ext1", "1"); dic.Add("Ext2", "CALLADDAGV"); dic.Add("N_CNTR_COUNT", ""); var res = NDC.AddNewOrder(5, dic); if (res != null && (res.Res.ErrCode == 0 || res.Res.ErrCode == 50009)) { //推送成功,修改任务优先级 mst.N_B_STATE = 1; WCSHelper.UpdateStatus(mst); result = true; } } return result; } /// /// 国自推送任务 /// /// internal static bool SendGZTask(WCSTask mst) { var result = false; var taskState = mst.N_B_STATE; if (taskState == 0) { Console.WriteLine($"任务mst {JsonConvert.SerializeObject(mst)}"); LogHelper.Info($"任务mst {JsonConvert.SerializeObject(mst)}", "任务"); var startLoc = LocationHelper.GetLoc(mst.S_START_LOC); var endLoc = LocationHelper.GetLoc(mst.S_END_LOC); if (startLoc != null && endLoc != null) { string src = $"\"src\":\"{startLoc.S_AGV_SITE}\","; string dst = $"\"dst\":\"{endLoc.S_AGV_SITE}\""; string parmeS = "{"; string parmeD = "}"; string parme = parmeS + src + dst + parmeD; int res = 0; LogHelper.Info($"推送任务参数{parme}", "任务"); res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme); #region //if (mst.S_TYPE == "呼叫空托" || mst.S_TYPE == "按钮盒调用空托" || mst.S_TYPE == "拆托") //{ // PlcDeviceTable plcDeviceTable = null; // //找到线体 根据线体找内存里的状态 // var reservoirs1 = Settings.ConveyorLinesInfos.Where(s => s.location == startLoc.S_CODE).FirstOrDefault(); // plcDeviceTable = S7Helper.plcDeviceTables.Find(a => a.DeviceNo == reservoirs1.code); // if (plcDeviceTable != null) // { // if (mst.S_TYPE == "呼叫空托" || mst.S_TYPE == "按钮盒调用空托") // { // LogHelper.Info($"呼叫空托状态参数{JsonConvert.SerializeObject(plcDeviceTable)}", "任务"); // //0-脱机状态,1-待机状态,2-运行中 待机且有托盘且请求取框才走 // if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 1 && plcDeviceTable.requestTake) // { // LogHelper.Info($"推送任务参数{parme}", "任务"); // res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme); // } // } // else if (mst.S_TYPE == "拆托") // { // LogHelper.Info($"拆托状态参数{JsonConvert.SerializeObject(plcDeviceTable)}", "任务"); // //0-脱机状态,1-待机状态,2-运行中 待机且无托盘且允许放框才走 // if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 0 && plcDeviceTable.requestPut) // { // LogHelper.Info($"推送任务参数{parme}", "任务"); // res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme); // } // } // } //} //else //{ // LogHelper.Info($"推送任务参数{parme}", "任务"); // res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme); //} #endregion if (res > 0) { //更新任务状态 mst.N_B_STATE = 1; mst.S_EQ_TASK_CODE = res.ToString(); WCSHelper.UpdateStatus(mst); WCSHelper.UpdateEQNo(mst); ////推送成功,修改任务状态 //TaskHelper.UpdateStatus(mst, "已推送"); ////推送成功,修改国自ID //TaskHelper.UpdateGzId(mst, res); LogHelper.Info($"任务mst {mst.S_CODE}推送成功", "任务"); result = true; } } } else { result = true; } return result; } /// /// 创建搬运任务 /// /// /// /// /// /// /// /// /// /// public static bool CreateTransport(string start, string end, string taskType, string cntrs, int startLayer, int endLayer, int trayCarryCount = 1, int priority = 1) { var result = false; var trayCodes = cntrs; var taskNo = DateTime.Now.Ticks.ToString(); var res = WCSHelper.CreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, trayCodes, trayCarryCount, startLayer, endLayer); if (res) { result = true; //任务创建成功,起点货位出库锁定,终点货位入库锁定 LocationHelper.LockLoc(start, 2); LocationHelper.LockLoc(end, 1); } return result; } /// /// 创建搬运任务 /// /// /// /// /// /// /// /// /// /// public static bool CreateTransport(string start, string end, string taskType, List cntrs, int startLayer, int endLayer, int trayCarryCount = 1, int priority = 1) { var result = false; var trayCodes = string.Join(",", cntrs); var taskNo = DateTime.Now.Ticks.ToString(); var res = WCSHelper.CreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, trayCodes, trayCarryCount, startLayer, endLayer); if (res) { result = true; //任务创建成功,起点货位出库锁定,终点货位入库锁定 LocationHelper.LockLoc(start, 2); LocationHelper.LockLoc(end, 1); } return result; } public static bool CreateTransport(string start, string end, string taskType, List cntrs, int priority = 1) { var result = false; //批次号存托盘号,1~3个托盘 var trayCodes = string.Join(",", cntrs); var taskNo = DateTime.Now.Ticks.ToString(); var res = WCSHelper.CreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, trayCodes, 1, 1, 1); if (res) { result = true; LocationHelper.LockLoc(start, 2); LocationHelper.LockLoc(end, 1); } return result; } internal static Result cancelTask1(cancleTaskParme model) { var result = new Result(); LogHelper.Info("cancelTask1取消任务信息:" + JsonConvert.SerializeObject(model), "API"); if (model == null) { result.success = false; result.errMsg = "参数为null"; result.errCode = 1; return result; } var task = WCSHelper.GetTask(model.taskNo); if (task != null) { if (task.S_B_STATE.Trim() == "未执行") { //未执行直接修改状态为取消 TaskProcess.OperateStatus(task, 7); WCSHelper.UpdateStatus(task, "取消"); result.success = true; result.errMsg = "取消任务成功"; result.errCode = 0; } else if (task.S_B_STATE.Trim() != "取消" && task.S_B_STATE.Trim() != "完成") { if (GZRobot.CancelOrder(int.Parse(task.S_EQ_TASK_CODE))) { TaskProcess.OperateStatus(task, 7); WCSHelper.Fail(task); result.success = true; result.errMsg = "国自取消任务成功"; result.errCode = 0; } else { result.success = false; result.errMsg = "国自取消任务失败"; result.errCode = 1; } } else { result.success = false; result.errMsg = "任务已经结束"; result.errCode = 1; } } else { result.success = false; result.errMsg = "任务不存在"; result.errCode = 1; } LogHelper.Info("cancelTask1取消任务返回结果:" + JsonConvert.SerializeObject(result), "API"); return result; } /// /// 创建入库任务 /// /// /// internal static Result CreateInWork(moboxParam model) { var result = new Result() { success = true, errMsg = "入库任务生成成功!" }; var db = new SqlHelper().GetInstance(); var loc = db.Queryable().Where(a => a.S_CODE == model.S_LOC_CODE).First(); if (loc == null || loc.S_LOCK_STATE.Trim() != "无") { return new Result { success = false, errMsg = $"{model.S_LOC_CODE}库位已被锁定!" }; } if (string.IsNullOrEmpty(model.S_LOC_CODE)) { return new Result { success = false, errMsg = "入库未传起点货位!" }; } var end = Settings.LocAreas.Where(s => s.startBit.Split(',').ToList().Contains(model.S_LOC_CODE)).FirstOrDefault(); if (end == null) { return new Result { success = false, errMsg = "起点未找到对应的终点库区!" }; } Location InLoc = TaskProcess.InWorkTransport(end.endArea); if (InLoc == null) { return new Result { success = false, errMsg = $"终点库区{end.endArea}未找到空货位!" }; } //if (model.S_TASK_TYPE == "成品入库") //{ // var locs = db.Queryable().Where(a => a.S_CODE == "KZB-A").First(); // if (locs == null || locs.S_LOCK_STATE.Trim() != "无") // { // return new Result { success = false, errMsg = $"KZB-A货位在锁定中!" }; // } // var locTray = db.Queryable().Where(a => a.S_LOC_CODE == "KZB-A").OrderByDescending(s=>s.T_CREATE).First(); // if (locTray != null) // { // var resl = TaskProcess.CreateTransport("KZB-A", "CP", "基坑空托转运", locTray.S_CNTR_CODE.Split(',').ToList(), locs.N_CURRENT_NUM, 1,1,15); // if (!resl) // { // return new Result { success = false, errMsg = "空托出库任务生成失败!" }; // } // } //} string trayCode = ContainerHelper.GenerateCntrNo(); var res = TaskProcess.CreateTransport(model.S_LOC_CODE, InLoc.S_CODE, model.S_TASK_TYPE, trayCode.Split(',').ToList(), 1, 1); if (!res) { return new Result { success = false, errMsg = "入库任务生成失败!" }; } ContainerHelper.BindLocCntrs(model.S_LOC_CODE, trayCode, model.S_ITEM_CODE, model.S_ITEM_NAME, model.S_CK == "是" ? 1 : 0); return result; } /// /// 创建出库任务 /// /// /// internal static Result CreateOutWork(moboxParam model) { var result = new Result() { success = true, errMsg = "出库任务生成成功!" }; var db = new SqlHelper().GetInstance(); var loc = db.Queryable().Where(a => a.S_CODE == model.S_LOC_CODE).First(); if (loc == null || loc.S_LOCK_STATE.Trim() != "无") { return new Result { success = false, errMsg = $"{model.S_LOC_CODE}库位已被锁定!" }; } if (string.IsNullOrEmpty(model.S_LOC_CODE)) { return new Result { success = false, errMsg = "出库未传终点货位!" }; } var start = Settings.LocAreas.Where(s => s.endBit != null && s.endBit.Split(',').ToList().Contains(model.S_LOC_CODE)).FirstOrDefault(); if (start == null) { return new Result { success = false, errMsg = "终点未找到对应的起点库区!" }; } Location OutLoc = TaskProcess.OutWorkTransport(start.startArea, model.S_ITEM_CODE); if (OutLoc == null) { return new Result { success = false, errMsg = $"起点库区{start.startArea}未找到对应的满货位!" }; } var locCntrRel = db.Queryable().Where(a => a.S_LOC_CODE == OutLoc.S_CODE).First(); var res = TaskProcess.CreateTransport(OutLoc.S_CODE, model.S_LOC_CODE, model.S_TASK_TYPE, locCntrRel.S_CNTR_CODE.Split(',').ToList(), 1, 1); if (!res) { return new Result { success = false, errMsg = "出库任务生成失败!" }; } return result; } /// /// 创建空托转运任务 /// /// /// internal static Result EmptyTrayTransport(moboxParam model) { var result = new Result() { success = true, errMsg = "空托转运任务生成成功!" }; var db = new SqlHelper().GetInstance(); var loc = db.Queryable().Where(a => a.S_CODE == model.S_START_LOC).First(); if (loc == null || loc.S_LOCK_STATE.Trim() != "无") { return new Result { success = false, errMsg = $"{model.S_START_LOC}库位已被锁定!" }; } if (string.IsNullOrEmpty(model.S_START_LOC)) { return new Result { success = false, errMsg = "空托转运未传起点货位!" }; } Location InLoc = TaskProcess.InWorkTransport(model.S_END_AREA); if (InLoc == null) { return new Result { success = false, errMsg = $"终点库区{model.S_END_AREA}未找到空货位!" }; } //string trayCode = ContainerHelper.GenerateCntrNo(); var locCntr = db.Queryable().Where(a => a.S_LOC_CODE == model.S_START_LOC).ToList(); if (!locCntr.Any()) { return new Result { success = false, errMsg = $"{model.S_START_LOC}货位未找到托盘!" }; } var res = TaskProcess.CreateTransport(model.S_START_LOC, InLoc.S_CODE, model.S_TASK_TYPE, locCntr.Select(s => s.S_CNTR_CODE).ToList(), loc.N_CURRENT_NUM, InLoc.N_CURRENT_NUM + 1); if (!res) { return new Result { success = false, errMsg = "空托转运任务生成失败!" }; } //ContainerHelper.BindLocCntrs(model.S_LOC_CODE, trayCode, model.S_ITEM_CODE, model.S_ITEM_NAME); return result; return result; } #endregion /// /// 入库货位 /// /// 库区 /// public static Location InWorkTransport(string area) { Location result = null; var db = new SqlHelper().GetInstance(); try { //查询这个库区的空托盘与满托盘 var list = db.Queryable().Where(a => a.S_AREA_CODE.Trim() == area).OrderByDescending(a => a.N_ROW).ToList(); //LogHelper.Info($"查询这个库区的空托盘与满托盘:{JsonConvert.SerializeObject(list)}"); if (list.Count > 0) { List loca = new List(); for (int i = 0; i < list.Count; i++) { //如果锁了或者容量满了 当前数量 容器容量 if (list[i].N_LOCK_STATE != 0 || list[i].N_CURRENT_NUM >= list[i].N_CAPACITY) { loca.Add(list[i].S_CODE); } } //移除 if (loca.Any()) { list.RemoveAll(s => loca.Contains(s.S_CODE)); } //符合条件的排序选第一个 先找第一个 if (list.Count > 0) { result = list.OrderBy(s => s.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault(); } } } catch (Exception ex) { Console.WriteLine("InWorkTransport:" + ex.Message + ex.StackTrace); LogHelper.Error("InWorkTransport:" + ex.Message, ex); } return result; } /// /// 出库算法 /// /// 库区 /// public static Location OutWorkTransport(string area) { Location result = null; try { var db = new SqlHelper().GetInstance(); var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area).ToList(); //list = list.OrderByDescending(s => s.N_ROW).OrderByDescending(s => s.N_COL).OrderByDescending(s => s.N_LAYER).ToList(); list = list.OrderBy(s => s.T_CREATE).ToList();//先进先出 for (int i = 0; i < list.Count; i++) { //判断货位是否被锁住了 与 是否有托盘 if (list[i].N_LOCK_STATE == 0) { var locCntrRel = db.Queryable().Where(s => s.S_LOC_CODE == list[i].S_CODE).First(); if (locCntrRel != null) { result = list[i]; } if (result != null) { break; } } } } catch (Exception ex) { Console.WriteLine("OutWorkTransport:" + ex.Message + ex.StackTrace); LogHelper.Error("OutWorkTransport:" + ex.Message, ex); } return result; } /// /// 常规送检缓存区货位 abc三个区 两层 /// /// 起点货位 /// 库区 /// public static Location InCgWorkTransport(string startloc, string area) { Location result = null; var db = new SqlHelper().GetInstance(); try { //A,B,C3个货架上,这个要有优先级了,CX03,04优先送到A区货架,CX01,CX02优先送到B,C货架 var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault(); var alllist = db.Queryable().Where(a => a.S_AREA_CODE.Trim() == reservoirs.areaCode).ToList(); // 从配置获取优先级规则 var mapping = Settings.PriorityLocs.FirstOrDefault(m => m.Location == startloc); LogHelper.Info($"配置的优先级规则{JsonConvert.SerializeObject(mapping)}"); if (mapping == null) { LogHelper.Info($"未找到产线{startloc}的优先级配置"); return null; } var primaryAreas = mapping.PrimaryArea.Split(','); var secondaryAreas = mapping.SecondaryArea.Split(','); LogHelper.Info($"优先:{JsonConvert.SerializeObject(primaryAreas)}次选:{JsonConvert.SerializeObject(secondaryAreas)}"); // 筛选未锁且有空的货位 var availablePrimaryLocations = FilterAvailableLocations(alllist, primaryAreas); //优先 result = availablePrimaryLocations.OrderBy(l => l.N_COL).ThenBy(l => l.N_LAYER).FirstOrDefault(); // 次选 if (result == null) { var availableSecondaryLocations = FilterAvailableLocations(alllist, secondaryAreas); result = availableSecondaryLocations.OrderBy(l => l.N_COL).ThenBy(l => l.N_LAYER).FirstOrDefault(); } return result; } catch (Exception ex) { Console.WriteLine("InWorkTransport:" + ex.Message + ex.StackTrace); LogHelper.Error("InWorkTransport:" + ex.Message, ex); } return result; } //筛选可用位置 private static List FilterAvailableLocations(List locations, string[] targetAreas) { return locations .Where(l => targetAreas.Any(area => l.S_CODE.Contains(area))) .Where(l => l.N_LOCK_STATE == 0 && l.N_CURRENT_NUM < l.N_CAPACITY) .ToList(); } /// /// 紧凑型入库货位 紧急送检区 空托缓存一、二区 /// /// 库区 /// public static Location CompactWorkTransport(string area) { Location result = null; var db = new SqlHelper().GetInstance(); try { //查询每排最后一列有托盘的货位 根据行分区 再找每一行的最后一列有货的货位 var list = db.Queryable(). Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE.Trim() == area).PartitionBy(a => a.N_ROW) .OrderByDescending(a => a.N_COL).Take(1).ToList(); if (list.Count > 0) { for (int i = 0; i < list.Count; i++) { LogHelper.Info($"有托盘排号{list[i].N_ROW},库区{area}"); //入货位后一位货位 result = db.Queryable().OrderBy(a => a.N_COL) .Where(a => a.S_AREA_CODE.Trim() == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).First(); if (result != null && result.N_LOCK_STATE == 0) { return result; } } } //没找到说明库区是空的 入里面 else { result = db.Queryable(). Where(a => a.S_AREA_CODE.Trim() == area && a.N_LOCK_STATE == 0 && a.N_CURRENT_NUM == 0) .OrderBy(a => a.N_COL).OrderBy(a => a.N_ROW).First(); } } catch (Exception ex) { Console.WriteLine("InWorkTransport:" + ex.Message + ex.StackTrace); LogHelper.Error("InWorkTransport:" + ex.Message, ex); } return result; } /// /// 托盘入库算法 /// /// /// /// internal static Location StorageCompute(string itemcode, string areacode) { var db = new SqlHelper().GetInstance(); Location result = null; //查询所有有托盘的排 var list = db.Queryable() .Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE.Trim() == areacode) .OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); if (list.Count > 0) { for (int i = 0; i < list.Count; i++) { LogHelper.Info($"有托盘排号{list[i].N_ROW},物料编码{itemcode},库区{areacode}"); //判断托盘物料是否相同物料信息相同 var cntr = db.Queryable().Where(a => a.S_LOC_CODE.Trim() == list[i].S_CODE).First(); if (cntr != null) { if (string.IsNullOrEmpty(itemcode))//空托入库 { var iteminfo = ContainerHelper.GetCntrItemRel(cntr.S_CNTR_CODE).FirstOrDefault(); if (iteminfo == null) { //物料相同入货位后一位货位 result = db.Queryable().OrderBy(a => a.N_COL) .Where(a => a.S_AREA_CODE.Trim() == areacode && a.N_ROW == list[i].N_ROW && a.N_COL > (list[i].N_COL + 1)).First(); } } else//满拖入库 { var iteminfo = ContainerHelper.GetCntrItemRel(cntr.S_CNTR_CODE).FirstOrDefault(); if (iteminfo != null) { if (iteminfo.S_ITEM_CODE == itemcode) { //物料相同入货位后一位货位 result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE.Trim() == areacode && a.N_ROW == list[i].N_ROW && a.N_COL > (list[i].N_COL + 1)).First(); } } } if (result != null) { return result; } } else { LogHelper.Info($"根据货物编码{list[i].S_CODE}未找到托盘货位绑定关系"); } } } return result; } /// /// WMS出库转运 /// /// 库区 /// 物料编码 /// public static Location OutWorkTransport(string area, string itemCode) { Location result = null; try { var db = new SqlHelper().GetInstance(); var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.N_LOCK_STATE == 0 && a.S_AREA_CODE == area).OrderBy(a => a.N_ROW).ToList(); list = list.OrderBy(s => s.N_ROW).ThenBy(s => s.N_COL).ToList(); for (int i = 0; i < list.Count; i++) { //判断货位是否被锁住了 与 是否有托盘 if (list[i].N_LOCK_STATE == 0) { var locCntrRel = db.Queryable().Where(s => s.S_LOC_CODE == list[i].S_CODE).First(); //判断是否传了物料 if (!string.IsNullOrEmpty(itemCode)) { #region 满托盘出库 if (locCntrRel != null) { var cntrItemRels = db.Queryable().Where(s => s.S_CNTR_CODE == locCntrRel.S_CNTR_CODE).First(); if (cntrItemRels != null) { LogHelper.Info($"货位有托盘:{JsonConvert.SerializeObject(cntrItemRels)}"); if (cntrItemRels.S_ITEM_CODE.Equals(itemCode)) { result = list[i]; } } } #endregion } else { if (locCntrRel != null) { result = list[i]; } } if (result != null) { break; } } } //if (result == null) //{ // for (int i = 0; i < list.Count; i++) // { // //判断货位是否被锁住了与是否有托盘 // if (list[i].S_LOCK_STATE.Trim() == "无") // { // var locCntrRel = db.Queryable().Where(s => s.S_LOC_CODE == list[i].S_CODE).First(); // //判断是否传了物料 // if (!string.IsNullOrEmpty(itemCode)) // { // #region 满托盘出库 // if (locCntrRel != null) // { // var cntrItemRels = db.Queryable().Where(s => s.S_CNTR_CODE == locCntrRel.S_CNTR_CODE).First(); // if (cntrItemRels != null) // { // LogHelper.Info($"货位有托盘:{JsonConvert.SerializeObject(cntrItemRels)}"); // if (cntrItemRels.S_ITEM_CODE.Equals(itemCode)) // { // result = list[i]; // } // } // } // #endregion // } // else // { // if (locCntrRel != null) // { // result = list[i]; // } // } // if (result != null) // { // break; // } // } // } //} } catch (Exception ex) { Console.WriteLine("OutWorkTransport:" + ex.Message + ex.StackTrace); LogHelper.Error("OutWorkTransport:" + ex.Message, ex); } return result; } /// /// 物料下线/送检缓存区->常规送检区 /// /// 起点货位 /// 终点货区 /// 物料(选填) /// internal static Results materialOffline(GetSubmitCheck model) { var result = new Results() { Code = "0", Message = "下线任务生成成功!", Data = null }; var db = new SqlHelper().GetInstance(); try { //校验起点货位是否存在/锁住 var loc = db.Queryable().Where(a => a.S_CODE == model.START_LOC).First(); if (loc == null || loc.N_LOCK_STATE != 0) { return new Results { Code = "1", Message = $"{model.START_LOC}库位已被锁定!", Data = null }; } //计算终点货位 if (string.IsNullOrEmpty(model.END_AREA)) { return new Results { Code = "1", Message = "出库未传终点库区!", Data = null }; } //如果是紧急送检区 紧凑型 var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault(); //如果是送检缓存区 var reservoirs2 = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault(); Location OutLoc = null; if (model.END_AREA.Equals(reservoirs.areaCode)) { LogHelper.Info($"紧急送检区=================="); OutLoc = CompactWorkTransport(model.END_AREA); } else if (model.END_AREA.Equals(reservoirs2.areaCode)) { LogHelper.Info($"送检缓存区=================="); OutLoc = InCgWorkTransport(model.START_LOC, model.END_AREA); } else { LogHelper.Info($"其他=================="); OutLoc = InWorkTransport(model.END_AREA); } //没传物料的话默认一个 string itemCode = null; string wlName = null; if (!string.IsNullOrEmpty(model.S_ITEM_CODE)) { itemCode = model.S_ITEM_CODE; wlName = "布卷"; //wlName = db.Queryable().Where(b => b.S_ITEM_CODE == model.S_ITEM_CODE).First().S_ITEM_NAME; } //创建托盘货位绑定关系 string trayCode = ContainerHelper.GenerateCntrNo(); //绑定起点货位(产线)和物料 不传的话这里没有绑物料托盘表 只绑了托盘货位表 ContainerHelper.BindLocCntrs(model.START_LOC, trayCode, itemCode, wlName); var reservoirs1 = Settings.ReservoirAreas.Where(s => s.areaName == "常规送检区").FirstOrDefault(); //创建任务 LogHelper.Info($"创建任务 起点:{model.START_LOC}终点:{OutLoc.S_CODE}", OutLoc.S_CODE == reservoirs1.areaCode ? "常规送检" : "物料下线"); var res = TaskProcess.CreateTransport(model.START_LOC, OutLoc.S_CODE, OutLoc.S_CODE == reservoirs1.areaCode ? "常规送检" : "物料下线", trayCode, 1, 1); if (!res) { return new Results { Code = "1", Message = "下线任务生成失败!", Data = null }; } return result; } catch (Exception ex) { Console.WriteLine("materialOffline:" + ex.Message + ex.StackTrace); LogHelper.Error("materialOffline:" + ex.Message, ex); throw; } } /// /// 呼叫空托 /// /// 起点类型(拆托机) /// 终点货位(产线) /// internal static Results CallEmptyTray(GetSubmitCheck model) { var result = new Results() { Code = "0", Message = "呼叫空托任务生成成功!", Data = null }; var db = new SqlHelper().GetInstance(); try { //必填参数校验 if (string.IsNullOrEmpty(model.START_LOC)) { return new Results { Code = "1", Message = "呼叫空托未传起点库位!", Data = null }; } if (string.IsNullOrEmpty(model.END_LOC)) { return new Results { Code = "1", Message = "呼叫空托未传终点库位!", Data = null }; } //校验终点货位是否存在/锁定 var loc = db.Queryable().Where(a => a.S_CODE == model.END_LOC).First(); if (loc == null || loc.N_LOCK_STATE != 0) { return new Results { Code = "1", Message = $"{model.END_LOC}库位已被锁定!", Data = null }; } ////从配置根据拆托机类型找到出口货位 //var reservoirs = Settings.linePlcInfos.Where(s => s.code == model.S_TYPE).FirstOrDefault(); //string OutLocStr = reservoirs.outLoca; //如果终点和产线下线是同一个货位 终点也不绑托盘 string trayCode = ContainerHelper.GenerateCntrNo(); //创建任务 LogHelper.Info($"创建任务 起点:{model.START_LOC}终点:{model.END_LOC}", "呼叫空托"); var res = TaskProcess.CreateTransport(model.START_LOC, model.END_LOC, "呼叫空托", trayCode, 1, 1); if (!res) { return new Results { Code = "1", Message = "呼叫空托任务生成失败!", Data = null }; } return result; } catch (Exception ex) { Console.WriteLine("CallEmptyTray:" + ex.Message + ex.StackTrace); LogHelper.Error("CallEmptyTray:" + ex.Message, ex); throw; } } /// /// 送检 常规送检区-->紧急送检区 /// /// 起点货位(选填) /// 物料(选填) /// internal static Results submitCheck(GetSubmitCheck model) { var result = new Results() { Code = "0", Message = "送检任务生成成功!", Data = null }; var db = new SqlHelper().GetInstance(); try { string startloc = ""; //物料不为空则根据物料找起点货位 if (!string.IsNullOrEmpty(model.S_ITEM_CODE)) { //根据物料找货位 var cgreservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "常规送检区").FirstOrDefault(); startloc = getLocByMaterial(model.S_ITEM_CODE, cgreservoirs.areaCode).S_CODE; if (startloc == null) { return new Results { Code = "1", Message = $"{model.S_ITEM_CODE}未找到该物料!", Data = null }; } } //如果传了起点 if (!string.IsNullOrEmpty(model.START_LOC)) { var loc = db.Queryable().Where(a => a.S_CODE == model.START_LOC).First(); if (loc == null || loc.N_LOCK_STATE != 0) { return new Results { Code = "1", Message = $"{model.START_LOC}库位已被锁定!", Data = null }; } startloc = loc.S_CODE; } //计算紧急送检区终点货位 var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault(); Location OutLoc = TaskProcess.CompactWorkTransport(reservoirs.areaCode); if (OutLoc == null) { return new Results { Code = "1", Message = $"终点库区紧急送检区未找到空货位!", Data = null }; } //创建送检任务 var locCntrRel = db.Queryable().Where(a => a.S_LOC_CODE == model.START_LOC).First(); LogHelper.Info($"创建任务 起点:{startloc}终点:{OutLoc.S_CODE}", "送检"); var res = TaskProcess.CreateTransport(startloc, OutLoc.S_CODE, "送检", locCntrRel.S_CNTR_CODE, 1, 1); if (!res) { return new Results { Code = "1", Message = "送检任务生成失败!", Data = null }; } return result; } catch (Exception ex) { Console.WriteLine("submitCheck:" + ex.Message + ex.StackTrace); LogHelper.Error("submitCheck:" + ex.Message, ex); throw; } } /// /// 根据物料找货位 根据CntrItemDetail时间 先进先出 连表查判断货位有没有锁 /// /// 物料 /// public static Location getLocByMaterial(string itemCode, string areaCode) { Location result = null; try { var db = new SqlHelper().GetInstance(); //两表联查查出有该物料的货位编号 (现场没有物料表) var locCntrs = db.Queryable().LeftJoin((p, m) => p.S_CNTR_CODE == m.S_CNTR_CODE) .Where((p, m) => m.S_ITEM_CODE == itemCode) .OrderBy((p, m) => p.T_CREATE) //按创建时间顺序 .Select((p, m) => p.S_LOC_CODE) // 选择托盘物料表的数据 .ToList(); LogHelper.Info($"有物料{itemCode}的货位编号{JsonConvert.SerializeObject(locCntrs)}"); //找常规送检区内含有查出物料货位的货位 var locList = db.Queryable() .Where(p => p.S_AREA_CODE == areaCode && p.N_LOCK_STATE == 0) .Where(s => locCntrs.Contains(s.S_CODE.Trim())) .ToList(); if (!locList.Any()) { return null; } result = locList.FirstOrDefault(); } catch (Exception ex) { Console.WriteLine("getLocByMaterial:" + ex.Message + ex.StackTrace); LogHelper.Error("getLocByMaterial:" + ex.Message, ex); } return result; } //存摄像头调用接口空满状态 货位,空满状态 private static string monitorStatus = null; /// /// 摄像头监测接口 /// /// 监测货位 /// 监测空满状态0空闲1占用3异常 /// internal static Results UpdateFullStatus(List models) { var result = new Results() { Code = "0", Message = "操作成功", Data = null }; var db = new SqlHelper().GetInstance(); //校验与内存是否一致 if (monitorStatus != null) { try { //string转成list var jsonList = JsonConvert.DeserializeObject>(monitorStatus); //找两个List的交集 var intersection = jsonList.Where(j => models.Any(m => m.PointCode == j.PointCode && m.PointStatus == j.PointStatus)).ToList(); LogHelper.Info($"摄像头与上次调用一致数据:{JsonConvert.SerializeObject(intersection)}"); foreach (var model in intersection) { //找到该点位的库区 var loc = db.Queryable().Where(a => a.S_CODE == model.PointCode).First(); //没锁再继续走 if (loc.N_LOCK_STATE == 0 && loc != null) { var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检入库区").FirstOrDefault(); //如果是送检入库区 if (reservoirs.areaCode.Equals(loc.S_AREA_CODE)) { var locCntrRel = db.Queryable().Where(a => a.S_LOC_CODE == model.PointCode).First(); var container = new Container(); if (locCntrRel == null) { //第一次自己绑定一个托盘 string trayCode = ContainerHelper.GenerateCntrNo(); ContainerHelper.BindLocCntrs(model.PointCode, trayCode, null, null); container = db.Queryable().Where(a => a.S_CODE == trayCode).First(); container.C_FULL = "2"; } else { //查数据库空满状态 跟缓存不一样则更新 //找到这个货位的容器 空满状态C_FULL改成2满 0 -- 空 1 -- 有货 2 -- 满 container = db.Queryable().Where(a => a.S_CODE == locCntrRel.S_CNTR_CODE).First(); if (container.C_FULL != model.PointStatus.ToString()) { container.C_FULL = "2"; } } var res = db.Updateable(container).UpdateColumns(it => it.C_FULL).ExecuteCommand() > 0; if (res) { LogHelper.Info($"修改{model.PointCode}货位空满状态成功", "摄像头监测"); } else { LogHelper.Info($"修改{model.PointCode}货位空满状态失败", "摄像头监测"); } } else { //如果是空托缓存区 判断拆托机是否有空位 空托缓存区满了且拆托机入口有空则创建任务 var reservoirs1 = Settings.ReservoirAreas.Where(s => s.areaName == "3min空托区").FirstOrDefault(); var reservoirs2 = Settings.ReservoirAreas.Where(s => s.areaName == "6min空托区").FirstOrDefault(); if (loc.S_AREA_CODE.Equals(reservoirs1.areaCode) || loc.S_AREA_CODE.Equals(reservoirs2.areaCode))//三寸空托 { ProcessEmptyTrayAreas(db, loc, reservoirs1.areaCode, reservoirs2.areaCode); } } } else { LogHelper.Info($"{model.PointCode}货位任务已经生成", "摄像头监测"); } } } catch (Exception ex) { Console.WriteLine("UpdateFullStatus:" + ex.Message + ex.StackTrace); LogHelper.Error("UpdateFullStatus:" + ex.Message, ex); throw; } } //list转string 存到内存 monitorStatus = JsonConvert.SerializeObject(models); return result; } //摄像头监测空托缓存区 private static void ProcessEmptyTrayAreas(SqlSugar.ISqlSugarClient db, Location loc, string areaCode1, string areaCode2) { var plcDeviceTable = new PlcDeviceTable(); string endLoc = null; if (loc.S_AREA_CODE.Equals(areaCode1)) { plcDeviceTable = S7Helper.plcDeviceTables.Find(s => s.DeviceNo == 1001); endLoc = Settings.linePlcInfos.Where(s => s.code == "拆托机1").FirstOrDefault().inLoca; } else if (loc.S_AREA_CODE.Equals(areaCode2))//六寸空托 { plcDeviceTable = S7Helper.plcDeviceTables.Find(s => s.DeviceNo == 1004); endLoc = Settings.linePlcInfos.Where(s => s.code == "拆托机2").FirstOrDefault().inLoca; } //判断是否允许放框 if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 0 && plcDeviceTable.requestPut) { //创建任务 从空托缓存区叉个料到拆托机 var list = db.Queryable().Where(a => a.S_AREA_CODE.Trim() == loc.S_AREA_CODE && a.N_CURRENT_NUM > 0 && a.N_LOCK_STATE == 0).OrderByDescending(a => a.N_ROW) .OrderByDescending(a => a.N_COL).First(); var startLoc = list.S_CODE; string trayCode = ContainerHelper.GenerateCntrNo(); LogHelper.Info($"创建任务 起点:{startLoc}终点:{endLoc}", "拆托"); var res = TaskProcess.CreateTransport(startLoc, endLoc, "拆托", trayCode, 1, 1); if (res) { LogHelper.Info($"起点:{startLoc}终点:{endLoc}任务创建成功", "拆托"); } else { LogHelper.Info($"起点:{startLoc}终点:{endLoc}任务创建失败", "拆托"); } } } /// /// 抽检主动呼叫 起点:送检缓存区 /// /// 物料 /// 终点货位 /// internal static Results activeCall(GetSubmitCheck model) { var result = new Results() { Code = "0", Message = "抽检主动呼叫任务生成成功!", Data = null }; var db = new SqlHelper().GetInstance(); try { //根据物料找某库区的货位 var cgreservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault(); var startloc = getLocByMaterial(model.S_ITEM_CODE, cgreservoirs.areaCode); if (startloc == null) { return new Results { Code = "1", Message = $"未找到包含物料{model.S_ITEM_CODE}的货位", Data = null }; } //终点 var endloc = db.Queryable().Where(a => a.S_CODE == model.END_LOC).First(); if (endloc == null || endloc.N_LOCK_STATE != 0) { return new Results { Code = "1", Message = $"{model.END_LOC}库位已被锁定!", Data = null }; } //创建任务 var locCntrRel = db.Queryable().Where(a => a.S_LOC_CODE == startloc.S_CODE).First(); LogHelper.Info($"创建任务 起点:{startloc.S_CODE}终点:{endloc.S_CODE}", "抽检主动呼叫"); var res = TaskProcess.CreateTransport(startloc.S_CODE, endloc.S_CODE, "抽检主动呼叫", locCntrRel.S_CNTR_CODE, 1, 1); if (!res) { return new Results { Code = "1", Message = "抽检主动呼叫任务生成失败!", Data = null }; } return result; } catch (Exception ex) { Console.WriteLine("submitCheck:" + ex.Message + ex.StackTrace); LogHelper.Error("submitCheck:" + ex.Message, ex); throw; } } /// /// 主动物料绑定 /// /// 物料编码 /// 绑定货位 /// internal static Results bindMaterial(GetSubmitCheck model) { var result = new Results() { Code = "0", Message = "物料绑定成功!", Data = null }; var db = new SqlHelper().GetInstance(); try { string cntrStr = ContainerHelper.GenerateCntrNo(); var locCntrRel = db.Queryable().Where(a => a.S_LOC_CODE == model.BIND_LOC).First(); if (locCntrRel != null) { cntrStr = locCntrRel.S_CNTR_CODE; } var res = ContainerHelper.BindLocCntrs(model.BIND_LOC, cntrStr, model.S_ITEM_CODE, "布卷"); if (!res) { return new Results { Code = "1", Message = $"物料{model.S_ITEM_CODE}货位{model.BIND_LOC}绑定失败", Data = null }; } return result; } catch (Exception ex) { Console.WriteLine("bindMaterial:" + ex.Message + ex.StackTrace); LogHelper.Error("bindMaterial:" + ex.Message, ex); throw; } } /// /// 按钮盒调用下线 /// /// 起点货位 /// 终点货区 /// internal static bool tcpOffline(string startLoc, string endArea) { var db = new SqlHelper().GetInstance(); try { //校验起点货位是否存在/锁住 var loc = db.Queryable().Where(a => a.S_CODE == startLoc).First(); if (loc == null || loc.N_LOCK_STATE != 0) { LogHelper.Info("起点货位不存在或已锁" + startLoc); return false; } //计算终点货位 //if (string.IsNullOrEmpty(endArea)) //{ // return new Results { Code = "1", Message = "出库未传终点库区!", Data = null }; //} //如果是紧凑型 var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault(); Location OutLoc = null; if (endArea.Equals(reservoirs.areaCode)) { OutLoc = CompactWorkTransport(endArea); } else { OutLoc = InWorkTransport(endArea); } //创建托盘货位绑定关系 string trayCode = ContainerHelper.GenerateCntrNo(); //没传物料的话默认一个 string itemCode = null; string wlName = null; //if (!string.IsNullOrEmpty(model.S_ITEM_CODE)) //{ // itemCode = model.S_ITEM_CODE; // wlName = db.Queryable().Where(b => b.S_ITEM_CODE == model.S_ITEM_CODE).First().S_ITEM_NAME; //} ContainerHelper.BindLocCntrs(OutLoc.S_CODE, trayCode, itemCode, wlName); //创建任务 LogHelper.Info($"创建任务 起点:{startLoc}终点:{OutLoc.S_CODE}", "按钮盒下线"); return TaskProcess.CreateTransport(startLoc, OutLoc.S_CODE, "按钮盒下线", trayCode, 1, 1); } catch (Exception ex) { Console.WriteLine("materialOffline:" + ex.Message + ex.StackTrace); LogHelper.Error("materialOffline:" + ex.Message, ex); throw; } } /// /// 按钮盒调用空托 /// /// 起点货位 /// 终点货位 /// internal static bool tcpEmptyTray(string startLoc, string endLoc) { var db = new SqlHelper().GetInstance(); try { //校验终点货位是否锁 var endloc = db.Queryable().Where(a => a.S_CODE == endLoc).First(); if (endloc == null || endloc.N_LOCK_STATE != 0) { LogHelper.Info("终点货位已锁" + endLoc); return false; } //创建托盘货位绑定关系 string trayCode = ContainerHelper.GenerateCntrNo(); //创建任务 LogHelper.Info($"创建任务 起点:{startLoc}终点:{endLoc}", "按钮盒调用空托"); return TaskProcess.CreateTransport(startLoc, endLoc, "按钮盒调用空托", trayCode, 1, 1); } catch (Exception ex) { Console.WriteLine("materialOffline:" + ex.Message + ex.StackTrace); LogHelper.Error("materialOffline:" + ex.Message, ex); throw; } } /// /// 安全交互 /// /// 请求点位 /// 请求码 /// internal static safeResult safetyInteraction(SafetyInteraction model) { //0允许进入 1不允许进入 var result = new safeResult() { code = "1", msg = "success" }; try { var reservoirs = Settings.SafeInteractions.Where(s => s.pointCode == model.STATION_NAME).FirstOrDefault();//y0-0000 y1-0001 on-FF00 off-0000 var rgvSafeInteraction = DeviceProcess.rgvSafeInteraction; //RGV if (reservoirs.type.Equals("RGV")) { LogHelper.Info($"RGV安全交互 请求点位:{model.STATION_NAME}请求码:{model.APPLY_CODE}"); //卸货请求进入 if (model.APPLY_CODE.Equals("5")) { //根据ip读状态 if (rgvSafeInteraction != null) { LogHelper.Info($"RGV安全交互参数{JsonConvert.SerializeObject(rgvSafeInteraction)}"); var safelist = JsonConvert.DeserializeObject>(rgvSafeInteraction); if (safelist.Any()) { var safedata = safelist.Where(s => s.ip == reservoirs.ip).First(); //1允许卸货 2卸货完成确认 if (safedata.data == "1") { LogHelper.Info($"RGV安全交互 允许卸货"); return new safeResult() { code = "0", msg = "success" }; } } } } } //拆托机 else if (reservoirs.type.Equals("CTJ")) { LogHelper.Info($"拆托机安全交互 请求点位:{model.STATION_NAME}请求码:{model.APPLY_CODE}"); //找到线体 根据线体找内存里的状态 var reservoirs1 = Settings.ConveyorLinesInfos.Where(s => s.location == model.STATION_NAME).FirstOrDefault(); var plcDeviceTable = S7Helper.plcDeviceTables.Find(a => a.DeviceNo == reservoirs1.code); if (plcDeviceTable != null) { LogHelper.Info($"拆托机安全交互参数{JsonConvert.SerializeObject(plcDeviceTable)}"); if (model.APPLY_CODE.Equals("1")) { //0-脱机状态,1-待机状态,2-运行中 待机且有托盘且请求取框才走 if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 1 && plcDeviceTable.requestTake) { LogHelper.Info($"拆托机安全交互 允许取框"); return new safeResult() { code = "0", msg = "success" }; } } else if (model.APPLY_CODE.Equals("5")) { //0-脱机状态,1-待机状态,2-运行中 待机且无托盘且允许放框才走 if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 0 && plcDeviceTable.requestPut) { LogHelper.Info($"拆托机安全交互 允许放框"); return new safeResult() { code = "0", msg = "success" }; } } } } //TcpClient tcpClient = new TcpClient(); ////发送信号写请求开门 //var str = tcpClient.WriteSingleRegisterRtu("01050000FF008C3A", reservoirs.ip, int.Parse(reservoirs.port)); ////发送信号读门状态 //var x0bool = tcpClient.ReadInputRegistersRtu("010200000001B9CA", reservoirs.ip, int.Parse(reservoirs.port)); ////如果开门到位 //if (x0bool) //{ // return new safeResult() { code = "0", msg = "success" }; //} ////请求离开 //else if (model.APPLY_CODE.Equals("8")) //{ // ////发送信号写请求关门 // //var str = tcpClient.WriteSingleRegisterRtu("010500000000CDCA", reservoirs.ip, int.Parse(reservoirs.port)); // //var str2 = tcpClient.WriteSingleRegisterRtu("01050001FF00DDFA", reservoirs.ip, int.Parse(reservoirs.port)); // ////发送信号读门状态 // //var x0bool = tcpClient.ReadInputRegistersRtu("010200010001E80A", reservoirs.ip, int.Parse(reservoirs.port)); // ////如果门已关 // //if (x0bool) // //{ // // return new safeResult() { code = "0", msg = "success" }; // //} //} return result; } catch (Exception ex) { Console.WriteLine("safetyInteraction:" + ex.Message + ex.StackTrace); LogHelper.Error("safetyInteraction:" + ex.Message, ex); throw; } } } }