using HH.WCS.QingXigongchang.core; using HH.WCS.QingXigongchang.device; using HH.WCS.QingXigongchang.dispatch; using HH.WCS.QingXigongchang.util; using HH.WCS.QingXigongchang.wms; using Microsoft.SqlServer.Server; using Newtonsoft.Json; using NLog.Time; using SqlSugar; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics.Eventing.Reader; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using System.Timers; using System.Web.Http.Results; using System.Web.Security; using System.Web.UI.WebControls; using static HH.WCS.QingXigongchang.dispatch.NDC; using static HH.WCS.QingXigongchang.util.Settings; namespace HH.WCS.QingXigongchang.process { public class devINFOS : deviceInfo { public string Infos { get; set; } } /// /// 设备信号处理 /// internal class DeviceProcess { public static Dictionary Deviceooo = new Dictionary(); public static Dictionary doorStatus = new Dictionary(); static object _lock = new object(); static bool First = true; internal static void Analysis(string data, string ip) { if (data.Length >= 6) { //去掉消息头3F 00 data = data.Substring(4); var plc = Settings.GetDeviceInfoList().Where(a => a.address == ip).FirstOrDefault(); if (plc == null) { LogHelper.Warn($"IP:{ip}的plc客户端 不存在配置中。", "机"); return; } else if (plc != null && plc.enable != 1) { LogHelper.Warn($"{plc.deviceName}-{plc.address}-{plc.deviceType}-data:{data}- 机器未启用。 ", "机"); return; } if (Deviceooo.ContainsKey(ip)) { Deviceooo[ip] = new { 产线号 = plc.deviceName, 富勒产线号 = plc.FuLeLineNo, 设备号 = plc.deviceNo, 设备类型 = plc.deviceType, 货位 = plc.location, 任务权重 = plc.taskPri, 信号 = data, 接收时间 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; } else Deviceooo.Add(ip, new { 产线号 = plc.deviceName, 富勒产线号 = plc.FuLeLineNo, 设备号 = plc.deviceNo, 设备类型 = plc.deviceType, 货位 = plc.location, 任务权重 = plc.taskPri, 信号 = data, 接收时间 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); Console.WriteLine($"接受到设备数据:{plc.deviceName}-{plc.address}-{plc.deviceType}-data:{data}。 "); LogHelper.Info($"{plc.deviceName}-{plc.address}-{plc.deviceType}-data:{data}。 "); if (plc != null) { if (plc.enable == 1) { // 门 if (plc.deviceType == 1) { if (!First) { AnalysisDoor(data, plc); } else { lock (_lock) { AnalysisDoor(data, plc); First = false; } } } //瓶盖 else if (plc.deviceType <= 3) { AnalysisBottleCap(data, plc); } //翻斗机 - 瓶坯 else if (plc.deviceType == 5) { AnalysisBottleCapTipper(data, plc); } //翻斗机 - 瓶盖 4 水盖。6 无菌 else if (plc.deviceType <= 6) { // 瓶盖翻斗机. AnalysisBottleCapTipper10(data, plc); } //翻斗机 - 10 水线翻斗机 else if (plc.deviceType == 10) { AnalysisBottleCapTipper10(data, plc); } // 瓶坯 else if (plc.deviceType == 8) { AnalysisBottlePEM(data, plc); } // 505水线 else if (plc.deviceType == 9) { Analysis505(data, plc); } ///水线 //else if (plc.deviceType == 10) //{ // //AnalysisBottleCapTipper10(data, plc); //} // 电梯,提升机。吊机。 管他啥,从一楼搬二楼。 else if (plc.deviceType == 11) { Analysis11(data, plc); } else if (plc.deviceType == 13) { Analysis13(data, plc); } } } else { Console.WriteLine($"TCP信号处理:未查询到IP为{ip}的数据,请检查deviceInfo配置中心是否存在该IP的数据!"); } } } private static void Analysis13(string data, deviceInfo plc) { //用于 出库时 是否可以直达 提升机。 00 后面还需增加退料工单处理。 //一个提升机 兼顾多个产线的原物料纸箱。 所以需要批量YWLWorkOrder 比如一个提升机需要 提供3线和4线2个成品的纸箱。 var ooo = LocationHelper.GetList(x => x.WorkType == 6 && x.SQL_State == "执行中"); var ods = ooo.FindAll(x => x.SQL_PLineNo.Contains(plc.deviceName)); if (ods.Count > 0) { foreach (var od in ooo) { if (string.IsNullOrEmpty(od.SQL_charge)) continue; var num = od.SQL_charge?.Split(':'); var v = Array.ConvertAll(num, Convert.ToInt32); if (v.Length == 2) { if (od.SQL_Total >= v[0]) { LogHelper.Info(plc.deviceName + $"已累计信号量{od.SQL_Total} 待领料数{od.OutNum}--开始转换(信号量>{(od.SQL_Total - v[0])} 领料数>{od.OutNum + v[1]}"); od.SQL_Total -= v[0]; od.OutNum += v[1]; WCSHelper.Do(db => { db.Updateable(od).UpdateColumns(x => new { x.SQL_Total, x.OutNum }).ExecuteCommand(); }); } else if (od.OutNum % 2 > 0)//奇数 { if (v[1] == 2 && v[0] % 2 == 0) // 比如 6:2 可以换算成 3:1 { if (od.SQL_Total >= (v[0] / 2)) { od.SQL_Total -= (v[0] / 2); od.OutNum += 1; WCSHelper.Do(db => { db.Updateable(od).UpdateColumns(x => new { x.SQL_Total, x.OutNum }).ExecuteCommand(); }); } } } } } } var si = data.Substring(1, 1); if (!ods.Any() || data.Contains("21")) si = "0"; if (data.Contains("11") || data.Contains("21")) { var _cl = LocationHelper.GetLoc(plc.location[0]); if (_cl.S_LOCK_STATE != "无") { goto ballll; } if (_cl == null) { LogHelper.Info($"{plc.deviceName}配置的位置没找到。"); goto ballll; } var _clrel = LocationHelper.GetLocCntrRel(_cl.S_LOC_CODE); var _clrel0 = _clrel.OrderByDescending(xx => xx.T_CREATE).FirstOrDefault(); var od = LocationHelper.GetList(x => x.SQL_PLineNo.Contains(plc.deviceName) && x.WorkType == 1 && x.SQL_State == "执行中").FirstOrDefault(); if (data.Contains("21")) { double v1 = 0; if (od == null) { Console.WriteLine(plc.deviceName + " 退料信号,但工单未开启。"); goto ballll; } if (od.SQL_PLineNo.Contains("标签") || od.SQL_PLineNo.Contains("收缩膜")) { switch (od.S_BQ_TRAY_TYPE) { case "零头板": v1 = .5; break; case "零头板2": v1 = .75; break; case "满板": v1 = 1; break; default: v1 = 0; break; } if (v1 == 0) { LogHelper.CErrorLog($"{od.SQL_WorkNo}-{od.S_BQ_TRAY_TYPE} 转换后为0,无法识别。"); goto ballll; } } if (!_clrel.Any()) { WMSTask task = null; WCSHelper.Do(db => { task = db.Queryable().Where(x => x.S_START_LOC == _cl.S_LOC_CODE).OrderBy(x => x.T_CREATE, OrderByType.Desc).First(); }); if (task.S_B_STATE != "取消" && task.S_B_STATE != "完成") { goto ballll; } //var enloc = LocationHelper.GetLoc(task.S_END_LOC); //if (enloc.S_LOCK_STATE != "无") return; LogHelper.Info(_cl.S_LOC_CODE + $"货位 的没有托盘 没有物料记录 退料,开始写入。"); List lirl = new List { new CntrItemRel { S_CNTR_CODE=Settings.GetTimeStamp(), S_ITEM_CODE=od.SQL_ItemCode, S_ITEM_NAME=od.SQL_ItemName, S_CJ_NAME = od.S_CJ_NAME, N_BQ_TRAY_TYPE=v1 } }; string ma = ""; List list = new List(); if (!string.IsNullOrEmpty(od.MidArea)) list.Add(od.MidArea); if (!string.IsNullOrEmpty(od.S_ROW)) list.Add(od.S_ROW); ma = string.Join(",", list); List lcrl = new List { new LocCntrRel { S_LOC_CODE=_cl.S_LOC_CODE, S_CNTR_CODE = lirl.FirstOrDefault().S_CNTR_CODE, S_TYPE=v1==0?ma:HH.WCS.QingXigongchang.core.Monitor.BQ_PRA.B } }; _cl.N_CURRENT_NUM += 1; WCSHelper.Do(db => { db.Insertable(lirl).ExecuteCommand(); db.Insertable(lcrl).ExecuteCommand(); db.Insertable(new Container { S_CNTR_CODE = lirl.FirstOrDefault().S_CNTR_CODE, }).ExecuteCommand(); db.Updateable(_cl).UpdateColumns(x => new { x.N_CURRENT_NUM }).ExecuteCommand(); }); goto ballll; } else if (string.IsNullOrEmpty(_clrel0.S_TYPE)) { LocationHelper.DoAction(db => { //_clrel0.S_TYPE = "YWLYLTKQ"; //return db.Updateable(_clrel0).UpdateColumns(it => new { it.S_TYPE }).ExecuteCommand() > 0; return db.Deleteable(_clrel).ExecuteCommand() > 0; }); } goto ballll; } if (od != null) { si = "0"; } else if (data.Contains("11"))// && (ods.Find(x => x.SQL_PLineNo.Contains("纸箱")) != null || plc.deviceName.Contains("T1")) { //if (!ods.Any()) // return; LogHelper.Info($" 数量:{_cl.N_CURRENT_NUM}= 托盘数:{_clrel.Count}"); if (_cl.N_CURRENT_NUM > 0 || _clrel.Any()) { LogHelper.Info($" time:{_clrel0?.T_CREATE} = s_type:{_clrel0.S_TYPE}"); if (_clrel.Any()) if (DateTime.Now.Subtract(_clrel0.T_CREATE).TotalSeconds < 10 || !string.IsNullOrEmpty(_clrel0.S_TYPE)) goto ballll; LocationHelper.DoAction(db => { db.Deleteable(_clrel).ExecuteCommand(); _cl.N_CURRENT_NUM = 0; return db.Updateable(_cl).UpdateColumns(x => new { x.N_CURRENT_NUM }).ExecuteCommand() > 0; }); } if (!plc.deviceName.Contains("T1")) goto ballll; else if (!plc.deviceName.Contains("水线标签")) { LogHelper.Info(_cl.S_LOC_CODE + $"货位 找起点"); Location sBit = null; foreach (var sRarea in plc.areaPriy) { var arloclist = LocationHelper.GetAreaNormalLocList(sRarea);// LocationHelper.GetList(x => x.S_AREA_CODE == _clrel0.S_TYPE && x.S_LOCK_STATE != "报废"); if (arloclist.Any()) { foreach (var rss in arloclist.GroupBy(x => x.N_ROW).OrderBy(x => x.Count(y => y.N_CURRENT_NUM > 0)).ThenBy(xx => xx.Key)) { var rowlist = rss.OrderBy(x => x.N_COL).ToList(); var _cl2 = rowlist.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (_cl2 != null) { _clrel = LocationHelper.GetLocCntrRel(_cl2.S_LOC_CODE); if (!_clrel.Any()) { LogHelper.Info(_cl.S_LOC_CODE + $"货位 的没有托盘 没有物料记录"); break; } sBit = _cl2; } if (sBit != null) break; } } if (sBit != null) break; } if (sBit != null) { var sign = Settings.GetTimeStamp(); var res = TaskProcess.CreateTransport(sign, sBit.S_LOC_CODE, _cl.S_LOC_CODE, "原物料搬运-纸箱", new List { _clrel.FirstOrDefault().S_CNTR_CODE }, sBit.N_CURRENT_NUM, 1, 1, 50);///, EdnRarea == "YWLYLTKQ" ? _clrel0.S_TYPE : ""); LogHelper.Info($"原物料搬运 上提升机。 {sign} 任务 ,创建{res} "); } } } } ballll: if (doorStatus.ContainsKey(plc.location[0])) { doorStatus[plc.location[0]].info = si; doorStatus[plc.location[0]].modify = DateTime.Now; } else { doorStatus.Add(plc.location[0], new signalInfo { info = si, modify = DateTime.Now }); } } #region 自动门 /// /// 自动门 /// /// /// internal static void AnalysisDoor(string data, Settings.deviceInfo plc) { //LogHelper.Info(plc.deviceName + "自动门状态:" + data + ",地址为:" + plc.address, "自动门"); if (data.Length / 2 != plc.deviceNo.Length) { return; } for (int i = 0; i < plc.deviceNo.Length; i++) { string _no = plc.deviceNo[i]; if (!string.IsNullOrEmpty(_no)) { string state = data.Substring(i * 2 + 1, 1); if (doorStatus.Keys.Contains(_no)) { doorStatus[_no].info = state; doorStatus[_no].modify = DateTime.Now; } else { doorStatus.Add(_no, new signalInfo { info = state, modify = DateTime.Now }); } } } } public class signalInfo { public string info { get; set; } public DateTime modify { get; set; } } private static Dictionary doorRecord = new Dictionary(); /// /// 交管请求 /// /// /// /// internal static void Traffic(string agv, string zone, int occupy) { List plcs = new List(); var ppcs = Settings.GetDoorOneToMany().Find(x => x.DoorNo == zone); //if (ppcs != null) //{ // foreach (var p in ppcs.deviceNo) // { // Settings.deviceInfo plc = (from a in Settings.GetDeviceInfoList() // where a.deviceNo.Contains(zone) // select a).FirstOrDefault(); // if (plc != null) // plcs.Add(plc); // } // if (ppcs.deviceNo.Length == plcs.Count) // { // LogHelper.Info($"{zone}门好对应的 门组:{string.Join(";", ppcs.deviceNo)}, 找到的设备{string.Join(";", plcs.Select(x => x.address))}数量不对, 缺少门地址,中断不开。"); // return; // } //} Settings.deviceInfo plc = (from a in Settings.GetDeviceInfoList() where a.deviceNo.Contains(zone) select a).FirstOrDefault(); if (plc != null) { int index = 1; for (int i = 0; i < plc.deviceNo.Length; i++) { if (plc.deviceNo[i] == zone) { index = i + 1; break; } } LogHelper.Info($"安全门对接:门号:{zone},index:{index},occupy{occupy}", "自动门"); switch (occupy) { case 1023: { string req2 = $"3f 00 {index}1 0d 0a"; PlcHelper.SendHex(plc.address, req2); string msg2 = $"安全门开门请求,门号:{zone},index:{index},ip={plc.address}, data={req2}"; LogHelper.Info(msg2, "自动门"); if (doorStatus.Keys.Contains(zone) && DateTime.Now.Subtract(doorStatus[zone].modify).TotalSeconds < 5.0 && doorStatus[zone].info == "1") { LogHelper.Info($"安全门已经打开:门号:{zone},index:{index}", "自动门"); NDCHelper.Traffic(zone, agv); } break; } case 1025: { string req = $"3f 00 {index}0 0d 0a"; PlcHelper.SendHex(plc.address, req); string msg = $"安全门关门请求,门号:{zone},index:{index},ip={plc.address}, data={req}"; LogHelper.Info(msg, "自动门"); if (new int[] { 4, 5 }.Contains(plc.deviceType)) { var loc = LocationHelper.GetLoc(plc.location[0]); //入库锁,或者没有锁。 货位有货 就翻斗。 if (loc.N_CURRENT_NUM == 1 && loc.S_LOCK_STATE.Trim() != "出库锁") { LogHelper.Info($"关门后 翻斗机有货(给翻斗信号。({plc.address})" + $"3f 00 10 0d 0a"); PlcHelper.SendHex(plc.address, $"3f 00 10 0d 0a"); LocationHelper.UnLockLoc(plc.location[0].Trim()); } else { LogHelper.Info($"{loc.S_LOCK_STATE},关门后 翻斗机没有货,不处理"); } } break; } } } else if (ppcs != null) { LogHelper.Info($"安全门对接:门号:{zone},门组{string.Join(";", ppcs.deviceNo)},occupy{occupy}", "自动门"); switch (occupy) { case 1023: { for (int i = 0; i < ppcs.deviceNo.Length; i++) { var zzz = ppcs.deviceNo[i]; //var close = ppcs.SignClose[i]; var open = ppcs.SignOpen[i]; plc = (from a in Settings.GetDeviceInfoList() where a.deviceNo.Contains(zzz) select a).FirstOrDefault(); if (plc == null) { LogHelper.Info($"安全门门号:{zzz},设备不存在", "自动门"); return; } LogHelper.Info($"安全门对接:门号:{zzz},打开信号{open}", "自动门"); string req2 = $"3f 00 {open} 0d 0a"; PlcHelper.SendHex(plc.address, req2); string msg2 = $"安全门开门请求,门号:{zzz},index:{open},ip={plc.address}, data={req2}"; LogHelper.Info(msg2, "自动门"); if (doorStatus.Keys.Contains(zzz) && DateTime.Now.Subtract(doorStatus[zzz].modify).TotalSeconds < 5.0 && doorStatus[zzz].info == "1") { LogHelper.Info($"安全门已经打开:门号:{zzz},index:{open}", "自动门"); } else { LogHelper.Info($"安全门未开:门组{zone}门号:{zzz}, 中断。不可入", "自动门"); return; } } //if(zoneIn) NDCHelper.Traffic(zone, agv); break; } case 1025: { for (int i = 0; i < ppcs.deviceNo.Length; i++) { var zzz = ppcs.deviceNo[i]; var close = ppcs.SignClose[i]; //var open = ppcs.SignOpen[i]; plc = (from a in Settings.GetDeviceInfoList() where a.deviceNo.Contains(zzz) select a).FirstOrDefault(); if (plc == null) { LogHelper.Info($"安全门门号:{zzz},设备不存在", "自动门"); continue; } //int index = 1; //for (int i = 0; i < plc.deviceNo.Length; i++) //{ // if (plc.deviceNo[i] == zzz) // { // index = i + 1; // break; // } //} string req = $"3f 00 {close} 0d 0a"; PlcHelper.SendHex(plc.address, req); string msg = $"安全门关门请求,门号:{zzz},index:{close},ip={plc.address}, data={req}"; LogHelper.Info(msg, "自动门"); } break; } } } else { LogHelper.Info("1023 信号 else", "======="); } } /* IO模块1 只用02功能码读取 1x0000 一楼开门到位信号 1x0001 二楼开门到位信号 IO模块2 只用05功能码写入 0x0000 一楼楼层按钮信号 0x0001 二楼楼层按钮信号 */ private static Dictionary elevatorRecord = new Dictionary(); /// /// 电梯只需要开门,不需要关门 /// /// /// private static void TrafficElevator(string zone, bool occupy) { //判断是否时电梯门 var elevatorDoor = Settings.GetelEvatorDoorList().Where(a => a.door == zone).FirstOrDefault(); if (elevatorDoor != null) { //oitcp中转 modbus rtu 方式开电梯 //BitConverter.ToString(CRC16LH(Hex2Bytes("01 02 00 03 00 01"))).Replace("-", string.Empty).ToLower() LogHelper.Info($"收到agv开电梯门请求{zone}", "电梯"); if (occupy) { var readAddr = elevatorDoor.addr == 1 ? 0 : 1; var read = $"01 02 00 0{readAddr} 00 01 "; read += BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(read))).Replace("-", " ").ToLower(); LogHelper.Info($"查询电梯门{zone}状态发送{read}", "电梯"); var res = OITcpHelper.HexTransit(new OITcpHelper.StrTransitData { host = Settings.ElevatorIP, data = read, port = 8899 }); if (res != null && res.errCode == 0 && res.result.Replace(" ", "").Substring(7, 1) == "1") { //判断门开了,通知agv走 LogHelper.Info($"电梯门{zone}开了,通知agv进去", "电梯"); NDCHelper.Traffic(zone); } else { if (!elevatorRecord.Keys.Contains(zone) || DateTime.Now.Subtract(elevatorRecord[zone]).TotalSeconds < 8) { //开门是一次吸合,一次断开 var write = $"01 05 00 0{elevatorDoor.addr} ff 00 "; write += BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(write))).Replace("-", " ").ToLower(); LogHelper.Info($"发送电梯{zone}开门请求{write},吸合", "电梯"); res = OITcpHelper.HexTransit(new OITcpHelper.StrTransitData { host = Settings.ElevatorIP, data = write, port = 8899 }); if (res != null && res.errCode == 0) { Console.WriteLine("准备发送断开信号"); Thread.Sleep(1000); write = $"01 05 00 0{elevatorDoor.addr} 00 00 "; write += BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(write))).Replace("-", " ").ToLower(); LogHelper.Info($"发送电梯{zone}开门请求{write},断开", "电梯"); OITcpHelper.HexTransit(new OITcpHelper.StrTransitData { host = Settings.ElevatorIP, data = write, port = 8899 }); Thread.Sleep(1000); LogHelper.Info($"发送电梯{zone}开门请求{write},断开", "电梯"); OITcpHelper.HexTransit(new OITcpHelper.StrTransitData { host = Settings.ElevatorIP, data = write, port = 8899 }); Thread.Sleep(1000); LogHelper.Info($"发送电梯{zone}开门请求{write},断开", "电梯"); OITcpHelper.HexTransit(new OITcpHelper.StrTransitData { host = Settings.ElevatorIP, data = write, port = 8899 }); if (!elevatorRecord.Keys.Contains(zone)) { elevatorRecord.Add(zone, DateTime.Now); } else { elevatorRecord[zone] = DateTime.Now; } } else { Console.WriteLine("发送吸合信号失败"); } } } } } } #endregion #region 瓶盖机 internal static void AnalysisBottleCap(string data, Settings.deviceInfo plc) { //LogHelper.Info($"{plc.deviceName}-{plc.address}-{data}"); /* 状态1 满托产生,需要取满送空,从满托产生到满托取走一直维持状态1 //状态2 送空完成之后为状态2 //状态3 满托取走,送空之前为状态3,开机默认状态也为状态3 空框放下后。 中间一直给1 写0 */ if (data.Length == 4) { if (data.Substring(1, 1) == "1") { //BottleCapInfoFull1(plc, plc.location[0]); BottleCapInfoFull(plc, plc.location[0]); } if (data.Substring(3, 1) == "1") { //BottleCapInfoFull1(plc, plc.location[1]); if (BottleCapInfoFull(plc, plc.location[1])) { } } } } static bool BottleCapInfoFull(Settings.deviceInfo plc, string location) { bool result = false; if (location == "") { Console.WriteLine($"{plc.deviceName} 的setting 没有配置货位数据。 "); return result; } var workOrder = WCSHelper.GetWorkOrder(plc.deviceName); if (workOrder == null) { LogHelper.Info(plc.deviceName + "工单没有【执行中】的工单"); return result; } if (workOrder.SQL_Modify_TIme == null) return false; if (DateTime.Now.Subtract(workOrder.SQL_Modify_TIme ?? DateTime.Now).TotalSeconds < 10) return false; LogHelper.Info($"{location} 检验下线数据"); //满框下线 bool isUsing = workOrder.SQL_UsingNow.Trim() == "Y"; var p0 = LocationHelper.GetLoc(location); if (p0 != null && p0.S_LOCK_STATE == "无") { if (p0.T_FULL_TIME == null && p0.N_CURRENT_NUM == 0) { // 瓶盖上空 LocationHelper.TakeEmptyToBottleBoyd(new WMSTask { S_START_LOC = location, }); return true; }//托盘放下 1分钟内 取货请求,都不处理。 else if (p0.N_CURRENT_NUM > 0 && DateTime.Now.Subtract(p0.T_FULL_TIME ?? DateTime.Now).Minutes < 1) { p0.T_FULL_TIME = DateTime.Now; for (var i = 0; i < plc.location.Length; i++) { if (location == plc.location[i]) { PlcHelper.SendHex(plc.address, "3F00" + (i + 1) + "0" + "0d0a"); LocationHelper.DoAction(db => { db.Updateable(p0).UpdateColumns(it => new { it.T_FULL_TIME }).ExecuteCommand(); return true; }); break; } } return false; } LogHelper.Info($"{location}满框下线"); Location endBit = null; string TaskDesc = ""; var _ctrl = LocationHelper.GetLocCntrRel(location); if (!_ctrl.Any()) { LogHelper.Info($"{plc.deviceName}-{location}没绑定托盘"); return result; } bool Uisng = false; if (_ctrl.FirstOrDefault().S_CNTR_CODE.StartsWith("J")) { Uisng = true; var LineTo = workOrder.SQL_LinkLineNO; LogHelper.Info($"{location}满框下线 J- " + LineTo); var plcTo = Settings.GetDeviceInfoList().Where(a => a.deviceName == LineTo).FirstOrDefault(); if (plcTo == null) { LogHelper.Info($"{plc.deviceName}-{workOrder.SQL_WorkNo}链接的产线号{LineTo} 没找到设备"); return result; } if (plcTo.deviceType != 4 && plcTo.deviceType != 6) { LogHelper.Info($"{plc.deviceName}-{workOrder.SQL_WorkNo}链接的产线号{LineTo} 不是瓶盖翻斗机。"); return result; } var ba = Settings.GetBolAreaList().Find(x => x.DeviceName == plcTo.deviceName && x.deviceType == plcTo.deviceType); if (ba == null) { LogHelper.Info($"{plc.deviceName}-{workOrder.SQL_WorkNo}链接的产线号{LineTo} BolArea 未配置。"); return result; } var loclist = LocationHelper.GetAreaNormalLocList(ba.UsingBolArea); if (true) { var t = DateTime.Now; var rowlist = LocationHelper.GetRowLock(ba.UsingBolArea); LogHelper.Info($"{location}满框下线 {ba.UsingBolArea}库区, rowlist:{rowlist.Count}"); foreach (var itemrs in loclist.GroupBy(x => x.N_ROW).OrderBy(y => rowlist.Find(x => x.S_LOCK_STATE == "入库锁" && x.N_ROW == y.Key)?.T_CREATE ?? t).ThenBy(x => x.Key)) //Descending x.Count(y => y.N_CURRENT_NUM > 0))) { var tnotnull = rowlist.Find(x => x.S_LOCK_STATE == "出库锁" && x.N_ROW == itemrs.Key); LogHelper.Info($"{location}满框下线 第{itemrs.Key}排 是否被出库锁排?:{tnotnull != null}"); if (tnotnull != null) continue; var _r = itemrs.ToList(); var f = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f != null) { if (f.N_CURRENT_NUM < f.N_CAPACITY) { endBit = f; } else endBit = _r.FindAll(x => x.N_COL > (f?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else { endBit = _r.OrderBy(x => x.N_COL).FirstOrDefault(); } if (endBit != null) { TaskDesc = "瓶盖即产转翻斗机线边"; break; } } } if (false) { var allrows = loclist.Select(x => x.N_ROW).Distinct(); var hasRows = loclist.FindAll(x => x.N_CURRENT_NUM > 0).OrderByDescending(x => x.T_FULL_TIME); var EptRows = allrows.Except(hasRows.Select(x => x.N_ROW).Distinct()); //最后一个入的排,如果是满的就找空的。 if (hasRows.Any()) { var lastFull = hasRows.FirstOrDefault(); if (lastFull != null) { //if (lastFull.N_CURRENT_NUM < lastFull.N_CAPACITY) //{ // endBit = lastFull; //} //else endBit = loclist.Find(x => x.N_ROW == lastFull.N_ROW && x.N_COL >= lastFull.N_COL && x.N_CURRENT_NUM < x.N_CAPACITY); } } else LogHelper.Info($"{plc.deviceName} - 即产下线,最后入库位是满的 或者 没有曾入库数据。"); //如过没有最后一个入排,直接找空的。-- 只需要看endbit 就好了。 if (endBit == null && EptRows.Any()) { endBit = loclist.FindAll(x => x.N_ROW == EptRows.FirstOrDefault()).OrderBy(x => x.N_COL).FirstOrDefault(); } else LogHelper.Info($"{plc.deviceName} -已找到可用位置:{endBit?.S_LOC_CODE},或没有空排可用。 等着吧,不能把要出的堵住。"); if (endBit != null) { TaskDesc = "瓶盖即产转翻斗机线边"; //var cntrEnd2 = LocationHelper.GetLocCntrRel(endBit.S_LOC_CODE); //var citem = ContainerHelper.GetCntrItemRel(cntrEnd2.FirstOrDefault().S_CNTR_CODE); } } if (false) foreach (var item in loclist.OrderByDescending(x => x.T_FULL_TIME).GroupBy(x => x.N_ROW)) { var ilist = item.OrderBy(x => x.N_COL).ToList(); var lastFull = ilist.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (lastFull != null) { if (lastFull.N_CURRENT_NUM < lastFull.N_CAPACITY) { endBit = lastFull; var cntrEnd2 = LocationHelper.GetLocCntrRel(endBit.S_LOC_CODE); var citem = ContainerHelper.GetCntrItemRel(cntrEnd2.FirstOrDefault().S_CNTR_CODE); //if (citem.Any() && citem.FirstOrDefault().S_ORDER_NO.Contains(workOrder.SQL_WorkNo)) //{ // LogHelper.Info($"{lastFull.S_LOC_CODE} 位置数量{lastFull.N_CURRENT_NUM}.已有的托盘不是这个工单的。"); // continue; //} } else endBit = ilist.Find(x => x.N_COL > lastFull.N_COL); } else endBit = ilist.FirstOrDefault(); if (endBit != null) { TaskDesc = "瓶盖即产转翻斗机线边"; break; } } if (false) foreach (var item in loclist.OrderByDescending(x => x.N_CURRENT_NUM).ThenBy(x => x.N_ROW).ThenBy(x => x.N_COL)) { if (item.N_CURRENT_NUM < item.N_CAPACITY) { if (item.N_CURRENT_NUM > 0) { var cntrEnd2 = LocationHelper.GetLocCntrRel(endBit.S_LOC_CODE); var citem = ContainerHelper.GetCntrItemRel(cntrEnd2.FirstOrDefault().S_CNTR_CODE); if (citem.Any() && citem.FirstOrDefault().S_ORDER_NO.Contains(workOrder.SQL_WorkNo)) { LogHelper.Info($"{item.S_LOC_CODE} 位置数量{item.N_CURRENT_NUM}.已有的托盘不是这个工单的。"); continue; } } endBit = item; TaskDesc = "瓶盖即产转翻斗机线边"; break; } } ///按列排序。 最后一个满框。后街接着入。 //var loclist = LocationHelper.GetAreaNormalLocList(ba.UsingBolArea); //var locs = LocationHelper.GetLocList(x => x.S_AREA_CODE == ba.UsingBolArea && x.S_LOC_CODE != "报废").OrderBy(x => x.N_COL).ThenBy(x => x.N_ROW).ToList(); //var lastffl = locs.FindAll(x => x.N_CURRENT_NUM > 0 && x.T_FULL_TIME != null).OrderBy(x => x.T_FULL_TIME).LastOrDefault(); //var lastEmpty = locs.FindAll(x => x.N_CURRENT_NUM == 0 && x.T_EMPTY_TIME != null).OrderBy(x => x.T_EMPTY_TIME).LastOrDefault(); //if (lastffl != null) //{ // if (lastEmpty == null) lastffl = null; // else if (lastffl.N_COL <= lastEmpty.N_COL) { lastffl = null; lastEmpty = null; } // else if (lastffl == locs.LastOrDefault()) lastffl = null; //} /////最后一个满框入库位往后找。 //foreach (var item in locs.Skip((lastffl == null || lastffl == locs.LastOrDefault() ? 0 : locs.IndexOf(lastffl))).GroupBy(x => x.N_COL)) //{ // ///先放小排, 先取大排 取放按列 // var collist = item.OrderBy(x => x.N_ROW).ToList(); // if (!collist.Any()) continue; // if (collist.Find(x => x.S_LOCK_STATE != "无") != null) continue; // var collastful = collist.Find(x => x.N_CURRENT_NUM > 0); // Location nex = null; // if (collastful == null) nex = collist.FirstOrDefault(); // else nex = collist.Find(x => x.N_ROW >= collastful.N_ROW && x.N_CURRENT_NUM < x.N_CAPACITY); // if (nex != null) // { // endBit = nex; // TaskDesc = "瓶盖即产转翻斗机线边"; // break; // } //} } else if (false) { LogHelper.Info($"{location}满框下线 F"); var ba = Settings.GetBolAreaList().Find(x => x.DeviceName == plc.deviceName && x.deviceType == plc.deviceType); if (ba == null) { LogHelper.Info($"{plc.deviceName}-{workOrder.SQL_WorkNo}的 BolArea 未配置。"); return result; } var loclist = LocationHelper.GetAreaNormalLocList(ba.NotUsingBolArea); foreach (var item in loclist.OrderByDescending(x => x.N_CURRENT_NUM).ThenBy(x => x.N_ROW).ThenBy(x => x.N_COL)) { if (item.N_CURRENT_NUM < item.N_CAPACITY) { if (item.N_CURRENT_NUM > 0) { var cntrEnd2 = LocationHelper.GetLocCntrRel(item.S_LOC_CODE); var citem = ContainerHelper.GetCntrItemRel(cntrEnd2.FirstOrDefault().S_CNTR_CODE); if (citem.Any() && TaskProcess.UPFule && !string.IsNullOrEmpty(citem.FirstOrDefault()?.S_ORDER_NO) && citem.FirstOrDefault().S_ORDER_NO.Contains(workOrder.SQL_WorkNo)) { LogHelper.Info($"{item.S_LOC_CODE} 位置数量{item.N_CURRENT_NUM}.已有的托盘不是这个工单的。"); continue; } } endBit = item; TaskDesc = "瓶盖非即产线边"; break; } } } else { TaskDesc = "瓶盖非即产线边"; LogHelper.Info($"{location}满框下线 F 非即产满框下线 按 plc.areaPriy 顺序。"); /*-对应的 翻斗机上线(指定产线号) 也是。*/ var db = new SqlHelper().GetInstance(); foreach (var item in plc.areaPriy) { var _l = LocationHelper.GetAreaNormalLocList(item); var rowlist = LocationHelper.GetRowLock(item); var t = DateTime.Now; foreach (var itemrs in _l.GroupBy(x => x.N_ROW).OrderBy(y => rowlist.Find(x => x.S_LOCK_STATE == "入库锁" && x.N_ROW == y.Key)?.T_CREATE ?? t).ThenBy(x => x.Key)) //Descending x.Count(y => y.N_CURRENT_NUM > 0))) { if (rowlist.Find(x => x.S_LOCK_STATE == "出库锁" && x.N_ROW == itemrs.Key) != null) continue; var _r = itemrs.ToList(); var f = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f != null) { var rel = LocationHelper.GetLocCntrRel(f.S_LOC_CODE); var cntrrel = ContainerHelper.GetCntrItemRel(rel.FirstOrDefault()?.S_CNTR_CODE); if (cntrrel.FirstOrDefault()?.S_ITEM_CODE != $"{workOrder.SQL_PLineNo}>{workOrder.SQL_ItemCode}") { LogHelper.Info($"{f.S_LOC_CODE} 位置的 物料{cntrrel.FirstOrDefault()?.S_ITEM_CODE} 与本次下线{workOrder.SQL_PLineNo}>{workOrder.SQL_ItemCode} 不符。 筛选下一排"); continue; } ///// 看看是否出库记录 //var row = rowlist.FindAll(x => x.S_AREA_CODE == f.S_AREA_CODE && f.N_ROW == x.N_ROW).ToList();//db.Queryable().Where(x => x.S_AREA_CODE == f.S_AREA_CODE && f.N_ROW == x.N_ROW).ToList(); //if (row.Any()) //{ // if (row.FirstOrDefault().S_LOCK_STATE != "入库锁") // continue; //} if (f.N_CURRENT_NUM < f.N_CAPACITY) { endBit = f; } else endBit = _r.FindAll(x => x.N_COL > (f?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else { endBit = _r.OrderBy(x => x.N_COL).FirstOrDefault(); } if (endBit != null) break; } if (endBit != null) break; } } LogHelper.Info($"{location}满框下线 终点位:{endBit?.S_LOC_CODE}"); if (endBit != null) { int endLayer = endBit.N_CURRENT_NUM + 1; //if (endLayer > 1) //{ // var cntrEnd2 = LocationHelper.GetLocCntrRel(endBit.S_LOC_CODE); // var citem = ContainerHelper.GetCntrItemRel(cntrEnd2.FirstOrDefault().S_CNTR_CODE); // if (!cntrEnd2.Any() || !citem.Any()) // { // LogHelper.Info($"{endBit.S_LOC_CODE} 位置数量{endBit.N_CURRENT_NUM}.但没有托盘或没有托盘物料数据。"); // return false; // } //} var carryCntrs = new List { _ctrl.FirstOrDefault().S_CNTR_CODE };//DateTime.Now.ToString("yyMMddHHmmss") }; var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, location, endBit.S_LOC_CODE, TaskDesc, carryCntrs, 1, endLayer, carryCntrs.Count, plc.taskPri); if (bb) { // 写入托盘物料表。 LocationHelper.DoAction(db => { db.Deleteable().Where(it => it.S_CNTR_CODE == _ctrl.FirstOrDefault().S_CNTR_CODE).ExecuteCommand(); db.Insertable(new CntrItemRel { S_CNTR_CODE = _ctrl.FirstOrDefault().S_CNTR_CODE, //S_ITEM_CODE = workOrder.SQL_ItemCode, S_ITEM_CODE = $"{workOrder.SQL_PLineNo}>{workOrder.SQL_ItemCode}", F_QTY = Uisng ? workOrder.SQL_PCNumber_using : workOrder.SQL_PCNumber, S_ORDER_NO = workOrder.SQL_WorkNo + ("_" + (workOrder.FromFuLe?.Trim() ?? "")), S_BATCH_NO = workOrder.SQL_BatchNo, }).ExecuteCommand(); return true; }); LogHelper.Info($"{plc.deviceName} 当前机器{location}位置状态{p0} 正在执行取满任务"); } result = bb; } } else LogHelper.Info($"{location}货位状态 {p0?.S_LOCK_STATE} 下线中断"); return result; } static bool BottleCapInfoFull1(Settings.deviceInfo plc, string location) { bool result = false; if (location == "") { Console.WriteLine($"{plc.deviceName} 的setting 没有配置货位数据。 "); return result; } var workOrder = WCSHelper.GetPGWorkOrder(plc.deviceName); if (workOrder == null) { LogHelper.Info(plc.deviceName + "工单没有【执行中】的工单"); return result; } LogHelper.Info($"{location} 检验下线数据"); //满框下线 bool isUsing = workOrder.SQL_UsingNow.Trim() == "Y"; var p0 = LocationHelper.GetLoc(location); if (p0 != null && p0.S_LOCK_STATE == "无") { if (p0.T_FULL_TIME == null && p0.N_CURRENT_NUM == 0) { // 瓶盖上空 LocationHelper.TakeEmptyToBottleBoyd2346(new WMSTask { S_START_LOC = location, }); return true; } //托盘放下 1分钟内 取货请求,都不处理。 else if (p0.N_CURRENT_NUM > 0 && DateTime.Now.Subtract(p0.T_FULL_TIME ?? DateTime.Now).Minutes < 1) { p0.T_FULL_TIME = DateTime.Now; for (var i = 0; i < plc.location.Length; i++) { if (location == plc.location[i]) { PlcHelper.SendHex(plc.address, "3F00" + (i + 1) + "0" + "0d0a"); LocationHelper.DoAction(db => { db.Updateable(p0).UpdateColumns(it => new { it.T_FULL_TIME }).ExecuteCommand(); return true; }); break; } } return false; } LogHelper.Info($"{location}满框下线"); Location endBit = null; List _l = new List(); var SQL_ItemCode = workOrder.SQL_ItemCode; string TaskDesc = ""; var _ctrl = LocationHelper.GetLocCntrRel(location); if (!_ctrl.Any()) { LogHelper.Info($"{plc.deviceName}-{location}没绑定托盘"); return result; } bool Uisng = false; if (_ctrl.FirstOrDefault().S_CNTR_CODE.Contains("J")) { TaskDesc = "瓶盖下线即产"; _l = LocationHelper.GetLocList(x => x.S_AREA_CODE == workOrder.SQL_Area && x.S_LOCK_STATE != "报废"); #region 直接去终点 var _arealock = _l.FindAll(x => x.S_LOCK_STATE != "无").Select(x => x.N_ROW).Distinct(); if (_arealock.Any()) _l.RemoveAll(x => _arealock.Contains(x.N_ROW)); foreach (var itemrs in _l.OrderByDescending(x => x.N_CURRENT_NUM).GroupBy(x => x.N_ROW)) { var _r = itemrs.ToList(); var f = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f != null) { var rel = LocationHelper.GetLocCntrRel(f.S_LOC_CODE); var cntrrel = ContainerHelper.GetCntrItemRel(rel.FirstOrDefault()?.S_CNTR_CODE); if (cntrrel.FirstOrDefault()?.S_ITEM_CODE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{f.S_LOC_CODE} 位置的 物料{cntrrel.FirstOrDefault()?.S_ITEM_CODE} 与本次下线{workOrder.SQL_PLineNo}>{SQL_ItemCode} 不符。 筛选下一排"); continue; } if (f.N_CURRENT_NUM < f.N_CAPACITY) { endBit = f; } else endBit = _r.FindAll(x => x.N_COL > (f?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else { endBit = _r.OrderBy(x => x.N_COL).FirstOrDefault(); } if (endBit != null) break; } #endregion } if (!_ctrl.FirstOrDefault().S_CNTR_CODE.Contains("J")) { LogHelper.Info($"{plc.deviceName} 注塑机下线 目标库区排{workOrder.S_ROW1} ."); if (string.IsNullOrEmpty(workOrder.S_ROW1)) { return false; } else { TaskDesc = "瓶盖下线非即产"; var rs = workOrder.S_ROW1.Split('='); var rows = Array.ConvertAll(rs[rs.Length - 1].Trim().Split('-'), Convert.ToInt32); //_l = LocationHelper.GetLocList(x => x.S_AREA_CODE == rs[0] && rows.Contains(x.N_ROW) && x.S_LOCK_STATE != "报废"); if (true) { _l = LocationHelper.GetAreaNormalLocList(rs[0]); foreach (var itemrs in _l.FindAll(x => rows.Contains(x.N_ROW)).GroupBy(x => x.N_ROW).OrderBy(x => x.Count(y => y.N_CURRENT_NUM > 0))) { var _r = itemrs.ToList(); var f = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f != null) { var rel = LocationHelper.GetLocCntrRel(f.S_LOC_CODE); var cntrrel = ContainerHelper.GetCntrItemRel(rel.FirstOrDefault()?.S_CNTR_CODE); if (cntrrel.FirstOrDefault()?.S_ITEM_CODE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") //if (rel.FirstOrDefault()?.S_TYPE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{f.S_LOC_CODE} 位置的 物料{cntrrel.FirstOrDefault()?.S_ITEM_CODE} 与本次下线{workOrder.SQL_PLineNo}>{SQL_ItemCode} 不符。 筛选下一排"); continue; } if (f.N_CURRENT_NUM < f.N_CAPACITY) { endBit = f; } else endBit = _r.FindAll(x => x.N_COL > (f?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else { endBit = _r.OrderBy(x => x.N_COL).FirstOrDefault(); } if (endBit != null) break; } } goto vvvvvv; } vvvvvv: //if (false)//endBit == null&& if (endBit == null && workOrder.S_Is_Auto.Trim() == "Y") foreach (var item in _l.GroupBy(x => (x.N_ROW + 1) / 2).OrderByDescending(x => x.Count(y => y.N_CURRENT_NUM > 0))) { var lst = item.ToList().Find(x => x.N_CURRENT_NUM > 0); var _r = item.ToList(); var f = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f != null) { var rel = LocationHelper.GetLocCntrRel(f.S_LOC_CODE); var cntrrel = ContainerHelper.GetCntrItemRel(rel.FirstOrDefault()?.S_CNTR_CODE); if (cntrrel.FirstOrDefault()?.S_ITEM_CODE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") continue; foreach (var rowlocs in item.GroupBy(x => x.N_ROW)) { List _cols = item.OrderBy(x => x.N_COL).ToList(); Location e = _cols.FindAll((Location x) => x.N_CURRENT_NUM > 0).LastOrDefault();//从左往右最后一个满位。 if (e != null) { rel = LocationHelper.GetLocCntrRel(e.S_LOC_CODE); cntrrel = ContainerHelper.GetCntrItemRel(rel.FirstOrDefault()?.S_CNTR_CODE); if (cntrrel.FirstOrDefault()?.S_ITEM_CODE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{e.S_LOC_CODE} 位置的 物料{cntrrel.FirstOrDefault()?.S_ITEM_CODE} 与本次下线{($"{workOrder.SQL_PLineNo}>{SQL_ItemCode}")} 不符。 筛选下一排"); continue; } } if (e != null && e.N_CURRENT_NUM < e.N_CAPACITY) { endBit = e; } else { var empT = _cols.FindAll(x => x.N_CURRENT_NUM == 0).FirstOrDefault();//从左往右第一个空位 if (empT != null) endBit = empT; } if (endBit != null) break; } } if (endBit != null) break; } } LogHelper.Info($"{location}满框下线 终点位:{endBit?.S_LOC_CODE}"); if (endBit != null) { int endLayer = endBit.N_CURRENT_NUM + 1; //if (endLayer > 1) //{ // var cntrEnd2 = LocationHelper.GetLocCntrRel(endBit.S_LOC_CODE); // var citem = ContainerHelper.GetCntrItemRel(cntrEnd2.FirstOrDefault().S_CNTR_CODE); // if (!cntrEnd2.Any() || !citem.Any()) // { // LogHelper.Info($"{endBit.S_LOC_CODE} 位置数量{endBit.N_CURRENT_NUM}.但没有托盘或没有托盘物料数据。"); // return false; // } //} var carryCntrs = new List { _ctrl.FirstOrDefault().S_CNTR_CODE };//DateTime.Now.ToString("yyMMddHHmmss") }; var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, location, endBit.S_LOC_CODE, TaskDesc, carryCntrs, 1, endLayer, carryCntrs.Count, plc.taskPri); if (bb) { // 写入托盘物料表。 LocationHelper.DoAction(db => { db.Deleteable().Where(it => it.S_CNTR_CODE == _ctrl.FirstOrDefault().S_CNTR_CODE).ExecuteCommand(); db.Insertable(new CntrItemRel { S_CNTR_CODE = _ctrl.FirstOrDefault().S_CNTR_CODE, //S_ITEM_CODE = workOrder.SQL_ItemCode, S_ITEM_CODE = $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}", F_QTY = Uisng ? workOrder.SQL_PCNumber_using : workOrder.SQL_PCNumber, S_ORDER_NO = workOrder.SQL_WorkNo + ("_" + (workOrder.FromFuLe?.Trim() ?? "")), S_BATCH_NO = workOrder.SQL_BatchNo, }).ExecuteCommand(); return true; }); LogHelper.Info($"{plc.deviceName} 当前机器{location}位置状态{p0} 正在执行取满任务"); } result = bb; } } else LogHelper.Info($"{location}货位状态 {p0?.S_LOCK_STATE} 下线中断"); return result; } /// /// 非即产空框堆叠位 入库 /// public static void TakeEmpty2WH() { try { foreach (var areas in Settings.GetBolAreaList().FindAll(x => x.deviceType == 4 || x.deviceType == 10 || x.deviceType == 6))//.Select(x => x.NotUsingEmpty).Distinct()) { var area = areas.NotUsingEmpty; var loclist = LocationHelper.GetAreaNormalLocList(area, false); if (loclist.Find(x => x.N_CURRENT_NUM == x.N_CAPACITY && x.S_LOCK_STATE == "出库锁") != null) continue; IEnumerable lockcols = (from x in loclist.FindAll((Location x) => x.S_LOCK_STATE.Trim() != "无" && x.S_LOCK_STATE.Trim() != "报废") select x.N_ROW).Distinct(); if (lockcols.Any()) { loclist.RemoveAll((Location x) => lockcols.Contains(x.N_ROW)); } //var bo = Settings.GetBolAreaList().Find(x => x.NotUsingEmpty == area && !new int[] { 4, 6, 10 }.Contains(x.deviceType)); //if (bo != null) //{ // ///这里空框时翻斗机产生的, 如果瓶盖不需要了,那就都入库去。 瓶盖看工单的, 没开工单不会出库的。 // var workOrder = WCSHelper.GetWorkOrder(bo.DeviceName); // if (workOrder != null) // { // if (workOrder.SQL_UsingNow.Trim() != "Y") // { // //瓶盖是非即产的工单。 // // 如果有空位,就入了 // foreach (var item in loclist.GroupBy(x => x.N_ROW)) // { // if (item.ToList().Find(x => x.N_CURRENT_NUM > 0) == null) // { // LogHelper.Info($"{bo.DeviceName} 瓶盖 非即产。线边有空位,不入库"); // return; // } // } // LogHelper.Info($"{bo.DeviceName} 瓶盖 非即产。线边没空位了,去入库"); // } // } //} var startBit = loclist.Find(x => x.N_CURRENT_NUM == x.N_CAPACITY); Location endBit = null; int endLayer = 1; if (startBit != null) { // 入库不满排 最晚时间入库的排(先找N排一列。符合机器的。 防止因出库导致的不满排 loclist = LocationHelper.GetLocList(x => x.S_AREA_CODE == (areas.deviceType == 6 ? "PGWJCK" : "SGK")); //var oneonelist = loclist.GroupBy(x => x.N_ROW).Select(x => x.ToList().Find(y => y.N_CURRENT_NUM > 0)).ToList(); //foreach (var item in oneonelist.OrderByDescending(x => x.T_CREATE).ThenByDescending(x => x.N_ROW)) var oneonelist = loclist.OrderByDescending(x => x.T_FULL_TIME).GroupBy(x => x.N_ROW);//.Select(x => x.ToList().Find(y => y.N_CURRENT_NUM > 0)).ToList(); LogHelper.Info($"oneonelist非即产空框堆叠位 入库" + oneonelist?.Count()); foreach (var itemr in oneonelist) { var item = itemr.ToList().FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (item == null) continue; LogHelper.Info($"oneonelist非即产空框堆叠位 入库" + JsonConvert.SerializeObject(item)); var loccntr = LocationHelper.GetLocCntrRel(item.S_LOC_CODE); if (loccntr.Any() && loccntr.FirstOrDefault()?.S_TYPE == "空框") { //这里就是该机器的最后一次入库列。 var rl = loclist.FindAll(x => x.N_ROW == item.N_ROW); if (rl.Find(x => x.S_LOCK_STATE != "无" && x.S_LOCK_STATE != "报废") != null) { break; } var crl = rl.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (crl.N_CURRENT_NUM < crl.N_CAPACITY && crl.N_CURRENT_NUM + startBit.N_CURRENT_NUM <= crl.N_CAPACITY) { endBit = crl; break; } var lstE = rl.FindAll(x => x.N_COL > crl.N_COL).OrderBy(x => x.N_COL).FirstOrDefault(); if (lstE != null) { endBit = lstE; break; } } } //入空排 if (endBit == null) { lockcols = (from x in loclist.FindAll((Location x) => x.N_CURRENT_NUM > 0) select x.N_ROW).Distinct(); if (lockcols.Any()) { loclist.RemoveAll((Location x) => lockcols.Contains(x.N_ROW)); } endBit = loclist.OrderBy(x => x.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault(); } } if (endBit != null) { var _ctrl = LocationHelper.GetLocCntrRel(startBit.S_LOC_CODE); var carryCntrs = _ctrl.OrderByDescending(x => x.T_CREATE).Select(x => x.S_CNTR_CODE).ToList();//DateTime.Now.ToString("yyMMddHHmmss") }; var bb = TaskProcess.CreateTransport("", startBit.S_LOC_CODE, endBit.S_LOC_CODE, "瓶盖空筐转运-J2", carryCntrs, 1, endBit.N_CURRENT_NUM + 1, carryCntrs.Count, 60); continue; } } } catch (Exception ex) { LogHelper.Error("非即产空框112" + ex.Message, ex); } } /// /// 出非即产瓶盖空框 到 瓶盖线边 /// public static void TakeNotUsing2PGXB() { try { foreach (var plc in Settings.GetDeviceInfoList().FindAll(x => x.enable == 1 && (x.deviceType == 2 || x.deviceType == 3))) { WorkOrder workOrder = WCSHelper.GetWorkOrder(plc.deviceName); if (workOrder == null) continue; var USING = workOrder.SQL_UsingNow?.Trim() == "Y"; var bolarea = Settings.GetBolAreaList().Find(x => x.DeviceName == plc.deviceName); if (bolarea == null) continue; if (plc.deviceType == 2) { if (!USING) { LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, "空框", 0); } //else // LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, "空框", 1); } else if (plc.deviceType == 3) { if (!USING) { LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, "空框", 0); } //else // LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, "空框", 1); } else continue; } } catch (Exception ex) { LogHelper.Error("无水出空框" + ex.Message, ex); } } /// /// 非即产满框出翻斗机线边 /// public static void TakeNotUsing2FDJXB() { try { foreach (var plc in Settings.GetDeviceInfoList().FindAll(x => x.enable == 1 && (x.deviceType == 4 || x.deviceType == 6))) { WorkOrder workOrder = WCSHelper.GetWorkOrder(plc.deviceName); if (workOrder == null) continue; var USING = workOrder.SQL_UsingNow?.Trim() == "Y"; var bolarea = Settings.GetBolAreaList().Find(x => x.DeviceName == plc.deviceName); if (bolarea == null) continue; if (false) { if (plc.deviceType == 6) { if (!USING) { LocationHelper.WJGTakeFull2FDJXB(bolarea, plc, workOrder); //LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, plc.deviceName, 0); } //else // LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, plc.deviceName, 1); } else if (plc.deviceType == 4) { if (!USING) LocationHelper.SGTakeFull2FDJXB(bolarea, plc, workOrder); //if (!USING) //{ // LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, plc.deviceName, 0); //} //else // LocationHelper.TakeEmpty2PGxb(bolarea, plc, workOrder, plc.deviceName, 1); } } else { bool water = plc.deviceType == 4; ///领料查询 - - 查看是否有领料 ///1 有领料。 走领料 ///2.没有领料- 直接出 WorkOrder order = workOrder; LingItemOrder od = null; if (TaskProcess.UPFule) { var dvi = plc; LocationHelper.DoAction(db => { od = db.Queryable().Where(it => dvi.FuLeLineNo.Contains(it.DeviceNo) && it.State == "执行").First(); return true; }); if (order?.FromFuLe == "Y") { if (od == null) { LogHelper.Info((water ? "水盖" : "无菌") + "翻斗机;富勒工单,无领料单或 领料单已经完成,不出库。"); return; } } else { if (od != null) { LogHelper.Info((water ? "水盖" : "无菌") + "翻斗机;非富勒工单,但是有未完成领料单,无法识别出库。"); return; } } //至此。 有领料走领料出。 没领料走普通出 } LogHelper.Info((water ? "水盖" : "无菌") + "出库开始。" + order.FromFuLe); LocationHelper.WJGTakeFull2FDJXB(bolarea, plc, workOrder, od); } //else continue; } } catch (Exception ex) { LogHelper.Error("无水出满框" + ex.Message, ex); } } /// /// 非即产瓶盖 入库 /// public static void TakeNotUsing2WH() { TakeNotUsing2WH2(); } /// /// 非即产入库。 /// 有入库任务就等完成 /// 如果链接的翻斗机开着,且非即产工单,且线边有至少一个空位都不入了。 /// 否则,就循环入库。 /// /// public static bool TakeNotUsing2WH2() { var result = false; var plcl = Settings.GetDeviceInfoList().FindAll(x => x.deviceType == 2 || x.deviceType == 3); foreach (var plc in plcl) { //LogHelper.Info($"{plc.deviceName}--入库"); var workOrder = WCSHelper.GetWorkOrder(plc.deviceName); //if (workOrder == null) { // continue; //} var ba = Settings.GetBolAreaList().Find(x => x.DeviceName == plc.deviceName && x.deviceType == plc.deviceType); if (ba == null) { LogHelper.Info($"{plc.deviceName}-的 BolArea 未配置。"); continue; } LogHelper.Info($"{plc.deviceName}--入库" + ba.NotUsingBolArea); var loclist = LocationHelper.GetAreaNormalLocList(ba.NotUsingBolArea, false); /// 这里是 合并 出入区域的流程。 //if (loclist.Find(x => x.N_CURRENT_NUM == x.N_CAPACITY && x.S_LOCK_STATE == "出库锁") != null) // continue; //LogHelper.Info($"{plc.deviceName}--{ba.NotUsingBolArea}入库处理,查看翻斗机状态,如果翻斗机是非即产的,且线边有空位,就不入库。"); //{ // var bo = Settings.GetBolAreaList().Find(x => x.NotUsingEmpty == ba.NotUsingEmpty && new int[] { 4, 6, 10 }.Contains(x.deviceType)); // if (bo != null) /// 如果翻斗机没开 。 那就都入库去吧。 // { // ///查看链接的翻斗机。 // var Forder = WCSHelper.GetWorkOrder(bo.DeviceName); // if (Forder != null && Forder.SQL_UsingNow.Trim() != "Y") // { // //翻斗机是非即产的工单。 // // 如果有空位,就入了 // foreach (var item in loclist.GroupBy(x => x.N_ROW)) // { // if (item.ToList().Find(x => x.N_CURRENT_NUM > 0) == null) // { // LogHelper.Info($"{plc.deviceName} 链接的{bo.DeviceName} 翻斗机 非即产。线边有空位,不入库"); // return false; // } // } // LogHelper.Info($"{plc.deviceName} 链接的{bo.DeviceName} 翻斗机 非即产。线边没空位了,去入库"); // } // } //} IEnumerable lockcols = (from x in loclist.FindAll((Location x) => x.S_LOCK_STATE.Trim() != "无" && x.S_LOCK_STATE.Trim() != "报废") select x.N_ROW).Distinct(); if (lockcols.Any()) { loclist.RemoveAll((Location x) => lockcols.Contains(x.N_ROW)); } var startBit = loclist.Find(x => x.N_CURRENT_NUM == x.N_CAPACITY); Location endBit = null; int endLayer = 1; var brekkkkk = false;//需要中断 if (startBit != null) { // 入库不满排 最晚时间入库的排(先找N排一列。符合机器的。 防止因出库导致的不满排 loclist = LocationHelper.GetLocList(x => x.S_AREA_CODE == (plc.deviceType == 2 ? "PGWJCK" : "SGK")); var oneonelist = loclist.OrderByDescending(x => x.T_FULL_TIME).GroupBy(x => x.N_ROW);//.Select(x => x.ToList().Find(y => y.N_CURRENT_NUM > 0)).ToList(); LogHelper.Info($"非即产入库 。" + oneonelist?.Count()); foreach (var itemr in oneonelist) { var item = itemr.ToList().FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (item == null) continue; LogHelper.Info($"查看PGWJCK 有满框的排" + JsonConvert.SerializeObject(item)); var loccntr = LocationHelper.GetLocCntrRel(item.S_LOC_CODE); if (loccntr.Any() && loccntr.FirstOrDefault().S_TYPE.Contains(plc.deviceName)) { //这里就是该机器的最后一次入库列。 var rl = loclist.FindAll(x => x.N_ROW == itemr.Key); if (rl.Find(x => x.S_LOCK_STATE != "无" && x.S_LOCK_STATE != "报废") != null) { brekkkkk = true; break; } var crl = rl.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (crl.N_CURRENT_NUM < crl.N_CAPACITY && crl.N_CURRENT_NUM + startBit.N_CURRENT_NUM <= crl.N_CAPACITY) { endBit = crl; break; } var lstE = rl.FindAll(x => x.N_COL > crl.N_COL).OrderBy(x => x.N_COL).FirstOrDefault(); if (lstE != null) { endBit = lstE; break; } } } //入空排 if (endBit == null && !brekkkkk) { lockcols = (from x in loclist.FindAll((Location x) => x.N_CURRENT_NUM > 0) select x.N_ROW).Distinct(); if (lockcols.Any()) { loclist.RemoveAll((Location x) => lockcols.Contains(x.N_ROW)); } endBit = loclist.OrderBy(x => x.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault(); } } else { //LogHelper.Info($"T2WH2-1");//{ba.NotUsingBolArea}满框位,没有可以入库的满框。 continue; } if (brekkkkk) { //LogHelper.Info($" {ba.NotUsingBolArea} 最后一次仓库入库排,正在任务中。 等待。"); continue; } if (endBit != null) { var _ctrl = LocationHelper.GetLocCntrRel(startBit.S_LOC_CODE); var carryCntrs = _ctrl.OrderByDescending(x => x.T_CREATE).Select(x => x.S_CNTR_CODE).ToList();//DateTime.Now.ToString("yyMMddHHmmss") }; var bb = TaskProcess.CreateTransport(workOrder?.SQL_WorkNo, startBit.S_LOC_CODE, endBit.S_LOC_CODE, "瓶盖入库-J2", carryCntrs, 1, endBit.N_CURRENT_NUM + 1, carryCntrs.Count, plc.taskPri); result = bb; continue; } } return result; } /// /// 瓶坯机11(设备1) 21(设备2) /// /// /// internal static void AnalysisBottlePEM(string data, Settings.deviceInfo plc) { //LogHelper.Info($"{plc.deviceName}-{plc.address}-{data}"); /* 状态1 满托产生,需要取满送空,从满托产生到满托取走一直维持状态1 状态2 送空完成之后为状态2 状态3 满托取走,送空之前为状态3,开机默认状态也为状态3 */ if (data.Length == 4) { if (data.Substring(1, 1) == "1") { if (BottlePEMInfoFull(plc, plc.location[0])) { //设备没有托盘,或者已经有任务,不处理满托信号,返回已经取货完成 //3F 00 11 0d 0a //PlcHelper.SendHex(plc.address, "3F00110d0a"); } } //else if (data.Substring(1, 1) == "3") //{ // if (BottleCapInfoEmpty(plc, plc.location[0])) // { // PlcHelper.SendHex(plc.address, "3F00120d0a"); // } //} if (data.Substring(3, 1) == "1") { if (BottlePEMInfoFull(plc, plc.location[1])) { //PlcHelper.SendHex(plc.address, "3F00210d0a"); } } //else if (data.Substring(3, 1) == "3") //{ // if (BottleCapInfoEmpty(plc, plc.location[1])) // { // PlcHelper.SendHex(plc.address, "3F00220d0a"); // } //} //信号出错 //if (data.Substring(0, 1) != "1" || data.Substring(2, 1) != "2") //{ // //判断哪边没有托盘 // if (ContainerHelper.CheckEmpty(plc.location[0])) // { // PlcHelper.SendHex(plc.address, "3F00110d0a"); // } // if (ContainerHelper.CheckEmpty(plc.location[1])) // { // PlcHelper.SendHex(plc.address, "3F00210d0a"); // } //} } } public static bool Analysis5501 = false; public static bool Analysis5L = false; internal static void Analysis505(string data, Settings.deviceInfo plc) { /* 状态1 满托产生,需要取满送空,从满托产生到满托取走一直维持状态1 状态2 送空完成之后为状态2 状态3 满托取走,送空之前为状态3,开机默认状态也为状态3 */ //LogHelper.Info("成品满框下线信号" + $"{plc.deviceName}-{plc.address}-{data}"); var add = false; if (doorStatus.ContainsKey(plc.location[0])) { var lat = doorStatus[plc.location[0]].info; if (lat != data.Substring(1, 1) && data.Substring(1, 1) == "1") add = true; doorStatus[plc.location[0]].info = data.Substring(1, 1); doorStatus[plc.location[0]].modify = DateTime.Now; } else { doorStatus.Add(plc.location[0], new signalInfo { info = data.Substring(1, 1), modify = DateTime.Now }); if (data.Substring(1, 1) == "1") add = true; } if (add) { LogHelper.Info($@"{plc.deviceName}新到位信号。 执行YWL工单信号量增加1"); var ods = LocationHelper.GetList(x => x.SQL_State == "执行中" && x.WorkType == 6 && x.SQL_LinkLineNO == plc.deviceName);//.FirstOrDefault(); if (ods.Any()) { LogHelper.Info($@"{plc.deviceName}新到位信号,找到工单{JsonConvert.SerializeObject(ods.Select(x => new { x.SQL_PLineNo, x.SQL_LinkLineNO, x.SQL_Total, x.OutNum }))}"); foreach (var od in ods) { od.SQL_Total += 1; WCSHelper.Do(db => db.Updateable(od).UpdateColumns(x => new { x.SQL_Total }).ExecuteCommand()); } } } if (data.Length == 4) { if (data.Substring(1, 1) == "1" && !Analysis5501)// 满框下线 { //Analysis5501 = true; LogHelper.Info(plc.deviceName + "成品满框下线开始"); var A = Analysis505(plc, 0); LogHelper.Info(plc.deviceName + "成品满框下线结束"); //Analysis5501 = false; } if (data.Substring(3, 1) == "1")//空框上线 { if (Analysis505(plc, 1)) { //PlcHelper.SendHex(plc.address, "3F00210d0a"); } } else // 到位后 删掉数据。 这是生产线, 变了说明现场识别到了筐。 机可以删掉了 { //清溪逻辑流程开发 var loc = LocationHelper.GetLoc(plc.location[1]); if (loc?.N_CURRENT_NUM > 0) { LogHelper.Info(plc.deviceName + "成品空框2信号 ,重置货位数据"); LocationHelper.lOCReSetValue(x => x.S_LOC_CODE == plc.location[1].Trim(), x => { x.T_FULL_TIME = null; x.N_CURRENT_NUM = 0; }); } } } else if (data.Length == 6) { if (data.Substring(1, 1) == "1" && !Analysis5L)// 满框下线 { //Analysis5L = true; LogHelper.Info(plc.deviceName + "成品满框下线开始"); var A = Analysis505(plc, 0); LogHelper.Info(plc.deviceName + "成品满框下线结束"); //Analysis5L = false; } if (data.Substring(3, 1) == "1")//空框上线 { if (Analysis505(plc, 1)) { //PlcHelper.SendHex(plc.address, "3F00210d0a"); } } else // 到位后 删掉数据。 这是生产线, 变了说明现场识别到了筐。 机可以删掉了 { //清溪逻辑流程开发 var loc = LocationHelper.GetLoc(plc.location[1]); if (loc.N_CURRENT_NUM > 0) { LogHelper.Info(plc.deviceName + "成品空框2信号 ,重置货位数据"); LocationHelper.lOCReSetValue(x => x.S_LOC_CODE == plc.location[1].Trim(), x => { x.T_FULL_TIME = null; x.N_CURRENT_NUM = 0; }); } } if (data.Substring(5, 1) == "1")//套版上线 // 4L. { if (Analysis505(plc, 2, "超托板/套板")) { //PlcHelper.SendHex(plc.address, "3F00210d0a"); } } else // 到位后 删掉数据。 这是生产线, 变了说明现场识别到了筐。 机可以删掉了 { //清溪逻辑流程开发 var loc = LocationHelper.GetLoc(plc.location[2]); if (loc.N_CURRENT_NUM > 0) { LogHelper.Info("成品套版2信号 ,重置货位数据"); LocationHelper.lOCReSetValue(x => x.S_LOC_CODE == plc.location[2].Trim(), x => { x.T_FULL_TIME = null; x.N_CURRENT_NUM = 0; }); } } } } internal static void Analysis11(string data, Settings.deviceInfo plc) { LogHelper.Info("一楼搬2楼信号" + $"{plc.deviceName}-{plc.address}-{data}"); if (data.Length == 4) { if (data[1] == 1 || data[3] == 1) { var location = LocationHelper.GetLoc(plc.location[0]); if (location == null) { LogHelper.Info(plc.deviceName + "的货位数据不存在!"); return; } if (location.S_LOCK_STATE != "无") return; if (data.Substring(1, 1) == "1") { if (location.N_CURRENT_NUM == 1) { PlcHelper.SendHex(plc.address, "3F00100D0A"); } } if (data.Substring(3, 1) == "1") { if (location.N_CURRENT_NUM == 0) { PlcHelper.SendHex(plc.address, "3F00200D0A"); } } } } } //瓶坯满入库 static bool BottlePEMInfoFull(Settings.deviceInfo plc, string location) { var result = false; if (location != "") { var workOrder = WCSHelper.GetWorkOrder(plc.deviceName); if (workOrder == null) { LogHelper.Info(plc.deviceName + "没有【执行中】的工单"); return false; } //Console.WriteLine($"瓶盖机:{plc.deviceName} 下线信号:{location}"); //判断上次卸货完成时间,如果5分钟内,不处理请求,可能是设备请求还没有重置 // 同机器走一排。 两个位置一个一个来。 都没有锁才行。 string p0 = LocationHelper.CheckLocState(location).Trim(); // LocationHelper.CheckLocState(plc.location[0]); string p1 = ""; // LocationHelper.CheckLocState(plc.location[1]); if (plc.location[0] == location) p1 = plc.location[1]; else p1 = plc.location[0]; string p1s = LocationHelper.CheckLocState(p1); if (p0 == "无")//&& (p1s == "无" || p1s == "入库锁")) { var time = LocationHelper.GetT_FULL_TIME(location); var _loc = LocationHelper.GetLoc(location); LogHelper.Info(location + ":托盘放置时间:(" + time + ") 货位托盘数量(" + _loc.N_CURRENT_NUM + ")"); if (time == null || _loc == null || _loc.N_CURRENT_NUM == 0) { // TODO - 送空框任务。 LocationHelper.TakeEmptyToBottleBoyd(new WMSTask { S_START_LOC = location, }); return true; } //托盘放下 1分钟内 取货请求,都不处理。 else if (DateTime.Now.Subtract(time ?? DateTime.Now).TotalMinutes < 1) { for (var i = 0; i < plc.location.Length; i++) { if (location == plc.location[i]) { PlcHelper.SendHex(plc.address, "3F00" + (i + 1) + "0" + "0d0a"); break; } } return false; } LogHelper.Info($"PEM机:{plc.deviceName} 下线信号:{location} 查询工单", "PEM机"); //var workOrder = WCSHelper.GetWorkOrder(plc.deviceName); if (workOrder != null) { LogHelper.Info($"查到了工单{workOrder.SQL_WorkNo}", "PEM机"); //var cntrStart = LocationHelper.GetLocCntr(location); //取满,需要中间表查询,当前工位的容器是铁框还是塑料框 //判断是无菌盖还是水盖 if (true) { LogHelper.Info($"查找{location}对应终点->", "PEM机"); //var locationType = plc.deviceType == 2 ? 2 : 5; //var endBit = Settings.GetInStockCacheList().Where(a => a.deviceName == plc.deviceName && a.locationType == locationType).FirstOrDefault(); Location endBit = null; List _l = new List(); var SQL_ItemCode = workOrder.SQL_ItemCode; var _ctrl = LocationHelper.GetLocCntrRel(location); if (_ctrl.FirstOrDefault().S_CNTR_CODE.Contains("J")) { _l = LocationHelper.GetLocList(x => x.S_AREA_CODE == workOrder.SQL_Area && x.S_LOCK_STATE != "报废"); #region 直接去终点 //var loc_list_PEM = _l.FindAll(x => x.S_LOCK_STATE == "无" && x.N_CURRENT_NUM == 0).ToList(); //LogHelper.Info("即产空货位数量:" + loc_list_PEM.Count); //if (loc_list_PEM.Count == 0) //{ // LogHelper.Info($"查找{location}对应终点(库区没有货位了。)", "PEM机"); // return false; //} //var local_ = loc_list_PEM.FirstOrDefault(); //LogHelper.Info($"{local_.N_ROW}-{local_.N_COL}"); //// 所有排的 第一列 有值且不是这个机器的。 就remove整排 ////if(local_.N_CURRENT_NUM==0) //endBit = local_; var _arealock = _l.FindAll(x => x.S_LOCK_STATE != "无").Select(x => x.N_ROW).Distinct(); if (_arealock.Any()) _l.RemoveAll(x => _arealock.Contains(x.N_ROW)); foreach (var itemrs in _l.OrderByDescending(x => x.N_CURRENT_NUM).GroupBy(x => x.N_ROW)) { var _r = itemrs.ToList(); var f = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f != null) { var rel = LocationHelper.GetLocCntrRel(f.S_LOC_CODE); if (rel.FirstOrDefault()?.S_TYPE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{f.S_LOC_CODE} 位置的 物料{rel.FirstOrDefault()?.S_TYPE} 与本次下线{workOrder.SQL_PLineNo}>{SQL_ItemCode} 不符。 筛选下一排"); continue; } if (f.N_CURRENT_NUM < f.N_CAPACITY) { endBit = f; } else endBit = _r.FindAll(x => x.N_COL > (f?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else { endBit = _r.OrderBy(x => x.N_COL).FirstOrDefault(); } if (endBit != null) break; } #endregion } else if (!string.IsNullOrEmpty("2024年7月3日 变更 2排专供一个机器. 暂不更新.加了!非")) { if (false) { if (SQL_ItemCode.Contains("5L")) { //_l = LocationHelper.GetAllLocListByAreaCode("PPMKRK", 3, 4); _l = LocationHelper.GetLocList(x => x.S_AREA_CODE == "PPMKRK" && new int[] { 3, 4, 7, 8 }.Contains(x.N_ROW)); } else //_l = LocationHelper.GetAllLocListByAreaCode("PPMKRK", 1, 2); _l = LocationHelper.GetLocList(x => x.S_AREA_CODE == "PPMKRK" && new int[] { 1, 2, 5, 6 }.Contains(x.N_ROW)); } LogHelper.Info($"{plc.deviceName} 注塑机下线 目标库区排{workOrder.S_ROW1} ."); if (string.IsNullOrEmpty(workOrder.S_ROW1)) { return false; } else { //_l = LocationHelper.GetLocList(x => x.S_AREA_CODE == rs[0] && rows.Contains(x.N_ROW) && x.S_LOCK_STATE != "报废"); if (false) { _l = LocationHelper.GetAreaNormalLocList("");//rs[0]).FindAll(x => rows.Contains(x.N_ROW)).OrderBy(x => x.N_COL).ThenBy(x => x.N_ROW).ToList(); var _lful = _l.FindLastIndex(x => x.N_CURRENT_NUM > 0); Location _lsf = null;// if (_lful > -1) _lsf = _l[_lful]; LogHelper.Info($"{plc.deviceName}筛选到 可用排{JsonConvert.SerializeObject(_l.Select(x => x.N_ROW).Distinct())} 货位编码{_lsf?.S_LOC_CODE} 所在索引{_lful}"); int li____ = 0; foreach (var item in _l.Skip(_lful)) { if (li____ == 0) { LogHelper.Info($@"入库筛选,第一个位置是{JsonConvert.SerializeObject(new { item.S_LOC_CODE, item.N_CURRENT_NUM, item.S_LOCK_STATE })}"); li____++; } if (item.N_CURRENT_NUM < item.N_CAPACITY) { var rel = LocationHelper.GetLocCntrRel(item.S_LOC_CODE); if (rel.Any()) { if (rel.FirstOrDefault()?.S_TYPE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{item.S_LOC_CODE} 位置的 物料{rel.FirstOrDefault()?.S_TYPE} 与本次下线{workOrder.SQL_PLineNo}>{SQL_ItemCode} 不符。 筛选下一排"); continue; } } endBit = item; } if (endBit != null) break; } } if (true) { var nextArea = ""; var areaRows = workOrder.S_ROW1.Split('$'); //foreach (var item2 in areaRows) //{ var item2 = areaRows.First(); var rs = item2.Split('='); bool wait = true;// 如果给的2排并没满,这时候切不合适,等满了再切 var rows = Array.ConvertAll(rs[rs.Length - 1].Trim().Split('-'), Convert.ToInt32).Reverse(); if (string.IsNullOrEmpty(nextArea)) nextArea = rs[0]; _l = LocationHelper.GetAreaNormalLocList(rs[0]); var rowlist = LocationHelper.GetRowLock(rs[0]); LogHelper.Info($"{location}满框下线 {rs[0]}库区, rowlist:{rowlist.Count}"); foreach (var itemrs in _l.FindAll(x => rows.Take(2).Contains(x.N_ROW)).GroupBy(x => x.N_ROW).OrderBy(x => x.Count(y => y.N_CURRENT_NUM > 0)).ThenBy(x => x.Key)) { var tnotnull = rowlist.Find(x => x.S_LOCK_STATE == "出库锁" && x.N_ROW == itemrs.Key); if (tnotnull != null) continue; var _r = itemrs.ToList(); var f = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f != null) { var rel = LocationHelper.GetLocCntrRel(f.S_LOC_CODE); if (rel.FirstOrDefault()?.S_TYPE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{f.S_LOC_CODE} 位置的 物料{rel.FirstOrDefault()?.S_TYPE} 与本次下线{workOrder.SQL_PLineNo}>{SQL_ItemCode} 不符。 筛选下一排"); continue; } if (f.N_CURRENT_NUM < f.N_CAPACITY) { endBit = f; } else endBit = _r.FindAll(x => x.N_COL > (f?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else { endBit = _r.OrderBy(x => x.N_COL).FirstOrDefault(); } if (endBit != null) goto vvvvvv; } if (endBit == null && wait) { _l = LocationHelper.GetList(x => x.S_AREA_CODE == nextArea && x.S_LOCK_STATE != "报废"); if (wait) { //如果之前的 还有空位,那就不切了。 var _ll = _l.FindAll(x => rows.Take(2).Contains(x.N_ROW)); if (_ll.Find(x => x.N_CURRENT_NUM == 0) != null) goto vvvvvv; } var rowtuplist = SequentialGrouping(_l.Select(x => x.N_ROW).Max()); foreach (var group in rowtuplist) { var gn = _l.FindAll(x => x.N_ROW == group.Item1 || x.N_ROW == group.Item2); if (gn.Find(x => x.S_LOCK_STATE != "无" || x.N_CURRENT_NUM != 0) != null) //不是空排或有锁 ,歇。 下一个。 continue; endBit = gn.FindAll(x => x.N_ROW == group.Item1).OrderBy(x => x.N_COL).FirstOrDefault(); if (endBit != null) { var v1 = new List();// rows.Where(x => x != group.Item1 && x != group.Item2).ToList(); v1.Add(group.Item1); v1.Add(group.Item2); workOrder.S_ROW1 = nextArea + "=" + (string.Join("-", v1)); new SqlHelper().GetInstance().Updateable(workOrder).UpdateColumns(x => new { x.S_ROW1 }).ExecuteCommand(); goto vvvvvv; } } } } goto vvvvvv; } #region vvv //_l = LocationHelper.GetLocList(x => x.S_AREA_CODE == "PPMKRK" && x.S_LOCK_STATE != "报废"); //List lockcols = new List(); ;// = (from x in _l.FindAll((Location x) => x.S_LOCK_STATE.Trim() != "无" && x.S_LOCK_STATE.Trim() != "报废") /// select x.N_ROW).Distinct(); //int MaxRow = 0; //foreach (var item in _l.GroupBy(x => x.N_ROW)) //{ // if (MaxRow < item.Key) MaxRow = item.Key; // if (item.ToList().Find(x => x.S_LOCK_STATE.Trim() != "无") != null) // lockcols.Add(item.Key); //} //if (lockcols.Any()) //{ // _l.RemoveAll((Location x) => lockcols.Contains(x.N_ROW)); //} //1 是否存在 n 与 n+1 排都空且入库的情况, 如果存在,无法确认物料。 就等待 //var twoEmptyandLockin = false; //foreach (var r in _l.FindAll(x => x.S_LOCK_STATE.Trim() == "入库锁").Select(x => x.N_ROW).Distinct()) //{ // var _r = _l.FindAll(x => x.N_ROW == r); // var _radd1 = _l.FindAll(x => x.N_ROW == ((r % 2 == 1) ? (r + 1) : (r - 1))); // if (_r.Find(x => x.N_CURRENT_NUM > 0) == null && _radd1.Find(x => x.N_CURRENT_NUM > 0) == null) // { // LogHelper.Info($"{r}排和 乡邻组排,是双空排,且有入库,因无法确认物料,故此等待其完成后,再执行入库。"); // //var _lockloc = _r.Find(x => x.S_LOCK_STATE == "入库锁"); // //LocationHelper.DoAction(db => // //{ // // var task = db.Queryable().Where(x => x.S_END_LOC.Trim() == _lockloc.S_LOC_CODE && "未执行,已推送,执行中,开始取货,取货完成,开始卸货".Contains(x.S_B_STATE)).First(); // // LogHelper.Info(location + "起点(工单N_LimitNum:" + mmmmmnum + ")的运行中任务数量" + tasks.Count); // // //foreach (var task in tasks) // // { // // var _tloc = LocationHelper.GetLoc(task.S_END_LOC); // // LogHelper.Info(location + $"起点的运行中任务{task.S_TASK_NO}-{task.S_END_LOC}{_tloc.S_LOCK_STATE}"); // // if (_tloc != null && _tloc.S_LOCK_STATE == "入库锁") // // { // // string si = _tloc.S_AREA_CODE + "_" + _tloc.N_ROW; // // if (!AlTask.Contains(si)) { AlTask.Add(si); } // // } // // } // // LogHelper.Info($"{workOrder.FuLe_PLine_No}{workOrder.SQL_PLineNo}成品任务中锁排{JsonConvert.SerializeObject(AlTask)}"); // // return true; // //}); // twoEmptyandLockin = true; // } //} //if (twoEmptyandLockin) //{ // return false; //} if (false) { var rowlist = _l.OrderByDescending(x => x.N_CURRENT_NUM).Select(x => x.N_ROW); List rl = new List(); foreach (var r in rowlist) { if (rl.Contains(r)) continue; //if (r % 2 == 1) { var _r = _l.FindAll(x => x.N_ROW == r); var r22 = ((r % 2 == 1) ? (r + 1) : (r - 1)); var _radd1 = _l.FindAll(x => x.N_ROW == r22); rl.Add(r); rl.Add(r22); var f1 = _r.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); var f2 = _radd1.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(x => x.N_COL).LastOrDefault(); if (f1 != null || f2 != null) { var f = f1 != null ? f1 : f2; var rel = LocationHelper.GetLocCntrRel(f.S_LOC_CODE); if (rel.FirstOrDefault()?.S_TYPE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{f.S_LOC_CODE} 位置的 物料{rel.FirstOrDefault()?.S_TYPE} 与本次下线{workOrder.SQL_PLineNo}>{SQL_ItemCode} 不符。 筛选下一排"); continue; } else { var lockkk = false; if (_r.Find(x => x.S_LOCK_STATE.Trim() != "无") == null) { LogHelper.Info($"{plc.deviceName} PPMKRK {r}排无锁 分析中..."); //if (f1 != null) if (f1 != null && f1.N_CURRENT_NUM < f1.N_CAPACITY) { endBit = f1; } else endBit = _r.FindAll(x => x.N_COL > (f1?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else lockkk = true; if (endBit == null) { if (_radd1.Find(x => x.S_LOCK_STATE.Trim() != "无") == null) { LogHelper.Info($"{plc.deviceName} PPMKRK {r22}排无锁 分析中..."); //if (f2 != null) if (f2 != null && f2.N_CURRENT_NUM < f2.N_CAPACITY) { endBit = f2; } else endBit = _radd1.FindAll(x => x.N_COL > (f2?.N_COL ?? 0)).OrderBy(x => x.N_COL).FirstOrDefault(); } else lockkk = true; } if (endBit == null) { if (lockkk) { LogHelper.Info($"{plc.deviceName} 将要下在{r}排或者{r + 1}排。 但是现在排有锁。 等待..."); return false; } LogHelper.Info($"{plc.deviceName} 的 {r}排或者{r + 1}排。都没位置了, 找其他空排了"); } } } else if (_r.Find(x => x.S_LOCK_STATE.Trim() == "入库锁") != null || _radd1.Find(x => x.S_LOCK_STATE.Trim() == "入库锁") != null) { //看一下这个这任务的起点是不是当前机器的另一个口。如果不是,那就continue; //否则,就下在没任务的那一排。 var locklocs = new List() { _r.Find(x => x.S_LOCK_STATE == "入库锁"), _radd1.Find(x => x.S_LOCK_STATE == "入库锁") }.Where(x => x != null); bool Errcnil = false; bool SameandNotEnd = false; LocationHelper.DoAction(db => { foreach (var _lockloc in locklocs) { if (_lockloc == null) continue; var task = db.Queryable().Where(x => x.S_END_LOC.Trim() == _lockloc.S_LOC_CODE && "未执行,已推送,执行中,开始取货,取货完成,开始卸货".Contains(x.S_B_STATE)).First(); LogHelper.Info($"空排锁点{_lockloc.S_LOC_CODE}, 的所在任务为{task?.S_TASK_NO} 如果没找到,则异常锁"); if (task == null) { Errcnil = true; continue; } if (plc.location.Contains(task.S_START_LOC.Trim())) { if (locklocs.Count() == 2) { SameandNotEnd = true; break; } else { if (_lockloc.N_ROW == r) endBit = _radd1.OrderBy(x => x.N_COL).FirstOrDefault(); else _r.OrderBy(x => x.N_COL).FirstOrDefault(); break; } } } return true; }); if (SameandNotEnd) { LogHelper.Info($"将要下在{{{r} or {r22}双空有任务排,任务点符合。等待其完成就可入;"); break; } if (Errcnil) { LogHelper.Info($"{r} and {r22}双空有任务排,点所在任务未找到;continue;"); continue; } ; if (endBit == null) { LogHelper.Info($"{r} and {r22}双空有任务排,任务点不符合。 等一会再看;"); break; } } else { LogHelper.Info($"按 将要下在{r}排或者{r + 1}排。 双空排!"); //从大到小排。 2个都空。就可以入了 endBit = _r.OrderBy(x => x.N_COL).FirstOrDefault(); } if (endBit != null) break; } } } //for (int i = 1; i <= MaxRow; i += 2) //{ // var _i = _l.FindAll(x => x.N_ROW == i); // var _iadd1 = _l.FindAll(x => x.N_ROW == (i + 1)); // if (!_i.Any() || !_iadd1.Any()) // { // LogHelper.Info($"Attention:注塑机满入库,第{i}或{(i + 1)} 没有排数据。无法入库。"); // } //} // /// 。未满货位。 //endBit = _l?.OrderBy(x => x.N_ROW).ThenBy(x => x.N_COL).ToList().Find(x => x.N_CURRENT_NUM > 0 && x.N_CURRENT_NUM < x.N_CAPACITY); //var lrowlist = _l?.OrderBy(x => x.N_ROW).GroupBy(x=>x.N_ROW); #endregion vvvvvv: //if (false)//endBit == null&& if (endBit == null && workOrder.S_Is_Auto.Trim() == "Y") foreach (IGrouping item in _l.GroupBy(x => x.N_ROW)) { List _cols = item.OrderBy(x => x.N_COL).ToList(); Location e = _cols.FindAll((Location x) => x.N_CURRENT_NUM > 0).LastOrDefault();//从左往右最后一个满位。 if (e != null) { var rel = LocationHelper.GetLocCntrRel(e.S_LOC_CODE); //if (rel.FirstOrDefault()?.S_TYPE != SQL_ItemCode) if (rel.FirstOrDefault()?.S_TYPE != $"{workOrder.SQL_PLineNo}>{SQL_ItemCode}") { LogHelper.Info($"{e.S_LOC_CODE} 位置的 物料{rel.FirstOrDefault()?.S_TYPE} 与本次下线{($"{workOrder.SQL_PLineNo}>{SQL_ItemCode}")} 不符。 筛选下一排"); continue; } } if (e != null && e.N_CURRENT_NUM < e.N_CAPACITY) { endBit = e; } else { var empT = _cols.FindAll(x => x.N_CURRENT_NUM == 0).FirstOrDefault();//从左往右第一个空位 if (empT != null) endBit = empT; } if (endBit != null) break; } } else { /// 筛选完后的货位数据。 可以用原来的入库方法, if (!string.IsNullOrEmpty(workOrder.S_ROW1)) { var rs = workOrder.S_ROW1.Split('='); var rows = Array.ConvertAll(rs[rs.Length - 1].Split('-'), Convert.ToInt32); _l = LocationHelper.GetLocList(x => x.S_AREA_CODE == rs[0] && rows.Contains(x.N_ROW) && x.S_LOCK_STATE != "报废"); } } #region 筛选终点 if (endBit != null) { int endLayer = endBit.N_CURRENT_NUM + 1; var carryCntrs = new List { _ctrl.FirstOrDefault().S_CNTR_CODE };//DateTime.Now.ToString("yyMMddHHmmss") }; var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, location, endBit.S_LOC_CODE, "满瓶坯-入库", carryCntrs, 1, endLayer, carryCntrs.Count, plc.taskPri); if (bb) { LogHelper.Info($"{plc.deviceName} 当前机器{location}位置状态{p0} 正在执行取满任务"); } result = bb; } else { LogHelper.Info($"瓶p机{plc.deviceName} 没有找到可用的满托终点", "瓶坯机"); } #endregion } else { LogHelper.Info($"瓶盖机{plc.deviceName}起点没有托盘,不可以生成任务", "瓶盖机"); result = true; } } else { LogHelper.Info($"瓶坯机:{plc.deviceName} 下线信号:{location} 未找到工单", "瓶坯机"); } } else { //LogHelper.Info($"瓶PEM机:{plc.deviceName} 当前机器2个位置 有一个有任务,不可触发满托下线", "瓶坯机"); //if (p0 != "无") LogHelper.Info($"{plc.deviceName} {location}位置状态{p0} 正在执行{(p0.Replace("锁", "") == "入库" ? "送空" : "取满")}任务"); //if (!(p1s == "无" || p1s == "入库锁")) //{ // LogHelper.Info($"{plc.deviceName} 另外一个位置{p1}状态{p1s} 有任务,不可触发满托下线"); //} } } return result; } //LookShort 找不满排。 static Location GetareaLocationByBtypeandBatch(ItemInfo item1, string are, string Btype, string Batch, bool isFule, int MaxLayer, WorkOrder workOrder, bool LookShort = false, int row = 0) { LogHelper.Info("GetareaLocationByBtypeandBatch" + $"{item1.S_ITEM_CODE}-{item1.S_ITEM_NAME}-{are}-{Btype}-{Batch} {LookShort}"); var _tempList = new List(); List bts = new List { "大板", "小板", "集化板" }; Location endBit = null; bts.Remove(Btype); string area = are + Settings.areaSuffix(Btype); LogHelper.Info(area + " 库区的板型" + Btype); if (!area.Contains("_")) LogHelper.Info(area + " 库区的板型" + Btype + "不正确"); //找当前库区无锁不满的排 var _arealist = LocationHelper.GetLocList(x => x.S_AREA_CODE == area && x.S_LOCK_STATE != "报废"); if (!LookShort) goto Empty; var _arealock = _arealist.FindAll(x => x.S_LOCK_STATE != "无").Select(x => x.N_ROW).Distinct(); LogHelper.Info(area + " 库区 非报废货位量" + _arealist.Count + ":非正常货位锁排" + JsonConvert.SerializeObject(_arealock)); var lcollist = LocationHelper.GetRowLock(area)?.Select(x => x.N_ROW); _arealock = _arealock.Concat(lcollist).Distinct(); if (_arealock.Any()) _arealist.RemoveAll(x => x.N_ROW != row && _arealock.Contains(x.N_ROW)); if (!_arealist.Any()) return null; LogHelper.Info(area + "=可用排=" + JsonConvert.SerializeObject(_arealist.Select(x => x.N_ROW).Distinct())); //看看有没有 同物料 同板子 同批次 不满的, // foreach (var x in _arealist.OrderBy(x => x.N_ROW).GroupBy(x => x.N_ROW)) { //排最外侧有货位fz var xlist = x.OrderBy(xx => xx.N_COL).ToList(); var _cl = xlist.FindAll(xx => xx.N_CURRENT_NUM > 0).LastOrDefault(); //LogHelper.Info(" for 是否有货排!" + (_cl != null)); if (_cl == null) { //这是一个空排 //_tempList.AddRange(xlist); if (row == 0) continue; else { return xlist.FirstOrDefault(); } } //LogHelper.Info(" for 查看货位托盘!" + _cl.S_LOC_CODE); // 最外侧货位是是同.. 的话 就可以入了。 var _clrel = LocationHelper.GetLocCntrRel(_cl.S_LOC_CODE); if (!_clrel.Any()) { LogHelper.Info(_cl.S_LOC_CODE + " 没有货位托盘信息!"); continue; } //LogHelper.Info(" for 查看货位托盘版型!" + _cl.S_LOC_CODE); //板型相同 LogHelper.Info(_cl.S_LOC_CODE + $" 货位托盘信息{_clrel[0].S_CNTR_CODE}!isFule" + isFule); if (_clrel[0].S_CNTR_CODE.StartsWith("TP") && isFule) { continue; } if (!_clrel[0].S_CNTR_CODE.StartsWith("TP") && !isFule) { continue; } LogHelper.Info("识别托盘类型。"); if (_clrel[0].S_TYPE == Btype) { var _clcntitem = ContainerHelper.GetCntrItemRel(_clrel[0].S_CNTR_CODE.Trim()); if (!_clcntitem.Any()) { LogHelper.Info(_cl.S_LOC_CODE + $"货位 的托盘{_clrel[0].S_CNTR_CODE} 没有物料记录"); continue; } var _ci = _clcntitem.OrderByDescending(xx => xx.T_CREATE).First(); if ((_ci.S_ITEM_CODE == item1.S_ITEM_CODE || _ci.S_ITEM_CODE == item1.S_ITEM_NAME) && _ci.ItemLayer == workOrder.ItemLayer) { bool sameBatch = string.IsNullOrEmpty(_ci.S_BATCH_NO) ? true : _ci.S_BATCH_NO == Batch; //not full if (_cl.N_CURRENT_NUM < _cl.N_CAPACITY && (MaxLayer == 0 || (MaxLayer > 0 && _cl.N_CURRENT_NUM < MaxLayer))) // if (_cl.N_CURRENT_NUM < _cl.N_CAPACITY && (MaxLayer == 0 || (MaxLayer > 0 && _cl.N_CURRENT_NUM / 2 < MaxLayer))) { if (sameBatch) endBit = _cl; else { var empty = xlist.FindAll(xx => xx.N_CURRENT_NUM == 0 && xx.N_COL > _cl.N_COL); if (!empty.Any()) { //这一排没有空位 } else { //endBit = empty.FirstOrDefault(); if (empty.Count > 1) { endBit = empty.Skip(1).FirstOrDefault(); } } } } else//full { var empty = xlist.FindAll(xx => xx.N_CURRENT_NUM == 0 && xx.N_COL > _cl.N_COL); if (!empty.Any()) { //这一排没有空位 } else { if (sameBatch) endBit = empty.FirstOrDefault(); else { //满了, 中间间隔一个空位。 if (empty.Count > 1) { endBit = empty.Skip(1).FirstOrDefault(); } } } } } //Task = null; if (false) { bool thisDay = true; LocationHelper.DoAction(db => { WMSTask Task = db.Queryable().Where(t => t.S_TYPE.Contains("成品满框-入库") && t.S_CNTRS.Contains(_ci.S_CNTR_CODE)).ToList().FirstOrDefault(); thisDay = Task?.T_CREATE.Date == DateTime.Now.Date; return true; }); if (_ci.S_ITEM_CODE == item1?.ToString() && _ci.S_BATCH_NO == Batch) { //同物料同批次。 if (_cl.N_CURRENT_NUM < _cl.N_CAPACITY && (MaxLayer == 0 || MaxLayer > 0 && _cl.N_CURRENT_NUM < MaxLayer)) { //if (MaxLayer > 0) //{ // if (_cl.N_CURRENT_NUM < MaxLayer) // { // endBit = _cl; // } // else // continue; //} //else if (thisDay) endBit = _cl; else { //没满, 直接用下一个位置。 等于 间隔 var empty = xlist.FindAll(xx => xx.N_CURRENT_NUM == 0 && xx.N_COL > _cl.N_COL); if (!empty.Any()) { //这一排没有空位 } else { //endBit = empty.FirstOrDefault(); if (empty.Count > 1) { endBit = empty.Skip(1).FirstOrDefault(); } } } } else //找空位 { var empty = xlist.FindAll(xx => xx.N_CURRENT_NUM == 0 && xx.N_COL > _cl.N_COL); if (!empty.Any()) { //这一排没有空位 } else { if (thisDay) endBit = empty.FirstOrDefault(); else { //满了, 中间间隔一个空位。 if (empty.Count > 1) { endBit = empty.Skip(1).FirstOrDefault(); } } } } } } } if (endBit != null) break; } LogHelper.Info(" for over!" + endBit?.S_LOC_CODE); //就查看有没有空的排了。 //if (endBit != null) /// 寻找未满排, 直接返回结果。 return endBit; //LogHelper.Info(" _tempList over!"); //这里开始 寻找空排 Empty: var _arealock1 = _arealist.FindAll(x => x.S_LOCK_STATE != "无" || x.N_CURRENT_NUM > 0).Select(x => x.N_ROW).Distinct(); var lcollist1 = LocationHelper.GetRowLock(area)?.Select(x => x.N_ROW); _arealock1 = _arealock1.Concat(lcollist1).Distinct(); if (_arealock1.Any()) _arealist.RemoveAll(x => _arealock1.Contains(x.N_ROW)); _tempList = _arealist; if (!_tempList.Any())//该库区的空排。 return endBit; //没有空的就返回空。 (三板合一库的情况下, 一个库区没有空的了,说明都呗一种板子占了) //有空的就查看 其他版型库区都空且不锁定的排。 三板空排取交集,就是可用排 //foreach (var _a in bts) //{ // string ar_ = are + Settings.areaSuffix(Btype); // if (!ar_.Contains("_")) // { // continue; // } // var ar_loclist = LocationHelper.GetLocList(x => x.S_AREA_CODE == ar_ && x.S_LOCK_STATE != "报废"); // //锁定排和有货的排汇集 // var ar_row = ar_loclist.FindAll(x => x.S_LOCK_STATE != "无" || x.N_CURRENT_NUM > 0).Select(x => x.N_ROW).Distinct(); // if (ar_row.Any()) // _tempList.RemoveAll(x => ar_row.Contains(x.N_ROW)); //} LogHelper.Info(" ar_RplaceRow over!"); var ar_RplaceRows = LocationHelper.GetLocList(x => x.S_AREA_CODE != area && x.S_AREA_CODE.Contains(are) && x.S_LOCK_STATE != "报废");//.Select(x => x.N_ROW).Distinct(); IEnumerable ar_RplaceRow1 = ar_RplaceRows.FindAll(x => "入库锁;出库锁".Contains(x.S_LOCK_STATE?.Trim())).Select(x => x.N_ROW).Distinct(); LogHelper.Info(" 有锁排 - " + JsonConvert.SerializeObject(ar_RplaceRow1)); var ar_RplaceRow2 = ar_RplaceRows.FindAll(x => x.N_CURRENT_NUM > 0).Select(x => x.N_ROW).Distinct(); LogHelper.Info(" 有货排: - " + JsonConvert.SerializeObject(ar_RplaceRow2)); //var ar_RplaceRow_rowlock = LocationHelper.GetRowLock(x => x.S_AREA_CODE.Contains(are))?.Select(x => x.N_ROW); if (Btype != "小板" && "QX-02,QX-09".IndexOf(are) > -1) { ar_RplaceRow1 = ar_RplaceRow1.Concat(new int[] { 1, 2, 3, 4 }); LogHelper.Info(" QX-02,QX-09 非小板。 有锁排 增加1-4 : " + JsonConvert.SerializeObject(ar_RplaceRow1)); } var db1 = new SqlHelper().GetInstance(); var OtherArows = new List(); //var orders = db1.Queryable().Where(x => x.SQL_State == "执行中" && !string.IsNullOrEmpty(x.S_ROW) && x.SQL_Area.Contains(are)).ToList(); //{ // foreach (var ar in orders) // { // var rs = ar.S_ROW.Split('='); // int[] Irs = Array.ConvertAll(rs[rs.Length - 1].Split('-'), Convert.ToInt32); // foreach (var r in Irs) // { // if (!OtherArows.Contains(r)) // { // OtherArows.Add(r); // } // } // } //} var orders = db1.Queryable().Where(x => x.SQL_State == "执行中" && !string.IsNullOrEmpty(x.S_ROW)).ToList(); { foreach (var ar in orders) { var rs = ar.S_ROW.Split('='); if (rs.Length < 2) { if (!ar.SQL_Area.Contains(are)) continue; } var areaRows = ar.S_ROW.Split('$'); foreach (var item2 in areaRows) { if (!item2.Contains(are)) continue; rs = item2.Split('='); int[] Irs = Array.ConvertAll(rs[rs.Length - 1].Split('-'), Convert.ToInt32); foreach (var r in Irs) { if (!OtherArows.Contains(r)) { OtherArows.Add(r); } } } } } LogHelper.Info(" 所有工单该库区独占排: - " + JsonConvert.SerializeObject(OtherArows)); var ar_RplaceRow = ar_RplaceRow1.Concat(ar_RplaceRow2).Concat(OtherArows).Distinct();//.Concat(ar_RplaceRow_rowlock) //_arealock = _arealock.Concat(lcollist).Distinct(); { //用排锁表。 这里不用再管 移库 分拣出库 等的排锁定问题。 //var Tsr = WCSHelper.GetWorkOrder2(x => x.SQL_State == "执行中" && x.start_area.Contains(are)).Select(x => Convert.ToInt32(x.start_row)).Distinct(); ////LogHelper.Info(" Tsr - " + JsonConvert.SerializeObject(Tsr)); //var Ter = WCSHelper.GetWorkOrder2(x => x.SQL_State == "执行中" && x.end_area.Contains(are)).Select(x => Convert.ToInt32(x.end_row)).Distinct(); ////LogHelper.Info(" Ter - " + JsonConvert.SerializeObject(Ter)); //ar_RplaceRow = ar_RplaceRow.Concat(Tsr).Concat(Ter); } if (ar_RplaceRow.Any()) { LogHelper.Info("排除非空排 - " + JsonConvert.SerializeObject(ar_RplaceRow)); _tempList.RemoveAll(x => ar_RplaceRow.Contains(x.N_ROW)); } if (_tempList.Any())//三个库区的交集空排 { //if (MaxLayer > 0) 这里是三个库区的空排交集。 肯定是没有货在这里的。 //{ // endBit = _tempList.OrderBy(x => x.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault(x => x.N_CURRENT_NUM < x.N_CAPACITY && x.N_CURRENT_NUM < MaxLayer); //} //else endBit = _tempList.OrderBy(x => x.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault(); } else { LogHelper.Info($"{are},库区3板空排交集null"); } return endBit; } static bool Analysis505(Settings.deviceInfo plc, int _li, string banziType = null) { var location = plc.location[_li]; var result = false; if (location != "") { var workOrder = WCSHelper.GetWorkOrder(plc.deviceName); if (workOrder == null) { LogHelper.Info(plc.deviceName + "没有【执行中】的工单"); return false; } var size = banziType ?? workOrder.B_Type; var ItemName = workOrder.SQL_ItemName; var ItemCode = workOrder.SQL_ItemCode; var Batch = workOrder.SQL_BatchNo ?? ""; //if (string.IsNullOrEmpty(Batch)) //{ // workOrder.SQL_BatchNo = "";// DateTime.Now.ToString("yyMMdd"); // WCSHelper.Do(db => // { // db.Updateable().UpdateColumns(it => new // { // it.SQL_BatchNo // }).ExecuteCommand(); // Batch = workOrder.SQL_BatchNo; // }); //} if (string.IsNullOrEmpty(size)) { LogHelper.Info(plc.deviceName + "工单 没有指定版型"); return false; } if (string.IsNullOrEmpty(ItemCode)) { LogHelper.Info(plc.deviceName + "工单 没有指定物料"); return false; } //Console.WriteLine($"瓶盖机:{plc.deviceName} 下线信号:{location}"); //判断上次卸货完成时间,如果5分钟内,不处理请求,可能是设备请求还没有重置 string p0 = LocationHelper.CheckLocState(location).Trim(); // LocationHelper.CheckLocState(plc.location[0]); if (p0 == "无") { LogHelper.Info($"{plc.deviceName} {(_li == 0 ? "满框下线" : "空筐上线")}信号:{location} 查询工单"); if (_li > 0) { var time = LocationHelper.GetT_FULL_TIME(location); var _loc = LocationHelper.GetLoc(location); LogHelper.Info(location + ":托盘放置时间:(" + time + ") 货位托盘数量(" + _loc.N_CURRENT_NUM + ")"); if (_loc == null) { LogHelper.Info(location + " 货位数据不存在。 请确认!"); return false; } if (time == null || _loc.N_CURRENT_NUM == 0) { if (_loc.N_CURRENT_NUM > 0) { LogHelper.Info(location + "有筐但没有时间数据"); time = DateTime.Now; LocationHelper.SetT_FULL_TIME(location, time); } else { if (time != null) { time = null; LocationHelper.SetT_FULL_TIME(location, time); } // 这里可以进行送空了。 LogHelper.Info(location + "没有筐 - 送空框"); #region 505 送空。 var _kk = LocationHelper.GetLocList(x => x.S_AREA_CODE == "KTQ" && x.N_CURRENT_NUM > 0 && x.S_LOCK_STATE != "报废"); var _lockkk = _kk.FindAll(x => x.S_LOCK_STATE != "无").Select(x => x.N_ROW).Distinct(); if (_lockkk.Any()) { _kk.RemoveAll(x => _lockkk.Contains(x.N_ROW)); } if (!_kk.Any()) { LogHelper.Info("去除锁定排后,没有可用空框排了"); return false; } Location stabit = null; //foreach (var item in _kk.GroupBy(x => x.N_ROW).OrderBy(x => x.Count(y => y.N_CURRENT_NUM > 0)).ThenBy(x => x.Key)) //{ // var _ll = item.OrderBy(x => x.N_COL).ToList(); // var fulast = _ll.FindAll(x => x.N_CURRENT_NUM > 0).LastOrDefault(); // if (fulast != null) // { // var cntrEnd = LocationHelper.GetLocCntrRel(fulast.S_LOC_CODE); // if (cntrEnd.Any()) // { // if (cntrEnd[0].S_TYPE == size) // { // stabit = fulast; // break; // } // else // continue; // } // else // { // LogHelper.Info(fulast.S_LOC_CODE + "该位置有数量,但是没有托盘数据。需要核对。"); // continue; // } // } // if (stabit != null) { break; } //} while (_kk.Any() && stabit == null) { var _kkk = _kk.OrderBy(x => x.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault(); var cntr = LocationHelper.GetLocCntrRel(_kkk.S_LOC_CODE); //LogHelper.Info("去除锁定排后,没有可用空框排了" + _kkk.S_LOC_CODE + JsonConvert.SerializeObject(cntr)); if (!cntr.Any()) { LogHelper.Info(_kkk.S_LOC_CODE + "该位置有数量,但是没有托盘数据。需要核对。"); _kk.Remove(_kkk); continue; } if (cntr[0].S_TYPE == size) { stabit = _kkk; break; } else //版型不合 ,移除一排 _kk.RemoveAll(x => x.N_ROW == _kkk.N_ROW); } ; if (stabit != null) { var carryCntrs = LocationHelper.GetLocCntrRel(stabit.S_LOC_CODE).Select(x => x.S_CNTR_CODE).ToList(); var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, stabit.S_LOC_CODE, location, "成品-空托上线" + size, carryCntrs, 1, 1, carryCntrs.Count, plc.taskPri); LogHelper.Info($"{plc.deviceName} 当前机器{location}位置状态 创建“空托上线" + size + "”任务" + bb); } else { LogHelper.Info($"{plc.deviceName} 没有找到可用{size}空框"); } #endregion return true; } } //托盘放下 1分钟内 取货请求,都不处理。 if (time != null) if (DateTime.Now.Subtract(time ?? DateTime.Now).TotalSeconds < 30) { for (var i = 0; i < plc.location.Length; i++) { if (location == plc.location[i]) { PlcHelper.SendHex(plc.address, "3F00" + (i + 1) + "0" + "0d0a"); break; } } } LogHelper.Info(location + "空框位 防止时间够了。"); //else // //{ // //有筐 时间到了 清掉吧 , 不然下一个空框送不过来了。 // LocationHelper.lOCReSetValue(x => x.S_LOC_CODE == location, x => // { // x.T_FULL_TIME = null; // x.N_CURRENT_NUM = 0; // }); //} return false; } LogHelper.Info($"查到了工单{workOrder.SQL_WorkNo}"); //满框下线 if (_li == 0) { var _loc = LocationHelper.GetLoc(location); if (_loc.T_EMPTY_TIME != null) { if (DateTime.Now.Subtract(Convert.ToDateTime(_loc.T_EMPTY_TIME)).TotalSeconds < 30) { PlcHelper.SendHex(plc.address, "3F00100d0A"); LogHelper.Info($"{plc.address} 水线 取货完成。 30秒缓冲 写取货完成。3F00100d0A "); return false; } } //查询起点托盘 var ItemInfo = ContainerHelper.GetItem(workOrder.SQL_ItemName); var rel = LocationHelper.GetLocCntrRel(location); if (rel.Count > 0) { //if (!rel.FirstOrDefault().S_CNTR_CODE.Contains("TP" + Settings._TPcc)) //{ // //不是今天的托盘 - 大概率 还是 之前任务没执行成功,没取货。 // LocationHelper.UnBindingLoc(location, rel.Select(x => x.S_CNTR_CODE).ToList()); //} LocationHelper.UnBindingLoc(location, rel.Select(x => x.S_CNTR_CODE).ToList()); rel = new List { }; } var _bbbb = workOrder.FromFuLe?.Trim() == "Y"; var fuletraycodes = LocationHelper.GetFuLeTrayCodeList(X => X.SQL_State == "下发" && X.workNo == workOrder.SQL_WorkNo && X.deviceName == workOrder.FuLe_PLine_No); //LogHelper.Info($"{workOrder.SQL_WorkNo} -FromFuLe? {_bbbb}"); if (_bbbb) { if (rel.Count > 0) { LocationHelper.UnBindingLoc(location, rel.Select(x => x.S_CNTR_CODE).ToList()); rel = new List { }; } if (fuletraycodes.Count != 2) { LogHelper.Info($"富勒工单成品下线,托盘数量{fuletraycodes.Count},不足2。 "); return false; } else if (string.IsNullOrEmpty(Batch)) { if (fuletraycodes[0].batchNo != fuletraycodes[1].batchNo) { LogHelper.Info($"富勒工单成品下线,托盘数量2 ,单批次不同。 最后一个为准"); //return false; Batch = fuletraycodes.OrderByDescending(x => x.T_CREATE).FirstOrDefault().batchNo; } else Batch = fuletraycodes[0].batchNo; //if (fuletraycodes[0].batchNo != fuletraycodes[1].batchNo) //{ // LogHelper.Info($"富勒工单成品下线,托盘数量2 ,单批次不同。 "); // return false; //} //Batch = fuletraycodes[0].batchNo; } } else { if (rel.Count > 0) { if (!rel.FirstOrDefault().S_CNTR_CODE.Contains("TP" + Settings._TPcc)) { //不是今天的托盘 - 大概率 还是 之前任务没执行成功,没取货。 LocationHelper.UnBindingLoc(location, rel.Select(x => x.S_CNTR_CODE).ToList()); rel = new List { }; } } } //LogHelper.Info($"{workOrder.SQL_WorkNo} -rel.count? {rel.Count}"); // List locr = null; // List cnir = null; LocCntrRel locr = null; CntrItemRel cnir = null; if (rel.Count == 0) { LogHelper.Info("满眶下线 - "); //if (_bbbb) //{ // rel = new List // { // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = fuletraycodes[0].trayCode,S_TYPE=size }, // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = fuletraycodes[1].trayCode,S_TYPE=size } // }; // locr = new List // { // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = fuletraycodes[0].trayCode,S_TYPE=size }, // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = fuletraycodes[1].trayCode,S_TYPE=size } // }; // cnir = new List // { // new CntrItemRel { S_CNTR_CODE = fuletraycodes[0].trayCode, S_BATCH_NO = Batch, F_QTY = Convert.ToInt32(fuletraycodes[0].trayNum.Split('.')[0])+"", B_TYPE = size, ItemLayer = workOrder.ItemLayer, S_ITEM_CODE = ItemCode, S_ITEM_NAME = ItemName }, // new CntrItemRel { S_CNTR_CODE = fuletraycodes[1].trayCode, S_BATCH_NO = Batch, F_QTY = Convert.ToInt32(fuletraycodes[1].trayNum.Split('.')[0])+"", B_TYPE = size, ItemLayer = workOrder.ItemLayer, S_ITEM_CODE = ItemCode, S_ITEM_NAME = ItemName } // }; //} //else //{ // var tp1 = Settings.TPnum(); // rel = new List // { // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = tp1 + "_1",S_TYPE=size }, // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = tp1 + "_2",S_TYPE=size } // }; // locr = new List // { // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = tp1 + "_1",S_TYPE=size }, // new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = tp1 + "_2",S_TYPE=size } // }; // cnir = new List // { // new CntrItemRel { S_CNTR_CODE = tp1 + "_1", S_BATCH_NO = Batch, F_QTY = "0", S_ITEM_CODE = ItemName }, // new CntrItemRel { S_CNTR_CODE = tp1 + "_2", S_BATCH_NO = Batch, F_QTY = "0", S_ITEM_CODE = ItemName } // }; //} //创建容器-写货品容器-托盘容器 var tp1 = Settings.TPnum(); var cntr = tp1 + "_1v" + tp1 + "_2"; LogHelper.Info($"{workOrder.SQL_WorkNo} -tp1 {tp1}-{cntr}"); string qty = "0"; if (_bbbb) { cntr = "F" + fuletraycodes[0].trayCode + "v" + fuletraycodes[1].trayCode; qty = Convert.ToInt32(fuletraycodes[0].trayNum.Split('.')[0]) + Convert.ToInt32(fuletraycodes[1].trayNum.Split('.')[0]) + ""; } LogHelper.Info("满眶下线 - " + cntr); var tp2 = Settings.TPnum(); rel = new List { new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = cntr,S_TYPE=size } }; locr = new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = cntr, S_TYPE = size }; cnir = new CntrItemRel { S_CNTR_CODE = cntr, S_BATCH_NO = Batch, F_QTY = qty, B_TYPE = size, ItemLayer = workOrder.ItemLayer, S_ITEM_CODE = ItemCode, S_ITEM_NAME = ItemName }; /* UPDATE 托盘物料表 SET S_ITEM_CODE = A.S_ITEM_CODE, S_ITEM_NAME = A.S_ITEM_NAME FROM 物料表 A JOIN 托盘物料表 B ON A.S_ITEM_CODE=B.S_ITEM_CODE or A.S_ITEM_CODE=B.S_ITEM_NAME */ //var res = LocationHelper.DoAction(db => //{ // try // { // //db.BeginTran(); // db.Insertable(new LocCntrRel { S_LOC_CODE = location, S_CNTR_CODE = cntr, S_TYPE = size }).ExecuteCommand(); // db.Insertable(new CntrItemRel { S_CNTR_CODE = cntr, S_BATCH_NO = Batch, F_QTY = qty, S_ITEM_CODE = ItemName }).ExecuteCommand(); // //db.Ado.CommitTran(); // return true; // } // catch (Exception ex) // { // LogHelper.Info("成品满框下线口,初始化托盘数据失败," + ex.Message + ex.StackTrace); // return false; // } //}); //if (!res) //{ // return false; //} } LogHelper.Info($"查找{location}对应终点->"); Location endBit = null; int mmmmmnum = workOrder.N_LimitNum; //bool SendAudio = true; //var _audiolist = TaskHelper.GetTList(x => x.S_PlineNo == plc.deviceName && x.N_AUDIO < 3); //if (_audiolist.Any()) //{ // if (_audiolist.Find(x => x.N_AUDIO == 0) != null) // { // LogHelper.Info($"{plc.deviceName} - {location}->有目标区域等待审核。"); // return false; // } //} int MaxLayer = ItemInfo?.MaxLayer ?? 0; { var area = workOrder.SQL_Area; var areaLi = plc.areaPriy; #region oooo //if (false) //flword != null && //{ // var t1 = flword.T_MODIFY.Date != DateTime.Now.Date; // var row = int.Parse(flword.N_ROW); // var areacode = flword.S_AREA_CODE; // if (areacode.IndexOf(Settings.areaSuffix(size)) != -1)// 过了12点, 版型没变。 原来的排上找空一个位置。 换排就不需要空位置了 // { // var rowlist = LocationHelper.GetLocList(x => x.S_AREA_CODE == areacode && x.S_LOCK_STATE != "报废" && x.N_ROW == row); // if (rowlist.Find((Location x) => x.S_LOCK_STATE != "无") != null) goto NormalArea; // var last = rowlist.FindAll(x => x.N_CURRENT_NUM > 0).OrderBy(X => X.N_COL).LastOrDefault();// 该排最后一次入库位。 // if (last == null) goto NormalArea; // var _clrel = LocationHelper.GetLocCntrRel(last.S_LOC_CODE); // if (!_clrel.Any()) // { // LogHelper.Info(last.S_LOC_CODE + " 没有货位托盘信息!"); // goto NormalArea; // } // //LogHelper.Info(" for 查看货位托盘版型!" + _cl.S_LOC_CODE); // //板型相同 // //LogHelper.Info(last.S_LOC_CODE + $" 货位托盘信息{_clrel[0].S_CNTR_CODE}!isFule" + _bbbb); // if (_clrel[0].S_CNTR_CODE.StartsWith("TP") && _bbbb) // { // goto NormalArea; // } // if (!_clrel[0].S_CNTR_CODE.StartsWith("TP") && !_bbbb) // { // goto NormalArea; // } // LogHelper.Info("识别托盘类型。"); // if (_clrel[0].S_TYPE == size) // { // var _clcntitem = ContainerHelper.GetCntrItemRel(_clrel[0].S_CNTR_CODE.Trim()); // if (!_clcntitem.Any()) // { // LogHelper.Info(last.S_LOC_CODE + $"货位 的托盘{_clrel[0].S_CNTR_CODE} 没有物料记录"); // goto NormalArea; // } // var _ci = _clcntitem[0]; // if (_ci.S_ITEM_CODE == ItemName && _ci.S_BATCH_NO == Batch) // { // ////不 用 管。 // } // else // goto NormalArea; // } // if (last != null) // { // var emptyList = rowlist.FindAll(x => x.N_COL > last.N_COL).OrderBy(x => x.N_COL).ToList(); // if (!t1) // { // if (last.N_CURRENT_NUM < last.N_CAPACITY && (MaxLayer == 0 || last.N_CURRENT_NUM < MaxLayer)) // endBit = last; // else if (emptyList.Any()) // endBit = emptyList.FirstOrDefault(); // goto NormalArea; // } // // ↓↓↓ 变天了。 需要空位置了 // if (last.N_CURRENT_NUM < last.N_CAPACITY && (MaxLayer == 0 || last.N_CURRENT_NUM < MaxLayer)) // { // if (emptyList.Any()) // { // endBit = emptyList.First(); // goto NormalArea; // } // last.S_LOCK_STATE = "报废"; // last.T_EMPTY_TIME = new DateTime(1970, 1, 1, 1, 1, 1); // LocationHelper.DoAction(db => // { // db.Updateable(last).UpdateColumns(it => new { it.S_LOCK_STATE, it.T_EMPTY_TIME }).ExecuteCommand(); // return true; // }); // } // else if (emptyList.Count() == 0) goto NormalArea;// 一排已经满了, 不用隔了 // else // { // var e = emptyList.FirstOrDefault(); // if (emptyList.Count() == 1) //需要隔的是最后一个位子,就需要报废掉。 中间隔离就不用了。 // { // e.S_LOCK_STATE = "报废"; // e.T_EMPTY_TIME = new DateTime(1970, 1, 1, 1, 1, 1); // LocationHelper.DoAction(db => // { // db.Updateable(e).UpdateColumns(it => new { it.S_LOCK_STATE, it.T_EMPTY_TIME }).ExecuteCommand(); // return true; // }); // } // else // { // emptyList.Remove(e); // endBit = emptyList.First(); // goto NormalArea; // } // } // } // } //} #endregion List AlTask = new List(); if (mmmmmnum > 0) { LocationHelper.DoAction(db => { var tasks = db.Queryable().Where(x => x.S_START_LOC == location && "未执行,已推送,执行中,开始取货,取货完成,开始卸货,卸货完成".Contains(x.S_B_STATE)).ToList(); LogHelper.Info(location + "起点(工单N_LimitNum:" + mmmmmnum + ")的运行中任务数量" + tasks.Count); foreach (var task in tasks) { var _tloc = LocationHelper.GetLoc(task.S_END_LOC); LogHelper.Info(location + $"起点的运行中任务{task.S_TASK_NO}-{task.S_END_LOC}{_tloc.S_LOCK_STATE}"); if (_tloc != null && _tloc.S_LOCK_STATE == "入库锁") { string si = _tloc.S_AREA_CODE + "_" + _tloc.N_ROW; if (!AlTask.Contains(si)) { AlTask.Add(si); } } } LogHelper.Info($"{workOrder.FuLe_PLine_No}{workOrder.SQL_PLineNo}成品任务中锁排{JsonConvert.SerializeObject(AlTask)}"); return true; }); if (AlTask.Count() >= mmmmmnum) { LogHelper.Info($"{workOrder.FuLe_PLine_No}{workOrder.SQL_PLineNo}成品任务中锁排数{AlTask.Count()}不小于限制数{mmmmmnum},不在进行任务"); return false; } } var Auto = true;//workOrder.S_Is_Auto.Trim() == "Y"; int[] rows = null; ///有指定排, 就入指定排。非auto ,找不到位置就return; ///没有指定排 if (!string.IsNullOrEmpty(workOrder.S_ROW)) { var areaRows = workOrder.S_ROW.Split('$'); foreach (var item in areaRows) { if (string.IsNullOrEmpty(item.Trim())) continue; var rs = item.Split('='); rows = Array.ConvertAll(rs[rs.Length - 1].Split('-'), Convert.ToInt32); #region 优先指定排,有补就补,没补入空。 var _tempList = new List(); var Btype = size; //var bbbbbbbbt = LocationHelper.GetList(X => X.B_TYPE == Btype).FirstOrDefault(); //if (bbbbbbbbt == null) //{ // LogHelper.Debug(Btype + "满框下线 没有配置版型集合对应"); // return false; //} string usffix = Settings.areaSuffix(Btype); // bbbbbbbbt.S_B_TYPE; string are = rs.Length > 1 ? rs[0] : area; //area; string area1 = are + usffix; LogHelper.Info(area1 + " 库区的板型" + Btype); if (!area1.Contains("_")) LogHelper.Info(area1 + " 库区的板型" + Btype + "不正确"); //找当前库区无锁不满的排 var _arealist = LocationHelper.GetLocList(x => x.S_AREA_CODE == area1 && x.S_LOCK_STATE != "报废"); var _arealock = _arealist.FindAll(x => x.S_LOCK_STATE != "无").Select(x => x.N_ROW).Distinct(); LogHelper.Info(area1 + " 库区 非报废货位量" + _arealist.Count + ":非正常货位锁排" + JsonConvert.SerializeObject(_arealock)); var lcollist = LocationHelper.GetRowLock(area1)?.Select(x => x.N_ROW); _arealock = _arealock.Concat(lcollist).Distinct(); if (_arealock.Any()) _arealist.RemoveAll(x => _arealock.Contains(x.N_ROW)); var isFule = _bbbb; var thisrowlocli = _arealist.FindAll(x => rows.Contains(x.N_ROW)); if (thisrowlocli.Any()) foreach (var x in thisrowlocli.OrderBy(x => x.N_ROW).GroupBy(x => x.N_ROW)) { //排最外侧有货位 var xlist = x.OrderBy(xx => xx.N_COL).ToList(); var _cl = xlist.FindAll(xx => xx.N_CURRENT_NUM > 0).LastOrDefault(); if (_cl == null) { //这是一个空排 _tempList.AddRange(xlist); continue; } // 最外侧货位是是同.. 的话 就可以入了。 var _clrel = LocationHelper.GetLocCntrRel(_cl.S_LOC_CODE); if (!_clrel.Any()) { LogHelper.Info(_cl.S_LOC_CODE + " 没有货位托盘信息!"); continue; } //板型相同 var _clrel0 = _clrel.OrderByDescending(xx => xx.T_CREATE).First(); LogHelper.Info(_cl.S_LOC_CODE + $" 货位托盘信息{_clrel0.S_CNTR_CODE}!isFule" + isFule); if (_clrel0.S_CNTR_CODE.StartsWith("TP") && isFule) { continue; } if (!_clrel0.S_CNTR_CODE.StartsWith("TP") && !isFule) { continue; } LogHelper.Info("识别托盘类型。"); if (_clrel0.S_TYPE == Btype) { var _clcntitem = ContainerHelper.GetCntrItemRel(_clrel0.S_CNTR_CODE.Trim()); if (!_clcntitem.Any()) { LogHelper.Info(_cl.S_LOC_CODE + $"货位 的托盘{_clrel0.S_CNTR_CODE} 没有物料记录"); continue; } var _ci = _clcntitem.OrderByDescending(xx => xx.T_CREATE).First(); if ((_ci.S_ITEM_CODE == ItemName || _ci.S_ITEM_CODE == ItemCode) && _ci.ItemLayer == workOrder.ItemLayer) { DateTime bft = DateTime.Now; var Before_task = TaskHelper.GetTask(z => z.S_CNTRS.Contains(_ci.S_CNTR_CODE), y => y.T_CREATE, SqlSugar.OrderByType.Desc); LogHelper.Info($"找到匹配货位{_cl.S_LOC_CODE},查看货位最后一个托盘的任务{JsonConvert.SerializeObject(Before_task)} 如果没有,就默认是同一日期,不隔开"); if (Before_task != null) { bft = Before_task.T_CREATE; } bool sameDate = bft.Date == DateTime.Now.Date;// string.IsNullOrEmpty(_ci.S_BATCH_NO) ? true : _ci.S_BATCH_NO == Batch; //not full LogHelper.Info($"找到匹配货位{_cl.S_LOC_CODE} {bft.Date}=={DateTime.Now.Date}?{sameDate}"); if (_cl.N_CURRENT_NUM < _cl.N_CAPACITY && (MaxLayer == 0 || (MaxLayer > 0 && _cl.N_CURRENT_NUM < MaxLayer))) //if (_cl.N_CURRENT_NUM < _cl.N_CAPACITY && (MaxLayer == 0 || (MaxLayer > 0 && _cl.N_CURRENT_NUM / 2 < MaxLayer))) { if (sameDate) endBit = _cl; else { var empty = xlist.FindAll(xx => xx.N_CURRENT_NUM == 0 && xx.N_COL > _cl.N_COL); if (!empty.Any()) { //这一排没有空位 } else { if (empty.Count > 1) { endBit = empty.Skip(1).FirstOrDefault(); } } } } else//full { var empty = xlist.FindAll(xx => xx.N_CURRENT_NUM == 0 && xx.N_COL > _cl.N_COL); if (!empty.Any()) { //这一排没有空位 } else { if (sameDate) endBit = empty.FirstOrDefault(); else { //满了, 中间间隔一个空位。 if (empty.Count > 1) { endBit = empty.Skip(1).FirstOrDefault(); } } } } } } if (endBit != null) break; } if (endBit == null && _tempList.Any()) { LogHelper.Info(" ar_RplaceRow over!"); var ar_RplaceRows = LocationHelper.GetLocList(x => x.S_AREA_CODE != area1 && x.S_AREA_CODE.Contains(are) && x.S_LOCK_STATE != "报废");//.Select(x => x.N_ROW).Distinct(); //var ar_RplaceRow1 = ar_RplaceRows.FindAll(x => x.S_LOCK_STATE != "无").Select(x => x.N_ROW).Distinct(); IEnumerable ar_RplaceRow1 = ar_RplaceRows.FindAll(x => "入库锁;出库锁".Contains(x.S_LOCK_STATE?.Trim())).Select(x => x.N_ROW).Distinct(); LogHelper.Info(" 有锁排 - " + JsonConvert.SerializeObject(ar_RplaceRow1)); //LogHelper.Info(" 有锁排 - " + JsonConvert.SerializeObject(ar_RplaceRow1)); var ar_RplaceRow2 = ar_RplaceRows.FindAll(x => x.N_CURRENT_NUM > 0).Select(x => x.N_ROW).Distinct(); LogHelper.Info(" 有货排: - " + JsonConvert.SerializeObject(ar_RplaceRow2)); var ar_RplaceRow_rowlock = LocationHelper.GetRowLock(x => x.S_AREA_CODE.Contains(are))?.Select(x => x.N_ROW); var ar_RplaceRow = ar_RplaceRow1.Concat(ar_RplaceRow2).Concat(ar_RplaceRow_rowlock).Distinct(); if (ar_RplaceRow.Any()) { LogHelper.Info("排除非空排 - " + JsonConvert.SerializeObject(ar_RplaceRow)); _tempList.RemoveAll(x => ar_RplaceRow.Contains(x.N_ROW)); } if (_tempList.Any())//三个库区的交集空排 { endBit = _tempList.OrderBy(x => x.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault(); } } #endregion if (endBit != null) break; } } if (!Auto && endBit == null) { LogHelper.Info($"{plc.deviceName} {location} 非自动入排{workOrder.S_ROW}>.{JsonConvert.SerializeObject(rows)} 没有对应终点,终止!"); return false; } NormalArea: //任务切面 产线申请的所有 库区和排。 //if (_audiolist.Any()) //{ // var pass = _audiolist.Find(x => x.N_AUDIO == 1); // if (pass != null) // { // endBit = LocationHelper.GetLoc(pass.S_LOC_CODE); //GetareaLocationByBtypeandBatch(ItemName, pass.S_Area, size, Batch, _bbbb, MaxLayer, true, pass.N_ROW); // if (endBit != null) // { // if (endBit.N_CURRENT_NUM == 0) // SendAudio = false; // else // { // endBit = null; // SendAudio = true; // } // } // } //} //先找未满和 任务排 if (endBit == null && !string.IsNullOrEmpty(area)) { endBit = GetareaLocationByBtypeandBatch(ItemInfo, area, size, Batch, _bbbb, MaxLayer, workOrder, true); } if (endBit == null) { foreach (var _ar in areaLi) { if (area == _ar) continue; endBit = GetareaLocationByBtypeandBatch(ItemInfo, _ar, size, Batch, _bbbb, MaxLayer, workOrder, true); if (endBit != null) { break; } } } //if (endBit != null) // SendAudio = false; //找空排 if (endBit == null && !string.IsNullOrEmpty(area)) { endBit = GetareaLocationByBtypeandBatch(ItemInfo, area, size, Batch, _bbbb, MaxLayer, workOrder); } if (endBit == null) { foreach (var _ar in areaLi) { if (area == _ar) continue; endBit = GetareaLocationByBtypeandBatch(ItemInfo, _ar, size, Batch, _bbbb, MaxLayer, workOrder); if (endBit != null) { break; } } } } #region 筛选终点 if (endBit != null) { //if (SendAudio) //{ // TaskHelper.InsertT(new TaskAudio // { // S_LOC_CODE = endBit.S_LOC_CODE, // S_Area = endBit.S_AREA_CODE, // N_AUDIO = 0, // N_ROW = endBit.N_ROW, // S_PlineNo = plc.deviceName, // S_Note = $"[{DateTime.Now}-创建审核]", // CreateTime = DateTime.Now // }); // LocationHelper.LockLoc(endBit.S_LOC_CODE, "空间锁"); // return false; //} int endLayer = endBit.N_CURRENT_NUM + 1; //int endLayer = endBit.N_CURRENT_NUM /2+ 1; var carryCntrs = rel.Select(x => x.S_CNTR_CODE).ToList();//DateTime.Now.ToString("yyMMddHHmmss") }; var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, location, endBit.S_LOC_CODE, (_bbbb ? "Fu" : "") + "成品满框-入库", carryCntrs, 1, endLayer, carryCntrs.Count, plc.taskPri); if (bb) { //if (_audiolist.Any()) //{ // var _al = _audiolist.FindAll(x => 0 < x.N_AUDIO && x.N_AUDIO < 3); // foreach (var item in _al) // { // LogHelper.Info($"{item.S_PlineNo} {item.CreateTime}任务执行.废弃"); // item.S_Note += $"[{DateTime.Now}-任务执行.废弃]"; // item.N_AUDIO = 3; // TaskHelper.DoUpdate(item, x => new { x.S_Note, x.N_AUDIO }); // } //} var flwords = LocationHelper.GetRecord(x => x.S_IP_Address == plc.address); LogHelper.Info(plc.address + "" + JsonConvert.SerializeObject(flwords.Select(x => x.S_AREA_CODE))); InworkRecord flword = new InworkRecord { SQL_PLineNo = workOrder.SQL_PLineNo, S_Fule_Code = workOrder.FuLe_PLine_No, S_IP_Address = plc.address, N_ROW = endBit.N_ROW + "", S_AREA_CODE = endBit.S_AREA_CODE, T_MODIFY = DateTime.Now }; LocationHelper.DoAction(db => { //db.BeginTran(); db.Insertable(locr).ExecuteCommand(); db.Insertable(cnir).ExecuteCommand(); //db.Ado.CommitTran(); if (!flwords.Any()) { db.Insertable(flword).ExecuteCommand(); } else { var _bb = false; var fd = flwords.Find(x => x.S_AREA_CODE.Trim() == flword.S_AREA_CODE.Trim() && x.N_ROW.Trim() == flword.N_ROW.Trim()); LogHelper.Info(plc.address + "限制数:" + mmmmmnum + ";找到已存在记录?" + (fd != null)); if (mmmmmnum > 0) { //限制数量。 if (fd == null) { if (flwords.Count >= mmmmmnum) { LogHelper.Info(plc.address + "超限制数>"); var iCount = flwords.Count - mmmmmnum + 1; var fds = flwords.OrderBy(x => x.T_MODIFY).Take(iCount).ToList(); LogHelper.Info(plc.address + "超限制数 删除 " + JsonConvert.SerializeObject(fds.Select(x => x.S_AREA_CODE))); db.Deleteable(fds).ExecuteCommand(); } db.Insertable(flword).ExecuteCommand(); } else _bb = true; } else { // 只留一条。 if (flwords.Count > 1) { db.Deleteable(flwords).ExecuteCommand(); db.Insertable(flword).ExecuteCommand(); } else { _bb = true; } } if (_bb) { flword = fd; flword.SQL_PLineNo = workOrder.SQL_PLineNo; flword.S_Fule_Code = workOrder.FuLe_PLine_No; flword.N_ROW = endBit.N_ROW + ""; flword.S_AREA_CODE = endBit.S_AREA_CODE; flword.T_MODIFY = DateTime.Now; db.Updateable(flword).UpdateColumns(it => new { it.SQL_PLineNo, it.S_Fule_Code, it.N_ROW, it.S_AREA_CODE, it.T_MODIFY }).ExecuteCommand(); } //flword.S_AREA_CODE = endBit.S_AREA_CODE; //flword.N_ROW = endBit.N_ROW + ""; //flword.T_MODIFY = DateTime.Now; //db.Updateable(flword).UpdateColumns(it => new { it.S_AREA_CODE, it.N_ROW, it.T_MODIFY }).ExecuteCommand(); } return true; }); LogHelper.Info($"{plc.deviceName} 当前机器{location}位置状态{p0} 正在执行取满任务"); } result = bb; } else { LogHelper.Info($"成品终点没有可用空排,空位"); } #endregion } } else { //LogHelper.Info($"瓶PEM机:{plc.deviceName} 当前机器2个位置 有一个有任务,不可触发满托下线", "瓶坯机"); //if (p0 != "无") LogHelper.Info($"{plc.deviceName} {location}位置状态{p0} 正在执行{(p0.Replace("锁", "") == "入库" ? "送空" : "取满")}任务"); } } return result; } /// /// 收到关门22信号以后再发送 翻斗信号。后来。门信号清了以后,直接发翻斗,可以触发关门。 /// 所以改为, 收到1025 清了开门信号,就发翻斗。 /// [Obsolete("更换逻辑,不用这个标识了")] public static readonly List FDJ_writeFD = new List(); //卸货后给 0 收到11 也写0 收到12 开始累加 - 连续10次后的11 才 public static Dictionary FJD_wwwwFD = new Dictionary(); internal static void AnalysisBottleCapTipper(string data, Settings.deviceInfo plc) { //LogHelper.Info($"{plc.deviceName}-{plc.address}-{plc.deviceType}-data:{data}。 "); bool containsKey = true; int llll = 0; if (!FJD_wwwwFD.TryGetValue(plc.deviceName.Trim(), out llll)) { containsKey = false; LogHelper.Info(plc.location[0] + "交管缓存 10 信号失败。 数量:" + llll); llll = 6; } else { LogHelper.Info(plc.location[0] + "交管缓存 10 信号成功。 数量:" + llll); } bool flag = data.Length == 2; if (flag) { //LogHelper.Info(string.Concat(new string[] //{ // "翻斗机门 ", // plc.deviceNo[1], // " - 信号: ", // data, // " 门状态:(1开2关) ", // data.Substring(3, 1) // }), "自动门"); string s = "2";// data.Substring(3, 1); //bool flag4 = DeviceProcess.doorStatus.Keys.Contains(plc.deviceNo[1]); //if (flag4) //{ // DeviceProcess.doorStatus[plc.deviceNo[1]].info = s; // DeviceProcess.doorStatus[plc.deviceNo[1]].modify = DateTime.Now; //} //else //{ // DeviceProcess.doorStatus.Add(plc.deviceNo[1], new DeviceProcess.signalInfo // { // info = data.Substring(3, 1), // modify = DateTime.Now // }); //} //if (data.Substring(1, 1) == "1") //{ // LogHelper.Info(plc.location[0] + "读到11信号。(12信号持续数量):" + llll); // if (llll < 10) // { // llll = 0; // LogHelper.Info(plc.deviceName + "读到11信号,或连续12信号不足10次"); // if (containsKey) // FJD_wwwwFD[plc.deviceName.Trim()] = llll; // else FJD_wwwwFD.Add(plc.deviceName.Trim(), llll); // return; // } //} //else if (data.Substring(1, 1) == "0" || data.Substring(1, 1) == "2") { LogHelper.Info(plc.location[0] + $"读到1 0/2信号。(1 0/2信号持续数量):" + llll); llll++; if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = llll; else FJD_wwwwFD.Add(plc.deviceName.Trim(), llll); } //if (llll < 10) //{ // LogHelper.Info(plc.deviceName + "读到11信号 ,或连续12信号不足10次(" + llll + "次)"); // return; //} LogHelper.Info(plc.deviceName + "查看翻斗鸡空筐位" + (data.Substring(1, 1) == "1").ToString() + LocationHelper.CheckLocFree(plc.location[0]).ToString(), "翻斗机"); bool flag5 = data.Substring(1, 1) == "1" && LocationHelper.CheckLocFree(plc.location[0]) && s == "2"; if (flag5) { bool flag6 = DeviceProcess.FDJ_writeFD.Contains(plc.deviceName); if (flag6) { LogHelper.Info(plc.deviceName + "翻斗鸡卸货后, 翻斗信号还未重置。", "翻斗机"); } else { //if (llll > 10) //{ // LogHelper.Info(plc.deviceName + "交管给翻斗信号后还没有翻斗", "翻斗机"); // return; //} //else //{ // LogHelper.Info(plc.deviceName + "交管给翻斗信号后 已翻斗:" + llll, "翻斗机"); //} WorkOrder workOrder = WCSHelper.GetWorkOrder(plc.deviceName); bool flag7 = workOrder == null; if (flag7) { LogHelper.Info(plc.deviceName + "没有【执行中】的工单", "翻斗机"); if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = 1; else FJD_wwwwFD.Add(plc.deviceName.Trim(), 1); } else { Location loc2 = LocationHelper.GetLoc(plc.location[0]); bool flag8 = loc2.S_LOCK_STATE.Trim() != "无"; if (flag8) { LogHelper.Info(string.Concat(new string[] { plc.deviceName, " 货位", plc.location[0], "的状态位", loc2.S_LOCK_STATE, ",无法生成任务" }), "翻斗机"); } else { LogHelper.Info(plc.deviceName + " 翻斗机 呼叫" + ((workOrder.SQL_UsingNow.Trim() == "Y") ? "即产" : "出库") + "任务", "翻斗机"); bool flag9 = loc2.N_CURRENT_NUM > 0; if (flag9) { DateTime? time = LocationHelper.GetT_FULL_TIME(plc.location[0]); #region 反编译 日志参数 string[] array = new string[6]; array[0] = plc.location[0]; array[1] = ":托盘放置时间:("; int num = 2; DateTime? dateTime = time; array[num] = dateTime.ToString(); array[3] = ") 货位托盘数量("; array[4] = loc2.N_CURRENT_NUM.ToString(); array[5] = ")"; #endregion LogHelper.Info(string.Concat(array), "翻斗机"); bool flag10 = time == null || loc2 == null || loc2.N_CURRENT_NUM == 0; if (!flag10) { var flag11 = DateTime.Now.Subtract(time ?? DateTime.Now).TotalSeconds; if (flag11 > 30) { //if (data.Substring(1, 1) == "1") //{ LogHelper.Info(plc.location[0] + "读到11信号。(1 0/2信号持续数量):" + llll); //if (flag11 < 3.0) if (llll < 0) { //llll = 0; LogHelper.Info(plc.deviceName + "读到11信号,但是没出现过1 0/2"); //if (containsKey) // FJD_wwwwFD[plc.deviceName.Trim()] = llll; //else FJD_wwwwFD.Add(plc.deviceName.Trim(), llll); return; } //} var b = TaskProcess.FDJTakeEmpyt2(plc, workOrder); LogHelper.Info(plc.location[0] + "读到11信号, 重置1 0/2信号缓存数量 取空任务创建是否成功:" + b); if (b) { if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = 1; else FJD_wwwwFD.Add(plc.deviceName.Trim(), 1); } } else { ///- LogHelper.Info($"{plc.deviceName} 货位 {plc.location} 满框卸货不足30S缓冲时间。 "); //if (time != null && DateTime.Now.Subtract(time ?? DateTime.Now).TotalSeconds < 30) //{ LogHelper.Info($"翻斗机满框放下时间{time}不足30秒, 回写翻斗信号", "翻斗机"); PlcHelper.SendHex(plc.address, $"3f 00 11 0d 0a"); if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = 0; else FJD_wwwwFD.Add(plc.deviceName.Trim(), 0); return; //} } } } else { if (loc2.N_CURRENT_NUM == 0) TaskProcess.TakeFull2FDJ(plc, workOrder); else LogHelper.Info(" 送满任务 无筐或者无置满时间 不生成。" + JsonConvert.SerializeObject(loc2)); } } } } } } else { LogHelper.Info("翻斗机信号不明!", "翻斗机"); } } #endregion internal static void AnalysisBottleCapTipper10_(string data, Settings.deviceInfo plc) { bool containsKey = true; int llll = 0; if (!FJD_wwwwFD.TryGetValue(plc.deviceName.Trim(), out llll)) { containsKey = false; LogHelper.Info(plc.location[0] + "交管缓存 10 信号失败。 数量:" + llll); llll = 6; } else { LogHelper.Info(plc.location[0] + "交管缓存 10 信号成功。 数量:" + llll); } bool flag = data.Length == 2; if (flag) { string s = "2";// data.Substring(3, 1); if (data.Substring(1, 1) == "0") { LogHelper.Info(plc.location[0] + "读到10信号。(10信号持续数量):" + llll); llll++; if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = llll; else FJD_wwwwFD.Add(plc.deviceName.Trim(), llll); } LogHelper.Info(plc.deviceName + "查看翻斗鸡空筐位" + (data.Substring(1, 1) == "1").ToString() + LocationHelper.CheckLocFree(plc.location[0]).ToString(), "翻斗机"); bool flag5 = data.Substring(1, 1) == "1" && LocationHelper.CheckLocFree(plc.location[0]) && s == "2"; if (flag5) { bool flag6 = DeviceProcess.FDJ_writeFD.Contains(plc.deviceName); if (flag6) { LogHelper.Info(plc.deviceName + "翻斗鸡卸货后, 翻斗信号还未重置。", "翻斗机"); } else { WorkOrder workOrder = WCSHelper.GetWorkOrder(plc.deviceName); bool flag7 = workOrder == null; if (flag7) { LogHelper.Info(plc.deviceName + "没有【执行中】的工单", "翻斗机"); } else { Location loc2 = LocationHelper.GetLoc(plc.location[0]); bool flag8 = loc2.S_LOCK_STATE.Trim() != "无"; if (flag8) { LogHelper.Info(string.Concat(new string[] { plc.deviceName, " 货位", plc.location[0], "的状态位", loc2.S_LOCK_STATE, ",无法生成任务" }), "翻斗机"); } else { LogHelper.Info(plc.deviceName + " 翻斗机 呼叫" + ((workOrder.SQL_UsingNow.Trim() == "Y") ? "即产" : "出库") + "任务", "翻斗机"); bool flag9 = loc2.N_CURRENT_NUM > 0; if (flag9) { DateTime? time = LocationHelper.GetT_FULL_TIME(plc.location[0]); #region 反编译 日志参数 string[] array = new string[6]; array[0] = plc.location[0]; array[1] = ":托盘放置时间:("; int num = 2; DateTime? dateTime = time; array[num] = dateTime.ToString(); array[3] = ") 货位托盘数量("; array[4] = loc2.N_CURRENT_NUM.ToString(); array[5] = ")"; #endregion LogHelper.Info(string.Concat(array), "翻斗机"); bool flag10 = time == null || loc2 == null || loc2.N_CURRENT_NUM == 0; if (!flag10) { var flag11 = DateTime.Now.Subtract(time ?? DateTime.Now).TotalSeconds; if (flag11 > 30) { LogHelper.Info(plc.location[0] + "读到11信号。(10信号持续数量):" + llll); if (llll < 1) { LogHelper.Info(plc.deviceName + "读到11信号,但连续10信号不足1次"); return; } var b = TaskProcess.FDJTakeEmpyt2(plc, workOrder); LogHelper.Info(plc.location[0] + "读到11信号, 重置10信号缓存数量 取空任务创建是否成功:" + b); if (b) { if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = 0; else FJD_wwwwFD.Add(plc.deviceName.Trim(), 0); } } else { LogHelper.Info($"{plc.deviceName} 货位 {plc.location} 满框卸货不足30S缓冲时间。 "); LogHelper.Info($"翻斗机满框放下时间{time}不足30秒, 回写翻斗信号", "翻斗机"); PlcHelper.SendHex(plc.address, $"3f 00 11 0d 0a"); return; } } } else { if (loc2.N_CURRENT_NUM == 0) { TaskProcess.TakeFull2FDJ(plc, workOrder); } else LogHelper.Info(" 送满任务 无筐或者无置满时间 不生成。" + JsonConvert.SerializeObject(loc2)); } } } } } } else { LogHelper.Info("翻斗机信号不明!", "翻斗机"); } } /// /// /// /// /// internal static void AnalysisBottleCapTipper46(string data, Settings.deviceInfo plc) { //LogHelper.Info($"{plc.deviceName}-{plc.address}-{data}"); bool containsKey = true; int llll = 0; if (data.Length > 1 && data.Length % 2 == 0) { var workOrder = WCSHelper.GetPGWorkOrder(plc.deviceName); if (workOrder == null) { LogHelper.Info(plc.deviceName + "没有【执行中】的工单", "翻斗机"); return; } var USING = workOrder.SQL_UsingNow == "Y"; int _sii = 0; if (plc.deviceNo.Length > 0) { for (int i = 0; i < plc.deviceNo.Length; i++) { string _dorNo = plc.deviceNo[i]; //LogHelper.Info($"{plc.deviceName}{_dorNo} v {(i + 1) * 2}>-{data.Length}"); if (!string.IsNullOrEmpty(_dorNo)) { if ((i + 1) * 2 > data.Length) break; bool flag4 = DeviceProcess.doorStatus.Keys.Contains(_dorNo); if (flag4) { DeviceProcess.doorStatus[_dorNo].info = data.Substring(2 * i + 1, 1); DeviceProcess.doorStatus[_dorNo].modify = DateTime.Now; } else { DeviceProcess.doorStatus.Add(_dorNo, new DeviceProcess.signalInfo { info = data.Substring(2 * i + 1, 1), modify = DateTime.Now }); } LogHelper.Info($"{plc.deviceName}{_dorNo} v {data.Substring(2 * i + 1, 1)}"); } else { if (_sii == 0) { _sii = 2 * i + 1; } //LogHelper.Info($"{plc.deviceName}翻斗信号位置 v {_sii}"); } } } //if (data.Substring(_sii, 1) == "0") //{ // LogHelper.Info(plc.location[0] + "读到10信号。(10信号持续数量):" + llll); // llll++; // if (containsKey) // FJD_wwwwFD[plc.deviceName.Trim()] = llll; // else FJD_wwwwFD.Add(plc.deviceName.Trim(), llll); // return; //} var location = plc.location[0]; var _loc = LocationHelper.GetLoc(location); if (!(_loc.S_LOCK_STATE == "无" && data.Substring(_sii, 1) == "1")) return; var time = _loc?.T_FULL_TIME; LogHelper.Info(location + ":托盘放置时间:(" + time + ") 货位托盘数量(" + _loc?.N_CURRENT_NUM + ")"); List cntrStart = null; if (time == null) { if (_loc.N_CURRENT_NUM == 1) { cntrStart = LocationHelper.GetLocCntrRel(location); time = cntrStart.FirstOrDefault()?.T_CREATE; if (time == null) { LogHelper.Info(plc.deviceName + ">>" + location + "货位托盘数量(" + _loc?.N_CURRENT_NUM + ") 但是找不到托盘数据。 终止"); return; } } } if (_loc.N_CURRENT_NUM == 0)//time == null || _loc == null || { //搬走了。 如果本来就空的还给11 那就不是我的问题了。 // 后改 TODO - 送空框任务。 /// 取货时 给个 Empty_time /// 信号不清的, 读到EmptyTime + 满信号 = 送空托。 /// 同时清掉EmtpyTimt 这样空托任务取消了,也不会循环触发。 //var EMPTYTIME = _loc?.T_EMPTY_TIME; //if (EMPTYTIME == null || _loc == null || _loc?.N_CURRENT_NUM > 0) //{ // return; //} LocationHelper.TakeEmptyToBottleBoyd(new WMSTask { S_START_LOC = location, }); return; } //托盘放下 1分钟内 下空请求,都不处理。 else if (DateTime.Now.Subtract((DateTime)time).Minutes < 1) { PlcHelper.SendHex(plc.address, "3F00110d0a"); return; } LogHelper.Info($"翻斗机:{plc.deviceName} 下线信号:{location} 查询工单{workOrder.SQL_WorkNo}"); LogHelper.Info(plc.location[0] + "读到11信号。(10信号持续数量):" + llll); var _i = -1; if (llll < _i) { LogHelper.Info(plc.deviceName + $"读到11信号,但连续10信号不足{_i}次"); return; } if (cntrStart == null) cntrStart = LocationHelper.GetLocCntrRel(location); //关联表。 - 托盘决定去哪 - 工单可能临时切换。 if (cntrStart.Count == 1) { LogHelper.Info($"查找{location}对应终点->即产?{workOrder.SQL_UsingNow.Trim()}"); Location endBit = null; var Cont = cntrStart.FirstOrDefault(); int endLayer = 1; string Desc = ""; var USING2 = false; if (Cont.S_CNTR_CODE.StartsWith("J")) { Desc = "翻斗机即产空筐下线"; USING2 = true; } else { USING2 = false; Desc = "翻斗机库存空筐下线"; } //var ba = ""; var ba2 = Settings.GetBolAreaList().Find(x => x.DeviceName == plc.deviceName && x.deviceType == plc.deviceType); if (ba2 == null) { LogHelper.Info($"{plc.deviceName}-{workOrder.SQL_WorkNo}的BolArea 未配置。"); return; } List areaList = new List { (plc.deviceType == 6 ? "WJGRGDKQ" : "SGRGDKQ"), ba2.NotUsingEmpty }; if (plc.deviceType == 10) { areaList = new List { ba2.NotUsingEmpty }; } goturunnnn: var area = areaList.FirstOrDefault(); if (areaList.Count > 0) areaList.Remove(area); if (USING2) { areaList.Clear(); area = ba2.UsingEmpty; LogHelper.Info($"翻斗机{plc.deviceName} 筛选即产终点库区{area}"); var _endLoclist = LocationHelper.GetAreaNormalLocList(area); foreach (var item in _endLoclist.OrderBy(x => x.N_ROW).GroupBy(x => x.N_ROW)) { var _ll = item.OrderBy(x => x.N_COL).ToList(); var fulast = _ll.FindAll(x => x.N_CURRENT_NUM > 0).LastOrDefault(); if (fulast != null && fulast.N_CURRENT_NUM < fulast.N_CAPACITY) { endBit = fulast; } else { if (fulast == null) endBit = _ll.FirstOrDefault(); else endBit = _ll.Find(x => x.N_COL > fulast.N_COL); } if (endBit != null) { break; } } LogHelper.Info($"翻斗机 筛选J终点 endbit:{JsonConvert.SerializeObject(endBit)}"); } else { LogHelper.Info($"翻斗机{plc.deviceName} 筛选F即产终点库区{area}"); var _endLoclist = LocationHelper.GetAreaNormalLocList(area); foreach (var item in _endLoclist.OrderByDescending(x => x.N_CURRENT_NUM).GroupBy(x => x.N_ROW)) { var _ll = item.OrderBy(x => x.N_COL).ToList(); var fulast = _ll.FindAll(x => x.N_CURRENT_NUM > 0).LastOrDefault(); if (fulast != null && fulast.N_CURRENT_NUM < fulast.N_CAPACITY) { endBit = fulast; } else { if (fulast == null) endBit = _ll.FirstOrDefault(); else endBit = _ll.Find(x => x.N_COL > fulast.N_COL); } if (endBit != null) { break; } } LogHelper.Info($"翻斗机 筛选F终点 endbit:{JsonConvert.SerializeObject(endBit)}"); } if (endBit != null) { var carryCntrs = new List { Cont.S_CNTR_CODE }; var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, location, endBit.S_LOC_CODE, Desc + "(瓶盖)", carryCntrs, 1, endBit.N_CURRENT_NUM + 1, carryCntrs.Count, plc.taskPri); if (bb) { LogHelper.Info($"{plc.deviceName} 当前机器{location} 正在执行下空任务"); if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = 0; else FJD_wwwwFD.Add(plc.deviceName.Trim(), 0); } } else { if (!USING2 && areaList.Count > 0) goto goturunnnn; LogHelper.Info($"翻斗机{plc.deviceName} 没有可用的空托终点"); } } } else { LogHelper.Info("翻斗机信号不明!", "翻斗机"); } } internal static void AnalysisBottleCapTipper462(string data, Settings.deviceInfo plc) { //LogHelper.Info($"{plc.deviceName}-{plc.address}-{data}"); bool containsKey = true; int llll = 0; if (data.Length > 1 && data.Length % 2 == 0) { var workOrder = WCSHelper.GetPGWorkOrder(plc.deviceName); if (workOrder == null) { LogHelper.Info(plc.deviceName + "没有【执行中】的工单", "翻斗机"); return; } var USING = workOrder.SQL_UsingNow == "Y"; int _sii = 0; if (plc.deviceNo.Length > 0) { for (int i = 0; i < plc.deviceNo.Length; i++) { string _dorNo = plc.deviceNo[i]; //LogHelper.Info($"{plc.deviceName}{_dorNo} v {(i + 1) * 2}>-{data.Length}"); if (!string.IsNullOrEmpty(_dorNo)) { if ((i + 1) * 2 > data.Length) break; bool flag4 = DeviceProcess.doorStatus.Keys.Contains(_dorNo); if (flag4) { DeviceProcess.doorStatus[_dorNo].info = data.Substring(2 * i + 1, 1); DeviceProcess.doorStatus[_dorNo].modify = DateTime.Now; } else { DeviceProcess.doorStatus.Add(_dorNo, new DeviceProcess.signalInfo { info = data.Substring(2 * i + 1, 1), modify = DateTime.Now }); } LogHelper.Info($"{plc.deviceName}{_dorNo} v {data.Substring(2 * i + 1, 1)}"); } else { if (_sii == 0) { _sii = 2 * i + 1; } //LogHelper.Info($"{plc.deviceName}翻斗信号位置 v {_sii}"); } } } //if (data.Substring(_sii, 1) == "0") //{ // LogHelper.Info(plc.location[0] + "读到10信号。(10信号持续数量):" + llll); // llll++; // if (containsKey) // FJD_wwwwFD[plc.deviceName.Trim()] = llll; // else FJD_wwwwFD.Add(plc.deviceName.Trim(), llll); // return; //} var location = plc.location[0]; var _loc = LocationHelper.GetLoc(location); if (!(_loc.S_LOCK_STATE == "无" && data.Substring(_sii, 1) == "1")) return; var time = _loc?.T_FULL_TIME; LogHelper.Info(location + ":托盘放置时间:(" + time + ") 货位托盘数量(" + _loc?.N_CURRENT_NUM + ")"); List cntrStart = null; if (time == null) { if (_loc.N_CURRENT_NUM == 1) { cntrStart = LocationHelper.GetLocCntrRel(location); time = cntrStart.FirstOrDefault()?.T_CREATE; if (time == null) { LogHelper.Info(plc.deviceName + ">>" + location + "货位托盘数量(" + _loc?.N_CURRENT_NUM + ") 但是找不到托盘数据。 终止"); return; } } } if (_loc.N_CURRENT_NUM == 0)//time == null || _loc == null || { //搬走了。 如果本来就空的还给11 那就不是我的问题了。 // 后改 TODO - 送空框任务。 /// 取货时 给个 Empty_time /// 信号不清的, 读到EmptyTime + 满信号 = 送空托。 /// 同时清掉EmtpyTimt 这样空托任务取消了,也不会循环触发。 //var EMPTYTIME = _loc?.T_EMPTY_TIME; //if (EMPTYTIME == null || _loc == null || _loc?.N_CURRENT_NUM > 0) //{ // return; //} LocationHelper.TakeEmptyToBottleBoyd2346(new WMSTask { S_START_LOC = location, }); return; } //托盘放下 1分钟内 下空请求,都不处理。 else if (DateTime.Now.Subtract((DateTime)time).Minutes < 1) { PlcHelper.SendHex(plc.address, "3F00110d0a"); return; } LogHelper.Info($"翻斗机:{plc.deviceName} 下线信号:{location} 查询工单{workOrder.SQL_WorkNo}"); LogHelper.Info(plc.location[0] + "读到11信号。(10信号持续数量):" + llll); var _i = -1; if (llll < _i) { LogHelper.Info(plc.deviceName + $"读到11信号,但连续10信号不足{_i}次"); return; } if (cntrStart == null) cntrStart = LocationHelper.GetLocCntrRel(location); //关联表。 - 托盘决定去哪 - 工单可能临时切换。 if (cntrStart.Count == 1) { Location endBit = null; var Cont = cntrStart.FirstOrDefault(); LogHelper.Info($"查找{location}对应终点-> 工单类型:{workOrder.SQL_UsingNow.Trim()} 托盘类型:{(Cont.S_CNTR_CODE.StartsWith("J") ? "" : "非")}即产"); int endLayer = 1; string Desc = ""; var Locations = new List(); var USING2 = false; if (Cont.S_CNTR_CODE.StartsWith("J")) { Desc = "翻斗机即产空筐下线"; USING2 = true; } else { USING2 = false; Desc = "翻斗机库存空筐下线"; } //var ba = ""; var ba2 = Settings.GetBolAreaList().Find(x => x.DeviceName == plc.deviceName && x.deviceType == plc.deviceType); if (ba2 == null) { LogHelper.Info($"{plc.deviceName}-{workOrder.SQL_WorkNo}的BolArea 未配置。"); return; } List areaList = new List(); if (USING2) { areaList = ba2.UsingEmpty.Split(';').ToList(); } else { areaList = ba2.NotUsingEmpty.Split(';').ToList(); } goturunnnn: var area = areaList.FirstOrDefault(); if (areaList.Count > 0) areaList.Remove(area); var _endLoclist = LocationHelper.GetAreaNormalLocList(area); foreach (var item in _endLoclist.GroupBy(x => x.N_ROW).OrderByDescending(x => x.Count(y => y.N_CURRENT_NUM > 0))) { var _ll = item.OrderBy(x => x.N_COL).ToList(); var fulast = _ll.FindAll(x => x.N_CURRENT_NUM > 0).LastOrDefault(); if (fulast != null && fulast.N_CURRENT_NUM < fulast.N_CAPACITY) { endBit = fulast; } else { if (fulast == null) endBit = _ll.FirstOrDefault(); else endBit = _ll.Find(x => x.N_COL > fulast.N_COL); } if (endBit != null) { break; } } if (endBit != null) { var carryCntrs = new List { Cont.S_CNTR_CODE }; var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, location, endBit.S_LOC_CODE, Desc + "(瓶盖)", carryCntrs, 1, endBit.N_CURRENT_NUM + 1, carryCntrs.Count, plc.taskPri); if (bb) { LocationHelper.DoAction(db => db.Deleteable().Where(x => x.S_CNTR_CODE == Cont.S_CNTR_CODE).ExecuteCommand() > 0); LogHelper.Info($"{plc.deviceName} 当前机器{location} 正在执行下空任务"); if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = 0; else FJD_wwwwFD.Add(plc.deviceName.Trim(), 0); } } else { if (areaList.Count > 0) goto goturunnnn; LogHelper.Info($"翻斗机{plc.deviceName} 没有可用的空托终点"); } } } else { LogHelper.Info("翻斗机信号不明!", "翻斗机"); } } internal static void AnalysisBottleCapTipper10(string data, Settings.deviceInfo plc) { //LogHelper.Info($"{plc.deviceName}-{plc.address}-{data}"); bool containsKey = true; int llll = 0; //if (!FJD_wwwwFD.TryGetValue(plc.deviceName.Trim(), out llll)) //{ // containsKey = false; // LogHelper.Info(plc.location[0] + "交管缓存 10 信号失败。 数量:" + llll); // llll = 6; //} //else //{ // LogHelper.Info(plc.location[0] + "交管缓存 10 信号成功。 数量:" + llll); //} if (data.Length > 1 && data.Length % 2 == 0) { var workOrder = WCSHelper.GetWorkOrder(plc.deviceName); if (workOrder == null) { LogHelper.Info(plc.deviceName + "没有【执行中】的工单", "翻斗机"); return; } var USING = workOrder.SQL_UsingNow == "Y"; int _sii = 0; if (plc.deviceNo.Length > 0) { for (int i = 0; i < plc.deviceNo.Length; i++) { string _dorNo = plc.deviceNo[i]; //LogHelper.Info($"{plc.deviceName}{_dorNo} v {(i + 1) * 2}>-{data.Length}"); if (!string.IsNullOrEmpty(_dorNo)) { if ((i + 1) * 2 > data.Length) break; bool flag4 = DeviceProcess.doorStatus.Keys.Contains(_dorNo); if (flag4) { DeviceProcess.doorStatus[_dorNo].info = data.Substring(2 * i + 1, 1); DeviceProcess.doorStatus[_dorNo].modify = DateTime.Now; } else { DeviceProcess.doorStatus.Add(_dorNo, new DeviceProcess.signalInfo { info = data.Substring(2 * i + 1, 1), modify = DateTime.Now }); } LogHelper.Info($"{plc.deviceName}{_dorNo} v {data.Substring(2 * i + 1, 1)}"); } else { if (_sii == 0) { _sii = 2 * i + 1; } //LogHelper.Info($"{plc.deviceName}翻斗信号位置 v {_sii}"); } } } //if (data.Substring(_sii, 1) == "0") //{ // LogHelper.Info(plc.location[0] + "读到10信号。(10信号持续数量):" + llll); // llll++; // if (containsKey) // FJD_wwwwFD[plc.deviceName.Trim()] = llll; // else FJD_wwwwFD.Add(plc.deviceName.Trim(), llll); // return; //} var location = plc.location[0]; var _loc = LocationHelper.GetLoc(location); if (!(_loc.S_LOCK_STATE == "无" && data.Substring(_sii, 1) == "1")) return; var time = _loc?.T_FULL_TIME; LogHelper.Info(location + ":托盘放置时间:(" + time + ") 货位托盘数量(" + _loc?.N_CURRENT_NUM + ")"); List cntrStart = null; if (time == null) { if (_loc.N_CURRENT_NUM == 1) { cntrStart = LocationHelper.GetLocCntrRel(location); time = cntrStart.FirstOrDefault()?.T_CREATE; if (time == null) { LogHelper.Info(plc.deviceName + ">>" + location + "货位托盘数量(" + _loc?.N_CURRENT_NUM + ") 但是找不到托盘数据。 终止"); return; } } } if (_loc.N_CURRENT_NUM == 0)//time == null || _loc == null || { //搬走了。 如果本来就空的还给11 那就不是我的问题了。 // 后改 TODO - 送空框任务。 /// 取货时 给个 Empty_time /// 信号不清的, 读到EmptyTime + 满信号 = 送空托。 /// 同时清掉EmtpyTimt 这样空托任务取消了,也不会循环触发。 //var EMPTYTIME = _loc?.T_EMPTY_TIME; //if (EMPTYTIME == null || _loc == null || _loc?.N_CURRENT_NUM > 0) //{ // return; //} LocationHelper.TakeEmptyToBottleBoyd(new WMSTask { S_START_LOC = location, }); return; } //托盘放下 1分钟内 下空请求,都不处理。 else if (DateTime.Now.Subtract((DateTime)time).Minutes < 1) { PlcHelper.SendHex(plc.address, "3F00110d0a"); return; } LogHelper.Info($"翻斗机:{plc.deviceName} 下线信号:{location} 查询工单{workOrder.SQL_WorkNo}"); LogHelper.Info(plc.location[0] + "读到11信号。(10信号持续数量):" + llll); var _i = -1; if (llll < _i) { LogHelper.Info(plc.deviceName + $"读到11信号,但连续10信号不足{_i}次"); return; } if (cntrStart == null) cntrStart = LocationHelper.GetLocCntrRel(location); //关联表。 - 托盘决定去哪 - 工单可能临时切换。 if (cntrStart.Count == 1) { LogHelper.Info($"查找{location}对应终点->即产?{workOrder.SQL_UsingNow.Trim()}"); Location endBit = null; var Cont = cntrStart.FirstOrDefault(); int endLayer = 1; string Desc = ""; var USING2 = false; if (Cont.S_CNTR_CODE.StartsWith("J")) { Desc = "翻斗机即产空筐下线"; USING2 = true; } else { USING2 = false; Desc = "翻斗机库存空筐下线"; } //var ba = ""; var ba2 = Settings.GetBolAreaList().Find(x => x.DeviceName == plc.deviceName && x.deviceType == plc.deviceType); if (ba2 == null) { LogHelper.Info($"{plc.deviceName}-{workOrder.SQL_WorkNo}的BolArea 未配置。"); return; } List areaList = new List { (plc.deviceType == 6 ? "WJGRGDKQ" : "SGRGDKQ"), ba2.NotUsingEmpty }; areaList = new List { ba2.NotUsingEmpty }; if (plc.deviceType == 10) { areaList = new List { ba2.NotUsingEmpty }; } goturunnnn: var area = areaList.FirstOrDefault(); if (areaList.Count > 0) areaList.Remove(area); if (USING2) { areaList.Clear(); area = ba2.UsingEmpty; LogHelper.Info($"翻斗机{plc.deviceName} 筛选即产终点库区{area}"); var _endLoclist = LocationHelper.GetAreaNormalLocList(area); foreach (var item in _endLoclist.OrderBy(x => x.N_ROW).GroupBy(x => x.N_ROW)) { var _ll = item.OrderBy(x => x.N_COL).ToList(); var fulast = _ll.FindAll(x => x.N_CURRENT_NUM > 0).LastOrDefault(); if (fulast != null && fulast.N_CURRENT_NUM < fulast.N_CAPACITY) { endBit = fulast; } else { if (fulast == null) endBit = _ll.FirstOrDefault(); else endBit = _ll.Find(x => x.N_COL > fulast.N_COL); } if (endBit != null) { break; } } LogHelper.Info($"翻斗机 筛选J终点 endbit:{JsonConvert.SerializeObject(endBit)}"); //var locs = LocationHelper.GetLocList(x => x.S_AREA_CODE == ba2.UsingEmpty && x.S_LOC_CODE != "报废").OrderBy(x => x.N_COL).ThenBy(x => x.N_ROW).ToList(); //var lastffl = locs.FindAll(x => x.N_CURRENT_NUM > 0 && x.T_FULL_TIME != null).OrderBy(x => x.T_FULL_TIME).LastOrDefault(); //var lastEmpty = locs.FindAll(x => x.N_CURRENT_NUM == 0 && x.T_EMPTY_TIME != null).OrderBy(x => x.T_EMPTY_TIME).LastOrDefault(); //if (lastffl != null) //{ // if (lastEmpty == null) lastffl = null; // else if (lastffl.N_COL <= lastEmpty.N_COL) { lastffl = null; lastEmpty = null; } // else if (lastffl == locs.LastOrDefault()) lastffl = null; //} /////最后一个满框入库位往后找。 //foreach (var item in locs.Skip((lastffl == null || lastffl == locs.LastOrDefault() ? 0 : locs.IndexOf(lastffl))).GroupBy(x => x.N_COL)) //{ // ///先放小排, 先取大排 取放按列 // var collist = item.OrderBy(x => x.N_ROW).ToList(); // if (!collist.Any()) continue; // if (collist.Find(x => x.S_LOCK_STATE != "无") != null) continue; // var collastful = collist.Find(x => x.N_CURRENT_NUM > 0); // Location nex = null; // if (collastful == null) nex = collist.FirstOrDefault(); // else nex = collist.Find(x => x.N_ROW >= collastful.N_ROW && x.N_CURRENT_NUM < x.N_CAPACITY); // if (nex != null) // { // endBit = nex; // break; // } //} } else { LogHelper.Info($"翻斗机{plc.deviceName} 筛选F即产终点库区{area}"); var _endLoclist = LocationHelper.GetAreaNormalLocList(area); foreach (var item in _endLoclist.OrderByDescending(x => x.N_CURRENT_NUM).GroupBy(x => x.N_ROW)) { var _ll = item.OrderBy(x => x.N_COL).ToList(); var fulast = _ll.FindAll(x => x.N_CURRENT_NUM > 0).LastOrDefault(); if (fulast != null && fulast.N_CURRENT_NUM < fulast.N_CAPACITY) { endBit = fulast; } else { if (fulast == null) endBit = _ll.FirstOrDefault(); else endBit = _ll.Find(x => x.N_COL > fulast.N_COL); } if (endBit != null) { break; } } LogHelper.Info($"翻斗机 筛选F终点 endbit:{JsonConvert.SerializeObject(endBit)}"); } if (endBit != null) { var carryCntrs = new List { Cont.S_CNTR_CODE }; var bb = TaskProcess.CreateTransport(workOrder.SQL_WorkNo, location, endBit.S_LOC_CODE, Desc + "(瓶盖)", carryCntrs, 1, endBit.N_CURRENT_NUM + 1, carryCntrs.Count, plc.taskPri); if (bb) { LogHelper.Info($"{plc.deviceName} 当前机器{location} 正在执行下空任务"); if (containsKey) FJD_wwwwFD[plc.deviceName.Trim()] = 0; else FJD_wwwwFD.Add(plc.deviceName.Trim(), 0); } } else { if (!USING2 && areaList.Count > 0) goto goturunnnn; LogHelper.Info($"翻斗机{plc.deviceName} 没有可用的空托终点"); } } } else { LogHelper.Info("翻斗机信号不明!", "翻斗机"); } } static List> SequentialGrouping(int n) { List> groups = new List>(); for (int i = 1; i <= n; i += 2) { if (i + 1 <= n) // 确保不越界 { groups.Add(Tuple.Create(i, i + 1)); } else { // 如果 n 是奇数,最后一个数字单独一组(可选) groups.Add(Tuple.Create(i, 0)); // -1 表示无配对 } } return groups; } } }