using Quartz;
|
using System.Collections.Concurrent;
|
using System.Net.Sockets;
|
using WIDESEAWCS_Common.TaskEnum;
|
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 StackerCraneJob : IJob
|
{
|
private readonly TcpSocketServer _TcpSocket;
|
private static readonly ConcurrentDictionary<string, StackerSocketState> _socketStates = new();
|
private static int _eventSubscribedFlag;
|
private readonly ITaskService _taskService;
|
private readonly ITaskExecuteDetailService _taskExecuteDetailService;
|
private readonly ITaskRepository _taskRepository;
|
private readonly IRouterService _routerService;
|
|
public StackerCraneJob(TcpSocketServer TcpSocket, ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, ITaskRepository taskRepository, IRouterService routerService)
|
{
|
_TcpSocket = TcpSocket;
|
_taskService = taskService;
|
_taskExecuteDetailService = taskExecuteDetailService;
|
_taskRepository = taskRepository;
|
_routerService = routerService;
|
}
|
|
public async Task Execute(IJobExecutionContext context)
|
{
|
bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
|
StackerCraneDevice Crane = (StackerCraneDevice?)value ?? new StackerCraneDevice();
|
if (!flag || Crane.IsNullOrEmpty())
|
{
|
return;
|
}
|
|
string ipAddress = Crane.IPAddress;
|
|
// 获取或创建状态
|
StackerSocketState state = _socketStates.GetOrAdd(ipAddress, _ => new StackerSocketState
|
{
|
IPAddress = ipAddress,
|
StackerCrane = Crane
|
});
|
|
// 更新设备信息
|
state.StackerCrane = Crane;
|
|
// 检查是否有该客户端连接
|
var clientIds = _TcpSocket.GetClientIds();
|
if (!clientIds.Contains(ipAddress))
|
{
|
return;
|
}
|
|
// 订阅一次 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, Crane.IPAddress, _TcpSocket._cts.Token, state);
|
state.IsEventSubscribed = true;
|
}
|
// 获取当前需下发任务并缓存到状态中
|
Dt_Task? task = GetTask(Crane);
|
if (task != null && state.CurrentTask == null && state.StackerRunMode== && state.StackerTaskNum == 0)
|
{
|
SendStackerTask(task, state);
|
}
|
return;
|
}
|
|
/// <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, StackerSocketState state)
|
{
|
string messageLower = message.ToUpperInvariant();
|
|
//区分堆垛机发送命令
|
try
|
{
|
|
}
|
catch
|
{
|
|
}
|
|
return null;
|
}
|
/// <summary>
|
/// 堆垛机任务下发
|
/// </summary>
|
private bool SendStackerTask(Dt_Task task, StackerSocketState state)
|
{
|
string message = "<";
|
//获取对起始和终点位置进行解析
|
message += ">";
|
return _TcpSocket.SendToDeviceAsync(state.IPAddress, message).Result;
|
}
|
|
private Dt_Task? GetTask(StackerCraneDevice stackerCrane, TaskTypeGroup? taskTypeGroup = null)
|
{
|
return _taskService.QueryStackerTask(stackerCrane.DeviceCode,taskTypeGroup);
|
}
|
}
|
|
public class StackerSocketState
|
{
|
public string IPAddress { get; set; } = string.Empty;
|
|
/// <summary>
|
/// 是否已订阅消息事件
|
/// </summary>
|
public bool IsEventSubscribed { get; set; }
|
|
/// <summary>
|
/// 堆垛机当前任务号
|
/// </summary>
|
public int? StackerTaskNum { get; set; }
|
|
/// <summary>
|
/// 堆垛机运行模式<br/>
|
/// 1:自动模式<br/>
|
/// 2:停止模式<br/>
|
/// 3:手动模式或离线模式<br/>
|
/// </summary>
|
public int? StackerRunMode { get; set; }
|
|
/// <summary>
|
/// 堆垛机故障状态<br/>
|
/// 正常<br/>
|
/// 故障<br/>
|
/// </summary>
|
public int? StackerError { get; set; }
|
|
/// <summary>
|
/// 堆垛机设备信息
|
/// </summary>
|
public StackerCraneDevice? StackerCrane { get; set; }
|
|
/// <summary>
|
/// 取货位置
|
/// </summary>
|
public string? PickPosition { get; set; }
|
|
/// <summary>
|
/// 放货位置
|
/// </summary>
|
public string? PutPosition{ get; set; }
|
|
/// <summary>
|
/// 当前任务
|
/// </summary>
|
public Dt_Task? CurrentTask { get; set; }
|
}
|
public enum StackerModeEnum
|
{
|
/// <summary>
|
/// 自动模式
|
/// </summary>
|
Automatic = 1,
|
/// <summary>
|
/// 停止模式
|
/// </summary>
|
Unkonw = 2,
|
/// <summary>
|
/// 手动模式
|
/// </summary>
|
Manual = 3
|
}
|
public enum StackerErrorEnum
|
{
|
/// <summary>
|
/// 正常
|
/// </summary>
|
Normal = 1,
|
/// <summary>
|
/// 故障
|
/// </summary>
|
Fault = 2
|
}
|
}
|