add - TCP信号接收

master
SoulStar 5 months ago
parent 2feda5b29b
commit 0b6b31a706

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

@ -36,8 +36,16 @@ namespace SlnMesnac.TouchSocket
private WebApiClient CreateWebApiClient(string IpHost)
{
var client = new WebApiClient();
client.Connect(IpHost);
_logger.LogInformation(IpHost + "连接成功");
try
{
client.Connect(IpHost);
_logger.LogInformation(IpHost + "连接成功");
}
catch (Exception ex)
{
_logger.LogError("ERROR: " + ex.Message);
return null;
}
return client;
}
@ -50,7 +58,7 @@ namespace SlnMesnac.TouchSocket
}
catch (Exception ex)
{
_logger.LogError("ERROR: " + ex);
_logger.LogError("ERROR: " + ex.Message);
return Task.FromException(ex);
}
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()
{
SubscribeToAGVArrivalEvent();
}
public delegate void AGVArrivalStart(string message, AGVArrivalSingalEntity aGVArrivalSingalEntity);
/// <summary>
/// AGV呼叫事件刷新
/// AGV到位信号刷新
/// </summary>
public event AGVArrivalStart AGVArrivalStartEvent;
@ -57,7 +57,7 @@ namespace SlnMesnac.TouchSocket
public delegate void ManipulatorWorkDoneStart(string message, ManipulatorWorkDoneEntity manipulatorWorkDoneEntity);
/// <summary>
/// 机械臂开始抓取事件刷新
/// 机械臂抓取完毕事件刷新
/// </summary>
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.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
@ -29,10 +34,13 @@ using TouchSocket.Sockets;
#endregion << 版 本 注 释 >>
namespace SlnMesnac.TouchSocket
{
public class TcpServer
public class TcpServer : BackgroundService
{
private ILogger<TcpServer> _logger;
private readonly TcpService _service;
private readonly AppConfig _appConfig;
/// <summary>
/// 接收客户端指令委托
/// </summary>
@ -42,26 +50,63 @@ namespace SlnMesnac.TouchSocket
public delegate void RefreshClientInfo(TcpService tcpService);
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;
_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
{
_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);
ClientID = client.Id;
return EasyTask.CompletedTask;
};
_service.Disconnected = (client, e) => {
_service.Disconnected = (client, e) => {
_logger.LogInformation($"客户端{client.IP}断开连接");
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
@ -69,17 +114,18 @@ namespace SlnMesnac.TouchSocket
_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];
Array.Copy(e.ByteBlock.Buffer, 0, receivedBuffer, 0, e.ByteBlock.Len);
ReceivedClientBufferEvent?.Invoke(receivedBuffer);
//ReceivedClientBufferEvent?.Invoke(receivedBuffer);
DataClassify(BufferDataAnalysis.BufferRootAnalysis(receivedBuffer));
return EasyTask.CompletedTask;
};
_service.Setup(new TouchSocketConfig()//载入配置
.SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })
.SetListenIPHosts(new IPHost[] { new IPHost(serverPort) })
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
a.AddConsoleLogger();
@ -100,15 +146,37 @@ namespace SlnMesnac.TouchSocket
}
/// <summary>
/// 向所有客户端发送心跳
/// 数据类型区分
/// </summary>
public void SendHeartBeat()
/// <param name="entity"></param>
public void DataClassify(TcpVisionEntity entity)
{
var clients = _service.SocketClients.GetClients();
foreach (var item in clients)
if(entity == null)
{
_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
services.AddHostedService<AirPorthttpClient>();
//注册TCPServer
services.AddHostedService<TcpServer>();
//注册RFID工厂
//services.AddRfidFactorySetup();

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

@ -62,6 +62,8 @@
],
"redisConfig": "175.27.215.92:6379,password=redis@2023",
"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