add - TCP信号接收

master
SoulStar 5 months ago
parent 2feda5b29b
commit 0b6b31a706

@ -67,6 +67,11 @@ namespace SlnMesnac.Config
/// </summary> /// </summary>
public string ManipulatorIpConfig { get; set; } public string ManipulatorIpConfig { get; set; }
/// <summary>
/// 机械臂地址配置
/// </summary>
public string TCPVisionConfig { get; set; }
public AppConfig Value => this; public AppConfig Value => this;
} }
} }

@ -36,8 +36,16 @@ namespace SlnMesnac.TouchSocket
private WebApiClient CreateWebApiClient(string IpHost) private WebApiClient CreateWebApiClient(string IpHost)
{ {
var client = new WebApiClient(); var client = new WebApiClient();
client.Connect(IpHost); try
_logger.LogInformation(IpHost + "连接成功"); {
client.Connect(IpHost);
_logger.LogInformation(IpHost + "连接成功");
}
catch (Exception ex)
{
_logger.LogError("ERROR: " + ex.Message);
return null;
}
return client; return client;
} }
@ -50,7 +58,7 @@ namespace SlnMesnac.TouchSocket
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError("ERROR: " + ex); _logger.LogError("ERROR: " + ex.Message);
return Task.FromException(ex); return Task.FromException(ex);
} }
return Task.CompletedTask; return Task.CompletedTask;

@ -0,0 +1,19 @@
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SlnMesnac.TouchSocket
{
public class AirportTcpServer : BackgroundService
{
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
return Task.CompletedTask;
}
}
}

@ -33,12 +33,12 @@ namespace SlnMesnac.TouchSocket
{ {
public ApiServer() public ApiServer()
{ {
SubscribeToAGVArrivalEvent();
} }
public delegate void AGVArrivalStart(string message, AGVArrivalSingalEntity aGVArrivalSingalEntity); public delegate void AGVArrivalStart(string message, AGVArrivalSingalEntity aGVArrivalSingalEntity);
/// <summary> /// <summary>
/// AGV呼叫事件刷新 /// AGV到位信号刷新
/// </summary> /// </summary>
public event AGVArrivalStart AGVArrivalStartEvent; public event AGVArrivalStart AGVArrivalStartEvent;
@ -57,7 +57,7 @@ namespace SlnMesnac.TouchSocket
public delegate void ManipulatorWorkDoneStart(string message, ManipulatorWorkDoneEntity manipulatorWorkDoneEntity); public delegate void ManipulatorWorkDoneStart(string message, ManipulatorWorkDoneEntity manipulatorWorkDoneEntity);
/// <summary> /// <summary>
/// 机械臂开始抓取事件刷新 /// 机械臂抓取完毕事件刷新
/// </summary> /// </summary>
public event ManipulatorWorkDoneStart ManipulatorWorkDoneEvent; public event ManipulatorWorkDoneStart ManipulatorWorkDoneEvent;

@ -0,0 +1,83 @@
using Microsoft.Extensions.Logging;
using Serilog.Core;
using SlnMesnac.Config;
using SlnMesnac.Model.AirportApiEntity;
using SlnMesnac.TouchSocket.Entity;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using TouchSocket.Sockets;
namespace SlnMesnac.TouchSocket
{
public class BufferDataAnalysis
{
public static TcpVisionEntity BufferRootAnalysis(byte[] bytes)
{
TcpVisionEntity entity;
//数据校验从起始符开始到数据位按字节求和得出的结果对256求余
int checkDatalength = bytes.Length - 2;
byte checksum = bytes[checkDatalength];
byte[] checkData = new byte[checkDatalength];
Array.Copy(bytes, 0, checkData, 0, checkDatalength);
int sum = 0;
foreach (byte b in checkData)
{
sum += b;
}
int count = sum % 256;
if (count == checksum)
{
entity = new TcpVisionEntity();
entity.Checksum = checksum;
}
else
{
return null;
}
int index = 2;
//取序列号
entity.SN = new byte[2] { bytes[index], bytes[index + 1] };
index += 2;
//取时间戳
entity.Timestamp = new byte[4] { bytes[index], bytes[index + 1], bytes[index + 2], bytes[index + 3] };
index += 4;
//取命令字
entity.Command = bytes[index];
index += 1;
//取数据位长度
entity.DataLength = bytes[index];
index += 1;
//取数据位
byte[] dataBytes = new byte[entity.DataLength];
Array.Copy(bytes, index, dataBytes, 0, entity.DataLength);
entity.DataBytes = dataBytes;
index += entity.DataLength;
return entity;
}
public byte[] DataCombine(byte[] bytes)
{
return null;
}
public static byte[] GetCurrentUnixTimestampAsBytes()
{
// 获取当前的Unix时间戳表示自1970-01-01以来的秒数
int unixTimestamp = (int)(DateTimeOffset.UtcNow.ToUnixTimeSeconds());
// 将时间戳转换为字节数组
byte[] bytes = BitConverter.GetBytes(unixTimestamp);
return bytes;
}
}
}

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SlnMesnac.TouchSocket.Entity
{
public class TcpVisionEntity
{
/// <summary>
/// 序列号
/// </summary>
public byte[] SN { get; set; }
/// <summary>
/// 时间戳
/// </summary>
public byte[] Timestamp { get; set; }
/// <summary>
/// 命令字
/// </summary>
public byte Command { get; set; }
/// <summary>
/// 数据长度
/// </summary>
public byte DataLength { get; set; }
/// <summary>
/// 数据位
/// </summary>
public byte[]? DataBytes { get; set; }
/// <summary>
/// 校验和
/// </summary>
public byte Checksum { get; set; }
}
}

@ -1,7 +1,12 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using SlnMesnac.Config;
using SlnMesnac.TouchSocket.Entity;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TouchSocket.Core; using TouchSocket.Core;
using TouchSocket.Sockets; using TouchSocket.Sockets;
@ -29,10 +34,13 @@ using TouchSocket.Sockets;
#endregion << 版 本 注 释 >> #endregion << 版 本 注 释 >>
namespace SlnMesnac.TouchSocket namespace SlnMesnac.TouchSocket
{ {
public class TcpServer public class TcpServer : BackgroundService
{ {
private ILogger<TcpServer> _logger; private ILogger<TcpServer> _logger;
private readonly TcpService _service; private readonly TcpService _service;
private readonly AppConfig _appConfig;
/// <summary> /// <summary>
/// 接收客户端指令委托 /// 接收客户端指令委托
/// </summary> /// </summary>
@ -42,26 +50,63 @@ namespace SlnMesnac.TouchSocket
public delegate void RefreshClientInfo(TcpService tcpService); public delegate void RefreshClientInfo(TcpService tcpService);
public event RefreshClientInfo? RefreshClientInfoEvent; public event RefreshClientInfo? RefreshClientInfoEvent;
public TcpServer(ILogger<TcpServer> logger,TcpService tcpService) public delegate void GetVisionData(TcpVisionEntity entity);
/// <summary>
/// 视觉系统反馈给上位机调度系统状态
/// </summary>
public event GetVisionData? VisionSysStateEvent;
/// <summary>
/// 视觉系统回复给上位机调度系统开始工作状态
/// </summary>
public event GetVisionData? VisionStartWorkEvent;
/// <summary>
/// 一次码垛完成,发送码垛结果
/// </summary>
public event GetVisionData? StackWorkDoneEvent;
/// <summary>
/// 视觉系统发送给机器人码垛位置定位结果
/// </summary>
public event GetVisionData? StackRobotLocationEvent;
/// <summary>
/// 人工异常处理完成并更新计数
/// </summary>
public event GetVisionData? ManualExceptionDealDoneEvent;
private string ClientID = "";
public TcpServer(ILogger<TcpServer> logger,TcpService tcpService, AppConfig appConfig)
{ {
_logger = logger; _logger = logger;
_service = tcpService; _service = tcpService;
_appConfig = appConfig;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
Init(_appConfig.TCPVisionConfig);
return Task.CompletedTask;
} }
public void Init(int serverPort) public void Init(string serverPort)
{ {
try try
{ {
_service.Connecting = (client, e) => { _service.Connecting = (client, e) => {
_logger.LogInformation($"客户端{client.IP}正在接入服务"); _logger.LogInformation($"客户端{client.IP}正在接入服务");
return EasyTask.CompletedTask; return EasyTask.CompletedTask;
}; };
_service.Connected = (client, e) => { _service.Connected = (client, e) => {
_logger.LogInformation($"客户端{client.IP}接入服务成功"); _logger.LogInformation($"客户端{client.IP}接入服务成功");
RefreshClientInfoEvent?.Invoke(_service); RefreshClientInfoEvent?.Invoke(_service);
ClientID = client.Id;
return EasyTask.CompletedTask; return EasyTask.CompletedTask;
}; };
_service.Disconnected = (client, e) => { _service.Disconnected = (client, e) => {
_logger.LogInformation($"客户端{client.IP}断开连接"); _logger.LogInformation($"客户端{client.IP}断开连接");
RefreshClientInfoEvent?.Invoke(_service); RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask; return EasyTask.CompletedTask;
@ -69,17 +114,18 @@ namespace SlnMesnac.TouchSocket
_service.Received = (client, e) => _service.Received = (client, e) =>
{ {
//从客户端收到信息 //从客户端收到信息
var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意数据长度是byteBlock.Len //var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意数据长度是byteBlock.Len
byte[] receivedBuffer = new byte[e.ByteBlock.Len]; byte[] receivedBuffer = new byte[e.ByteBlock.Len];
Array.Copy(e.ByteBlock.Buffer, 0, receivedBuffer, 0, e.ByteBlock.Len); Array.Copy(e.ByteBlock.Buffer, 0, receivedBuffer, 0, e.ByteBlock.Len);
ReceivedClientBufferEvent?.Invoke(receivedBuffer); //ReceivedClientBufferEvent?.Invoke(receivedBuffer);
DataClassify(BufferDataAnalysis.BufferRootAnalysis(receivedBuffer));
return EasyTask.CompletedTask; return EasyTask.CompletedTask;
}; };
_service.Setup(new TouchSocketConfig()//载入配置 _service.Setup(new TouchSocketConfig()//载入配置
.SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") }) .SetListenIPHosts(new IPHost[] { new IPHost(serverPort) })
.ConfigureContainer(a =>//容器的配置顺序应该在最前面 .ConfigureContainer(a =>//容器的配置顺序应该在最前面
{ {
a.AddConsoleLogger(); a.AddConsoleLogger();
@ -100,15 +146,37 @@ namespace SlnMesnac.TouchSocket
} }
/// <summary> /// <summary>
/// 向所有客户端发送心跳 /// 数据类型区分
/// </summary> /// </summary>
public void SendHeartBeat() /// <param name="entity"></param>
public void DataClassify(TcpVisionEntity entity)
{ {
var clients = _service.SocketClients.GetClients(); if(entity == null)
foreach (var item in clients)
{ {
_service.Send(item.Id,"heartbeat"); _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;
} }
} }
///// <summary>
///// 向所有客户端发送心跳
///// </summary>
//public void SendHeartBeat()
//{
// var clients = _service.SocketClients.GetClients();
// foreach (var item in clients)
// {
// _service.Send(item.Id,"heartbeat");
// }
//}
} }
} }

@ -48,6 +48,9 @@ namespace SlnMesnac.WPF
//注册httpClient //注册httpClient
services.AddHostedService<AirPorthttpClient>(); services.AddHostedService<AirPorthttpClient>();
//注册TCPServer
services.AddHostedService<TcpServer>();
//注册RFID工厂 //注册RFID工厂
//services.AddRfidFactorySetup(); //services.AddRfidFactorySetup();

@ -75,11 +75,11 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
private void Init() private void Init()
{ {
#region 测试数据 #region 测试数据
_StateRefreshBusiness.UpdateManipulatorStateByResposne( //_StateRefreshBusiness.UpdateManipulatorStateByResposne(
new Model.AirportApiEntity.ManipulatorStateRequestEntity() // new Model.AirportApiEntity.ManipulatorStateRequestEntity()
{ ManipulatorNo = "1", SignalSendTime = DateTime.Now.ToString()}); // { ManipulatorNo = "1", SignalSendTime = DateTime.Now.ToString()});
List<AirportTask> AirportTaskItem = _taskservice.GetTaskInfos(); //List<AirportTask> AirportTaskItem = _taskservice.GetTaskInfos();
TaskItems = new ObservableCollection<AirportTask>(AirportTaskItem); //TaskItems = new ObservableCollection<AirportTask>(AirportTaskItem);
// TaskItems = new ObservableCollection<AirportTask> // TaskItems = new ObservableCollection<AirportTask>
// { // {
// new AirportTask { TaskCode = "1", StationName = "1#站台", TaskDetails = "入库P04->C01", Status = "任务状态:执行中" }, // new AirportTask { TaskCode = "1", StationName = "1#站台", TaskDetails = "入库P04->C01", Status = "任务状态:执行中" },

@ -62,6 +62,8 @@
], ],
"redisConfig": "175.27.215.92:6379,password=redis@2023", "redisConfig": "175.27.215.92:6379,password=redis@2023",
"AGVIpConfig": "127.0.0.1:4523", "AGVIpConfig": "127.0.0.1:4523",
"ManipulatorIpConfig": "127.0.0.1:4523" "ManipulatorIpConfig": "127.0.0.1:4523",
"TCPVisionConfig": "127.0.0.1:6000"
} }
} }

Loading…
Cancel
Save