You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

413 lines
14 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Core;
using SlnMesnac.Config;
using SlnMesnac.Repository;
using SlnMesnac.TouchSocket.Entity;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* 版权所有 (c) 2024 WenJY 保留所有权利。
* CLR版本4.0.30319.42000
* 机器名称LAPTOP-E0N2L34V
* 命名空间SlnMesnac.TouchSocket
* 唯一标识496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
*
* 创建者WenJY
* 电子邮箱wenjy@mesnac.com
* 创建时间2024-03-27 21:58:35
* 版本V1.0.0
* 描述:
*
*--------------------------------------------------------------------
* 修改人:
* 时间:
* 修改说明:
*
* 版本V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
namespace SlnMesnac.TouchSocket
{
public class TcpServer
{
private ILogger<TcpServer> _logger;
private readonly TcpService _service;
private readonly AppConfig _appConfig;
/// <summary>
/// 接收客户端指令委托
/// </summary>
public delegate void ReceivedClientBuffer(byte[] buffer);
public event ReceivedClientBuffer? ReceivedClientBufferEvent;
public delegate void RefreshClientInfo(TcpService tcpService);
public event RefreshClientInfo? RefreshClientInfoEvent;
public delegate void GetVisionData(TcpVisionEntity entity, string id);
/// <summary>
/// 视觉系统反馈给上位机调度系统状态
/// </summary>
public event GetVisionData? ReceiveVisionSysStateEvent;
/// <summary>
/// 视觉系统回复给上位机调度系统开始工作状态
/// </summary>
public event GetVisionData? ReceiveVisionStartWorkEvent;
/// <summary>
/// 一次码垛完成,发送码垛结果
/// </summary>
public event GetVisionData? ReceiveStackWorkDoneEvent;
/// <summary>
/// 视觉系统发送给机器人码垛位置复位结果
/// </summary>
public event GetVisionData? ReceiveStackRobotResetEvent;
/// <summary>
/// 人工异常处理完成并更新计数
/// </summary>
public event GetVisionData? ReceiveManualExceptionDealDoneEvent;
/// <summary>
/// 连接状态
/// </summary>
public int GetState
{
get
{
if(_service.ServerState == ServerState.Running)
{
if(_service.Count > 0)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 2;
}
}
}
private string TestClientID = "";
public string VID;
public TcpServer(ILogger<TcpServer> logger, TcpService tcpService, AppConfig appConfig)
{
_logger = logger;
_service = tcpService;
_appConfig = appConfig;
}
public void Init(int serverPort)
{
try
{
_service.Connecting = (client, e) =>
{
_logger.LogInformation($"客户端{client.IP}:{client.Port}正在接入服务");
return EasyTask.CompletedTask;
};
_service.Connected = (client, e) =>
{
_logger.LogInformation($"客户端{client.IP}:{client.Port}接入服务成功");
RefreshClientInfoEvent?.Invoke(_service);
client.ResetId(client.IP);
TestClientID = client.IP;
VID = client.IP;
return EasyTask.CompletedTask;
};
_service.Disconnected = (client, e) =>
{
_logger.LogInformation($"客户端{client.IP}:{client.Port}断开连接");
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
};
_service.Received = (client, e) =>
{
//var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意数据长度是byteBlock.Len
//_logger.LogInformation($"客户端{client.IP}:{client.Port} " + mes);
//区分一下指令类型,委托传参
//if (mes == "heartbeat")
//{
// RefreshStateAction?.Invoke(client.IP, true);
//}
byte[] receivedBuffer = new byte[e.ByteBlock.Len];
Array.Copy(e.ByteBlock.Buffer, 0, receivedBuffer, 0, e.ByteBlock.Len);
var mes = ByteArrayToHexString(receivedBuffer);
_logger.LogInformation($"客户端{client.IP}:{client.Port} " + mes);
DataClassify(BufferDataAnalysis.BufferRootAnalysis(receivedBuffer), client.Id);
return EasyTask.CompletedTask;
};
_service.Setup(new TouchSocketConfig()//载入配置
.SetListenIPHosts(new IPHost[] { new IPHost(serverPort) })
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
//自定义插件
}));
_service.Start();
_logger.LogInformation($"TcpServer启动成功监听端口{serverPort}");
}
catch (Exception ex)
{
//throw new InvalidOperationException($"TcpServer启动异常{ex.Message}");
_logger.LogError($"TcpServer启动异常{ex.Message}");
}
}
/// <summary>
/// byte数组转字符串
/// </summary>
/// <param name="byteArray"></param>
/// <returns></returns>
private string ByteArrayToHexString(byte[] byteArray)
{
if (byteArray == null || byteArray.Length == 0)
{
return string.Empty;
}
return string.Join(" ", byteArray.Select(b => b.ToString("X2")));
}
//private void Test()
//{
// try
// {
// Task.Run(() =>
// {
// // 设置计时器
// Stopwatch stopwatch = new Stopwatch();
// stopwatch.Start();
// ISocketClient client = _service.SocketClients.GetClients().FirstOrDefault(x => x.IP == "127.0.0.1");
// if (client != null)
// {
// Thread.Sleep(4000);
// _service.Send(client.Id, new byte[0x01]);
// }
// // 检查是否超过两秒
// if (stopwatch.ElapsedMilliseconds > 2000)
// {
// _logger.LogError("超时");
// }
// Thread.Sleep(100);
// });
// }
// catch (Exception ex)
// {
// }
//}
/// <summary>
/// 接收数据类型区分
/// </summary>
/// <param name="entity"></param>
public void DataClassify(TcpVisionEntity entity, string id)
{
if (entity == null)
{
_logger.LogError("数据格式校验错误!");
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: ReceiveStackRobotResetEvent?.Invoke(entity, id); break;
case 0x14: ReceiveManualExceptionDealDoneEvent?.Invoke(entity, id); break;
default: _logger.LogInformation("未知命令字!"); return;
}
}
#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
public void InitGetVisionMessage()
{
ReceiveVisionSysStateEvent = (entity, id) =>
{
_logger.LogInformation("视觉系统被动反馈给上位机调度系统状态,端口:" + id);
};
ReceiveVisionStartWorkEvent = (entity, id) =>
{
_logger.LogInformation("视觉系统回复给上位机调度系统开始工作状态,端口:" + id);
};
ReceiveStackRobotResetEvent = (entity, id) =>
{
_logger.LogInformation("视觉系统回复机器人复位结果,端口:" + id);
};
}
}
}