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 _logger; private readonly TcpService _service; private readonly AppConfig _appConfig; /// /// 接收客户端指令委托 /// 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); /// /// 视觉系统反馈给上位机调度系统状态 /// public event GetVisionData? ReceiveVisionSysStateEvent; /// /// 视觉系统回复给上位机调度系统开始工作状态 /// public event GetVisionData? ReceiveVisionStartWorkEvent; /// /// 一次码垛完成,发送码垛结果 /// public event GetVisionData? ReceiveStackWorkDoneEvent; /// /// 视觉系统发送给机器人码垛位置复位结果 /// public event GetVisionData? ReceiveStackRobotResetEvent; /// /// 人工异常处理完成并更新计数 /// public event GetVisionData? ReceiveManualExceptionDealDoneEvent; /// /// 连接状态 /// 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 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}"); } } /// /// byte数组转字符串 /// /// /// 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) // { // } //} /// /// 接收数据类型区分 /// /// 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 数据发送 /// /// 上位机调度系统请求视觉系统状态 /// /// SN码 /// 客户端ID 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); } } /// /// AMR就绪,请求视觉开始工作 /// /// SN码 /// 数据体 /// 客户端ID 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); } } /// /// 上位机调度系统回复收到码垛结果 /// /// SN码 /// 客户端ID 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); } } /// /// 码垛结束,请求视觉系统复位 /// /// SN码 /// 客户端ID 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); } } /// /// 上位机调度系统回复收到人工异常处理 /// /// SN码 /// 客户端ID 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); } } /// /// 上位机调度系统请求视觉系统状态(默认SN) /// /// 客户端ID public void SendRequestVisionSysState(string id) { SendRequestVisionSysState(new byte[2] { 0x00, 0x00 }, id); } /// /// AMR就绪,请求视觉开始工作(默认SN) /// /// 数据体 /// 客户端ID public void SendAMRRequestVisionStartWork(byte[] data, string id) { SendAMRRequestVisionStartWork(new byte[2] { 0x00, 0x00 }, data, id); } /// /// 上位机调度系统回复收到码垛结果(默认SN) /// /// 客户端ID public void SendReplayStackResult(string id) { SendReplayStackResult(new byte[2] { 0x00, 0x00 }, id); } /// /// 码垛结束,请求视觉系统复位(默认SN) /// /// 客户端ID public void SendStackOverRequestVisionSysReplace(string id) { SendStackOverRequestVisionSysReplace(new byte[2] { 0x00, 0x00 }, id); } /// /// 上位机调度系统回复收到人工异常处理(默认SN) /// /// 客户端ID 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); }; } } }