1.入库移库更新

2.小料箱进接驳位信号变更
3.保存错误日志
master
zhangxy 6 months ago
parent 73bd807e31
commit 0fdc58a03e

@ -157,6 +157,53 @@ namespace SlnMesnac.Business.@base
}
}
/// <summary>
/// 连廊使用---根据RFID Key读取RFID信息并返回读取类型:type-0读取失败; type-1读取oktype-2串读
/// </summary>
/// <param name="rfidKey"></param>
/// <param name="epcStr"></param>
/// <exception cref="InvalidOperationException"></exception>
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<TagInfo> 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 "";
}
}
/// <summary>
/// 使用---根据RFID Key读取RFID信息
/// </summary>

@ -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<WmsBaseLocation>()
.InnerJoin<WmsPalletInfo>((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<WmsBaseLocation>()
.InnerJoin<WmsPalletInfo>((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}");
}
}
/// <summary>
/// agv状态实时刷新
/// </summary>
@ -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($"线体空闲了,可以锁定使用远处小车进行取料");

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>

@ -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<WcsBaseEquip>().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到达终点接驳位等待料箱离开接驳位
{

@ -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<WmsPalletInfo>().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<WmsBaseLocation> startLocations = sqlSugarClient.Ado.SqlQuery<WmsBaseLocation>(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<WmsBaseLocation> startLocations = sqlSugarClient.Ado.SqlQuery<WmsBaseLocation>(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<WmsBaseLocation>().Any(x => x.LocationCode == targetLocation.LocationCode && string.IsNullOrEmpty(x.ContainerCode));
if (!hasPallet)
{
_logger.Info($"库位:{targetLocation.LocationCode}有托盘暂不处理");
return;
}
#endregion 二次核查确认目标库位是否有托盘
WcsBaseEquip startEquip = sqlSugarClient.Queryable<WcsBaseEquip>().First(it => it.EquipNo == "3DeliverBigGoodsStartPoint");
WmsPalletInfo wmsPalletInfo = sqlSugarClient.Queryable<WmsPalletInfo>().First(it => it.PalletInfoCode == rfid);
WcsTask task = new WcsTask();
@ -948,6 +986,19 @@ namespace SlnMesnac.WCS.WCS
return null;
// todo推送预警 // 目标机台没有空库位,没有可移库的空箱,等待
}
#region 如果有补空箱任务,并且起点是要送料机台的库位,就不再生成移库任务
//目标机台的两个库位编号
List<string> locationCodes = AllWmsBaseLocationList.Where(x => x.MachineId == machineId).Select(x => x.LocationCode).ToList();
bool hasTask = sqlSugarClient.Queryable<WcsTask>().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)

@ -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<TonerBoxingViewModel> _logger;
public TonerBoxingViewModel()
{
sqlSugarClient = App.ServiceProvider.GetService<ISqlSugarClient>();
SelectWindow.RefreshMsgEvent += RefreshMessage;
_logger = App.ServiceProvider.GetService<ILogger<TonerBoxingViewModel>>()!;
}
#region 界面属性定义
@ -94,6 +97,7 @@ namespace SlnMesnac.WPF.ViewModel
string flag = wmsPalletInfo.TonerFlag == 1 ? "是" : "否";
Msg += $"库存:{wmsPalletInfo.Amount},是否携带色粉:{flag}";
}
_logger.LogInformation($"料箱{code}人工操作记录:" + Msg);
}
//[RelayCommand]

Loading…
Cancel
Save