diff --git a/SlnMesnac.Business/base/BaseBusiness.cs b/SlnMesnac.Business/base/BaseBusiness.cs
index 16a648e..b9f4f3e 100644
--- a/SlnMesnac.Business/base/BaseBusiness.cs
+++ b/SlnMesnac.Business/base/BaseBusiness.cs
@@ -157,6 +157,53 @@ namespace SlnMesnac.Business.@base
}
}
+ ///
+ /// 连廊使用---根据RFID Key读取RFID信息,并返回读取类型:type-0读取失败; type-1读取ok;type-2串读
+ ///
+ ///
+ ///
+ ///
+ public string ReadEpcStrByRfidKeyAndReturnType(string rfidKey, out int type)
+ {
+ try
+ {
+ type = 0;
+ string epcStr = string.Empty;
+ var rfidEquip = GetRfidByKey(rfidKey);
+ if (rfidEquip == null || rfidEquip.GetOnlineStatus() == false)
+ {
+ return "";
+ }
+
+ List tagInfoList = rfidEquip.GetRFID();
+ if (tagInfoList == null || tagInfoList.Count == 0) return "";
+ //读取到不同RFID的个数
+ int codeDistinctCount = tagInfoList.Select(x => x.EPCstring).Distinct().Count();
+ if (codeDistinctCount == 0)
+ {
+ type = 0;
+ }
+ else if (codeDistinctCount == 1)
+ {
+ type = 1;
+ }
+ else if (codeDistinctCount > 1)
+ {
+ //串读
+ type = 2;
+ }
+ epcStr = tagInfoList.OrderByDescending(x => x.Count).First().EPCstring;
+ epcStr = epcStr.Replace(" ", "").Replace("\r\n", "").Replace("\0", "").Replace("\n", "");
+ return epcStr;
+ }
+ catch (Exception ex)
+ {
+ // throw new InvalidOperationException($"根据RFID Key读取RFID信息异常:{ex.Message}");
+ type = 0;
+ return "";
+ }
+ }
+
///
/// 使用---根据RFID Key读取RFID信息
///
diff --git a/SlnMesnac.WCS/MainCentralControl.cs b/SlnMesnac.WCS/MainCentralControl.cs
index f7d3a8f..f718e23 100644
--- a/SlnMesnac.WCS/MainCentralControl.cs
+++ b/SlnMesnac.WCS/MainCentralControl.cs
@@ -176,6 +176,9 @@ namespace SlnMesnac.WCS
//色粉库位有未取走色粉声光报警
ListeningTonerLocation();
+
+ //大托盘库位有未取走色粉声光报警
+ ListeningBigPlateLocation();
}
catch (Exception ex)
{
@@ -243,6 +246,46 @@ namespace SlnMesnac.WCS
}
}
+ private void ListeningBigPlateLocation()
+ {
+ try
+ {
+ PlcAbsractFactory? workShop3Plc = plcList.FirstOrDefault(x => x.ConfigKey == "workShop3Plc");
+ bool hasRecords = SqlSugarClient.Ado.Context.CopyNew().Queryable()
+ .InnerJoin((wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode
+ && !string.IsNullOrEmpty(wbe.ContainerCode)
+ && wpi.Amount > 0 && wbe.MachineId > 0 && wbe.MachineId < 12).Any();
+ bool hasRecords12 = SqlSugarClient.Ado.Context.CopyNew().Queryable()
+ .InnerJoin((wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode
+ && !string.IsNullOrEmpty(wbe.ContainerCode)
+ && wpi.Amount > 0 && wbe.MachineId == 12).Any();
+ if (workShop3Plc != null && workShop3Plc.IsConnected)
+ {
+ if (hasRecords)
+ {
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#机台校验失败提示"), true);
+ }
+ else
+ {
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#机台校验失败提示"), false);
+ }
+
+ if (hasRecords12)
+ {
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#12号机台未校验提示"), true);
+ }
+ else
+ {
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#12号机台未校验提示"), false);
+ }
+ }
+ }
+ catch(Exception ex)
+ {
+ _logger.Error($"监听大托盘库位异常:{ex.Message}");
+ }
+ }
+
///
/// agv状态实时刷新
///
@@ -317,8 +360,9 @@ namespace SlnMesnac.WCS
else
{
_logger.Agv($"当前没有空闲小车离取料点最近,等线体空闲后进行取料");
- var flag = bearAgv.workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态"));
- if (flag == 0)
+ bearAgv.workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"),true);
+ bool flag = bearAgv.workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"));
+ if (flag == true)
{
//线体空闲了,可以锁定进行取料
_logger.Agv($"线体空闲了,可以锁定使用远处小车进行取料");
diff --git a/SlnMesnac.WCS/SlnMesnac.WCS.csproj b/SlnMesnac.WCS/SlnMesnac.WCS.csproj
index 6fd8526..e6c365a 100644
--- a/SlnMesnac.WCS/SlnMesnac.WCS.csproj
+++ b/SlnMesnac.WCS/SlnMesnac.WCS.csproj
@@ -1,4 +1,4 @@
-
+
Exe
diff --git a/SlnMesnac.WCS/WCS/BearAgv.cs b/SlnMesnac.WCS/WCS/BearAgv.cs
index 2707ff6..fdeef4f 100644
--- a/SlnMesnac.WCS/WCS/BearAgv.cs
+++ b/SlnMesnac.WCS/WCS/BearAgv.cs
@@ -244,17 +244,18 @@ namespace SlnMesnac.WCS.WCS
_logger.Agv($"读到RFID:{readEpc}");
//todo:12号机台装上RFID以后删除--------------------------------
- if (endLocation.MachineId == 12)
+ /*if (endLocation.MachineId == 12)
{
readEpc = task.PalletInfoCode;
- }
+ }*/
//----------------------------------
if (string.IsNullOrEmpty(readEpc) || readEpc != task.PalletInfoCode)
{
- // workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#机台校验失败提示"), true);
+ //workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#机台校验失败提示"), true);
_logger.Error("入库校验RFID失败,当前库位RFID:" + readEpc + ",任务RFID:" + task.PalletInfoCode);
return;
}
+ //workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#机台校验失败提示"), false);
endLocation.LocationStatus = 0;
endLocation.ContainerCode = task.PalletInfoCode;
sqlSugarClient.AsTenant().BeginTran();
@@ -666,7 +667,32 @@ namespace SlnMesnac.WCS.WCS
_logger.Plc(DateTime.Now + "2#PLC未连接,请检查网络!");
return;
}
- int busyFlag = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态"));
+
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"),true);
+ bool busyFlag = workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"));
+
+ if (busyFlag == false) {
+ return;
+ }
+ if(busyFlag == true)
+ {
+ Thread.Sleep(3000);
+ busyFlag = workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"));
+ if (busyFlag == true)
+ {
+ bool result = await ContinueTaskHandle(task);
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"), false);
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"), false);
+ if (!result)
+ {
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"), false);
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"), false);
+ }
+ }
+ }
+
+
+ /*int busyFlag = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态"));
if (busyFlag == 1)
{
return;
@@ -685,7 +711,7 @@ namespace SlnMesnac.WCS.WCS
workShop3Plc.writeInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态"), 0);
}
}
- }
+ }*/
}
else if (task.TaskStatus == 8) //agv到达终点接驳位,等待料箱离开接驳位
{
@@ -705,7 +731,7 @@ namespace SlnMesnac.WCS.WCS
bool result = await ContinueTaskHandle(task);
if (result)
{
- //从下料点直接取,清空RFID及机台号,条码等信息--ok
+ //从下料点直接取,清空RFID及机台号,条码等信息,复位请求信号--ok
workShop3Plc.writeInt16ByAddress(StaticData.GetPlcAddress("3#接驳位到位信号"), 0);
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#出接驳位信号"), false);
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#小料箱agv已取走反馈"), true);
@@ -778,7 +804,44 @@ namespace SlnMesnac.WCS.WCS
_logger.Plc(DateTime.Now + "2#PLC未连接,请检查网络!");
return;
}
- int busyFlag = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态"));
+
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"), true);
+ bool busyFlag = workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"));
+
+ if (busyFlag == false)
+ {
+ return;
+ }
+ if (busyFlag == true)
+ {
+ Thread.Sleep(1000);
+ busyFlag = workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"));
+ if (busyFlag == true)
+ {
+ bool result = await ContinueTaskHandle(task);
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"), false);
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"), false);
+
+ if (result)
+ {
+ //解锁起始色粉库位
+ WcsBaseEquip? baseEquip = sqlSugarClient.Queryable().First(t => t.AgvPositionCode == task.CurrPointNo);
+ if (baseEquip != null)
+ {
+ baseEquip.EquipStatus = 0;
+ baseEquip.ContainerCode = null;
+ sqlSugarClient.Updateable(baseEquip).ExecuteCommand();
+ }
+ }
+ else //下发任务继续失败
+ {
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"), false);
+ workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"), false);
+ }
+ }
+ }
+
+ /*int busyFlag = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态"));
if (busyFlag == 1)
{
return;
@@ -808,7 +871,7 @@ namespace SlnMesnac.WCS.WCS
workShop3Plc.writeInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态"), 0);
}
}
- }
+ }*/
}
else if (task.TaskStatus == 6) //agv到达终点接驳位,等待料箱离开接驳位
{
diff --git a/SlnMesnac.WCS/WCS/CreateTaskByRecord.cs b/SlnMesnac.WCS/WCS/CreateTaskByRecord.cs
index c8753ed..2877488 100644
--- a/SlnMesnac.WCS/WCS/CreateTaskByRecord.cs
+++ b/SlnMesnac.WCS/WCS/CreateTaskByRecord.cs
@@ -160,12 +160,13 @@ namespace SlnMesnac.WCS.WCS
bool anyTonerPallet = HasAnyTonerInLine();
if (returnJudgeSignal && busy2Flag == 0 && (Amount < 3 || anyTonerPallet))
{
- string rfid = ReadEpcStrByRfidKey("2#Transplant");
- if (string.IsNullOrEmpty(rfid))
+ int type = 0;
+ string rfid = ReadEpcStrByRfidKeyAndReturnType("2#Transplant", out type);
+ if (type == 0 || type == 2)
{//二次读取
- rfid = ReadEpcStrByRfidKey("2#Transplant");
+ rfid = ReadEpcStrByRfidKeyAndReturnType("2#Transplant", out type);
}
- if (!string.IsNullOrEmpty(rfid))
+ if (type == 1) //读到1个标签
{
int hoistFloor = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#提升机当前层"));
if (Amount < 3 && hoistFloor == 1) //如果提升机正好在1楼
@@ -186,7 +187,9 @@ namespace SlnMesnac.WCS.WCS
{
//注意:plc上旋转移栽必须锁住线体状态才可以,2#接驳位如果有满料,那么通知plc信号,plc在连廊不再把箱体放到旋转移栽上
//调度系统结合上面缓存链条线库存,如果上面低于3,那么空箱可以上来缓存线
+ workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#缓存空箱线体状态"), 1);
workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1);
+ workShop2Plc.writeInt16ByAddress("DB100.DBW40", 1);
bool createResult = CreateDeliverTonerTask(rfid);
if (createResult)
{
@@ -232,14 +235,25 @@ namespace SlnMesnac.WCS.WCS
}
}
}
- else
+ else if (type == 0) //读到0个标签
{
+ //RFID 未读到报警(2#移栽平台处)
+ workShop2Plc.writeBoolByAddress("DB100.DBX42.1", true);
+ _logger.Error("RFID 未读取报警(2#移栽平台处)");
+ workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false);
//没读到2空箱转运
// _logger.Info($"1#移栽====没读到,空箱转运");
//workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1);
//workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 2);
//workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false);
}
+ else if (type == 2) //串读
+ {
+ //RFID 串读报警(2#移栽平台处)
+ workShop2Plc.writeBoolByAddress("DB100.DBX42.0", true);
+ _logger.Error("RFID 串读报警(2#移栽平台处)");
+ workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false);
+ }
}
}
@@ -254,13 +268,13 @@ namespace SlnMesnac.WCS.WCS
if (returnJudgeSignal && busy1Flag == 0)
{
//test
-
- string rfid = ReadEpcStrByRfidKey("1#MetrologyRoom");
+ int type = 0;
+ string rfid = ReadEpcStrByRfidKeyAndReturnType("1#MetrologyRoom", out type);
if (string.IsNullOrEmpty(rfid))
{
- rfid = ReadEpcStrByRfidKey("1#MetrologyRoom");
+ rfid = ReadEpcStrByRfidKeyAndReturnType("1#MetrologyRoom", out type);
}
- if (!string.IsNullOrEmpty(rfid))
+ if (type == 1)
{
// 判断有无料, 如果没有料,wcs下发空箱旋转信号,有料,通知plc上提升机计量室
WmsPalletInfo? wmsPalletInfo = sqlSugarClient.Queryable().First(it => it.PalletInfoCode == rfid);
@@ -286,14 +300,26 @@ namespace SlnMesnac.WCS.WCS
workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false);
}
}
- else
+ else if (type == 0)
{
+ //RFID 未读到报警(1#移栽平台处)
+ workShop2Plc.writeBoolByAddress("DB100.DBX42.3", true);
+ _logger.Error("RFID 未读取报警(1#移栽平台处)");
+ workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false);
+
//没读到,当成空箱子旋转一圈
//1#移栽平台任务(1上提升机,2空箱转运)
// _logger.Info($"1#移栽====没读到,空箱转运");
//workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("1#移栽平台任务"), 2);
//workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false);
}
+ else if (type == 2)//串读
+ {
+ //RFID 串读报警(1#移栽平台处)
+ workShop2Plc.writeBoolByAddress("DB100.DBX42.2", true);
+ _logger.Error("RFID 串读报警(1#移栽平台处)");
+ workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false);
+ }
}
}
@@ -377,24 +403,24 @@ namespace SlnMesnac.WCS.WCS
WmsBaseLocation? startLocation = null;
//todo:优化点:为避免送料时尽可能少的移库任务,因此在这里可以先读取下一个料包要去的机台号,提前调度这里的空箱
- string nextGoMachineCode = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#实时机台号")).ToString();
- bool hasAny = StaticData.WmsMachineInfos.Any(x => x.MachineCode == nextGoMachineCode && x.WorkshopId == 3);
- if (hasAny)
- {
- int machineId = StaticData.WmsMachineInfos.First(x => x.MachineCode == nextGoMachineCode).MachineId;
- if (machineId >= 12 && machineId <= 16)
- {
- //12 - 16号机台都送往12号机台
- machineId = 12;
- }
- //判断该机台有无空料箱,优先补充
- string sql = $"SELECT wbl.* FROM wms_base_location wbl join wms_pallet_info wpi on wbl.container_code = wpi.pallet_info_code where wbl.container_code is not null and wbl.container_code!='' and wbl.location_status=0 and wbl.machineid ={machineId} and wpi.amount=0";
- List startLocations = sqlSugarClient.Ado.SqlQuery(sql).OrderByDescending(x => x.MachineId).ToList();
- if (startLocations.Count > 0)
- {
- startLocation = startLocations[0];
- }
- }
+ //string nextGoMachineCode = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#实时机台号")).ToString();
+ //bool hasAny = StaticData.WmsMachineInfos.Any(x => x.MachineCode == nextGoMachineCode && x.WorkshopId == 3);
+ //if (hasAny)
+ //{
+ // int machineId = StaticData.WmsMachineInfos.First(x => x.MachineCode == nextGoMachineCode).MachineId;
+ // if (machineId >= 12 && machineId <= 16)
+ // {
+ // //12 - 16号机台都送往12号机台
+ // machineId = 12;
+ // }
+ // //判断该机台有无空料箱,优先补充
+ // string sql = $"SELECT wbl.* FROM wms_base_location wbl join wms_pallet_info wpi on wbl.container_code = wpi.pallet_info_code where wbl.container_code is not null and wbl.container_code!='' and wbl.location_status=0 and wbl.machineid ={machineId} and wpi.amount=0";
+ // List startLocations = sqlSugarClient.Ado.SqlQuery(sql).OrderByDescending(x => x.MachineId).ToList();
+ // if (startLocations.Count > 0)
+ // {
+ // startLocation = startLocations[0];
+ // }
+ //}
//1-12机台,优先12
if (startLocation == null)
{
@@ -480,6 +506,18 @@ namespace SlnMesnac.WCS.WCS
_logger.Info($"机台:{machineCode}没有可用空库位,无法配送");
return;
}
+
+ #region 二次核查确认目标库位是否有托盘
+
+ bool hasPallet = sqlSugarClient.Queryable().Any(x => x.LocationCode == targetLocation.LocationCode && string.IsNullOrEmpty(x.ContainerCode));
+ if (!hasPallet)
+ {
+ _logger.Info($"库位:{targetLocation.LocationCode}有托盘暂不处理");
+ return;
+ }
+
+ #endregion 二次核查确认目标库位是否有托盘
+
WcsBaseEquip startEquip = sqlSugarClient.Queryable().First(it => it.EquipNo == "3DeliverBigGoodsStartPoint");
WmsPalletInfo wmsPalletInfo = sqlSugarClient.Queryable().First(it => it.PalletInfoCode == rfid);
WcsTask task = new WcsTask();
@@ -948,6 +986,19 @@ namespace SlnMesnac.WCS.WCS
return null;
// todo推送预警 // 目标机台没有空库位,没有可移库的空箱,等待
}
+
+ #region 如果有补空箱任务,并且起点是要送料机台的库位,就不再生成移库任务
+
+ //目标机台的两个库位编号
+ List locationCodes = AllWmsBaseLocationList.Where(x => x.MachineId == machineId).Select(x => x.LocationCode).ToList();
+ bool hasTask = sqlSugarClient.Queryable().Any(x => x.TaskType == StaticTaskType.SupplyEmptyPalletTask && locationCodes.Contains(x.CurrPointNo));
+ if (hasTask)
+ {
+ return null;
+ }
+
+ #endregion 如果有补空箱任务,并且起点是要送料机台的库位,就不再生成移库任务
+
//需要生成从该库位到其他机台的移库任务,找寻移库终点库位
moveEndLocation = AllWmsBaseLocationList.FirstOrDefault(x => x.LocationId != moveStartLocation.LocationId && x.LocationStatus == 0 && string.IsNullOrEmpty(x.ContainerCode));
if (moveEndLocation == null)
diff --git a/SlnMesnac.WPF/ViewModel/TonerBoxingViewModel.cs b/SlnMesnac.WPF/ViewModel/TonerBoxingViewModel.cs
index 4ea6eea..f3f2e16 100644
--- a/SlnMesnac.WPF/ViewModel/TonerBoxingViewModel.cs
+++ b/SlnMesnac.WPF/ViewModel/TonerBoxingViewModel.cs
@@ -2,6 +2,7 @@
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
using SlnMesnac.Model.domain;
using SlnMesnac.WPF.Page;
using SqlSugar;
@@ -17,11 +18,13 @@ namespace SlnMesnac.WPF.ViewModel
public partial class TonerBoxingViewModel : ViewModelBase
{
private ISqlSugarClient? sqlSugarClient;
+ private readonly ILogger _logger;
public TonerBoxingViewModel()
{
sqlSugarClient = App.ServiceProvider.GetService();
SelectWindow.RefreshMsgEvent += RefreshMessage;
+ _logger = App.ServiceProvider.GetService>()!;
}
#region 界面属性定义
@@ -94,6 +97,7 @@ namespace SlnMesnac.WPF.ViewModel
string flag = wmsPalletInfo.TonerFlag == 1 ? "是" : "否";
Msg += $"库存:{wmsPalletInfo.Amount},是否携带色粉:{flag}";
}
+ _logger.LogInformation($"料箱{code}人工操作记录:" + Msg);
}
//[RelayCommand]