diff --git a/SlnMesnac.Config/AppConfig.cs b/SlnMesnac.Config/AppConfig.cs
index 84ca71a..ca3759b 100644
--- a/SlnMesnac.Config/AppConfig.cs
+++ b/SlnMesnac.Config/AppConfig.cs
@@ -67,6 +67,11 @@ namespace SlnMesnac.Config
///
public string ManipulatorIpConfig { get; set; }
+ ///
+ /// 机械臂地址配置
+ ///
+ public string TCPVisionConfig { get; set; }
+
public AppConfig Value => this;
}
}
diff --git a/SlnMesnac.TouchSocket/AirPorthttpClient.cs b/SlnMesnac.TouchSocket/AirPorthttpClient.cs
index a4e1659..8b27196 100644
--- a/SlnMesnac.TouchSocket/AirPorthttpClient.cs
+++ b/SlnMesnac.TouchSocket/AirPorthttpClient.cs
@@ -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;
diff --git a/SlnMesnac.TouchSocket/AirportTcpServer.cs b/SlnMesnac.TouchSocket/AirportTcpServer.cs
new file mode 100644
index 0000000..784afc4
--- /dev/null
+++ b/SlnMesnac.TouchSocket/AirportTcpServer.cs
@@ -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;
+ }
+
+
+ }
+}
diff --git a/SlnMesnac.TouchSocket/ApiServer.cs b/SlnMesnac.TouchSocket/ApiServer.cs
index c5d5212..30b7e31 100644
--- a/SlnMesnac.TouchSocket/ApiServer.cs
+++ b/SlnMesnac.TouchSocket/ApiServer.cs
@@ -33,12 +33,12 @@ namespace SlnMesnac.TouchSocket
{
public ApiServer()
{
- SubscribeToAGVArrivalEvent();
+
}
public delegate void AGVArrivalStart(string message, AGVArrivalSingalEntity aGVArrivalSingalEntity);
///
- /// AGV呼叫事件刷新
+ /// AGV到位信号刷新
///
public event AGVArrivalStart AGVArrivalStartEvent;
@@ -57,7 +57,7 @@ namespace SlnMesnac.TouchSocket
public delegate void ManipulatorWorkDoneStart(string message, ManipulatorWorkDoneEntity manipulatorWorkDoneEntity);
///
- /// 机械臂开始抓取事件刷新
+ /// 机械臂抓取完毕事件刷新
///
public event ManipulatorWorkDoneStart ManipulatorWorkDoneEvent;
diff --git a/SlnMesnac.TouchSocket/BufferDataAnalysis.cs b/SlnMesnac.TouchSocket/BufferDataAnalysis.cs
new file mode 100644
index 0000000..3836c54
--- /dev/null
+++ b/SlnMesnac.TouchSocket/BufferDataAnalysis.cs
@@ -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;
+ }
+
+ }
+}
diff --git a/SlnMesnac.TouchSocket/Entity/TcpVisionEntity.cs b/SlnMesnac.TouchSocket/Entity/TcpVisionEntity.cs
new file mode 100644
index 0000000..395b51b
--- /dev/null
+++ b/SlnMesnac.TouchSocket/Entity/TcpVisionEntity.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SlnMesnac.TouchSocket.Entity
+{
+ public class TcpVisionEntity
+ {
+ ///
+ /// 序列号
+ ///
+ public byte[] SN { get; set; }
+
+ ///
+ /// 时间戳
+ ///
+ public byte[] Timestamp { get; set; }
+
+ ///
+ /// 命令字
+ ///
+ public byte Command { get; set; }
+
+ ///
+ /// 数据长度
+ ///
+ public byte DataLength { get; set; }
+
+ ///
+ /// 数据位
+ ///
+ public byte[]? DataBytes { get; set; }
+
+ ///
+ /// 校验和
+ ///
+ public byte Checksum { get; set; }
+ }
+}
diff --git a/SlnMesnac.TouchSocket/TcpServer.cs b/SlnMesnac.TouchSocket/TcpServer.cs
index 70f8afc..d61eeef 100644
--- a/SlnMesnac.TouchSocket/TcpServer.cs
+++ b/SlnMesnac.TouchSocket/TcpServer.cs
@@ -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 _logger;
private readonly TcpService _service;
+ private readonly AppConfig _appConfig;
+
///
/// 接收客户端指令委托
///
@@ -42,26 +50,63 @@ namespace SlnMesnac.TouchSocket
public delegate void RefreshClientInfo(TcpService tcpService);
public event RefreshClientInfo? RefreshClientInfoEvent;
- public TcpServer(ILogger logger,TcpService tcpService)
+ public delegate void GetVisionData(TcpVisionEntity entity);
+
+ ///
+ /// 视觉系统反馈给上位机调度系统状态
+ ///
+ public event GetVisionData? VisionSysStateEvent;
+
+ ///
+ /// 视觉系统回复给上位机调度系统开始工作状态
+ ///
+ public event GetVisionData? VisionStartWorkEvent;
+
+ ///
+ /// 一次码垛完成,发送码垛结果
+ ///
+ public event GetVisionData? StackWorkDoneEvent;
+
+ ///
+ /// 视觉系统发送给机器人码垛位置定位结果
+ ///
+ public event GetVisionData? StackRobotLocationEvent;
+
+ ///
+ /// 人工异常处理完成并更新计数
+ ///
+ public event GetVisionData? ManualExceptionDealDoneEvent;
+
+ private string ClientID = "";
+
+ public TcpServer(ILogger 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
}
///
- /// 向所有客户端发送心跳
+ /// 数据类型区分
///
- public void SendHeartBeat()
+ ///
+ 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;
}
}
+
+ /////
+ ///// 向所有客户端发送心跳
+ /////
+ //public void SendHeartBeat()
+ //{
+ // var clients = _service.SocketClients.GetClients();
+ // foreach (var item in clients)
+ // {
+ // _service.Send(item.Id,"heartbeat");
+ // }
+ //}
}
}
diff --git a/SlnMesnac.WPF/Startup.cs b/SlnMesnac.WPF/Startup.cs
index 3014da7..0809e26 100644
--- a/SlnMesnac.WPF/Startup.cs
+++ b/SlnMesnac.WPF/Startup.cs
@@ -48,6 +48,9 @@ namespace SlnMesnac.WPF
//注册httpClient
services.AddHostedService();
+ //注册TCPServer
+ services.AddHostedService();
+
//注册RFID工厂
//services.AddRfidFactorySetup();
diff --git a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs
index 6f5c118..d7b69b8 100644
--- a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs
+++ b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs
@@ -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 AirportTaskItem = _taskservice.GetTaskInfos();
- TaskItems = new ObservableCollection(AirportTaskItem);
+ //_StateRefreshBusiness.UpdateManipulatorStateByResposne(
+ // new Model.AirportApiEntity.ManipulatorStateRequestEntity()
+ // { ManipulatorNo = "1", SignalSendTime = DateTime.Now.ToString()});
+ //List AirportTaskItem = _taskservice.GetTaskInfos();
+ //TaskItems = new ObservableCollection(AirportTaskItem);
// TaskItems = new ObservableCollection
// {
// new AirportTask { TaskCode = "1", StationName = "1#站台", TaskDetails = "入库:P04->C01", Status = "任务状态:执行中" },
diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json
index a9ef935..95b9835 100644
--- a/SlnMesnac.WPF/appsettings.json
+++ b/SlnMesnac.WPF/appsettings.json
@@ -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"
+
}
}