wanshenmean
10 小时以前 f288ccc545f8cc32bc922c96dfb3cab9a1f92ec6
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
using Microsoft.Extensions.Logging;
using System.Net.Sockets;
using WIDESEAWCS_Common;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_Tasks.Workflow.Abstractions;
 
namespace WIDESEAWCS_Tasks
{
    /// <summary>
    /// 机器人消息处理器 - 消息路由入口
    /// </summary>
    /// <remarks>
    /// 核心职责:
    /// 1. 状态接收:从调用方获取机器人最新的状态
    /// 2. 命令分发:根据消息类型分发给不同的处理器
    ///    - 简单命令(如 homing、running):由 <see cref="IRobotSimpleCommandHandler"/> 处理
    ///    - 前缀命令(如 pickfinished、putfinished):由 <see cref="IRobotPrefixCommandHandler"/> 处理
    /// 3. 回包触发:将原始消息回写到客户端
    ///
    /// 这是消息处理管道的入口点,由 TcpSocketServer 的 MessageReceived 事件触发。
    /// </remarks>
    public class RobotMessageHandler : IRobotMessageRouter
    {
        /// <summary>
        /// Socket 客户端网关接口
        /// </summary>
        private readonly ISocketClientGateway _socketClientGateway;
 
        /// <summary>
        /// 机械手状态管理器
        /// </summary>
        private readonly RobotStateManager _stateManager;
 
        /// <summary>
        /// 简单命令处理器
        /// </summary>
        private readonly IRobotSimpleCommandHandler _simpleCommandHandler;
 
        /// <summary>
        /// 前缀命令处理器
        /// </summary>
        private readonly IRobotPrefixCommandHandler _prefixCommandHandler;
 
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<RobotJob> _logger;
 
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="socketClientGateway">Socket 网关</param>
        /// <param name="stateManager">状态管理器</param>
        /// <param name="simpleCommandHandler">简单命令处理器</param>
        /// <param name="prefixCommandHandler">前缀命令处理器</param>
        /// <param name="logger">日志记录器</param>
        public RobotMessageHandler(
            ISocketClientGateway socketClientGateway,
            RobotStateManager stateManager,
            IRobotSimpleCommandHandler simpleCommandHandler,
            IRobotPrefixCommandHandler prefixCommandHandler,
            ILogger<RobotJob> logger)
        {
            _socketClientGateway = socketClientGateway;
            _stateManager = stateManager;
            _simpleCommandHandler = simpleCommandHandler;
            _prefixCommandHandler = prefixCommandHandler;
            _logger = logger;
        }
 
        /// <summary>
        /// 处理接收到的消息
        /// </summary>
        /// <remarks>
        /// 处理流程:
        /// 1. 记录日志(记录原始消息内容)
        /// 2. 尝试用简单命令处理器处理(状态更新类命令)
        ///    - 如果处理成功,回写原消息并更新状态
        /// 3. 如果不是简单命令,检查是否是前缀命令(pickfinished/putfinished)
        ///    - 如果是,调用前缀命令处理器处理
        /// 4. 保持原有行为:简单命令和前缀命令都回写原消息
        ///
        /// 注意:此方法可能在 TCP 消息接收的上下文中被频繁调用,需注意性能。
        /// </remarks>
        /// <param name="message">原始消息字符串</param>
        /// <param name="isJson">消息是否为 JSON 格式(当前未使用)</param>
        /// <param name="client">TCP 客户端连接</param>
        /// <param name="state">机器人当前状态</param>
        /// <returns>响应消息,如果无需回复则返回 null</returns>
        public async Task<string?> HandleMessageReceivedAsync(string message, bool isJson, TcpClient client, RobotSocketState state)
        {
            // 记录接收到的消息日志
            _logger.LogInformation($"接收到客户端【{state.RobotCrane?.DeviceName}】发送消息【{message}】");
            QuartzLogger.Info($"接收到客户端消息【{message}】", state.RobotCrane?.DeviceName);
 
            // 检查任务总数是否未达到上限
            if (state.RobotTaskTotalNum > RobotConst.MaxTaskTotalNum)
            {
                _logger.LogInformation($"接收到客户端【{state.RobotCrane?.DeviceName}】发送消息【{message}】");
                QuartzLogger.Info($"接收到客户端消息【{message}】", state.RobotCrane?.DeviceName);
                await _socketClientGateway.SendMessageAsync(client, message);
                return null;
            }
 
            // 将消息转换为小写(用于简单命令匹配)
            string messageLower = message.ToLowerInvariant();
 
            // 尝试用简单命令处理器处理
            // 简单命令包括:homing、homed、running、pausing、runmode、controlmode 等
            if (await _simpleCommandHandler.HandleAsync(messageLower, state))
            {
                // 处理成功后,将原消息回写到客户端(保持原有行为)
                await _socketClientGateway.SendMessageAsync(client, message);
                QuartzLogger.Info($"发送消息:【{message}】", state.RobotCrane?.DeviceName);
 
                // 安全更新状态到数据库
                _stateManager.TryUpdateStateSafely(state.IPAddress, state);
                return null;
            }
 
            // 如果不是简单命令,检查是否是前缀命令
            // 前缀命令包括:pickfinished、putfinished(后面跟逗号分隔的位置参数)
            if (_prefixCommandHandler.IsPrefixCommand(messageLower))
            {
                // 调用前缀命令处理器
                await _prefixCommandHandler.HandleAsync(message, state, client);
            }
 
            return null;
        }
    }
}