@ -1,10 +1,16 @@
using Microsoft.Extensions.Logging ;
using SlnMesnac.Model.domain ;
using SlnMesnac.Model.Enum ;
using SlnMesnac.Repository ;
using SlnMesnac.Repository.service ;
using SlnMesnac.TouchSocket ;
using SlnMesnac.TouchSocket.Entity ;
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using System.Transactions ;
namespace SlnMesnac.Business.@base
{
@ -17,14 +23,20 @@ namespace SlnMesnac.Business.@base
private static VisionBusiness instance ;
private TcpServer _tcpServer ;
private IAirportTaskService _airportTaskService ;
private IVisionSettingService _visionSettingService ;
private IAGVStateService _aGVStateService ;
private IAGVJobService _AGVJobService ;
private BaseAGVBusiness _baseAGVBusiness ;
public VisionBusiness ( ILogger < VisionBusiness > logger , TcpServer tcpServer , IAirportTaskService airportTaskService )
public VisionBusiness ( ILogger < VisionBusiness > logger , TcpServer tcpServer , IAirportTaskService airportTaskService , IVisionSettingService visionSettingService , IAGVStateService aGVStateService , IAGVJobService aGVJobService )
{
_logger = logger ;
_tcpServer = tcpServer ;
_airportTaskService = airportTaskService ;
_visionSettingService = visionSettingService ;
_aGVStateService = aGVStateService ;
_AGVJobService = aGVJobService ;
//视觉系统回复状态
_tcpServer . ReceiveVisionSysStateEvent + = VisionStateRequest ;
@ -32,17 +44,19 @@ namespace SlnMesnac.Business.@base
_tcpServer . ReceiveVisionStartWorkEvent + = GetVisionWorkState ;
//视觉系统通知一次码垛完成结果
_tcpServer . ReceiveStackWorkDoneEvent + = StackResultSend ;
//_tcpServer.ReceiveStackWorkDoneEvent += AutoStackResultSend;
//视觉系统通知人工异常处理完成
_tcpServer . ReceiveManualExceptionDealDoneEvent + = GetManualExceptionDealDone ;
//视觉系统回复复位结果
_tcpServer . ReceiveStackRobotResetEvent + = GetResetResult ;
_AGVJobService = aGVJobService ;
}
public static VisionBusiness GetInstance ( ILogger < VisionBusiness > logger , TcpServer tcpServer , IAirportTaskService airportTaskService )
public static VisionBusiness GetInstance ( ILogger < VisionBusiness > logger , TcpServer tcpServer , IAirportTaskService airportTaskService , IVisionSettingService visionSettingService , IAGVStateService aGVStateService , IAGVJobService aGVJobService )
{
if ( instance = = null )
{
instance = new VisionBusiness ( logger , tcpServer , airportTaskService );
instance = new VisionBusiness ( logger , tcpServer , airportTaskService , visionSettingService , aGVStateService , aGVJobService );
}
return instance ;
}
@ -107,6 +121,262 @@ namespace SlnMesnac.Business.@base
}
}
/// <summary>
/// 收到堆筐请求
/// </summary>
/// <param name="entity"></param>
/// <param name="id"></param>
/// <exception cref="Exception"></exception>
public void AutoStackResultSend ( TcpVisionEntity entity , string id )
{
if ( entity . DataLength = = 1 )
{
if ( entity . DataBytes [ 0 ] = = 0x00 )
{
_logger . LogInformation ( $"视觉系统一次码垛结束,码垛完成 Deliver:{VDCount} AMR:{VACount}" ) ;
//上位机回复收到码垛结果
_tcpServer . SendReplayStackResult ( id ) ;
VisionSetting record = _visionSettingService . GetList ( x = > x . VisionID = = id ) . ToList ( ) . First ( ) ;
AirportTask airportTask = _airportTaskService . GetTaskInfos ( x = > x . amragvno = = record . AMRGUID & &
x . visiontaskno = = ( BitConverter . ToInt16 ( entity . SN , 0 ) - 1 ) . ToString ( ) & & x . taskstate = = "抓取中" ) . First ( ) ;
//成功码垛先码垛计数
StackCount ( airportTask , entity . DataBytes [ 1 ] ) ;
//////////////下面是下一次码垛的综合判断条件//////////////
//先判断总数是否需要继续工作
if ( airportTask . totalcount > airportTask . loadcount )
{
//如上一次是AMR 如有Deliver 判断是否到达 到达向deliver发送开始工作, 没就判断amr是否装满 继续向amr
//上一次是AMR
if ( entity . DataBytes [ 1 ] = = 0x01 )
{
//妹有Deliver的任务( 小车号和是否已到达都没有) amr肯定能抓完 继续amr抓取
if ( string . IsNullOrEmpty ( airportTask . deliveragvno ) & & string . IsNullOrEmpty ( airportTask . deliveragvisarrive ) )
{
//一直向amr抓, 直到抓满
RequestVisionStartWork ( StackState . AMRNoPositioning , id ) ;
}
//有Delievr任务( 有任务号且状态为未到达) 继续amr抓取
else if ( ! string . IsNullOrEmpty ( airportTask . deliveragvno ) & & airportTask . deliveragvisarrive = = "未到达" )
{
//判断AMR小车是否装满, 没满就开装, 满了就结束, 开始循环判断deliver是否到达
//amr没满 继续装amr
if ( _aGVStateService . GetSingleAGVState ( airportTask . amragvno ) . stackcount < BaseTaskInfoBusiness . AMRStackNumber )
{
RequestVisionStartWork ( StackState . AMRNoPositioning , id ) ;
}
//AMR满了
else
{
AirportTask task ;
//结束抓取、循环判断deliver是否到达, 到了就向新的Deliver开始抓取
Task . Run ( ( ) = >
{
//请求复位
RequestVisionReplace ( id ) ;
while ( true )
{
//循环判断该任务的deliver是否到达
Task . Delay ( 1000 ) ;
task = _airportTaskService . GetTaskInfos ( x = > x . amragvno = = record . AMRGUID & & x . taskstate = = "抓取中" ) . First ( ) ;
if ( task . deliveragvisarrive = = "已到达" )
{
RequestVisionStartWork ( StackState . AGVNeedPositioning , id ) ;
break ;
}
}
} ) ;
}
}
//有Deliver任务( 有任务号且已到达) 向Deliver发送开始抓取
else if ( ! string . IsNullOrEmpty ( airportTask . deliveragvno ) & & airportTask . deliveragvisarrive = = "已到达" )
{
RequestVisionStartWork ( StackState . AGVNeedPositioning , id ) ;
}
//异常情况
else
{
throw new Exception ( $"任务 {airportTask.taskno} 状态异常!请清除任务并重新下发任务!" ) ;
}
}
//如上一次是deliver-->则判断deliver是否装满-->装满则deliver入库-->判断剩下的数量用不用调新的deliver-->用就调新的deliver然后发向amr抓取(还得判断AMR是否抓满)-->不用就直接向amr抓取
//上一次是Deliver
else if ( entity . DataBytes [ 1 ] = = 0x00 )
{
//判断Deliver是否装满,装满就直接入库,未装满继续装
//deliver没满, 继续装
if ( _aGVStateService . GetSingleAGVState ( airportTask . deliveragvno ) . stackcount < BaseTaskInfoBusiness . DeliverStackNumber )
{
RequestVisionStartWork ( StackState . AGVNoPositioning , id ) ;
}
//deliver满了, 入库然后判断
else
{
//入库代码
_baseAGVBusiness . EndTaskAndClearErrorAndDownloadTask ( airportTask . deliveragvno ,
_AGVJobService . GetAGVJobListByTypeAndConveyorNo ( "800入库" , airportTask . conveyorno ) . JobName ) ;
airportTask . deliveragvno = null ;
airportTask . deliveragvisarrive = null ;
_airportTaskService . UpdateTaskAsync ( airportTask ) ;
//判断剩下的数量用不用调用新的deliver
//剩下的数量不用 直接向amr抓取
int amrleft = BaseTaskInfoBusiness . AMRStackNumber - _aGVStateService . GetSingleAGVState ( airportTask . amragvno ) . stackcount ;
if ( airportTask . totalcount - airportTask . loadcount < amrleft )
{
RequestVisionStartWork ( StackState . AMRNeedPositioning , id ) ;
}
//剩下的数量需要调用, 并判断向AMR抓取
else
{
//调新的deliver
AGVState newagv = _baseAGVBusiness . GetBestAGV ( AgvType . Deliver ) ;
_baseAGVBusiness . EndTaskAndClearErrorAndDownloadTask ( newagv . agvno ,
_AGVJobService . GetAGVJobListByTypeAndConveyorNo ( "800入位" , airportTask . conveyorno ) . JobName ) ;
airportTask . deliveragvno = newagv . agvno ;
airportTask . deliveragvisarrive = "未到达" ;
_airportTaskService . UpdateTaskAsync ( airportTask ) ;
//amr无容量, 结束抓取, 等待Deliver到达
if ( amrleft = = 0 )
{
AirportTask task ;
//结束抓取、循环判断deliver是否到达, 到了就向新的Deliver开始抓取
Task . Run ( ( ) = >
{
//请求复位
RequestVisionReplace ( id ) ;
while ( true )
{
//循环判断该任务的deliver是否到达
Task . Delay ( 1000 ) ;
task = _airportTaskService . GetTaskInfos ( x = > x . amragvno = = record . AMRGUID & & x . taskstate = = "抓取中" ) . First ( ) ;
if ( task . deliveragvisarrive = = "已到达" )
{
RequestVisionStartWork ( StackState . AGVNeedPositioning , id ) ;
break ;
}
}
} ) ;
}
//amr有容量, 抓
else
{
RequestVisionStartWork ( StackState . AMRNeedPositioning , id ) ;
}
}
}
}
//未知代码
else
{
throw new Exception ( $"任务 {airportTask.taskno} 未知上次码垛代码!请检查视觉系统状态!" ) ;
}
}
//总数达标,结束任务,复位机械臂,调回小车,任务状态调整
else
{
_baseAGVBusiness . EndTaskAndClearErrorAndDownloadTask ( airportTask . amragvno ,
_AGVJobService . GetAGVJobListByTypeAndConveyorNo ( "1000入库" , airportTask . conveyorno ) . JobName ) ;
airportTask . amragvno = null ;
airportTask . amragvisarrive = null ;
airportTask . visiontaskno = null ;
if ( ! string . IsNullOrEmpty ( airportTask . deliveragvno ) )
{
_baseAGVBusiness . EndTaskAndClearErrorAndDownloadTask ( airportTask . deliveragvno ,
_AGVJobService . GetAGVJobListByTypeAndConveyorNo ( "800入库" , airportTask . conveyorno ) . JobName ) ;
airportTask . deliveragvno = null ;
airportTask . deliveragvisarrive = null ;
}
airportTask . finishtime = DateTime . Now ;
airportTask . taskstate = "已完成" ;
_airportTaskService . UpdateTaskAsync ( airportTask ) ;
}
}
//码垛过程失败
else if ( entity . DataBytes [ 0 ] = = 0x01 )
{
_logger . LogError ( $"视觉系统一次码垛结束,码垛过程失败,重新发送码垛信号" ) ;
if ( entity . DataBytes [ 1 ] = = 0x01 )
{
//发送向复合机器人( AMR) 码垛的信号
RequestVisionStartWork ( StackState . AMRNoPositioning , id ) ;
_logger . LogInformation ( "下一次码垛开始,方向:复合机器人" ) ;
}
else if ( entity . DataBytes [ 1 ] = = 0x00 )
{
//发送向搬运机器人( AGVDeliver) 码垛的信号
RequestVisionStartWork ( StackState . AGVNoPositioning , id ) ;
_logger . LogInformation ( "下一次码垛开始,方向:搬运机器人" ) ;
}
else
{
_logger . LogError ( $"码垛失败返回未知码垛结果代码,请手动重新发送码垛信号" ) ;
}
}
//码垛检查失败
else if ( entity . DataBytes [ 0 ] = = 0x02 )
{
_logger . LogError ( $"视觉系统一次码垛结束,码垛检查失败,请手动矫正并手动开始下一次码垛" ) ;
//仍然要码垛计数,只是筐码的不准
VisionSetting record = _visionSettingService . GetList ( x = > x . VisionID = = id ) . ToList ( ) . First ( ) ;
AirportTask airportTask = _airportTaskService . GetTaskInfos ( x = > x . amragvno = = record . AMRGUID & &
x . visiontaskno = = ( BitConverter . ToInt16 ( entity . SN , 0 ) - 1 ) . ToString ( ) & & x . taskstate = = "抓取中" ) . First ( ) ;
StackCount ( airportTask , entity . DataBytes [ 1 ] ) ;
}
//未知代码
else
{
_logger . LogError ( $"视觉系统一次码垛结束,未知返回代码!请检查视觉系统状态!" ) ;
throw new Exception ( $"视觉系统 {id }一次码垛结束,未知返回代码!请检查视觉系统状态!" ) ;
}
}
//数据格式错误
else
{
_logger . LogError ( $"视觉系统一次码垛结束,返回数据格式错误,请检查视觉系统状态!" ) ;
}
}
public void StackCount ( AirportTask airportTask , byte lastCount )
{
//AMR码垛计数
if ( lastCount = = 0x01 )
{
airportTask . loadcount + + ;
AGVState aGVState = _aGVStateService . GetSingleAGVState ( airportTask . amragvno ) ;
aGVState . stackcount + + ;
//判断返回结果
if ( _aGVStateService . UpdateAsync ( aGVState ) . Result | | _airportTaskService . UpdateTaskAsync ( airportTask ) . Result )
{
_logger . LogInformation ( $"计数更新成功 {airportTask.amragvno} AMR: {aGVState.stackcount} Total: {airportTask.loadcount}" ) ;
}
else
{
_logger . LogError ( "计数更新失败!" ) ;
throw new Exception ( "计数更新失败!" ) ;
}
}
//Deliver码垛计数
else if ( lastCount = = 0x00 )
{
airportTask . loadcount + + ;
AGVState aGVState = _aGVStateService . GetSingleAGVState ( airportTask . deliveragvno ) ;
aGVState . stackcount + + ;
//判断返回结果
if ( _aGVStateService . UpdateAsync ( aGVState ) . Result | | _airportTaskService . UpdateTaskAsync ( airportTask ) . Result )
{
_logger . LogInformation ( $"计数更新成功 {airportTask.amragvno} AMR: {aGVState.stackcount} Total: {airportTask.loadcount}" ) ;
}
else
{
_logger . LogError ( "计数更新失败!" ) ;
throw new Exception ( "计数更新失败!" ) ;
}
}
else
{
throw new Exception ( $"任务 {airportTask.taskno} 未知上次码垛代码!请检查视觉系统状态!" ) ;
}
}
int VDCount = 1 ;
int VACount = 0 ;
int VDTotal = 8 ;
@ -127,16 +397,7 @@ namespace SlnMesnac.Business.@base
//上位机回复收到码垛结果
_tcpServer . SendReplayStackResult ( id ) ;
//这里写是否继续下一次码垛的判断条件
//判断总数是否继续工作
if ( true )
{
}
//如有Deliver 判断是否到达 到达向deliver发送开始工作
//如上一次是deliver-->则判断deliver是否装满-->装满则deliver入库-->判断剩下的数量用不用调新的deliver-->用就调新的deliver然后发向amr抓取-->不用就直接向amr抓取
if ( ( VDCount < VDTotal & & Vjudge = = true & & TotalJudge = = true ) | | ( VACount < VATotal & & Vjudge = = false & & TotalJudge = = true ) )
{
//如果码垛没结束继续发下一次的码垛信号