|
|
|
@ -56,58 +56,67 @@ namespace SlnMesnac.TouchSocket
|
|
|
|
|
|
|
|
|
|
public Action<String, bool> RefreshStateAction;
|
|
|
|
|
|
|
|
|
|
public delegate void GetVisionData(TcpVisionEntity entity);
|
|
|
|
|
public delegate void GetVisionData(TcpVisionEntity entity, string id);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 视觉系统反馈给上位机调度系统状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event GetVisionData? VisionSysStateEvent;
|
|
|
|
|
public event GetVisionData? ReceiveVisionSysStateEvent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 视觉系统回复给上位机调度系统开始工作状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event GetVisionData? VisionStartWorkEvent;
|
|
|
|
|
public event GetVisionData? ReceiveVisionStartWorkEvent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 一次码垛完成,发送码垛结果
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event GetVisionData? StackWorkDoneEvent;
|
|
|
|
|
public event GetVisionData? ReceiveStackWorkDoneEvent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 视觉系统发送给机器人码垛位置定位结果
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event GetVisionData? StackRobotLocationEvent;
|
|
|
|
|
public event GetVisionData? ReceiveStackRobotLocationEvent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 人工异常处理完成并更新计数
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event GetVisionData? ManualExceptionDealDoneEvent;
|
|
|
|
|
public event GetVisionData? ReceiveManualExceptionDealDoneEvent;
|
|
|
|
|
|
|
|
|
|
private string ClientID = "";
|
|
|
|
|
private string TestClientID = "";
|
|
|
|
|
|
|
|
|
|
public TcpServer(ILogger<TcpServer> logger,TcpService tcpService, AppConfig appConfig)
|
|
|
|
|
public TcpServer(ILogger<TcpServer> logger, TcpService tcpService, AppConfig appConfig)
|
|
|
|
|
{
|
|
|
|
|
_logger = logger;
|
|
|
|
|
_service = tcpService;
|
|
|
|
|
_appConfig = appConfig;
|
|
|
|
|
|
|
|
|
|
ReceiveStackWorkDoneEvent += StackResultSend;
|
|
|
|
|
ReceiveManualExceptionDealDoneEvent += ManualExceptionDealDone;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Init(int serverPort)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_service.Connecting = (client, e) => {
|
|
|
|
|
_service.Connecting = (client, e) =>
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"客户端{client.IP}正在接入服务");
|
|
|
|
|
return EasyTask.CompletedTask;
|
|
|
|
|
};
|
|
|
|
|
_service.Connected = (client, e) => {
|
|
|
|
|
_service.Connected = (client, e) =>
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"客户端{client.IP}接入服务成功");
|
|
|
|
|
RefreshClientInfoEvent?.Invoke(_service);
|
|
|
|
|
RefreshStateAction?.Invoke(client.IP,true);
|
|
|
|
|
ClientID = client.Id;
|
|
|
|
|
RefreshStateAction?.Invoke(client.IP, true);
|
|
|
|
|
client.ResetId(client.Port.ToString());
|
|
|
|
|
TestClientID = client.Port.ToString();
|
|
|
|
|
return EasyTask.CompletedTask;
|
|
|
|
|
};
|
|
|
|
|
_service.Disconnected = (client, e) => {
|
|
|
|
|
_service.Disconnected = (client, e) =>
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"客户端{client.IP}断开连接");
|
|
|
|
|
RefreshStateAction?.Invoke(client.IP, false);
|
|
|
|
|
RefreshClientInfoEvent?.Invoke(_service);
|
|
|
|
@ -116,18 +125,19 @@ namespace SlnMesnac.TouchSocket
|
|
|
|
|
_service.Received = (client, e) =>
|
|
|
|
|
{
|
|
|
|
|
var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意:数据长度是byteBlock.Len
|
|
|
|
|
_logger.LogInformation($"客户端{client.IP}:"+ mes);
|
|
|
|
|
_logger.LogInformation($"客户端{client.IP}:" + mes);
|
|
|
|
|
//区分一下指令类型,委托传参
|
|
|
|
|
|
|
|
|
|
if (mes == "heartbeat")
|
|
|
|
|
{
|
|
|
|
|
RefreshStateAction?.Invoke(client.IP, true);
|
|
|
|
|
}
|
|
|
|
|
//var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意:数据长度是byteBlock.Len
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
byte[] receivedBuffer = new byte[e.ByteBlock.Len];
|
|
|
|
|
Array.Copy(e.ByteBlock.Buffer, 0, receivedBuffer, 0, e.ByteBlock.Len);
|
|
|
|
|
//ReceivedClientBufferEvent?.Invoke(receivedBuffer);
|
|
|
|
|
DataClassify(BufferDataAnalysis.BufferRootAnalysis(receivedBuffer));
|
|
|
|
|
DataClassify(BufferDataAnalysis.BufferRootAnalysis(receivedBuffer), client.Id);
|
|
|
|
|
|
|
|
|
|
return EasyTask.CompletedTask;
|
|
|
|
|
};
|
|
|
|
@ -185,37 +195,243 @@ namespace SlnMesnac.TouchSocket
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 数据类型区分
|
|
|
|
|
/// 接收数据类型区分
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="entity"></param>
|
|
|
|
|
public void DataClassify(TcpVisionEntity entity)
|
|
|
|
|
public void DataClassify(TcpVisionEntity entity, string id)
|
|
|
|
|
{
|
|
|
|
|
if(entity == null)
|
|
|
|
|
if (entity == null)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("数据格式校验错误!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
switch(entity.Command)
|
|
|
|
|
{
|
|
|
|
|
case 10: VisionSysStateEvent?.Invoke(entity); break;
|
|
|
|
|
case 11: VisionStartWorkEvent?.Invoke(entity); break;
|
|
|
|
|
case 12: StackWorkDoneEvent?.Invoke(entity); break;
|
|
|
|
|
case 13: StackRobotLocationEvent?.Invoke(entity); break;
|
|
|
|
|
case 14: ManualExceptionDealDoneEvent?.Invoke(entity); break;
|
|
|
|
|
default: _logger.LogInformation("未知命令字!"); return;
|
|
|
|
|
switch (entity.Command)
|
|
|
|
|
{
|
|
|
|
|
case 0x10: ReceiveVisionSysStateEvent?.Invoke(entity, id); break;
|
|
|
|
|
case 0x11: ReceiveVisionStartWorkEvent?.Invoke(entity, id); break;
|
|
|
|
|
case 0x12: ReceiveStackWorkDoneEvent?.Invoke(entity, id); break;
|
|
|
|
|
case 0x13: ReceiveStackRobotLocationEvent?.Invoke(entity, id); break;
|
|
|
|
|
case 0x14: ReceiveManualExceptionDealDoneEvent?.Invoke(entity, id); break;
|
|
|
|
|
default: _logger.LogInformation("未知命令字!"); return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///// <summary>
|
|
|
|
|
///// 向所有客户端发送心跳
|
|
|
|
|
///// </summary>
|
|
|
|
|
//public void SendHeartBeat()
|
|
|
|
|
//{
|
|
|
|
|
// var clients = _service.SocketClients.GetClients();
|
|
|
|
|
// foreach (var item in clients)
|
|
|
|
|
// {
|
|
|
|
|
// _service.Send(item.Id,"heartbeat");
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
#region 数据发送
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上位机调度系统请求视觉系统状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="SN">SN码</param>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendRequestVisionSysState(byte[] SN, string id)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_service.SendAsync(id, BufferDataAnalysis.DataCombine(SN, 0x00, new byte[0]));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("Error:" + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// AMR就绪,请求视觉开始工作
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="SN">SN码</param>
|
|
|
|
|
/// <param name="data">数据体</param>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendAMRRequestVisionStartWork(byte[] SN, byte[] data, string id)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_service.SendAsync(id, BufferDataAnalysis.DataCombine(SN, 0x01, data));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("Error:" + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上位机调度系统回复收到码垛结果
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="SN">SN码</param>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendReplayStackResult(byte[] SN, string id)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_service.SendAsync(id, BufferDataAnalysis.DataCombine(SN, 0x02, new byte[0]));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("Error:" + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 码垛结束,请求视觉系统复位
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="SN">SN码</param>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendStackOverRequestVisionSysReplace(byte[] SN, string id)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_service.SendAsync(id, BufferDataAnalysis.DataCombine(SN, 0x03, new byte[0]));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("Error:" + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上位机调度系统回复收到人工异常处理
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="SN">SN码</param>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendReplyGetManualException(byte[] SN, string id)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_service.SendAsync(TestClientID, BufferDataAnalysis.DataCombine(SN, 0x04, new byte[0]));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("Error:" + e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上位机调度系统请求视觉系统状态(默认SN)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendRequestVisionSysState(string id)
|
|
|
|
|
{
|
|
|
|
|
SendRequestVisionSysState(new byte[2] { 0x00, 0x00 }, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// AMR就绪,请求视觉开始工作(默认SN)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">数据体</param>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendAMRRequestVisionStartWork(byte[] data, string id)
|
|
|
|
|
{
|
|
|
|
|
SendAMRRequestVisionStartWork(new byte[2] { 0x00, 0x00 }, data, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上位机调度系统回复收到码垛结果(默认SN)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendReplayStackResult(string id)
|
|
|
|
|
{
|
|
|
|
|
SendReplayStackResult(new byte[2] { 0x00, 0x00 }, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 码垛结束,请求视觉系统复位(默认SN)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendStackOverRequestVisionSysReplace(string id)
|
|
|
|
|
{
|
|
|
|
|
SendStackOverRequestVisionSysReplace(new byte[2] { 0x00, 0x00 }, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上位机调度系统回复收到人工异常处理(默认SN)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">客户端ID</param>
|
|
|
|
|
public void SendReplyGetManualException(string id)
|
|
|
|
|
{
|
|
|
|
|
SendReplyGetManualException(new byte[2] { 0x00, 0x00 }, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上位机调度系统每隔固定时间,请求视觉系统状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void VisionStateRequest(int port)
|
|
|
|
|
{
|
|
|
|
|
SendRequestVisionSysState(port.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// AMR就绪,请求视觉开始工作
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void RequestVisionStartWork(StackState state, int port)
|
|
|
|
|
{
|
|
|
|
|
SendAMRRequestVisionStartWork(new byte[1] { (byte)state }, port.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 一次码垛完成,发送码垛结果
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void StackResultSend(TcpVisionEntity entity, string id)
|
|
|
|
|
{
|
|
|
|
|
SendReplayStackResult(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 码垛结束,请求视觉系统复位
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void RequestVisionReplace(int port)
|
|
|
|
|
{
|
|
|
|
|
SendStackOverRequestVisionSysReplace(port.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 人工异常处理完成并更新计数
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void ManualExceptionDealDone(TcpVisionEntity entity, string id)
|
|
|
|
|
{
|
|
|
|
|
SendReplyGetManualException(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void InitGetVisionMessage()
|
|
|
|
|
{
|
|
|
|
|
ReceiveVisionSysStateEvent = (entity, id) =>
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation("视觉系统被动反馈给上位机调度系统状态,端口:" + id);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ReceiveVisionStartWorkEvent = (entity, id) =>
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation("视觉系统回复给上位机调度系统开始工作状态,端口:" + id);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ReceiveStackRobotLocationEvent = (entity, id) =>
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation("视觉系统回复机器人复位结果,端口:" + id);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum StackState
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 复合机器人码垛无需定位
|
|
|
|
|
/// </summary>
|
|
|
|
|
AMRNoPositioning = 0x00,
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 复合机器人码垛需要定位
|
|
|
|
|
/// </summary>
|
|
|
|
|
AMRNeedPositioning = 0x01,
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 搬运机器人码垛无需定位
|
|
|
|
|
/// </summary>
|
|
|
|
|
RGVNoPositioning = 0x10,
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 搬运机器人码垛需要定位
|
|
|
|
|
/// </summary>
|
|
|
|
|
RGVNeedPositioning = 0x11,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|