HHRCSHub.cs 4.41 KB
using Microsoft.AspNetCore.SignalR;

namespace Rcs.Api.Hubs
{
    /// <summary>
    /// 机器人状态实时推送 Hub(支持地图隔离)
    /// @author zzy
    /// </summary>
    public class HHRCSHub : Hub
    {
        private readonly ILogger<HHRCSHub> _logger;

        public HHRCSHub(ILogger<HHRCSHub> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 从路径参数获取地图 ID
        /// @author zzy
        /// </summary>
        private string GetMapId()
        {
            if (Context.GetHttpContext()?.Request.RouteValues.TryGetValue("mapId", out var mapId) == true)
            {
                return mapId?.ToString() ?? "default";
            }
            return "default";
        }

        /// <summary>
        /// 生成带地图隔离的组名
        /// @author zzy
        /// </summary>
        private string GetMapGroupName(string baseGroup)
        {
            var mapId = GetMapId();
            return $"{mapId}_{baseGroup}";
        }

        public override async Task OnConnectedAsync()
        {
            var mapId = GetMapId();
            _logger.LogInformation("[HHRCSHub] 客户端连接: {ConnectionId}, 地图ID: {MapId}", Context.ConnectionId, mapId);
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception? exception)
        {
            var mapId = GetMapId();
            _logger.LogInformation("[HHRCSHub] 客户端断开: {ConnectionId}, 地图ID: {MapId}", Context.ConnectionId, mapId);
            await base.OnDisconnectedAsync(exception);
        }

        /// <summary>
        /// 订阅指定的数据类型(支持多选)
        /// 可选值: "robot_status" - 机器人状态, "storage_location" - 库位信息
        /// @author zzy
        /// </summary>
        /// <param name="types">订阅类型数组,如 ["robot_status", "storage_location"]</param>
        public async Task Subscribe(string[] types)
        {
            var mapId = GetMapId();
            foreach (var type in types)
            {
                switch (type)
                {
                    case "robot_status":
                        await Groups.AddToGroupAsync(Context.ConnectionId, GetMapGroupName("robot_status"));
                        _logger.LogInformation("[HHRCSHub] 客户端 {ConnectionId} 订阅机器人状态, 地图ID: {MapId}", Context.ConnectionId, mapId);
                        break;

                    case "storage_location":
                        await Groups.AddToGroupAsync(Context.ConnectionId, GetMapGroupName("storage_location"));
                        _logger.LogInformation("[HHRCSHub] 客户端 {ConnectionId} 订阅库位信息, 地图ID: {MapId}", Context.ConnectionId, mapId);
                        break;

                    default:
                        _logger.LogWarning("[HHRCSHub] 客户端 {ConnectionId} 尝试订阅未知类型: {Type}, 地图ID: {MapId}", Context.ConnectionId, type, mapId);
                        break;
                }
            }
        }

        /// <summary>
        /// 取消订阅指定的数据类型
        /// @author zzy
        /// </summary>
        /// <param name="types">订阅类型数组,如 ["robot_status", "storage_location"]</param>
        public async Task Unsubscribe(string[] types)
        {
            var mapId = GetMapId();
            foreach (var type in types)
            {
                switch (type)
                {
                    case "robot_status":
                        await Groups.RemoveFromGroupAsync(Context.ConnectionId, GetMapGroupName("robot_status"));
                        _logger.LogInformation("[HHRCSHub] 客户端 {ConnectionId} 取消订阅机器人状态, 地图ID: {MapId}", Context.ConnectionId, mapId);
                        break;

                    case "storage_location":
                        await Groups.RemoveFromGroupAsync(Context.ConnectionId, GetMapGroupName("storage_location"));
                        _logger.LogInformation("[HHRCSHub] 客户端 {ConnectionId} 取消订阅库位信息, 地图ID: {MapId}", Context.ConnectionId, mapId);
                        break;

                    default:
                        _logger.LogWarning("[HHRCSHub] 客户端 {ConnectionId} 尝试取消订阅未知类型: {Type}, 地图ID: {MapId}", Context.ConnectionId, type, mapId);
                        break;
                }
            }
        }
    }
}