using Quartz;
|
using System.Collections.Concurrent;
|
using System.Net.Sockets;
|
using WIDESEAWCS_Core.Helper;
|
using WIDESEAWCS_ITaskInfoRepository;
|
using WIDESEAWCS_ITaskInfoService;
|
using WIDESEAWCS_Model.Models;
|
using WIDESEAWCS_QuartzJob;
|
using WIDESEAWCS_QuartzJob.Service;
|
using WIDESEAWCS_Tasks.SocketServer;
|
|
namespace WIDESEAWCS_Tasks
|
{
|
[DisallowConcurrentExecution]
|
public class RobotJob : IJob
|
{
|
private readonly TcpSocketServer _TcpSocket;
|
private static readonly ConcurrentDictionary<string, RobotSocketState> _socketStates = new();
|
private static int _eventSubscribedFlag;
|
private readonly ITaskService _taskService;
|
private readonly ITaskExecuteDetailService _taskExecuteDetailService;
|
private readonly ITaskRepository _taskRepository;
|
private readonly IRouterService _routerService;
|
|
public RobotJob(TcpSocketServer TcpSocket, ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, ITaskRepository taskRepository, IRouterService routerService)
|
{
|
_TcpSocket = TcpSocket;
|
_taskService = taskService;
|
_taskExecuteDetailService = taskExecuteDetailService;
|
_taskRepository = taskRepository;
|
_routerService = routerService;
|
}
|
|
public Task Execute(IJobExecutionContext context)
|
{
|
bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
|
RobotCraneDevice robotCrane = (RobotCraneDevice?)value ?? new RobotCraneDevice();
|
if (!flag || robotCrane.IsNullOrEmpty())
|
{
|
return Task.CompletedTask;
|
}
|
|
string ipAddress = robotCrane.IPAddress;
|
|
// 获取或创建状态
|
RobotSocketState state = _socketStates.GetOrAdd(ipAddress, _ => new RobotSocketState
|
{
|
IPAddress = ipAddress,
|
RobotCrane = robotCrane
|
});
|
|
// 更新设备信息
|
state.RobotCrane = robotCrane;
|
|
// 检查是否有该客户端连接
|
var clientIds = _TcpSocket.GetClientIds();
|
if (!clientIds.Contains(ipAddress))
|
{
|
return Task.CompletedTask;
|
}
|
|
// 订阅一次 message 事件(全局一次)
|
if (Interlocked.CompareExchange(ref _eventSubscribedFlag, 1, 0) == 0)
|
{
|
_TcpSocket.MessageReceived += _TcpSocket_MessageReceived;
|
_TcpSocket.RobotReceived += _TcpSocket_RobotReceived;
|
}
|
|
if (!state.IsEventSubscribed)
|
{
|
_TcpSocket._clients.TryGetValue(ipAddress, out TcpClient client);
|
Task clientTask = _TcpSocket.HandleClientAsync(client, robotCrane.IPAddress, _TcpSocket._cts.Token, state);
|
state.IsEventSubscribed = true;
|
}
|
|
// 获取任务并缓存到状态中
|
Dt_Task? task = GetTask(robotCrane);
|
if (task != null)
|
{
|
state.CurrentTask = task;
|
}
|
|
return Task.CompletedTask;
|
}
|
|
/// <summary>
|
/// 事件:客户端断开连接时触发
|
/// </summary>
|
/// <param name="clientId"></param>
|
/// <returns></returns>
|
private Task<string?> _TcpSocket_RobotReceived(string clientId)
|
{
|
_socketStates.TryRemove(clientId, out _);
|
return Task.FromResult<string?>(null);
|
}
|
|
/// <summary>
|
/// 事件:收到消息时触发
|
/// </summary>
|
/// <param name="message"></param>
|
/// <param name="isJson"></param>
|
/// <param name="client"></param>
|
/// <param name="state"></param>
|
/// <returns></returns>
|
private async Task<string?> _TcpSocket_MessageReceived(string message, bool isJson, TcpClient client, RobotSocketState state)
|
{
|
string messageLower = message.ToLowerInvariant();
|
|
if (IsSimpleCommand(messageLower, state))
|
{
|
return null;
|
}
|
|
if (IsPrefixCommand(messageLower))
|
{
|
try
|
{
|
var parts = message.Split(',');
|
if (parts.Length >= 1)
|
{
|
var cmd = parts[0].ToLowerInvariant();
|
int[] positions = new int[4];
|
for (int i = 1; i <= 4 && i < parts.Length; i++)
|
{
|
int.TryParse(parts[i], out positions[i - 1]);
|
}
|
|
if (cmd.StartsWith("pickfinished"))
|
{
|
state.LastPickPositions = positions;
|
state.CurrentAction = "PickFinished";
|
}
|
else if (cmd.StartsWith("putfinished"))
|
{
|
state.LastPutPositions = positions;
|
state.CurrentAction = "PutFinished";
|
}
|
}
|
}
|
catch { }
|
|
return null;
|
}
|
|
return null;
|
}
|
|
/// <summary>
|
/// 机械手简单命令处理
|
/// </summary>
|
/// <param name="message"></param>
|
/// <param name="state"></param>
|
/// <returns></returns>
|
private bool IsSimpleCommand(string message, RobotSocketState state)
|
{
|
switch (message)
|
{
|
case "homing":
|
state.CurrentAction = "Homing";
|
return true;
|
|
case "homed":
|
state.CurrentAction = "Homed";
|
return true;
|
|
case "picking":
|
state.CurrentAction = "Picking";
|
return true;
|
|
case "puting":
|
state.CurrentAction = "Putting";
|
return true;
|
|
case "allpickfinished":
|
state.CurrentAction = "AllPickFinished";
|
return true;
|
|
case "allputfinished":
|
state.CurrentAction = "AllPutFinished";
|
return true;
|
|
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 "runmodemode,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>
|
/// <param name="message"></param>
|
/// <returns></returns>
|
private static bool IsPrefixCommand(string message)
|
{
|
return message.StartsWith("pickfinished") || message.StartsWith("putfinished");
|
}
|
|
private Dt_Task? GetTask(RobotCraneDevice robotCrane)
|
{
|
return _taskService.QueryRobotCraneTask(robotCrane.DeviceCode);
|
}
|
}
|
|
public class RobotSocketState
|
{
|
public string IPAddress { get; set; } = string.Empty;
|
|
/// <summary>
|
/// 是否已订阅消息事件
|
/// </summary>
|
public bool IsEventSubscribed { get; set; }
|
|
/// <summary>
|
/// 机械手运行模式
|
/// </summary>
|
public int? RobotRunMode { get; set; }
|
|
/// <summary>
|
/// 机械手控制模式
|
/// </summary>
|
public int? RobotControlMode { get; set; }
|
|
/// <summary>
|
/// 机械手抓取对象
|
/// </summary>
|
public int? RobotArmObject { get; set; }
|
|
/// <summary>
|
/// 机械手设备信息
|
/// </summary>
|
public RobotCraneDevice? RobotCrane { get; set; }
|
|
/// <summary>
|
/// 当前动作
|
/// </summary>
|
public string? CurrentAction { get; set; }
|
|
/// <summary>
|
/// 当前状态
|
/// </summary>
|
public string? OperStatus { get; set; }
|
|
/// <summary>
|
/// 取货完成位置
|
/// </summary>
|
public int[]? LastPickPositions { get; set; }
|
|
/// <summary>
|
/// 放货完成位置
|
/// </summary>
|
public int[]? LastPutPositions { get; set; }
|
|
/// <summary>
|
/// 当前抓取任务
|
/// </summary>
|
public Dt_Task? CurrentTask { get; set; }
|
}
|
}
|