using HH.WCS.Mobox3.DoubleCoin.device;
using HH.WCS.Mobox3.DoubleCoin.models;
using HH.WCS.Mobox3.DoubleCoin.util;
using HH.WCS.Mobox3.DoubleCoin.wms;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.DoubleCoin.core
{
///
/// 定时轮询任务
///
internal class Monitor
{
///
/// 满托下线入库,空托出库上线
///
internal static void CheckS7Devices()
{
if (S7Helper.ip_Plc.Count <= 0 || Settings.ProductionLines.Count <= 0)
{
LogHelper.Info($"没有配置S7设备信息,CheckDevices跳过", "PLC");
return;
}
S7Helper.RestLink();
foreach (var plcD in Settings.ProductionLines)//遍历每个产线
{
Task task = Task.Run(() =>
{
if (Settings.S7TestMoni)
{
LogHelper.Info($"配置文件中S7TestMoni为True,已跳过原材料生产线S7通讯的自动任务生成,如果生产线可以使用,S7TestMoni改为false");
return;
}
CheckDeciveModel result = new CheckDeciveModel();
var db = new SqlHelper().GetInstance();
byte[] readBytes1;
try
{
if (S7Helper.WriteBytes(plcD.ProductionLine_IP, 10, 4, new byte[] { 1 }))
{
LogHelper.Info($"产线{result.LineIP}写入DB10的偏移4为1,P2_Turn on the signal = 1,成功");
}
else
{
LogHelper.Info($"产线{result.LineIP}写入DB10的偏移4为1,P2_Turn on the signal = 1,失败");
}
Task.Delay(500); // 延迟 0.5 秒,让它称重
//通过S7协议获取下位机信号
result.LineIP = plcD.ProductionLine_IP;
readBytes1 = S7Helper.ReadBytes(plcD.ProductionLine_IP, 20, 0, 13);
if (readBytes1 == null)
{
LogHelper.Info($"读取S7_PLC信息为空" + plcD.ProductionLine_IP, "PLC");
return;
}
result.Heart = ((readBytes1[0]) << 8) + readBytes1[1];
byte[] rfid = new byte[4] { readBytes1[2], readBytes1[3], readBytes1[4], readBytes1[5] };
string rfids16 = BitConverter.ToString(rfid);
string rfids = (((readBytes1[2]) << 24) + (readBytes1[3] << 16) + (readBytes1[4] << 8) + readBytes1[5]).ToString();
LogHelper.Info($"产线容器号:{rfids},其16进制形式:{rfids16}");
result.RfidData = rfids;
result.AgvAllow = (((readBytes1[6]) << 8) + readBytes1[7]);
result.TaskProperties = readBytes1[8];
result.Ready = readBytes1[9];
result.CargoStatus = readBytes1[10];
result.StationStatus = readBytes1[11];
result.DestinationRequests = readBytes1[12];
result.BarcodeCode = S7Helper.ReadString(plcD.ProductionLine_IP, 20, 14, 10);
var readBytes2 = S7Helper.ReadBytes(plcD.ProductionLine_IP, 20, 26, 2);
result.Weight = ((readBytes2[0]) << 8) + readBytes2[1];
LogHelper.Info($"PLC解析后详细信息,{JsonConvert.SerializeObject(result)}");
}
catch (Exception ex)
{
LogHelper.Info($"读取S7_PLC信息异常:{ex.Message}" + plcD.ProductionLine_IP, "Error");
return;
}
//生成满托下线入库任务
if (result.AgvAllow == 21 && result.Ready == 1 && result.DestinationRequests == 1)
{
LogHelper.Info($"触发开始生成满托下线入库任务");
//该产线的满托下线位置,起点
var startPoint = Settings.ProductionLines.FirstOrDefault(a => a.ProductionLine_IP == result.LineIP);
if (startPoint != null)//起点存在
{
var woInfo = db.Queryable().Where(a => a.S_LINE_NO == startPoint.ProductionLine_Name && a.S_B_STATE == "开启").OrderBy(b => b.T_CREATE, OrderByType.Desc).First();
if (woInfo != null)//当前产线不存在开启的最新的工单
{
var startLoc = db.Queryable().First(a => a.S_LOCK_STATE == "无" && a.N_LOCK_STATE == 0 && a.S_CODE == startPoint.PointOut && a.C_ENABLE == "Y");
if (startLoc != null)//该产线的起点没锁住
{
var modelCI = db.Queryable().First(i => i.S_CNTR_CODE == result.RfidData && i.S_B_STATE == "0");//查询是否有这个对应的且状态正常的容器车号子表
if (modelCI != null)//容器车号子表存在
{
var cgInfo = db.Queryable().First(a => a.S_CNTR_CODE == result.RfidData);
if (cgInfo != null)//有残留的容器货品明细关系表信息
{
LogHelper.Info($"容器{result.RfidData}已绑定货品{cgInfo.S_ITEM_CODE},如果是其他库区的容器,想要使用,先解绑");
}
else
{
var locCntrRel = db.Queryable().First(a => a.S_CNTR_CODE == result.RfidData);
if (locCntrRel != null)//当前容器是否绑定了货位,绑定了就删除旧的再新增
{
LogHelper.Info($"容器{result.RfidData}已绑定货位{locCntrRel.S_LOC_CODE},如果是其他库区的容器,想要使用,先解绑");
}
else
{
var endLoc = db.Queryable().
Where(c => c.S_AREA_CODE == Settings.Areas[1] && c.S_LOCK_STATE == "无"
&& c.N_LOCK_STATE == 0 && c.N_CURRENT_NUM == 0
&& SqlFunc.Subqueryable().Where(b => b.S_LOC_CODE == c.S_CODE).NotAny()//不能有货
&& c.C_ENABLE == "Y").
OrderBy(o => o.T_MODIFY, OrderByType.Asc).First();//查询合适的终点货位,直接判断当前数量为0即可
if (endLoc != null)
{
//新增货位容器关系表
locCntrRel = new TN_Loc_Container()
{
S_LOC_CODE = startPoint.PointOut,
S_CNTR_CODE = result.RfidData,
};
TN_CG_Detail tN_CG_Detail = new TN_CG_Detail()//新增容器货品明细表
{
S_CNTR_CODE = result.RfidData,
S_ITEM_CODE = woInfo.S_ITEM_CODE,
S_BATCH_NO = woInfo.S_BATCH_CODE,
S_ITEM_SPEC = woInfo.S_ITEM_SPEC,
S_SPE = woInfo.S_ITEM_SPEC,
S_CAR_CODE = modelCI.S_CAR_CODE,
N_ITEM_STATE = 1,
S_ITEM_STATE = "待检",
F_QTY = result.Weight,//这里的重量要当成数量来使用
};
var task1 = new TN_Task()
{
S_CODE = WCSHelper.GenerateTaskNo(),
S_START_AREA = startLoc.S_AREA_CODE,
S_END_AREA = endLoc.S_AREA_CODE,
S_START_LOC = startLoc.S_CODE,
S_END_LOC = endLoc.S_CODE,
S_TYPE = "PLC满托下线入库",
N_B_STATE = 0,
S_B_STATE = "等待",
S_CNTR_CODE = result.RfidData,
S_SPEC = woInfo.S_ITEM_SPEC,
};
startLoc.N_LOCK_STATE = 2;
startLoc.S_LOCK_STATE = "出库锁";
startLoc.N_CURRENT_NUM = 1;
startLoc.T_MODIFY = System.DateTime.Now;
endLoc.N_LOCK_STATE = 1;
endLoc.S_LOCK_STATE = "入库锁";
endLoc.T_MODIFY = System.DateTime.Now;
using (var tran = db.Ado.UseTran())
{
if (db.Insertable(task1).ExecuteCommand() > 0 &&
db.Updateable(startLoc).ExecuteCommand() > 0 &&
db.Updateable(endLoc).ExecuteCommand() > 0 &&
db.Insertable(locCntrRel).ExecuteCommand() > 0 &&
db.Insertable(tN_CG_Detail).ExecuteCommand() > 0)//创建搬送任务,起点终点容器
{
tran.CommitTran();
LogHelper.Info($"生成满托下线入库任务成功,容器:{modelCI.S_CNTR_CODE},起点:{startPoint.PointOut},终点:{endLoc.S_CODE}");
Task task98 = Task.Run(() =>
{
var target = new TN_EquipProDetail()
{
S_ID = tN_CG_Detail.S_ID,
TASKTYPE = "PLC满托下线入库",
RFID = result.RfidData,
SPEC = woInfo.S_ITEM_SPEC,
CARCODE = modelCI.S_CAR_CODE,
WEIGHT = result.Weight,
ITEMSTATE = "待检",
ITEMCODE = woInfo.S_ITEM_CODE,
LOGINNAME = woInfo.S_LINE_NO,
SHIFT = "None",
STARTLOC = startLoc.S_CODE,
};
SpecHelper.InsertEquipProDetail(target);
});
Task task27 = Task.Run(() =>
{
var target = new TN_InventoryM()
{
S_ID = tN_CG_Detail.S_ID,
RFID = result.RfidData,
SPEC = woInfo.S_ITEM_SPEC,
WEIGHT = result.Weight,
ITEMSTATE = "待检",
ITEMCODE = woInfo.S_ITEM_CODE,
LOGINNAME = woInfo.S_LINE_NO,
SHIFT = "None",
};
SpecHelper.InsertInventoryM(target);
});
}
else
{
tran.RollbackTran();
LogHelper.Info($"生成满托下线入库任务失败,容器:{modelCI.S_CNTR_CODE},起点:{startPoint.PointOut},终点:{endLoc.S_CODE}");
}
}
}
else
{
LogHelper.Info($"未找到合适的终点,容器:{modelCI.S_CNTR_CODE},需要满足:有未锁定的,当前数量为0的,属于{Settings.Areas[1]}的货位");
}
}
}
}
else
{
LogHelper.Info($"未找到对应的容器车号子表信息,容器{result.RfidData}");
}
}
else
{
LogHelper.Info($"此起点位置:{startPoint.PointOut}已锁住");
}
}
else
{
LogHelper.Info($"当前产线{startPoint.ProductionLine_Name}位置{startPoint.PointOut}没有开启的工单");
}
}
else
{
LogHelper.Info($"未在配置文件里找到该产线{result.LineIP}起点PointOut");
}
}
else
{
LogHelper.Info($"生成满托下线入库任务失败,不满足result.AgvAllow == 21 && result.Ready == 1 && result.DestinationRequests == 1");
}
if (result.AgvAllow == 11 && result.Ready == 1)
{
LogHelper.Info($"触发开始生成空托出库上线任务");
var endPoint = Settings.ProductionLines.FirstOrDefault(a => a.ProductionLine_IP == result.LineIP);
if (endPoint == null)
{
LogHelper.Info($"未找到配置信息,产线IP:{result.LineIP}");
return;
}
var endLoc = db.Queryable().//空托上线的终点不校验是否有货
First(a => a.S_CODE == endPoint.PointIn && a.S_LOCK_STATE == "无" && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y");
if (endLoc == null)
{
LogHelper.Info($"此位置:{endPoint.PointIn}已锁住或未启用");
return;
}
if (endLoc.N_CURRENT_NUM > 0)
{
LocationHelper.ErrorLocCntReset(new ErrorLocCntResetInfo() { locID = endPoint.PointIn, reqCode = 1 });
LogHelper.Info($"终点货位{endPoint.PointIn}容器数量不为0,已重置该货位");
}
var startLoc = db.Queryable().
Where(o => o.S_AREA_CODE == Settings.Areas[4] && o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无" && o.C_ENABLE == "Y" && o.N_CURRENT_NUM > 0).
OrderBy(o => o.N_CURRENT_NUM, OrderByType.Desc).
First();
if (startLoc == null)
{
LogHelper.Info($"未在{Settings.Areas[4]}找到合适的起点,需要满足:货位当前数量大于0,货位未锁定");
return;
}
var cntrList = db.Queryable().Where(a => a.S_LOC_CODE == startLoc.S_CODE).ToList();
if (cntrList.Count == 0)
{
LogHelper.Info($"起点货位{startLoc.S_CODE}未找到货位容器关系表信息");
return;
}
string cntrString = "";
for (int i = 0; i < cntrList.Count; i++)
{
if (i == cntrList.Count - 1)//最后一个字符串连接不加逗号
{
cntrString += cntrList[i].S_CNTR_CODE;
}
else
{
cntrString += cntrList[i].S_CNTR_CODE + ",";
}
}
if (WCSHelper.CreateTask(startLoc.S_CODE, endPoint.PointIn, "空托出库入线", 3, cntrString))//创建搬送任务,起点终点容器
{
LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
LogHelper.Info($"生成空托出库上线任务成功,容器:{cntrString},起点:{startLoc.S_CODE}");
}
else
{
LogHelper.Info($"生成空托出库上线任务失败,容器:{cntrString},起点:{startLoc.S_CODE}");
}
}
else
{
LogHelper.Info($"生成空托出库上线任务失败,不满足result.AgvAllow == 11 && result.Ready == 1");
}
});
task.Wait(1000);
}
}
///
/// 在复检区检测物品合格,合格的物品自动回库
///
internal static void CGOkCheck()
{
var db = new SqlHelper().GetInstance();
try
{
var startLoc = db.Queryable()
.LeftJoin((o, i) => o.S_CODE == i.S_LOC_CODE)
.LeftJoin((o, i, s) => i.S_CNTR_CODE == s.S_CNTR_CODE)
.Where((o, i, s) => s.N_ITEM_STATE == 0 && s.S_ITEM_STATE == "合格"
&& o.S_AREA_CODE == Settings.Areas[7] && o.N_CURRENT_NUM > 0
&& o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无").First();
if (startLoc== null)
{
LogHelper.Info("复检区没有合格的物品,无需自动返回");
return;
}
var endLoc = db.Queryable().First(a => a.S_AREA_CODE == Settings.Areas[1]
&& a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无"
&& SqlFunc.Subqueryable().Where(b => b.S_LOC_CODE == a.S_CODE).NotAny()//不能有货
);
if (endLoc == null)
{
LogHelper.Info("终点库区已满或者已全部锁住");
return;
}
var cginfo = db.Queryable()
.LeftJoin((o, i) => o.S_CNTR_CODE == i.S_CNTR_CODE)
.Where((o, i) => i.S_LOC_CODE == startLoc.S_CODE).First();
if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "复检合格自动回库", 3, cginfo.S_CNTR_CODE, out string taskNo, cginfo.S_SPE))//创建搬送任务,起点终点容器
{
LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
LogHelper.Info($"生成复检合格自动回库任务成功,容器号{cginfo.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
Task task99 = Task.Run(() =>
{
WMSHelper.InsertOpInfo("自动轮询", "复检合格自动回库", cginfo.S_CNTR_CODE);
});
Task task27 = Task.Run(() =>
{
var target = new TN_InventoryM()
{
S_ID = cginfo.S_ID,
RFID = cginfo.S_CNTR_CODE,
SPEC = cginfo.S_SPE,
WEIGHT = cginfo.F_QTY,
ITEMSTATE = cginfo.S_ITEM_STATE,
ITEMCODE = cginfo.S_ITEM_CODE,
LOGINNAME = "自动轮询",
SHIFT = "无",
};
SpecHelper.InsertInventoryM(target);
});
return ;
}
else
{
LogHelper.Info($"生成复检合格自动回库任务失败,容器号{cginfo.S_CNTR_CODE},起点{startLoc.S_CODE},终点{endLoc.S_CODE}");
return;
}
}
catch(Exception ex)
{
LogHelper.Error("CGOkCheck发生了异常", ex);
}
}
///
/// 满托过期出库 过期合格回库,过期次品回炉
///
internal static void FullOutTime()
{
try
{
var db = new SqlHelper().GetInstance();
//满托过期出库
var startLoc_1 = db.Queryable()
.LeftJoin((o, i) => o.S_CODE == i.S_LOC_CODE)
.LeftJoin((o, i, s) => i.S_CNTR_CODE == s.S_CNTR_CODE)
.Where((o, i, s) => s.N_ITEM_STATE == 3 && s.S_ITEM_STATE == "过期"
&& o.S_AREA_CODE == Settings.Areas[1] && o.N_CURRENT_NUM > 0
&& o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无").First();
if (startLoc_1 != null)
{
var endLoc_1 = db.Queryable()
.Where(o => o.S_AREA_CODE == Settings.Areas[12]
&& SqlFunc.Subqueryable().Where(b => b.S_LOC_CODE == o.S_CODE).NotAny()//不能有货
&& o.N_CURRENT_NUM == 0 && o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无").First();
if (endLoc_1 != null)
{
var cntCode = db.Queryable().First(a => a.S_LOC_CODE == startLoc_1.S_CODE);
var outTimeCg = db.Queryable().First(a => a.S_CNTR_CODE == cntCode.S_CNTR_CODE);
if (WCSHelper.CreateTask(startLoc_1.S_CODE, endLoc_1.S_CODE, "满托过期出库", 3, outTimeCg.S_CNTR_CODE, outTimeCg.S_SPE))
{
LocationHelper.LockLoc(startLoc_1.S_CODE, 2);//起点出库锁,
LocationHelper.LockLoc(endLoc_1.S_CODE, 1);//终点入库锁
LogHelper.Info($"生成满托过期出库任务成功,容器号{outTimeCg.S_CNTR_CODE},起点{startLoc_1.S_CODE},终点{endLoc_1.S_CODE}");
Task task27 = Task.Run(() =>
{
SpecHelper.DeleteInventoryM(outTimeCg.S_ID);
});
}
}
}
//过期合格回库
var startLoc_2 = db.Queryable()
.LeftJoin((o, i) => o.S_CODE == i.S_LOC_CODE)
.LeftJoin((o, i, s) => i.S_CNTR_CODE == s.S_CNTR_CODE)
.Where((o, i, s) => s.N_ITEM_STATE == 0 && s.S_ITEM_STATE == "合格"
&& o.S_AREA_CODE == Settings.Areas[12] && o.N_CURRENT_NUM > 0
&& o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无").First();
if (startLoc_2 != null)
{
var endLoc_2 = db.Queryable()
.Where(o => o.S_AREA_CODE == Settings.Areas[2]
&& SqlFunc.Subqueryable().Where(b => b.S_LOC_CODE == o.S_CODE).NotAny()//不能有货
&& o.N_CURRENT_NUM == 0 && o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无").First();
if (endLoc_2 != null)
{
var cntCode = db.Queryable().First(a => a.S_LOC_CODE == startLoc_2.S_CODE);
var outTimeCg = db.Queryable().First(a => a.S_CNTR_CODE == cntCode.S_CNTR_CODE);
if (WCSHelper.CreateTask(startLoc_2.S_CODE, endLoc_2.S_CODE, "过期合格回库", 3, outTimeCg.S_CNTR_CODE, outTimeCg.S_SPE))
{
LocationHelper.LockLoc(startLoc_2.S_CODE, 2);//起点出库锁,
LocationHelper.LockLoc(endLoc_2.S_CODE, 1);//终点入库锁
Task task27 = Task.Run(() =>
{
var target = new TN_InventoryM()
{
S_ID = outTimeCg.S_ID,
RFID = outTimeCg.S_CNTR_CODE,
SPEC = outTimeCg.S_SPE,
WEIGHT = outTimeCg.F_QTY,
ITEMSTATE = outTimeCg.S_ITEM_STATE,
ITEMCODE = outTimeCg.S_ITEM_CODE,
LOGINNAME = "过期合格回库轮询",
SHIFT = "None",
};
SpecHelper.InsertInventoryM(target);
});
LogHelper.Info($"生成过期合格回库任务成功,容器号{outTimeCg.S_CNTR_CODE},起点{startLoc_2.S_CODE},终点{endLoc_2.S_CODE}");
}
}
}
//过期次品回炉
var startLoc_3 = db.Queryable()
.LeftJoin((o, i) => o.S_CODE == i.S_LOC_CODE)
.LeftJoin((o, i, s) => i.S_CNTR_CODE == s.S_CNTR_CODE)
.Where((o, i, s) => s.N_ITEM_STATE == 2 && s.S_ITEM_STATE == "不合格"
&& o.S_AREA_CODE == Settings.Areas[12] && o.N_CURRENT_NUM > 0
&& o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无").First();
if (startLoc_3 != null)
{
var endLoc_3 = db.Queryable()
.Where(o => o.S_AREA_CODE == Settings.Areas[11]
&& SqlFunc.Subqueryable().Where(b => b.S_LOC_CODE == o.S_CODE).NotAny()//不能有货
&& o.N_CURRENT_NUM == 0 && o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无").First();
if (endLoc_3 != null)
{
var cntCode = db.Queryable().First(a => a.S_LOC_CODE == startLoc_3.S_CODE);
var outTimeCg = db.Queryable().First(a => a.S_CNTR_CODE == cntCode.S_CNTR_CODE);
if (WCSHelper.CreateTask(startLoc_3.S_CODE, endLoc_3.S_CODE, "过期次品回炉", 3, outTimeCg.S_CNTR_CODE,out string taskno, outTimeCg.S_SPE))
{
LocationHelper.LockLoc(startLoc_3.S_CODE, 2);//起点出库锁,
LocationHelper.LockLoc(endLoc_3.S_CODE, 1);//终点入库锁
Task task2 = Task.Run(() =>
{
var target = new TN_RemeltDetail()
{
TASKNO = taskno,
CNTCODE = outTimeCg.S_CNTR_CODE,
STARTLOC = startLoc_3.S_CODE,
LOGINNAME = "过期次品回炉轮询",
ITEMCODE = outTimeCg.S_ITEM_CODE,
SPEC = outTimeCg.S_SPE,
CARCODE = outTimeCg.S_CAR_CODE,
WEIGHT = outTimeCg.F_QTY,
REMELTTIME = DateTime.Now,
SHIFT = "None",
};
SpecHelper.InsertRemeltDetail(target);
});
LogHelper.Info($"生成过期次品回炉任务成功,容器号{outTimeCg.S_CNTR_CODE},起点{startLoc_3.S_CODE},终点{endLoc_3.S_CODE}");
}
}
}
}
catch (Exception ex)
{
LogHelper.Error($"发生了异常,满托过期出库 过期合格回库,过期次品回炉 异常,{ex.Message}", ex);
}
}
///
/// 同步TN_EquipProDetail等等
///
internal static void SynchronizationEquipPro()
{
try
{
var db = new SqlHelper().GetInstance();
// 同步 TN_EquipProDetail 与 TN_CG_Detail
var targetEPD = db.Queryable().LeftJoin((o, i) => o.S_ID == i.S_ID).
Where((o, i) => o.ITEMSTATE != i.S_ITEM_STATE && i.S_ITEM_STATE != "待检" && i.N_ITEM_STATE != 1).First();
if (targetEPD != null)//同步货品状态
{
targetEPD.ITEMSTATE = db.Queryable().First(a => a.S_ID == targetEPD.S_ID).S_ITEM_STATE;
db.Updateable(targetEPD).UpdateColumns(it => new { it.ITEMSTATE }).ExecuteCommand();
}
targetEPD = db.Queryable().LeftJoin((o, i) => o.S_ID == i.S_ID).
Where((o, i) => System.DateTime.Now >= o.EXPIRATION && i.S_ITEM_STATE == "待检" && i.N_ITEM_STATE == 1).First();
if (targetEPD != null)//检测出过期的货品
{
targetEPD.ITEMSTATE = "过期";
db.Updateable(targetEPD).UpdateColumns(it => new { it.ITEMSTATE }).ExecuteCommand();
var cginfo = db.Queryable().First(a => a.S_ID == targetEPD.S_ID);
if (cginfo != null)
{
cginfo.S_ITEM_STATE = "过期";
cginfo.N_ITEM_STATE = 3;
db.Updateable(cginfo).UpdateColumns(it => new { it.S_ITEM_STATE, it.N_ITEM_STATE }).ExecuteCommand();
}
}
// 同步 TN_InventoryM 与 TN_CG_Detail
var targetInM = db.Queryable().LeftJoin((o, i) => o.S_ID == i.S_ID).
Where((o, i) => o.ITEMSTATE != i.S_ITEM_STATE && i.S_ITEM_STATE != "待检" && i.N_ITEM_STATE != 1).First();
if (targetInM != null)//同步货品状态
{
targetInM.ITEMSTATE = db.Queryable().First(a => a.S_ID == targetInM.S_ID).S_ITEM_STATE;
db.Updateable(targetInM).UpdateColumns(it => new { it.ITEMSTATE }).ExecuteCommand();
}
targetInM = db.Queryable().LeftJoin((o, i) => o.S_ID == i.S_ID).
Where((o, i) => System.DateTime.Now >= o.EXPIRATION
&& ((i.S_ITEM_STATE == "待检" && i.N_ITEM_STATE == 1)
|| (i.S_ITEM_STATE == "合格" && i.N_ITEM_STATE == 0))
).First();
if (targetInM != null)//检测出已过期的货品
{
targetInM.ITEMSTATE = "过期";
targetInM.EXPIRATION_DAY = "0";
db.Updateable(targetInM).UpdateColumns(it => new { it.ITEMSTATE }).ExecuteCommand();
var cginfo = db.Queryable().First(a => a.S_ID == targetInM.S_ID);
if (cginfo != null)
{
cginfo.S_ITEM_STATE = "过期";
cginfo.N_ITEM_STATE = 3;
db.Updateable(cginfo).UpdateColumns(it => new { it.S_ITEM_STATE, it.N_ITEM_STATE }).ExecuteCommand();
}
}
var targetInMList = db.Queryable().LeftJoin((o, i) => o.S_ID == i.S_ID).
Where((o, i) => System.DateTime.Now < o.EXPIRATION
&& ((i.S_ITEM_STATE == "待检" && i.N_ITEM_STATE == 1)
|| (i.S_ITEM_STATE == "合格" && i.N_ITEM_STATE == 0))
).ToList();
if (targetInMList.Count > 0)//检测出快过期的货品
{
foreach (var item in targetInMList)
{
item.EXPIRATION_DAY = SpecHelper.CalculateDaysDifference(System.DateTime.Now, item.EXPIRATION).ToString();
}
db.Updateable(targetInMList).UpdateColumns(it => new { it.EXPIRATION_DAY }).ExecuteCommand();
}
targetInM = db.Queryable().First(a => Convert.ToInt32(a.EXPIRATION_DAY) > 0 && a.ITEMSTATE == "过期");
if (targetInM != null)//已过期的货品,剩余天数改为0
{
targetInM.EXPIRATION_DAY = "0";
db.Updateable(targetInM).UpdateColumns(it => new { it.EXPIRATION_DAY }).ExecuteCommand();
}
// 同步 TN_DayProDetail
var curDay = System.DateTime.Now.Date;
var targetEPDs = db.Queryable().Where(a => a.DOWNLINETIME >= curDay && a.DOWNLINETIME <= curDay.AddDays(1)).ToList();
var specList = targetEPDs.Select(a => a.SPEC).Distinct().ToList();//当天的货品有哪些规格
if (specList.Count>0)
{
foreach (var item in specList)
{
var targetDay = db.Queryable().First(a => a.DAYTIME == curDay && a.SPEC == item);
if (targetDay == null)
{
targetDay = new TN_DayProDetail()
{
DAYTIME = curDay,
SPEC = item,
};
db.Insertable(targetDay).ExecuteCommand();
}
else
{
var sumWeight = targetEPDs.Where(b=>b.SPEC == item).Sum(a => a.WEIGHT);
if (targetDay.WEIGHT != sumWeight)
{
targetDay.WEIGHT = sumWeight;
db.Updateable(targetDay).ExecuteCommand();
}
else
{
LogHelper.Info("重量相等,同步TN_DayProDetail跳过");
}
}
}
}
else
{
LogHelper.Info("当天的货品规格列表为0,同步TN_DayProDetail跳过");
}
// 同步 TN_WeekProSpcDetail
var curWeek = System.DateTime.Now.Date.AddDays(-(int)System.DateTime.Now.DayOfWeek + 1);
targetEPDs = db.Queryable().Where(a => a.DOWNLINETIME >= curWeek && a.DOWNLINETIME <= curWeek.AddDays(7)).ToList();
specList = targetEPDs.Select(a => a.SPEC).Distinct().ToList();//当周的货品有哪些规格
if (specList.Count > 0)
{
foreach (var item in specList)
{
var targetWeek = db.Queryable().First(a => a.DAYTIME == curWeek && a.SPEC == item);
if (targetWeek == null)
{
targetWeek = new TN_WeekProDetail()
{
DAYTIME = curWeek,
SPEC = item,
};
db.Insertable(targetWeek).ExecuteCommand();
}
else
{
var sumWeight = targetEPDs.Where(b => b.SPEC == item).Sum(a => a.WEIGHT);
if (targetWeek.WEIGHT != sumWeight)
{
targetWeek.WEIGHT = sumWeight;
db.Updateable(targetWeek).ExecuteCommand();
}
else
{
LogHelper.Info("重量相等,同步TN_WeekProSpcDetail跳过");
}
}
}
}
else
{
LogHelper.Info("当周的货品规格列表为0,同步TN_WeekProSpcDetail跳过");
}
// 同步 TN_MonthProSpcDetail
var curMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).Date;
targetEPDs = db.Queryable().Where(a => a.DOWNLINETIME >= curMonth && a.DOWNLINETIME <= curMonth.AddMonths(1)).ToList();
specList = targetEPDs.Select(a => a.SPEC).Distinct().ToList();//当月的货品有哪些规格
if (specList.Count > 0)
{
foreach (var item in specList)
{
var targetMonth = db.Queryable().First(a => a.DAYTIME == curMonth && a.SPEC == item);
if (targetMonth == null)
{
targetMonth = new TN_MonthProDetail()
{
DAYTIME = curMonth,
SPEC = item,
};
db.Insertable(targetMonth).ExecuteCommand();
}
else
{
var sumWeight = targetEPDs.Where(b => b.SPEC == item).Sum(a => a.WEIGHT);
if (targetMonth.WEIGHT != sumWeight)
{
targetMonth.WEIGHT = sumWeight;
db.Updateable(targetMonth).ExecuteCommand();
}
else
{
LogHelper.Info("重量相等,同步TN_MonthProSpcDetail跳过");
}
}
}
}
else
{
LogHelper.Info("当月的货品规格列表为0,同步TN_MonthProSpcDetail跳过");
}
// 同步 TN_YearProSpcDetail
var curYear = new DateTime(DateTime.Now.Year, 1, 1).Date;
targetEPDs = db.Queryable().Where(a => a.DOWNLINETIME >= curYear && a.DOWNLINETIME <= curYear.AddYears(1)).ToList();
specList = targetEPDs.Select(a => a.SPEC).Distinct().ToList();//当年的货品有哪些规格
if (specList.Count > 0)
{
foreach (var item in specList)
{
var targetYear = db.Queryable().First(a => a.DAYTIME == curYear && a.SPEC == item);
if (targetYear == null)
{
targetYear = new TN_YearProDetail()
{
DAYTIME = curYear,
SPEC = item,
};
db.Insertable(targetYear).ExecuteCommand();
}
else
{
var sumWeight = targetEPDs.Where(b => b.SPEC == item).Sum(a => a.WEIGHT);
if (targetYear.WEIGHT != sumWeight)
{
targetYear.WEIGHT = sumWeight;
db.Updateable(targetYear).ExecuteCommand();
}
else
{
LogHelper.Info("重量相等,同步TN_YearProSpcDetail跳过");
}
}
}
}
else
{
LogHelper.Info("当年的货品规格列表为0,同步TN_YearProSpcDetail跳过");
}
}
catch (Exception ex)
{
// 获取最内层异常(通常是实际引发问题的异常)
Exception innerEx = ex;
while (innerEx.InnerException != null)
{
innerEx = innerEx.InnerException;
}
// 获取堆栈帧信息
var stackTrace = new System.Diagnostics.StackTrace(innerEx, true);
var stackFrame = stackTrace.GetFrame(0); // 获取最顶层的堆栈帧
// 获取文件名和行号
string fileName = stackFrame.GetFileName();
int lineNumber = stackFrame.GetFileLineNumber();
LogHelper.Error($"发生了异常,同步TN_EquipProDetail异常,文件:{fileName}, 行号:{lineNumber}, 错误:{ex.Message}\r\n{ex.StackTrace}", ex);
}
}
///
/// 同步 TN_Container 均要实时显示
///
internal static void CheckCntAndBoard()
{
try
{
var db = new SqlHelper().GetInstance();
//同步TN_Container
var fullLocList = db.Queryable().Where(a => a.N_CURRENT_NUM > 0).ToList();
if (fullLocList.Count > 0)
{
var fullLocCntList = db.Queryable().Where(a => fullLocList.Select(b => b.S_CODE).ToList().Contains(a.S_LOC_CODE)).ToList();
var fullLocCntListStr = fullLocCntList.Select(b => b.S_CNTR_CODE).ToList();
var fullCntList = db.Queryable().Where(a => fullLocCntListStr.Contains(a.S_CODE)).ToList();
var fullCntListStr = fullCntList.Select(b => b.S_CODE).ToList();
var except = fullLocCntListStr.Except(fullCntListStr).ToList();
if (except.Count > 0)
{
var addCntList = new List();
foreach (var item in except)
{
addCntList.Add(new TN_Container()
{
S_CODE = item,
N_DETAIL_COUNT = 1
});
}
db.Insertable(addCntList).ExecuteCommand();
}
}
var emptyCntList = db.Queryable().Where(a => a.S_CODE != string.Empty && a.S_CODE != null).ToList();
if (emptyCntList.Count > 0)
{
var emptyCntListStr = emptyCntList.Select(b => b.S_CODE).ToList();
var emptyLocCntList = db.Queryable().Where(a => emptyCntListStr.Contains(a.S_CNTR_CODE)).ToList();
var emptyLocCntListStr = emptyLocCntList.Select(a => a.S_CNTR_CODE).ToList();
var deleteCntList = emptyCntListStr.Except(emptyLocCntListStr).ToList();
if (deleteCntList.Count > 0)
{
db.Deleteable(emptyCntList).ExecuteCommand();
}
}
}
catch (Exception ex)
{
LogHelper.Error($"发生了异常,同步 TN_Container 异常,{ex.Message}", ex);
}
}
///
/// 检测满托缓存库区不合格的物品,满托出库复检
///
internal static void CheckNoOkCg()
{
var db = new SqlHelper().GetInstance();
try
{
var startLoc = db.Queryable().
LeftJoin((o, i) => o.S_CODE == i.S_LOC_CODE).
LeftJoin((o, i, s) => i.S_CNTR_CODE == s.S_CNTR_CODE).
Where((o, i, s) => o.N_CURRENT_NUM == 1 && o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == "无" && o.S_AREA_CODE == Settings.Areas[1]
&& s.N_ITEM_STATE == 2 && s.S_ITEM_STATE == "不合格").First();
if (startLoc == null)
{
LogHelper.Info($"未找到合适的起点货位,要求o.N_CURRENT_NUM == 1 && o.N_LOCK_STATE == 0 && o.S_LOCK_STATE == 无 && o.S_AREA_CODE == Settings.Areas[1] && s.N_ITEM_STATE ==2 && s.S_ITEM_STATE==不合格");
return;
}
var endLoc = db.Queryable()
.Where(a => a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无"
&& SqlFunc.Subqueryable().Where(b => b.S_LOC_CODE == a.S_CODE).NotAny()//不能有货
&& a.S_AREA_CODE == Settings.Areas[7]).First();
if (endLoc == null)
{
LogHelper.Info($"未找到合适的终点货位,要求a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == 无 && a.S_AREA_CODE == Settings.Areas[7]");
return;
}
var cntId = db.Queryable().First(a => a.S_LOC_CODE == startLoc.S_CODE);
if (cntId == null)
{
LogHelper.Info($"未找到对应的容器,要求 a.S_LOC_CODE == startLoc.S_CODE");
return;
}
var cgInfo = db.Queryable().First(a => a.S_CNTR_CODE == cntId.S_CNTR_CODE);
if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "满托出库复检", 3, cntId.S_CNTR_CODE, cgInfo.S_SPE))//创建搬送任务,起点终点容器
{
LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
LogHelper.Info($"生成满托出库复检任务成功,容器:{cntId.S_CNTR_CODE},起点:{startLoc.S_CODE},终点:{endLoc.S_CODE}");
Task task27 = Task.Run(() =>
{
SpecHelper.DeleteInventoryM(cgInfo.S_ID);
});
}
else
{
LogHelper.Info($"生成满托出库复检任务失败,容器:{cntId.S_CNTR_CODE},起点:{startLoc.S_CODE},终点:{endLoc.S_CODE}");
}
}
catch (Exception ex)
{
LogHelper.Error($"发生了异常,生成满托出库复检任务失败,{ex.Message}", ex);
}
}
///
/// 空托堆叠入库
///
internal static void CheckEmptyCnt()
{
var db = new SqlHelper().GetInstance();
try
{
var startLoc = db.Queryable().
Where(a => a.S_AREA_CODE == Settings.Areas[3] && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == a.N_CAPACITY).
OrderBy(a => a.T_MODIFY, OrderByType.Desc).
First();
if (startLoc == null)
{
LogHelper.Info($"空托堆叠区{Settings.Areas[3]}暂无堆满的空托");
return;
}
var endLoc = db.Queryable().
Where(a => a.S_AREA_CODE == Settings.Areas[4] && a.N_LOCK_STATE == 0
&& a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0
&& SqlFunc.Subqueryable().Where(b => b.S_LOC_CODE == a.S_CODE).NotAny()
).
OrderBy(a => a.N_CURRENT_NUM, OrderByType.Asc).
First();
if (endLoc == null)
{
LogHelper.Info($"未找到合适的终点货位,需满足{Settings.Areas[4]}里有未锁定且当前数量等于0的货位");
return;
}
var cntrList = db.Queryable().Where(a => a.S_LOC_CODE == startLoc.S_CODE).OrderBy(a => a.T_CREATE, OrderByType.Asc).ToList();
if (cntrList.Count < 1)
{
LogHelper.Info($"起点{startLoc.S_CODE}未找到货位容器关系信息");
return;
}
string cntrString = "";
for (int i = 0; i < cntrList.Count; i++)
{
if (i == cntrList.Count - 1)//最后一个字符串连接不加逗号
{
cntrString += cntrList[i].S_CNTR_CODE;
}
else
{
cntrString += cntrList[i].S_CNTR_CODE + ",";
}
}
if (WCSHelper.CreateTask(startLoc.S_CODE, endLoc.S_CODE, "空托堆叠入库", 3, cntrString))//创建搬送任务,起点终点容器
{
LocationHelper.LockLoc(startLoc.S_CODE, 2);//起点出库锁,
LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
LogHelper.Info($"生成空托堆叠入库任务成功,容器:{cntrString},起点:{startLoc.S_CODE}");
}
else
{
LogHelper.Info($"生成空托堆叠入库任务失败,容器:{cntrString},起点:{startLoc.S_CODE}");
}
}
catch (Exception ex)
{
LogHelper.Info($"空托堆叠入库异常:{ex.Message}");
}
}
}
///
/// 与S7设备交互时的model
///
public class CheckDeciveModel
{
///
/// 心跳
///
public int Heart { set; get; }
///
/// RFID,是容器是托盘
///
public string RfidData { set; get; }
///
/// 允许上下料 0=无任务,11=上料,21=下料,(请求AGV工作)
///
public int AgvAllow { set; get; }
///
/// 任务属性 1 OK,2称重失败,3条码失败,4 RFID读取失败
///
public int TaskProperties { set; get; }
///
/// 准备就绪 0=未准备好,1=准备好
///
public int Ready { set; get; }
///
/// 载货状态 0=输送线无产品,1=输送线有产品
///
public int CargoStatus { set; get; }
///
/// 工位状态 0待机中,1入库方向运行中,2出库方向运行中,3设备故障
///
public int StationStatus { set; get; }
///
/// 去向请求 0待机中,1到位请求
///
public int DestinationRequests { set; get; }
///
/// 扫码信息 扫码枪反馈信息
///
public string BarcodeCode { set; get; }
///
/// 重量
///
public float Weight { set; get; }
///
/// 产线地址
///
public string LineIP { set; get; }
}
}