From ce1292c9cf37195b6abd2699dfc5d6cb3e143c9b Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期日, 12 四月 2026 23:38:19 +0800
Subject: [PATCH] feat(MES): 添加MES接口相关实体和DTO JS扩展文件至JSX格式并更新配置

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs |  139 ++++++++++++++++++++++++++++++----------------
 1 files changed, 90 insertions(+), 49 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
index a0b8a91..571cd45 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
@@ -8,16 +8,21 @@
     public partial class TcpSocketServer
     {
         /// <summary>
-        /// 异步处理与已连接的TCP客户端的通信,处理机器人起重机会话中的传入消息和客户端状态更新。
+        /// 澶勭悊瀹㈡埛绔繛鎺ョ殑娑堟伅寰幆
         /// </summary>
-        /// <remarks>此方法管理客户端连接的生命周期,包括读取消息、更新客户端状态和调用相关事件。
-        /// 当处理结束时,客户端和相关的网络资源将被释放。如果启用心跳或空闲超时选项,
-        /// 将应用额外的取消逻辑。事件调用期间的异常将被捕获并抑制,以确保会话处理的鲁棒性。</remarks>
-        /// <param name="client">表示要处理的远程连接的TCP客户端。方法完成后将释放此对象。</param>
-        /// <param name="clientId">已连接客户端的唯一标识符。用于在整个会话中跟踪和更新客户端状态。</param>
-        /// <param name="cancellationToken">可用于取消客户端处理操作的取消令牌。如果请求取消,方法将立即终止处理。</param>
-        /// <param name="robotCrane">表示与客户端关联的机器人起重机的当前状态对象。用于为消息处理和事件调用提供上下文。</param>
-        /// <returns>表示处理客户端连接的异步操作的任务。当客户端断开连接或请求取消时任务完成。</returns>
+        /// <remarks>
+        /// 鎸佺画鎺ユ敹瀹㈡埛绔秷鎭紝鐩村埌杩炴帴鏂紑鎴栧彇娑堛��
+        /// 澶勭悊娴佺▼锛�
+        /// 1. 鎺ユ敹娑堟伅锛堝抚瑙f瀽锛�
+        /// 2. 鏇存柊瀹㈡埛绔姸鎬侊紙娲昏穬鏃堕棿銆佺紪鐮侊級
+        /// 3. 澶勭悊璁惧娉ㄥ唽
+        /// 4. 瑙﹀彂 MessageReceived 浜嬩欢
+        /// 杩炴帴鏂紑鏃舵竻鐞嗚祫婧愬苟瑙﹀彂 RobotReceived 浜嬩欢銆�
+        /// </remarks>
+        /// <param name="client">TCP 瀹㈡埛绔繛鎺�</param>
+        /// <param name="clientId">瀹㈡埛绔敮涓�鏍囪瘑</param>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <param name="robotCrane">鏈哄櫒浜虹姸鎬�</param>
         public async Task HandleClientAsync(TcpClient client, string clientId, CancellationToken cancellationToken, RobotSocketState robotCrane)
         {
             using (client)
@@ -28,19 +33,21 @@
                 CancellationTokenSource? localCts = null;
                 if (_options.EnableHeartbeat || _options.IdleTimeoutSeconds > 0)
                 {
+                    // 鍒涘缓閾炬帴鐨勫彇娑堜护鐗屾簮
                     localCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                 }
 
                 try
                 {
+                    // 娑堟伅鎺ユ敹寰幆
                     while (!cancellationToken.IsCancellationRequested && client.Connected)
                     {
                         string? message;
                         try
                         {
                             var ct = localCts?.Token ?? cancellationToken;
+                            // 鎺ユ敹瀹屾暣娑堟伅锛堝抚瑙f瀽锛�
                             message = await ReceiveFullMessageAsync(networkStream, _textEncoding, ct);
-                            //message = await reader.ReadLineAsync().WaitAsync(ct);
                         }
                         catch (OperationCanceledException)
                         {
@@ -52,20 +59,23 @@
                             break;
                         }
 
+                        // 鏇存柊瀹㈡埛绔姸鎬�
                         UpdateClientStatus(clientId, message);
 
                         string messageLower = message.ToLowerInvariant();
 
+                        // 澶勭悊娉ㄥ唽娑堟伅
                         if (TryHandleRegister(messageLower, message, clientId, networkStream, cancellationToken))
                         {
                             continue;
                         }
 
+                        // 瑙﹀彂娑堟伅鎺ユ敹浜嬩欢
                         if (MessageReceived != null)
                         {
                             try
                             {
-                                // 判断是否为 JSON 格式
+                                // 鍒ゆ柇鏄惁涓� JSON 鏍煎紡
                                 bool isJsonFormat = TryParseJsonSilent(message);
                                 _ = MessageReceived.Invoke(message, isJsonFormat, client, robotCrane);
                             }
@@ -75,6 +85,7 @@
                 }
                 finally
                 {
+                    // 娓呯悊璧勬簮
                     try { localCts?.Cancel(); localCts?.Dispose(); } catch { }
                     RemoveClient(clientId);
                     try { _ = RobotReceived.Invoke(clientId); } catch { }
@@ -83,17 +94,18 @@
         }
 
         /// <summary>
-        /// 尝试处理来自客户端的设备注册请求。返回一个值指示该消息是否被作为注册请求处理。
+        /// 澶勭悊璁惧娉ㄥ唽娑堟伅
         /// </summary>
-        /// <remarks>如果消息是有效的注册请求且包含非空的设备标识符,
-        /// 则将设备绑定到客户端并发送确认信息。此方法不会因无效消息而抛出异常;
-        /// 它仅返回 false。</remarks>
-        /// <param name="messageLower">客户端消息的小写版本,用于判断消息是否为注册请求。</param>
-        /// <param name="message">包含注册命令和设备标识符的原始客户端消息。</param>
-        /// <param name="clientId">发送注册请求的客户端的唯一标识符。</param>
-        /// <param name="client">与客户端通信的TCP客户端连接。</param>
-        /// <param name="cancellationToken">可用于取消注册操作的取消令牌。</param>
-        /// <returns>如果消息被识别并作为注册请求处理,则返回 true;否则返回 false。</returns>
+        /// <remarks>
+        /// 娉ㄥ唽娑堟伅鏍煎紡锛歳egister,{deviceId}
+        /// 灏嗚澶� ID 缁戝畾鍒板綋鍓嶅鎴风 ID銆�
+        /// </remarks>
+        /// <param name="messageLower">娑堟伅灏忓啓鐗堟湰</param>
+        /// <param name="message">鍘熷娑堟伅</param>
+        /// <param name="clientId">瀹㈡埛绔� ID</param>
+        /// <param name="networkStream">缃戠粶娴�</param>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <returns>鏄惁澶勭悊浜嗘敞鍐屾秷鎭�</returns>
         private bool TryHandleRegister(string messageLower, string message, string clientId, NetworkStream networkStream, CancellationToken cancellationToken)
         {
             if (!messageLower.StartsWith("register,"))
@@ -101,14 +113,17 @@
                 return false;
             }
 
+            // 鎻愬彇璁惧 ID
             string deviceId = message.Substring("register,".Length).Trim();
             if (!string.IsNullOrEmpty(deviceId))
             {
                 lock (_syncRoot)
                 {
+                    // 缁戝畾璁惧鍒板鎴风
                     _deviceBindings[deviceId] = clientId;
                 }
 
+                // 鍥炲娉ㄥ唽鎴愬姛
                 _ = WriteToClientAsync(clientId, networkStream, $"Registered,{deviceId}", cancellationToken);
             }
 
@@ -116,20 +131,27 @@
         }
 
         /// <summary>
-        /// 更新客户端状态
+        /// 鏇存柊瀹㈡埛绔姸鎬�
         /// </summary>
-        /// <param name="clientId"></param>
-        /// <param name="message"></param>
+        /// <remarks>
+        /// 鏇存柊鏈�鍚庢椿璺冩椂闂村拰瀛楃缂栫爜銆�
+        /// 濡傛灉寮�鍚簡鑷姩缂栫爜妫�娴嬶紝鏍规嵁娑堟伅鍐呭鍒ゆ柇鏄� UTF-8 杩樻槸 GBK銆�
+        /// </remarks>
+        /// <param name="clientId">瀹㈡埛绔� ID</param>
+        /// <param name="message">鏈�鏂版帴鏀剁殑娑堟伅</param>
         private void UpdateClientStatus(string clientId, string message)
         {
             lock (_syncRoot)
             {
+                // 鏇存柊鏈�鍚庢椿璺冩椂闂�
                 _clientLastActive[clientId] = DateTime.Now;
 
+                // 濡傛灉杩樻病鏈夎褰曠紪鐮�
                 if (!_clientEncodings.ContainsKey(clientId))
                 {
                     if (_options.AutoDetectEncoding && _autoDetectedGb2312 != null)
                     {
+                        // 鑷姩妫�娴嬬紪鐮侊細JSON 鎴� UTF-8 瀛楄妭鐗瑰緛鍒欑敤 UTF-8锛屽惁鍒欑敤 GBK
                         bool isUtf8 = TryParseJsonSilent(message) || IsLikelyUtf8(_textEncoding.GetBytes(message));
                         _clientEncodings[clientId] = isUtf8 ? _textEncoding : _autoDetectedGb2312;
                     }
@@ -142,13 +164,11 @@
         }
 
         /// <summary>
-        /// 写入消息到客户端
+        /// 寮傛鍙戦�佹秷鎭埌瀹㈡埛绔�
         /// </summary>
-        /// <param name="clientId"></param>
-        /// <param name="networkStream"></param>
-        /// <param name="message"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
+        /// <remarks>
+        /// 鍐呴儴鏂规硶锛屼笉浣跨敤甯ф牸寮忥紝鐩存帴鍙戦�佸師濮嬫秷鎭��
+        /// </remarks>
         private async Task WriteToClientAsync(string clientId, NetworkStream networkStream, string message, CancellationToken cancellationToken)
         {
             SemaphoreSlim? sem = null;
@@ -175,10 +195,13 @@
         }
 
         /// <summary>
-        /// 添加消息帧头尾
+        /// 鏋勫缓甯ф秷鎭�
         /// </summary>
-        /// <param name="message"></param>
-        /// <returns></returns>
+        /// <remarks>
+        /// 鍦ㄦ秷鎭墠鍚庢坊鍔犲ご灏炬爣璇嗐��
+        /// </remarks>
+        /// <param name="message">鍘熷娑堟伅</param>
+        /// <returns>甯﹀抚鏍囪瘑鐨勬秷鎭�</returns>
         private string BuildFramedMessage(string message)
         {
             var header = _options.MessageHeader ?? string.Empty;
@@ -187,10 +210,14 @@
         }
 
         /// <summary>
-        /// JSON格式尝试解析(静默失败)
+        /// 闈欓粯灏濊瘯瑙f瀽 JSON
         /// </summary>
-        /// <param name="message"></param>
-        /// <returns></returns>
+        /// <remarks>
+        /// 鍒ゆ柇娑堟伅鏄惁浠� { 鎴� [ 寮�澶达紝濡傛灉鏄垯灏濊瘯瑙f瀽銆�
+        /// 瑙f瀽澶辫触涓嶆姏寮傚父銆�
+        /// </remarks>
+        /// <param name="message">娑堟伅鍐呭</param>
+        /// <returns>鏄惁鏄湁鏁堢殑 JSON 鏍煎紡</returns>
         private static bool TryParseJsonSilent(string message)
         {
             if (string.IsNullOrWhiteSpace(message)) return false;
@@ -200,30 +227,35 @@
         }
 
         /// <summary>
-        /// utf-8 可能性检测
+        /// 鍒ゆ柇瀛楄妭鏁扮粍鏄惁涓� UTF-8 缂栫爜
         /// </summary>
-        /// <param name="data"></param>
-        /// <returns></returns>
+        /// <remarks>
+        /// 閫氳繃妫�鏌ュ瓧鑺傚簭鍒楁槸鍚︾鍚� UTF-8 澶氬瓧鑺傚瓧绗︾殑缂栫爜瑙勫垯銆�
+        /// </remarks>
+        /// <param name="data">瀛楄妭鏁扮粍</param>
+        /// <returns>鏄惁鍙兘鏄� UTF-8 缂栫爜</returns>
         private static bool IsLikelyUtf8(byte[] data)
         {
             int i = 0;
             while (i < data.Length)
             {
                 byte b = data[i];
-                if (b <= 0x7F) { i++; continue; }
-                if (b >= 0xC2 && b <= 0xDF)
+                if (b <= 0x7F) { i++; continue; }  // ASCII 瀛楃
+
+                // 妫�鏌ュ瀛楄妭瀛楃
+                if (b >= 0xC2 && b <= 0xDF)  // 2瀛楄妭瀛楃
                 {
                     if (i + 1 >= data.Length) return false;
                     if ((data[i + 1] & 0xC0) != 0x80) return false;
                     i += 2; continue;
                 }
-                if (b >= 0xE0 && b <= 0xEF)
+                if (b >= 0xE0 && b <= 0xEF)  // 3瀛楄妭瀛楃
                 {
                     if (i + 2 >= data.Length) return false;
                     if ((data[i + 1] & 0xC0) != 0x80 || (data[i + 2] & 0xC0) != 0x80) return false;
                     i += 3; continue;
                 }
-                if (b >= 0xF0 && b <= 0xF4)
+                if (b >= 0xF0 && b <= 0xF4)  // 4瀛楄妭瀛楃
                 {
                     if (i + 3 >= data.Length) return false;
                     if ((data[i + 1] & 0xC0) != 0x80 || (data[i + 2] & 0xC0) != 0x80 || (data[i + 3] & 0xC0) != 0x80) return false;
@@ -235,12 +267,16 @@
         }
 
         /// <summary>
-        /// 读取完整消息
+        /// 鎺ユ敹瀹屾暣娑堟伅锛堝抚瑙f瀽锛�
         /// </summary>
-        /// <param name="networkStream">字节流</param>
-        /// <param name="encoding">编码格式</param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
+        /// <remarks>
+        /// 鏍规嵁閰嶇疆鐨勫ご灏炬爣璇嗚В鏋愭秷鎭��
+        /// 濡傛灉鏈厤缃ご灏撅紝鍒欎竴鐩磋鍒版暟鎹笉鍙敤銆�
+        /// </remarks>
+        /// <param name="networkStream">缃戠粶娴�</param>
+        /// <param name="encoding">瀛楃缂栫爜</param>
+        /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+        /// <returns>鎺ユ敹鍒扮殑娑堟伅</returns>
         private async Task<string?> ReceiveFullMessageAsync(NetworkStream networkStream, Encoding encoding, CancellationToken cancellationToken)
         {
             var header = _options.MessageHeader ?? string.Empty;
@@ -251,15 +287,18 @@
 
             while (true)
             {
+                // 璇诲彇鏁版嵁
                 int bytesRead = await networkStream.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken);
                 if (bytesRead <= 0)
                 {
                     if (builder.Length == 0) return null;
+                    // 鏃犲ご灏鹃厤缃椂锛岃繑鍥炲凡鏈夋暟鎹�
                     return string.IsNullOrEmpty(header) && string.IsNullOrEmpty(footer) ? builder.ToString() : null;
                 }
 
                 builder.Append(encoding.GetString(buffer, 0, bytesRead));
 
+                // 濡傛灉娌℃湁閰嶇疆澶村熬锛屼笖鏁版嵁涓嶅彲鐢紝杩斿洖宸叉湁鏁版嵁
                 if (string.IsNullOrEmpty(header) && string.IsNullOrEmpty(footer))
                 {
                     if (!networkStream.DataAvailable)
@@ -269,6 +308,7 @@
                     continue;
                 }
 
+                // 鏌ユ壘甯уご
                 var data = builder.ToString();
                 var headerIndex = string.IsNullOrEmpty(header) ? 0 : data.IndexOf(header, StringComparison.Ordinal);
                 if (headerIndex < 0)
@@ -276,6 +316,7 @@
                     continue;
                 }
 
+                // 鎻愬彇甯у唴瀹�
                 var startIndex = headerIndex + header.Length;
                 var footerIndex = string.IsNullOrEmpty(footer) ? data.Length : data.IndexOf(footer, startIndex, StringComparison.Ordinal);
                 if (footerIndex >= 0)
@@ -287,4 +328,4 @@
             return builder.ToString();
         }
     }
-}
\ No newline at end of file
+}

--
Gitblit v1.9.3