using HH.WCS.QingXigongchang.device;
using HH.WCS.QingXigongchang.dispatch;
using HH.WCS.QingXigongchang.util;
using HH.WCS.QingXigongchang.wms;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
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;
//plg 2025年6月23日 去除10秒时间限制
if (DateTime.Now.Subtract(_clrel0.T_CREATE).TotalSeconds < 3 || !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