using System.Collections.Concurrent; using System.Net.Sockets; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_Tasks.SocketServer; namespace WIDESEAWCS_Tasks { /// /// 机械手客户端连接管理器 - 负责TCP客户端连接管理和事件订阅 /// public class RobotClientManager { private readonly TcpSocketServer _tcpSocket; private readonly RobotStateManager _stateManager; // 跟踪已经启动 HandleClientAsync 的客户端 private static readonly ConcurrentDictionary _handleClientStarted = new(); private static int _eventSubscribedFlag; public event EventHandler? OnClientDisconnected; public RobotClientManager(TcpSocketServer tcpSocket, RobotStateManager stateManager) { _tcpSocket = tcpSocket; _stateManager = stateManager; } /// /// 确保客户端已连接并订阅消息事件 /// /// 设备IP地址 /// 机器人设备信息 /// 客户端是否可用(已连接且消息处理已启动) public bool EnsureClientSubscribed(string ipAddress, RobotCraneDevice robotCrane) { // 检查是否有该客户端连接 var clientIds = _tcpSocket.GetClientIds(); bool isClientConnected = clientIds.Contains(ipAddress); if (!isClientConnected) { // 客户端未连接,清理 HandleClientAsync 状态 _handleClientStarted.TryRemove(ipAddress, out _); return false; } // 订阅一次 robot 事件(全局一次)- message事件由RobotJob订阅 if (System.Threading.Interlocked.CompareExchange(ref _eventSubscribedFlag, 1, 0) == 0) { _tcpSocket.RobotReceived += OnRobotReceived; Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 机器人TCP断开事件已订阅"); } // 获取TcpClient TcpClient? tcpClient = null; _tcpSocket._clients.TryGetValue(ipAddress, out tcpClient); if (tcpClient == null) { // isClientConnected为true但无法获取tcpClient,列表可能不同步 _handleClientStarted.TryRemove(ipAddress, out _); return false; } // 检查是否已经为这个客户端启动过 HandleClientAsync bool alreadyStarted = _handleClientStarted.TryGetValue(ipAddress, out _); if (!alreadyStarted) { Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 启动客户端消息处理: {ipAddress}"); // 重新获取最新的 state 对象 var latestStateForSubscribe = _stateManager.GetState(ipAddress); if (latestStateForSubscribe != null) { // 标记为已启动 _handleClientStarted[ipAddress] = true; _ = _tcpSocket.HandleClientAsync(tcpClient, robotCrane.IPAddress, _tcpSocket._cts.Token, latestStateForSubscribe) .ContinueWith(t => { if (t.IsFaulted) { Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] HandleClientAsync error: {t.Exception?.GetBaseException().Message}"); // 发生错误时,移除启动标志,允许下次重试 _handleClientStarted.TryRemove(ipAddress, out _); } }, TaskContinuationOptions.OnlyOnFaulted); // 更新 IsEventSubscribed 状态 _stateManager.TryUpdateStateSafely(ipAddress, s => { s.IsEventSubscribed = true; return s; }); } } return true; } /// /// 事件:客户端断开连接时触发 /// private Task OnRobotReceived(string clientId) { // 客户端断开连接,清理 HandleClientAsync 启动标志 _handleClientStarted.TryRemove(clientId, out _); _stateManager.TryUpdateStateSafely(clientId, state => { state.IsEventSubscribed = false; state.CurrentAction = ""; state.OperStatus = ""; state.RobotArmObject = 0; state.RobotControlMode = 0; state.RobotRunMode = 0; return state; }); // 触发断开连接事件 OnClientDisconnected?.Invoke(this, _stateManager.GetState(clientId) ?? new RobotSocketState { IPAddress = clientId }); return Task.FromResult(null); } /// /// 检查客户端是否已连接 /// public bool IsClientConnected(string ipAddress) { var clientIds = _tcpSocket.GetClientIds(); return clientIds.Contains(ipAddress); } /// /// 发送消息到客户端 /// public async Task SendToClientAsync(string ipAddress, string message) { return await _tcpSocket.SendToClientAsync(ipAddress, message); } /// /// 获取TcpSocketServer引用(用于RobotJob直接访问) /// public TcpSocketServer TcpSocket => _tcpSocket; } }