using Microsoft.AspNetCore.Mvc ;
using Microsoft.Extensions.DependencyInjection ;
using SlnMesnac.Business.@base ;
using SlnMesnac.Model.domain ;
using SlnMesnac.Model.dto.taskType ;
using SlnMesnac.Plc ;
using SlnMesnac.Serilog ;
using SlnMesnac.WCS.Global ;
using SlnMesnac.WCS.Library ;
using SqlSugar ;
using System.Threading.Tasks ;
namespace SlnMesnac.WCS.WCS
{
/// <summary>
/// 根据条件创建任务
/// </summary>
public class CreateTaskByRecord : BaseBusiness
{
private readonly SerilogHelper _logger ;
//3#车间上料点plc
private readonly PlcAbsractFactory workShop3Plc ;
//2#计量室相关点位
private readonly PlcAbsractFactory workShop2Plc ;
private readonly ISqlSugarClient sqlSugarClient ;
public CreateTaskByRecord ( IServiceProvider serviceProvider ) : base ( serviceProvider )
{
workShop3Plc = base . GetPlcByKey ( "workShop3Plc" ) ;
workShop2Plc = base . GetPlcByKey ( "workShop2Plc" ) ;
sqlSugarClient = serviceProvider . GetRequiredService < ISqlSugarClient > ( ) ;
_logger = serviceProvider . GetRequiredService < SerilogHelper > ( ) ;
//test();
}
/// <summary>
/// 启动扫描监听
/// </summary>
public void StartPoint ( )
{
CreateTaskByReadPlcSignal ( ) ;
//监听2#计量室旋转移栽plc信号, 处理相关流程
var CreateProductTaskByLocationCodeThread = new Thread ( ListeningWorkShop2TransplantingMachine ) ;
CreateProductTaskByLocationCodeThread . IsBackground = true ;
CreateProductTaskByLocationCodeThread . Name = "监听1#2#计量室旋转移栽plc信号处理连廊箱体旋转相关流程" ;
CreateProductTaskByLocationCodeThread . Start ( ) ;
}
/// <summary>
/// 通过读plc条件创建任务
/// todo:现在放在同一个线程,正式上线的时候,如果每一轮循环耗时太长可以分开多个线程
/// </summary>
private void CreateTaskByReadPlcSignal ( )
{
Task . Run ( ( ) = >
{
while ( true )
{
try
{
if ( workShop3Plc = = null | | ! workShop3Plc . IsConnected )
{
_logger . Plc ( DateTime . Now + "3#PLC未连接,请检查网络!" ) ;
continue ;
}
#region 3#车间补四宫格空箱流程---监听3#1号光电状态
bool signal1 = workShop3Plc . readBoolByAddress ( StaticData . GetPlcAddress ( "3#大料箱进料为空" ) ) ;
if ( signal1 )
{
CreateSupplementBigPalletTask ( ) ;
}
#endregion 3#车间补四宫格空箱流程---监听3#1号光电状态
#region 从下料点到1-16机台送料任务--或者1-12移库任务 --监听3#2号光电状态
bool getBigFlag = workShop3Plc . readBoolByAddress ( StaticData . GetPlcAddress ( "3#大料箱agv取料通知" ) ) ;
string machineCodeS = workShop3Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "3#四宫格下料点机台号" ) ) . ToString ( ) ;
string rfidS = workShop3Plc . readStringByAddress ( StaticData . GetPlcAddress ( "3#四宫格下料点RFID号" ) , 12 ) . Replace ( "\0" , "" ) ;
int amount = workShop3Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "3#四宫格下料点数量" ) ) ;
if ( getBigFlag & & machineCodeS ! = "0" & & rfidS . Contains ( "SH" ) )
{
CreatDeliverWorkShop3Task ( machineCodeS , rfidS , amount ) ;
}
#endregion 从下料点到1-16机台送料任务--或者1-12移库任务 --监听3#2号光电状态
#region 3#往2#计量室送料流程
bool getSmallFlag = workShop3Plc . readBoolByAddress ( StaticData . GetPlcAddress ( "3#小料箱agv取料通知" ) ) ;
int smallAmount = workShop3Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "3#小料箱下料点数量" ) ) ;
string machineCodeX = workShop3Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "3#小料箱下料点机台号" ) ) . ToString ( ) ;
string rfidX = workShop3Plc . readStringByAddress ( StaticData . GetPlcAddress ( "3#小料箱下料点RFID号" ) , 12 ) . Replace ( "\0" , "" ) ;
if ( getSmallFlag & & machineCodeX ! = "0" & & rfidX . Contains ( "SH" ) )
{
if ( machineCodeX = = "1" )
{
machineCodeX = "1006" ;
}
CreatDeliverWorkShop2Task ( machineCodeX , rfidX ) ;
}
#endregion 3#往2#计量室送料流程
#region 3#补充小空托盘流程--3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务
int work3EmptyAmount = workShop3Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "3#缓存皮带线库存数" ) ) ;
int busy3Flag = workShop3Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "3#线体忙碌状态" ) ) ;
if ( work3EmptyAmount < 2 & & busy3Flag = = 0 )
{
//3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务
CreateSupplySmallPalletToWorkshop3Task ( ) ;
}
#endregion 3#补充小空托盘流程--3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务
}
catch ( Exception ex )
{
_logger . Error ( $"CreateTaskByReadPlcSignal方法异常:" + ex . StackTrace ) ;
}
finally
{
Thread . Sleep ( 2000 ) ;
}
}
} ) ;
}
/// <summary>
/// 监听2#计量室旋转移栽plc信号, 处理连廊箱体旋转相关流程
/// </summary>
private void ListeningWorkShop2TransplantingMachine ( )
{
while ( true )
{
try
{
if ( workShop2Plc = = null | | ! workShop2Plc . IsConnected )
{
continue ;
}
#region 计量室料箱返回处理流程:空箱入缓存链条线,色粉派送至色粉存放点
//2#接驳位色粉派送至色粉存放点任务
if ( workShop2Plc ! = null & & workShop2Plc . IsConnected )
{
bool returnJudgeSignal = workShop2Plc . readBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运回RFID读取" ) ) ;
int busy2Flag = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) ) ;
int Amount = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "2#缓存链条线库存数" ) ) ;
//是否还有未在色粉库位的色粉箱体
bool anyTonerPallet = HasAnyTonerInLine ( ) ;
if ( returnJudgeSignal & & busy2Flag = = 0 & & ( Amount < 3 | | anyTonerPallet ) )
{
string rfid = ReadEpcStrByRfidKey ( "2#Transplant" ) ;
if ( string . IsNullOrEmpty ( rfid ) )
{ //二次读取
rfid = ReadEpcStrByRfidKey ( "2#Transplant" ) ;
}
if ( ! string . IsNullOrEmpty ( rfid ) )
{
//让其他线程
Thread . Sleep ( 4000 ) ;
busy2Flag = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) ) ;
if ( busy2Flag = = 0 )
{
// 判断有无色粉, 如果没有色粉, wcs给 旋转移栽方向信号 写2, plc将料箱运到 缓存皮带线。
WmsPalletInfo ? wmsPalletInfo = sqlSugarClient . Queryable < WmsPalletInfo > ( ) . First ( it = > it . PalletInfoCode = = rfid ) ;
if ( wmsPalletInfo ! = null & & wmsPalletInfo . Amount > 0 & & wmsPalletInfo . TonerFlag = = 1 ) //携带色粉
{
//注意: plc上旋转移栽必须锁住线体状态才可以, 2#接驳位如果有满料, 那么通知plc信号, plc在连廊不再把箱体放到旋转移栽上
//调度系统结合上面缓存链条线库存, 如果上面低于3, 那么空箱可以上来缓存线
bool createResult = CreateDeliverTonerTask ( rfid ) ;
if ( createResult )
{
//3色粉上提升机移栽等待
_logger . Info ( $"2#移栽===={rfid}携带色粉去往色粉库位" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) , 1 ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#移栽平台任务" ) , 3 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运回RFID读取" ) , false ) ;
}
else
{ //色粉库位无空闲位置,空转一圈
//2空箱转运
_logger . Info ( $"2#移栽===={rfid}携带色粉,色粉库位无空闲位置,空转一圈" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) , 1 ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#移栽平台任务" ) , 2 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运回RFID读取" ) , false ) ;
}
}
else if ( wmsPalletInfo ! = null & & wmsPalletInfo . Amount > 0 & & wmsPalletInfo . TonerFlag = = 0 ) //携带满料
{
//2空箱转运
_logger . Info ( $"2#移栽===={rfid}携带满料,空转一圈" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) , 1 ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#移栽平台任务" ) , 2 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运回RFID读取" ) , false ) ;
}
else if ( wmsPalletInfo ! = null & & wmsPalletInfo . Amount = = 0 ) //空托盘
{
if ( Amount < 3 )
{
//1上提升机去缓存线
_logger . Info ( $"2#移栽===={rfid}空箱,去缓存区" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) , 1 ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#移栽平台任务" ) , 1 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运回RFID读取" ) , false ) ;
}
else
{
//2空箱转运
_logger . Info ( $"2#移栽===={rfid}空箱,空箱转运" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) , 1 ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#移栽平台任务" ) , 2 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运回RFID读取" ) , false ) ;
}
}
}
}
else
{
//没读到2空箱转运
// _logger.Info($"1#移栽====没读到,空箱转运");
//workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1);
//workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 2);
//workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false);
}
}
}
#endregion 计量室料箱返回处理流程:空箱入缓存链条线,色粉派送至色粉存放点
#region 连廊料箱在计量室连廊移栽处理流程: wcs读RFID判断是否空箱, 空箱下plc信号旋转, 非空箱通知plc上提升机计量室
if ( workShop2Plc ! = null & & workShop2Plc . IsConnected )
{
bool returnJudgeSignal = workShop2Plc . readBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运进计量室RFID读取" ) ) ;
int busy1Flag = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "1#提升机忙碌状态" ) ) ;
if ( returnJudgeSignal & & busy1Flag = = 0 )
{
//test
string rfid = ReadEpcStrByRfidKey ( "1#MetrologyRoom" ) ;
if ( string . IsNullOrEmpty ( rfid ) )
{
rfid = ReadEpcStrByRfidKey ( "1#MetrologyRoom" ) ;
}
if ( ! string . IsNullOrEmpty ( rfid ) )
{
// 判断有无料, 如果没有料, wcs下发空箱旋转信号, 有料, 通知plc上提升机计量室
WmsPalletInfo ? wmsPalletInfo = sqlSugarClient . Queryable < WmsPalletInfo > ( ) . First ( it = > it . PalletInfoCode = = rfid ) ;
if ( wmsPalletInfo ! = null & & wmsPalletInfo . Amount > 0 & & wmsPalletInfo . TonerFlag = = 1 ) //携带色粉
{
//2空箱转运
_logger . Info ( $"1#移栽===={rfid}携带色粉,空箱转运" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "1#移栽平台任务" ) , 2 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运进计量室RFID读取" ) , false ) ;
}
if ( wmsPalletInfo ! = null & & wmsPalletInfo . Amount > 0 & & wmsPalletInfo . TonerFlag = = 0 ) //携带满料
{
//1#移栽平台任务( 1上提升机,2空箱转运)
_logger . Info ( $"1#移栽===={rfid}携带满料,去提升机计量室" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "1#移栽平台任务" ) , 1 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运进计量室RFID读取" ) , false ) ;
}
else if ( wmsPalletInfo ! = null & & wmsPalletInfo . Amount = = 0 )
{
//1#移栽平台任务( 1上提升机,2空箱转运)
_logger . Info ( $"1#移栽===={rfid}空箱,空箱转运" ) ;
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "1#移栽平台任务" ) , 2 ) ;
workShop2Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "2#料箱运进计量室RFID读取" ) , false ) ;
}
}
else
{
//没读到,当成空箱子旋转一圈
//1#移栽平台任务( 1上提升机,2空箱转运)
// _logger.Info($"1#移栽====没读到,空箱转运");
//workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("1#移栽平台任务"), 2);
//workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false);
}
}
}
#endregion 连廊料箱在计量室连廊移栽处理流程: wcs读RFID判断是否空箱, 空箱下plc信号旋转, 非空箱通知plc上提升机计量室
#region 色粉存放点空托盘派送至2#接驳位-----暂时不使用
/////如果色粉存放点可用空库位小于等于2个, 并且有空托盘在库位, 判断2#缓存链条线库存( 容量3) 低于2个, 并且无 从3#接驳位到2#接驳位的送料任务或 色粉存放点到2#缓存链条线任务,
/////2.生成色粉存放点到2#缓存链条线任务
//int canUseAmount = sqlSugarClient.Queryable<WcsBaseEquip>().Count(it => it.EquipType == 7 && it.EquipStatus == 0 && string.IsNullOrEmpty(it.ContainerCode));
////判断色粉存放处是否有空托盘
//WcsBaseEquip? startEquip = sqlSugarClient.Queryable<WcsBaseEquip>().InnerJoin<WmsPalletInfo>(
// (wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode && wpi.Amount == 0 && wbe.EquipStatus == 0)
// .Where(wbe => wbe.EquipType == 7 && !string.IsNullOrEmpty(wbe.ContainerCode)).First();
//if (canUseAmount < 2 && startEquip != null)
//{
// int cacheLineAmount = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#缓存链条线库存数"));
// bool hasTask = sqlSugarClient.Queryable<WcsTask>().Any(it => it.TaskType == StaticTaskType.EmptyReturnFromTonerTask || it.TaskType == StaticTaskType.TransferMaterialMetrologyRoomBoxTask);
// if (cacheLineAmount < 2 && !hasTask)
// {
// try
// {
// sqlSugarClient.AsTenant().BeginTran();
// WcsTask task = new WcsTask();
// task.TaskType = StaticTaskType.EmptyReturnFromTonerTask;
// task.CurrPointNo = startEquip.AgvPositionCode;
// task.EndPointNo = "2DeliverMetrologyRoomPoint";
// task.TaskStatus = 0;
// task.CreatedTime = DateTime.Now;
// task.CreatedBy = "wcs";
// task.TaskName = "色粉存放点空托盘派送至2#接驳位";
// task.PalletInfoCode = startEquip.ContainerCode;
// int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity();
// WcsTaskLog wcsTaskLog = CoreMapper.Map<WcsTaskLog>(task);
// wcsTaskLog.Id = id;
// startEquip.EquipStatus = 1;
// sqlSugarClient.Updateable(startEquip).ExecuteCommand();
// sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand();
// sqlSugarClient.AsTenant().CommitTran();
// _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}");
// }
// catch (Exception ex)
// {
// sqlSugarClient.AsTenant().RollbackTran();
// _logger.Error($"色粉存放点空托盘派送至2#接驳位任务提交事务异常{ex.Message}");
// }
// }
//}
#endregion 色粉存放点空托盘派送至2#接驳位-----暂时不使用
}
catch ( Exception ex )
{
_logger . Error ( $"ListeningWorkShop2TransplantingMachine方法异常:" + ex . StackTrace ) ;
}
finally
{
Thread . Sleep ( 1000 * 2 ) ;
}
}
}
#region 任务流程
/// <summary>
/// 3#车间补四宫格空箱流程
/// </summary>
private async void CreateSupplementBigPalletTask ( )
{
try
{
//判断agv是否有来这里的任务
bool hasTask = sqlSugarClient . Queryable < WcsTask > ( ) . Any ( it = > it . TaskType = = StaticTaskType . SupplyEmptyPalletTask & & it . EndPointNo = = "3SuppleEmptyPalletPoint" ) ;
if ( hasTask )
{
//_logger.Info("Agv已有3#车间补四宫格空箱任务");
return ;
}
#region 寻找机台空托盘
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 ] ;
}
}
//1-12机台, 优先12
if ( startLocation = = null )
{
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<=12 and wpi.amount=0" ;
List < WmsBaseLocation > emptyLocations = sqlSugarClient . Ado . SqlQuery < WmsBaseLocation > ( sql ) . OrderBy ( x = > x . MachineId ) . ToList ( ) ;
if ( emptyLocations . Count = = 0 )
{
_logger . Info ( "暂时没有可用空托盘库位" ) ;
//todo报警
return ;
}
//暂时排序,后期结合小料正在生产的计划提前调度要配送机台的空托盘,或者可以根据实际位置调度最近的空料箱
startLocation = emptyLocations . First ( ) ;
}
WcsBaseEquip ? endEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . Where ( it = > it . EquipNo = = "3SuppleEmptyPalletPoint" ) . ToList ( ) . First ( ) ;
#endregion 寻找机台空托盘
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . SupplyEmptyPalletTask ;
task . TaskName = StaticTaskType . GetDescription ( task . TaskType ) ;
task . CurrPointNo = startLocation . AgvPositionCode ;
startLocation . LocationStatus = 1 ;
sqlSugarClient . Updateable ( startLocation ) . ExecuteCommand ( ) ;
endEquip . EquipStatus = 1 ;
sqlSugarClient . Updateable ( endEquip ) . ExecuteCommand ( ) ;
// task.NextPointNo = agvEquip.AgvPositionCode;
task . EndPointNo = endEquip . AgvPositionCode ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . PalletInfoCode = startLocation . ContainerCode ;
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"生成3#车间补四宫格空箱流程异常{ex.Message}" ) ;
}
}
/// <summary>
/// 从下料点到1-16机台送料任务 创建移库任务
/// </summary>
private async void CreatDeliverWorkShop3Task ( string machineCode , string rfid , int amount )
{
try
{
bool hasMachineCode = StaticData . WmsMachineInfos . Any ( x = > x . MachineCode = = machineCode ) ;
if ( ! string . IsNullOrEmpty ( rfid ) & & hasMachineCode )
{
//判断agv是否有来这里的任务
bool hasTask = sqlSugarClient . Queryable < WcsTask > ( ) . Any ( it = > it . TaskType = = StaticTaskType . TransferMaterialBoxTask & & it . PalletInfoCode = = rfid ) ;
if ( hasTask )
{
_logger . Info ( $"该托盘{rfid}已有下料点到1-16机台送料任务" ) ;
return ;
}
//判断该托盘是否已经在库里
bool isInLocation = sqlSugarClient . Queryable < WmsBaseLocation > ( ) . Any ( it = > it . ContainerCode = = rfid ) ;
if ( isInLocation )
{
//todo推送报警
_logger . Info ( $"该托盘{rfid}已存在库位,请检查托盘号是否重复" ) ;
return ;
}
List < WmsBaseLocation > AllWmsBaseLocationList = await sqlSugarClient . Queryable < WmsBaseLocation > ( ) . Where ( x = > x . MachineId < = 12 ) . ToListAsync ( ) ;
WmsBaseLocation ? targetLocation ;
// 根据机台号寻找终点库位、判断机台的两个库位是否有空位置、没有的话先生成移库任务
targetLocation = GetTargetLocation ( machineCode , AllWmsBaseLocationList ) ;
if ( targetLocation = = null )
{
//todo:推送预警
_logger . Info ( $"机台:{machineCode}没有可用空库位,无法配送" ) ;
return ;
}
WcsBaseEquip startEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . First ( it = > it . EquipNo = = "3DeliverBigGoodsStartPoint" ) ;
WmsPalletInfo wmsPalletInfo = sqlSugarClient . Queryable < WmsPalletInfo > ( ) . First ( it = > it . PalletInfoCode = = rfid ) ;
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . TransferMaterialBoxTask ;
task . CurrPointNo = startEquip . AgvPositionCode ;
task . EndPointNo = targetLocation . AgvPositionCode ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . TaskName = "下料点到1-16机台送料任务" ;
task . PalletInfoCode = rfid ;
task . MachineCode = machineCode ;
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
try
{
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
startEquip . EquipStatus = 1 ;
sqlSugarClient . Updateable ( startEquip ) . ExecuteCommand ( ) ;
targetLocation . LocationStatus = 1 ;
sqlSugarClient . Updateable ( targetLocation ) . ExecuteCommand ( ) ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
#region 修改托盘信息
if ( wmsPalletInfo ! = null )
{
wmsPalletInfo . Amount = amount ! = 0 ? amount : 1 ;
wmsPalletInfo . UpdatedTime = DateTime . Now ;
sqlSugarClient . Updateable ( wmsPalletInfo ) . ExecuteCommand ( ) ;
}
#endregion 修改托盘信息
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
workShop3Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "3#大料箱agv取料通知" ) , false ) ;
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"生成3#车间从下料点到1-16机台送料任务提交事务异常{ex.Message}" ) ;
}
}
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"生成3#车间从下料点到1-16机台送料任务异常{ex.Message}" ) ;
}
}
/// <summary>
/// 从3#接驳位到2#计量室接驳位的送料任务
/// </summary>
private void CreatDeliverWorkShop2Task ( string machineCode , string rfid )
{
try
{
bool hasMachineCode = StaticData . WmsMachineInfos . Any ( x = > x . MachineCode = = machineCode ) ;
if ( ! string . IsNullOrEmpty ( rfid ) & & hasMachineCode )
{
//判断agv是否有来这里的任务
bool hasTask = sqlSugarClient . Queryable < WcsTask > ( ) . Any ( it = > it . TaskType = = StaticTaskType . TransferMaterialMetrologyRoomBoxTask & & it . PalletInfoCode = = rfid ) ;
if ( hasTask )
{
_logger . Info ( $"该托盘{rfid}已有3#接驳位到2#计量室接驳位的送料任务" ) ;
return ;
}
//起点库位 3#车间小料箱取送货接驳点
WcsBaseEquip startEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . First ( it = > it . EquipNo = = "3DeliverSmallGoodsPoint" ) ;
//终点库位 2#车间计量室接驳点
WcsBaseEquip endEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . First ( it = > it . EquipNo = = "2DeliverMetrologyRoomPoint" ) ;
WmsPalletInfo wmsPalletInfo = sqlSugarClient . Queryable < WmsPalletInfo > ( ) . First ( it = > it . PalletInfoCode = = rfid ) ;
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . TransferMaterialMetrologyRoomBoxTask ;
task . CurrPointNo = startEquip . AgvPositionCode ;
// task.NextPointNo = agvEquip.AgvPositionCode;
task . EndPointNo = endEquip . AgvPositionCode ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . TaskName = "3#接驳位到2#计量室接驳位的送料任务" ;
task . PalletInfoCode = rfid ;
task . MachineCode = machineCode ;
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
startEquip . EquipStatus = 1 ;
// endEquip.EquipStatus = 1; 终点无需锁,其他地方还可以用
//sqlSugarClient.Updateable(endEquip).ExecuteCommand();
sqlSugarClient . Updateable ( startEquip ) . ExecuteCommand ( ) ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
#region 修改托盘信息
if ( wmsPalletInfo ! = null )
{
wmsPalletInfo . TonerFlag = 0 ;
wmsPalletInfo . Amount = 1 ;
wmsPalletInfo . UpdatedTime = DateTime . Now ;
sqlSugarClient . Updateable ( wmsPalletInfo ) . ExecuteCommand ( ) ;
}
#endregion 修改托盘信息
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
workShop3Plc . writeBoolByAddress ( StaticData . GetPlcAddress ( "3#小料箱agv取料通知" ) , false ) ;
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
}
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"3#接驳位到2#计量室接驳位的送料任务{ex.Message}" ) ;
}
}
/// <summary>
/// 3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务
/// .wcs检测到 3#缓存皮带线库存数 (容量2)不满时,且色粉存放处有空托盘时,优先生成色粉存放处补充小料箱任务
///2.如果色粉存放处无空托盘, 且2#缓存链条线库存数 大于0个, 并且 2#线体忙碌状态 0时, 2s后 2#线体忙碌状态 0时, wcs把 2#线体忙碌状态 改为1, wcs下发缓存链条线 2#出一个空托盘信号( plc自己复位) , wcs并且生成一个3#补充空托盘任务呼叫agv
/// </summary>
private void CreateSupplySmallPalletToWorkshop3Task ( )
{
try
{
//判断是否已经有空托盘补充任务
bool hasTask = sqlSugarClient . Queryable < WcsTask > ( ) . Any ( x = > x . TaskType = = StaticTaskType . SupplySmallPalletTask | | x . TaskType = = StaticTaskType . SupplySmallPalletFromTonerTask ) ;
if ( hasTask )
{
return ;
}
//判断色粉存放处是否有空托盘
WcsBaseEquip ? emptyPalletEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . InnerJoin < WmsPalletInfo > (
( wbe , wpi ) = > wbe . ContainerCode = = wpi . PalletInfoCode & & wpi . Amount = = 0 & & wbe . EquipStatus = = 0 )
. Where ( wbe = > wbe . EquipType = = 7 & & ! string . IsNullOrEmpty ( wbe . ContainerCode ) ) . First ( ) ;
if ( emptyPalletEquip ! = null ) //从色粉存放处生成补充空托盘任务
{
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . SupplySmallPalletFromTonerTask ;
task . CurrPointNo = emptyPalletEquip . AgvPositionCode ;
task . EndPointNo = "3DeliverSmallGoodsPoint" ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . TaskName = "3#车间从色粉存放点补充小托盘任务" ;
task . PalletInfoCode = emptyPalletEquip . ContainerCode ;
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
try
{
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
//锁住起止库位
emptyPalletEquip . EquipStatus = 1 ;
sqlSugarClient . Updateable ( emptyPalletEquip ) . ExecuteCommand ( ) ;
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"3#车间从色粉存放点补充小托盘任务生成提交事务异常{ex.Message}" ) ;
}
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
return ;
}
else //从2#缓存链条线生成补充空托盘任务
{
if ( workShop2Plc = = null | | ! workShop2Plc . IsConnected )
{
_logger . Plc ( DateTime . Now + "2#PLC未连接,请检查网络!" ) ;
return ;
}
int work2EmptyAmount = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "2#缓存链条线库存数" ) ) ;
int work2BusyFlag = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) ) ;
if ( work2EmptyAmount > 0 & & work2BusyFlag = = 0 )
{
//防止抢占其他任务节奏
Thread . Sleep ( 2500 ) ;
work2BusyFlag = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) ) ;
work2EmptyAmount = workShop2Plc . readInt16ByAddress ( StaticData . GetPlcAddress ( "2#缓存链条线库存数" ) ) ;
if ( work2EmptyAmount > 0 & & work2BusyFlag = = 0 )
{
workShop2Plc . writeInt16ByAddress ( StaticData . GetPlcAddress ( "2#线体忙碌状态" ) , 1 ) ;
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . SupplySmallPalletTask ;
task . CurrPointNo = "2DeliverMetrologyRoomPoint" ;
task . EndPointNo = "3DeliverSmallGoodsPoint" ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . TaskName = " 3#车间从2#接驳位补充小托盘任务" ;
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
try
{
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
//锁住起止库位
//emptyPalletEquip.EquipStatus = 1;
//sqlSugarClient.Updateable(emptyPalletEquip).ExecuteCommand();
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"3#车间从2#接驳位补充小托盘任务生成提交事务异常{ex.Message}" ) ;
}
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
return ;
}
}
}
}
catch ( Exception ex )
{
_logger . Error ( $"CreateSupplySmallPalletToWorkshop3Task异常{ex.Message}" ) ;
}
}
/// <summary>
/// 从2#接驳位到3#接驳位补小空箱任务 :3#车间补小空箱流程
/// </summary>
private void CreateSupplementSmallPalletTask ( )
{
try
{
//判断是否有该任务
bool hasTask = sqlSugarClient . Queryable < WcsTask > ( ) . Any ( it = > it . TaskType = = StaticTaskType . SupplySmallPalletTask & & it . TaskStatus < 5 ) ;
if ( hasTask )
{
_logger . Info ( "Agv已有2#接驳位到3#接驳位补小空箱任务" ) ;
return ;
}
//寻找可用agv
//WcsBaseEquip? agvEquip = GetCanUseAgv();
//if (agvEquip == null)
//{
// _logger.Info("暂时没有可用agv");
// return;
//}
//起点库位 3#车间小料箱取送货接驳点
WcsBaseEquip startEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . First ( it = > it . EquipNo = = "2DeliverMetrologyRoomPoint" ) ;
//终点库位 2#车间计量室接驳点
WcsBaseEquip endEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . First ( it = > it . EquipNo = = "3DeliverSmallGoodsPoint" ) ;
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . SupplySmallPalletTask ;
task . CurrPointNo = startEquip . AgvPositionCode ;
// task.NextPointNo = agvEquip.AgvPositionCode;
task . EndPointNo = endEquip . AgvPositionCode ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . TaskName = "2#接驳位到3#接驳位补小空箱任务" ;
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
startEquip . EquipStatus = 1 ;
endEquip . EquipStatus = 1 ;
sqlSugarClient . Updateable ( startEquip ) . ExecuteCommand ( ) ;
sqlSugarClient . Updateable ( endEquip ) . ExecuteCommand ( ) ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"2#接驳位到3#接驳位补小空箱任务异常{ex.Message}" ) ;
}
}
/// <summary>
/// 2#色粉派送至色粉存放点任务
/// </summary>
private bool CreateDeliverTonerTask ( string rfid )
{
bool createResult = false ;
try
{
//判断是否有该任务
bool hasTask = sqlSugarClient . Queryable < WcsTask > ( ) . Any ( it = > it . TaskType = = StaticTaskType . DeliverTonerTask & & it . PalletInfoCode = = rfid ) ;
if ( hasTask )
{
_logger . Info ( $"Agv已有托盘:{rfid}2#色粉派送至色粉存放点任务" ) ;
return true ;
}
//起点库位 2#计量室车间小料箱取送货接驳点
WcsBaseEquip startEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . First ( it = > it . EquipNo = = "2DeliverMetrologyRoomPoint" ) ;
//终点库位 2#返程色粉人工拿取点
WcsBaseEquip ? endEquip = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . First ( it = > it . EquipStatus = = 0 & & it . EquipType = = 7 & & string . IsNullOrEmpty ( it . ContainerCode ) ) ;
if ( endEquip = = null )
{
//todo推送报警
_logger . Error ( "暂时没有可用色粉存放点库位" ) ;
return false ;
}
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
try
{
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . DeliverTonerTask ;
task . CurrPointNo = startEquip . AgvPositionCode ;
task . EndPointNo = endEquip . AgvPositionCode ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . TaskName = "2#色粉派送至色粉存放点任务" ;
task . PalletInfoCode = rfid ;
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
startEquip . EquipStatus = 1 ;
endEquip . EquipStatus = 1 ;
sqlSugarClient . Updateable ( startEquip ) . ExecuteCommand ( ) ;
sqlSugarClient . Updateable ( endEquip ) . ExecuteCommand ( ) ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
createResult = true ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"2#色粉派送至色粉存放点任务提交事务异常{ex.Message}" ) ;
}
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
_logger . Error ( $"生成2#色粉派送至色粉存放点并空箱送回2#接驳位任务异常{ex.Message}" ) ;
}
return createResult ;
}
#endregion 任务流程
#region 辅助方法
/// <summary>
/// 判断是否还有色粉在连廊输送线或者没在色粉库位
/// </summary>
/// <returns></returns>
private bool HasAnyTonerInLine ( )
{
try
{
// 色粉料箱
List < WmsPalletInfo > tonerPallets = sqlSugarClient . Queryable < WmsPalletInfo > ( ) . Where ( x = > x . TonerFlag = = 1 & & x . Amount > 0 ) . ToList ( ) ;
// 色粉库位的料箱码
List < WcsBaseEquip > equipPalletInfos = sqlSugarClient . Queryable < WcsBaseEquip > ( ) . Where ( x = > x . EquipType = = 7 & & ! string . IsNullOrEmpty ( x . ContainerCode ) ) . ToList ( ) ;
// 获取 tonerPallets 中的所有 PalletInfoCode
var tonerPalletCodes = tonerPallets . Select ( x = > x . PalletInfoCode ) . ToList ( ) ;
// 获取 equipPalletInfos 中的所有 ContainerCode
var equipPalletCodes = equipPalletInfos . Select ( x = > x . ContainerCode ) . ToList ( ) ;
// 检查是否有 tonerPalletCodes 不在 equipPalletCodes 中
bool result = tonerPalletCodes . Any ( code = > ! equipPalletCodes . Contains ( code ) ) ;
return result ;
}
catch ( Exception ex )
{
return false ;
}
}
///// <summary>
///// 从12号机台获取空托盘, 返回库位信息
///// </summary>
///// <param name="machineId"></param>
///// <returns></returns>
//private async Task<WmsBaseLocation?> GetEmptyContainerByMachine12Async(string rfidKey)
//{
// try
// {
// bool flag1 = await ReadSignalByRfidKeyAsync(rfidKey);
// if (flag1)
// {
// string code = await ReadEpcStrByRfidKeyAsync(rfidKey);
// if (!string.IsNullOrEmpty(code))
// {
// // 通过该料箱是否绑定有物料来判断是否为空托盘
// bool hasMaterial = await sqlSugarClient.Queryable<WmsPalletInfo>().AnyAsync(it => it.PalletInfoCode == code);
// if (!hasMaterial)
// {
// WmsBaseLocation? location = await sqlSugarClient.Queryable<WmsBaseLocation>().FirstAsync(it => it.EquipKey == rfidKey);
// return location;
// }
// }
// }
// //_logger.Error($"12号机台库位{rfidKey}无空托盘");
// return null;
// }
// catch (Exception ex)
// {
// return null;
// }
//}
/// <summary>
/// 根据机台号寻找终点库位、判断机台的两个库位是否有空位置、没有的话先生成移库任务
/// machineId为该料箱目的地机台号
/// </summary>
/// <param name="machineId"></param>
/// <returns></returns>
private WmsBaseLocation ? GetTargetLocation ( string machineCode , List < WmsBaseLocation > AllWmsBaseLocationList )
{
try
{
bool hasMoveTask = sqlSugarClient . Queryable < WcsTask > ( ) . Any ( it = > it . TaskType = = StaticTaskType . MoveLocationTask & & it . TaskStatus < 3 ) ;
if ( hasMoveTask )
{
_logger . Info ( $"目标库位无空位置,正在执行移库任务,暂时不生成送料任务,请等待...." ) ;
return null ;
}
WmsBaseLocation ? targetLocation ;
//移库起点终点
WmsBaseLocation ? moveStartLocation ;
WmsBaseLocation ? moveEndLocation ;
int machineId = StaticData . WmsMachineInfos . First ( x = > x . MachineCode = = machineCode ) . MachineId ;
if ( machineId > = 12 & & machineId < = 16 )
{
//12 - 16号机台都送往12号机台
machineId = 12 ;
}
//12号机台读RFID判断
//if (machineId >= 12)
//{
// //光电信号
// bool flag1 = await ReadSignalByRfidKeyAsync("12-1");
// bool flag2 = await ReadSignalByRfidKeyAsync("12-2");
// if (!flag1)
// { //12-1有空位
// targetLocation = AllWmsBaseLocationList.First(it => it.EquipKey == "12-1" && it.LocationStatus == 1);
// return targetLocation;
// }
// //if (!flag2) //12-2有空位
// {
// //默认全送到12-2库位, 如果有料箱, agv送过去停着,人工取走库位上的箱子
// targetLocation = AllWmsBaseLocationList.First(it => it.EquipKey == "12-2" && it.LocationStatus == 1);
// return targetLocation;
// }
// // 后期考虑优化, 12号机台暂不考虑移库, 因为库位距离其他机台比较远
//}
//else if (machineId >= 1 && machineId <= 11)
{
targetLocation = AllWmsBaseLocationList . FirstOrDefault ( it = > it . MachineId = = machineId & & it . LocationStatus = = 0 & & string . IsNullOrEmpty ( it . ContainerCode ) ) ;
if ( targetLocation ! = null ) return targetLocation ;
//目标机台两个都有料箱,判断是否有机台里面的料箱是空的,有空箱可生成移库任务,否则等待
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" ;
moveStartLocation = sqlSugarClient . SqlQueryable < WmsBaseLocation > ( sql ) . First ( ) ;
if ( moveStartLocation = = null )
{
return null ;
// todo推送预警 // 目标机台没有空库位,没有可移库的空箱,等待
}
//需要生成从该库位到其他机台的移库任务,找寻移库终点库位
moveEndLocation = AllWmsBaseLocationList . FirstOrDefault ( x = > x . LocationId ! = moveStartLocation . LocationId & & x . LocationStatus = = 0 & & string . IsNullOrEmpty ( x . ContainerCode ) ) ;
if ( moveEndLocation = = null )
{
// 没有可以移库的库位,请等待
return null ;
// todo:推送预警
}
else //生成移库任务
{
//二次确认寻找可用agv, 避免在这期间agv被其他线程占用
try
{
//WcsBaseEquip? agvEquip = GetCanUseAgv();
//if (agvEquip == null)
//{
// _logger.Info("暂时没有可用agv");
// return null;
//}
WcsTask task = new WcsTask ( ) ;
task . TaskType = StaticTaskType . MoveLocationTask ;
task . CurrPointNo = moveStartLocation . AgvPositionCode ;
task . EndPointNo = moveEndLocation . AgvPositionCode ;
task . TaskStatus = 0 ;
task . CreatedTime = DateTime . Now ;
task . CreatedBy = "wcs" ;
task . TaskName = "1-12机台之间空托盘移库任务" ;
task . PalletInfoCode = moveStartLocation . ContainerCode ;
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
try
{
int id = sqlSugarClient . Insertable ( task ) . ExecuteReturnIdentity ( ) ;
WcsTaskLog wcsTaskLog = CoreMapper . Map < WcsTaskLog > ( task ) ;
wcsTaskLog . Id = id ;
//锁定库位
moveStartLocation . LocationStatus = 1 ;
moveEndLocation . LocationStatus = 1 ;
sqlSugarClient . Updateable ( moveStartLocation ) . ExecuteCommand ( ) ;
sqlSugarClient . Updateable ( moveEndLocation ) . ExecuteCommand ( ) ;
sqlSugarClient . Insertable ( wcsTaskLog ) . ExecuteCommand ( ) ;
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
_logger . Agv ( $"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}" ) ;
}
catch ( Exception ex )
{
_logger . Error ( $"生成移库任务提交事务异常:{ex.Message}" ) ;
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
}
}
catch ( Exception ex )
{
_logger . Error ( $"生成移库任务异常:{ex.Message}" ) ;
return null ;
}
}
}
return null ;
}
catch ( Exception ex )
{
_logger . Error ( $"GetTargetLocationAsync方法异常:{ex.StackTrace}" ) ;
return null ;
}
}
#endregion 辅助方法
#region 测试方法
private async void test ( )
{
// 读RFID条码
// string code = await ReadEpcStrByRfidKeyAsync("1");
//读光电信号
//bool flag = await ReadSignalByRfidKeyAsync("1");
//bool flag1 = await ReadSignalByRfidKeyAsync("1");
//testTransitional();
//testTransitionalRollback();
}
/// <summary>
/// 测多线程事务影响程度
/// </summary>
private void testTransitional ( )
{
Task . Run ( ( ) = >
{
try
{
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
for ( int i = 0 ; i < 10 ; i + + )
{
Console . WriteLine ( $"线程1{i}" ) ;
//WmsStock stock = new WmsStock();
// stock.WorkshopId = i;
// sqlSugarClient.Insertable(stock).ExecuteCommand();
Thread . Sleep ( 1000 ) ;
}
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
}
} ) ;
Task . Run ( ( ) = >
{
try
{
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
for ( int i = 20 ; i < 30 ; i + + )
{
//Console.WriteLine($"线程2{i}");
//WmsStock stock = new WmsStock();
//stock.WorkshopId = i;
//sqlSugarClient.Insertable(stock).ExecuteCommand();
//Thread.Sleep(1000);
//if (i == 25)
//{
// Console.WriteLine($"事务回滚");
// throw new Exception("事务回滚");
//}
}
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
}
} ) ;
}
/// <summary>
/// 测事务未开启但回滚
/// </summary>
private void testTransitionalRollback ( )
{
try
{
throw new Exception ( "事务回滚" ) ;
sqlSugarClient . AsTenant ( ) . BeginTran ( ) ;
for ( int i = 0 ; i < 10 ; i + + )
{
//Console.WriteLine($"线程1{i}");
//WmsStock stock = new WmsStock();
//stock.WorkshopId = i;
//sqlSugarClient.Insertable(stock).ExecuteCommand();
//Thread.Sleep(1000);
}
sqlSugarClient . AsTenant ( ) . CommitTran ( ) ;
}
catch ( Exception ex )
{
sqlSugarClient . AsTenant ( ) . RollbackTran ( ) ;
}
}
#endregion 测试方法
}
}