using System.Net.Sockets;
|
using WIDESEAWCS_Common;
|
using WIDESEAWCS_Common.HttpEnum;
|
using WIDESEAWCS_Common.TaskEnum;
|
using WIDESEAWCS_Core.Caches;
|
using WIDESEAWCS_Core.Helper;
|
using WIDESEAWCS_DTO.Stock;
|
using WIDESEAWCS_DTO.TaskInfo;
|
using WIDESEAWCS_ITaskInfoService;
|
using WIDESEAWCS_Model.Models;
|
using WIDESEAWCS_Tasks.SocketServer;
|
|
namespace WIDESEAWCS_Tasks
|
{
|
/// <summary>
|
/// 机械手消息处理器 - 负责处理来自TCP客户端的消息
|
/// </summary>
|
public class RobotMessageHandler
|
{
|
private readonly TcpSocketServer _tcpSocket;
|
private readonly RobotStateManager _stateManager;
|
private readonly ICacheService _cache;
|
private readonly IRobotTaskService _robotTaskService;
|
private readonly RobotTaskProcessor _taskProcessor;
|
|
public RobotMessageHandler(
|
TcpSocketServer tcpSocket,
|
RobotStateManager stateManager,
|
ICacheService cache,
|
IRobotTaskService robotTaskService,
|
RobotTaskProcessor taskProcessor)
|
{
|
_tcpSocket = tcpSocket;
|
_stateManager = stateManager;
|
_cache = cache;
|
_robotTaskService = robotTaskService;
|
_taskProcessor = taskProcessor;
|
}
|
|
/// <summary>
|
/// 处理接收到的消息
|
/// </summary>
|
public async Task<string?> HandleMessageReceivedAsync(string message, bool isJson, TcpClient client, RobotSocketState state)
|
{
|
if (!(_cache?.TryGetValue($"{RedisPrefix.Code}:{RedisName.SocketDevices}:{client.Client.RemoteEndPoint}", out state)) ?? false)
|
return null;
|
|
string messageLower = message.ToLowerInvariant();
|
|
if (await IsSimpleCommandAsync(messageLower, state))
|
{
|
await _tcpSocket.SendMessageAsync(client, message);
|
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
return null;
|
}
|
else if (IsPrefixCommand(messageLower))
|
{
|
await HandlePrefixCommandAsync(message, state, client);
|
}
|
|
return null;
|
}
|
|
/// <summary>
|
/// 处理前缀命令(pickfinished, putfinished)
|
/// </summary>
|
private async Task HandlePrefixCommandAsync(string message, RobotSocketState state, TcpClient client)
|
{
|
try
|
{
|
var parts = message.Split(',');
|
if (parts.Length >= 1 && state.CurrentTask != null)
|
{
|
var cmd = parts[0].ToLowerInvariant();
|
int[] positions = parts.Skip(1)
|
.Select(p => int.TryParse(p, out int value) ? value : (int?)null)
|
.Where(v => v.HasValue && v.Value != 0)
|
.Select(v => v!.Value)
|
.ToArray();
|
|
var task = await _robotTaskService.Repository.QueryFirstAsync(x => x.RobotTaskId == state.CurrentTask.RobotTaskId);
|
|
if (cmd.StartsWith("pickfinished"))
|
{
|
await HandlePickFinishedAsync(state, positions, task, client);
|
}
|
else if (cmd.StartsWith("putfinished"))
|
{
|
await HandlePutFinishedAsync(state, positions, task, client);
|
}
|
|
await _tcpSocket.SendMessageAsync(client, message);
|
}
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine($"RobotJob MessageReceived Error: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 处理取货完成命令
|
/// </summary>
|
private async Task HandlePickFinishedAsync(RobotSocketState state, int[] positions, Dt_RobotTask? task, TcpClient client)
|
{
|
if (state.IsSplitPallet)
|
{
|
var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
|
state.LastPickPositions = positions;
|
|
var result = _taskProcessor.PostSplitPalletAsync(stockDTO);
|
|
if (result.Data.Status && result.IsSuccess)
|
{
|
state.CurrentAction = "PickFinished";
|
}
|
}
|
else
|
{
|
state.CurrentAction = "PickFinished";
|
}
|
|
state.LastPickPositions = positions;
|
if (task != null)
|
{
|
task.RobotTaskState = TaskRobotStatusEnum.RobotPickFinish.GetHashCode();
|
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
await _robotTaskService.Repository.UpdateDataAsync(task);
|
}
|
}
|
|
/// <summary>
|
/// 处理放货完成命令
|
/// </summary>
|
private async Task HandlePutFinishedAsync(RobotSocketState state, int[] positions, Dt_RobotTask? task, TcpClient client)
|
{
|
bool putSuccess = true;
|
if (state.IsGroupPallet)
|
{
|
state.LastPutPositions = positions;
|
var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
|
var configKey = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()
|
? nameof(ConfigKey.ChangePalletAsync) : nameof(ConfigKey.GroupPalletAsync);
|
|
var result = _taskProcessor.PostGroupPalletAsync(configKey, stockDTO);
|
putSuccess = result.Data.Status && result.IsSuccess;
|
}
|
|
if (putSuccess)
|
{
|
state.CurrentAction = "PutFinished";
|
state.RobotTaskTotalNum += positions.Length;
|
if (task != null)
|
{
|
task.RobotTaskTotalNum += positions.Length;
|
}
|
}
|
|
if (task != null)
|
{
|
task.RobotTaskState = TaskRobotStatusEnum.RobotPutFinish.GetHashCode();
|
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
await _robotTaskService.Repository.UpdateDataAsync(task);
|
}
|
}
|
|
/// <summary>
|
/// 机械手简单命令处理
|
/// </summary>
|
private async Task<bool> IsSimpleCommandAsync(string message, RobotSocketState state)
|
{
|
RobotTaskTypeEnum? GetRobotTaskType() => state.CurrentTask != null ? (RobotTaskTypeEnum)state.CurrentTask.RobotTaskType : null;
|
switch (message)
|
{
|
case "homing":
|
state.OperStatus = "Homing";
|
return true;
|
|
case "homed":
|
state.OperStatus = "Homed";
|
return true;
|
|
case "picking":
|
state.CurrentAction = "Picking";
|
return true;
|
|
case "puting":
|
state.CurrentAction = "Putting";
|
return true;
|
|
case "allpickfinished": // 取货完成
|
state.CurrentAction = "AllPickFinished";
|
var robotTaskType = GetRobotTaskType();
|
|
if (robotTaskType == RobotTaskTypeEnum.SplitPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet)
|
{
|
if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true))
|
{
|
_taskProcessor.DeleteTask(state.CurrentTask.RobotTaskId);
|
return true;
|
}
|
}
|
return false;
|
|
case "allputfinished": // 放货完成
|
state.CurrentAction = "AllPutFinished";
|
robotTaskType = GetRobotTaskType();
|
|
if (robotTaskType == RobotTaskTypeEnum.GroupPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet)
|
{
|
if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false))
|
{
|
_taskProcessor.DeleteTask(state.CurrentTask.RobotTaskId);
|
state.CurrentTask = null;
|
state.RobotTaskTotalNum = 0;
|
state.CellBarcode = new List<string>();
|
return true;
|
}
|
}
|
return false;
|
|
case "running":
|
state.OperStatus = "Running";
|
return true;
|
|
case "pausing":
|
state.OperStatus = "Pausing";
|
return true;
|
|
case "warming":
|
state.OperStatus = "Warming";
|
return true;
|
|
case "emstoping":
|
state.OperStatus = "Emstoping";
|
return true;
|
|
case "runmode,1":
|
state.RobotRunMode = 1;
|
return true;
|
|
case "runmode,2":
|
state.RobotRunMode = 2;
|
return true;
|
|
case "controlmode,1":
|
state.RobotControlMode = 1;
|
return true;
|
|
case "controlmode,2":
|
state.RobotControlMode = 2;
|
return true;
|
|
case "armobject,1":
|
state.RobotArmObject = 1;
|
return true;
|
|
case "armobject,0":
|
state.RobotArmObject = 0;
|
return true;
|
|
default:
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// 判断是否为前缀命令
|
/// </summary>
|
private static bool IsPrefixCommand(string message)
|
{
|
return message.StartsWith("pickfinished") || message.StartsWith("putfinished");
|
}
|
}
|
}
|