wanshenmean
2026-03-17 737dec3c384f394fd6f9849b4480b697d1ba35d5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
using System.Collections.Concurrent;
using System.Net.Sockets;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_Tasks.SocketServer;
 
namespace WIDESEAWCS_Tasks
{
    /// <summary>
    /// 机械手客户端连接管理器 - 负责TCP客户端连接管理和事件订阅
    /// </summary>
    public class RobotClientManager
    {
        private readonly TcpSocketServer _tcpSocket;
        private readonly RobotStateManager _stateManager;
 
        // 跟踪已经启动 HandleClientAsync 的客户端
        private static readonly ConcurrentDictionary<string, bool> _handleClientStarted = new();
        private static int _eventSubscribedFlag;
 
        public event EventHandler<RobotSocketState>? OnClientDisconnected;
 
        public RobotClientManager(TcpSocketServer tcpSocket, RobotStateManager stateManager)
        {
            _tcpSocket = tcpSocket;
            _stateManager = stateManager;
        }
 
        /// <summary>
        /// 确保客户端已连接并订阅消息事件
        /// </summary>
        /// <param name="ipAddress">设备IP地址</param>
        /// <param name="robotCrane">机器人设备信息</param>
        /// <returns>客户端是否可用(已连接且消息处理已启动)</returns>
        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;
        }
 
        /// <summary>
        /// 事件:客户端断开连接时触发
        /// </summary>
        private Task<string?> 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<string?>(null);
        }
 
        /// <summary>
        /// 检查客户端是否已连接
        /// </summary>
        public bool IsClientConnected(string ipAddress)
        {
            var clientIds = _tcpSocket.GetClientIds();
            return clientIds.Contains(ipAddress);
        }
 
        /// <summary>
        /// 发送消息到客户端
        /// </summary>
        public async Task<bool> SendToClientAsync(string ipAddress, string message)
        {
            return await _tcpSocket.SendToClientAsync(ipAddress, message);
        }
 
        /// <summary>
        /// 获取TcpSocketServer引用(用于RobotJob直接访问)
        /// </summary>
        public TcpSocketServer TcpSocket => _tcpSocket;
    }
}