wanshenmean
2026-03-26 8e42d0c1b7ae36cff2e7c69999117911a4b6f300
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
@@ -4,86 +4,164 @@
namespace WIDESEAWCS_Tasks
{
    /// <summary>
    /// 机械手Socket通信状态
    /// 机械手 Socket 通信状态数据类
    /// </summary>
    /// <remarks>
    /// 该类用于在 Redis 缓存中存储机械手的实时状态,包括位置、任务、手臂对象等信息。
    /// 所有属性均设计为线程安全更新,通过 <see cref="RobotStateManager"/> 的版本控制机制来防止并发覆盖。
    /// </remarks>
    public class RobotSocketState
    {
        /// <summary>
        /// 机械手的 IP 地址,作为缓存键的唯一标识
        /// </summary>
        public string IPAddress { get; set; } = string.Empty;
        /// <summary>
        /// 版本号,用于防止并发更新时旧值覆盖新值
        /// 每次修改状态时都应该更新此值
        /// 版本号,用于乐观并发控制
        /// </summary>
        /// <remarks>
        /// 每次修改状态时更新为 DateTime.UtcNow.Ticks。
        /// <see cref="RobotStateManager"/> 使用此字段实现乐观锁,防止并发更新时旧值覆盖新值。
        /// </remarks>
        public long Version { get; set; } = DateTime.UtcNow.Ticks;
        /// <summary>
        /// 是否已订阅消息事件
        /// 是否已订阅消息事件标志
        /// </summary>
        /// <remarks>
        /// 确保每个客户端只启动一次消息处理循环,避免重复订阅导致的消息重复处理。
        /// </remarks>
        public bool IsEventSubscribed { get; set; }
        /// <summary>
        /// 机械手运行模式
        /// </summary>
        /// <remarks>
        /// 1: 手动模式
        /// 2: 自动模式
        /// 当 RobotRunMode == 2 且 RobotControlMode == 1 时,系统进入自动控制状态。
        /// </remarks>
        public int? RobotRunMode { get; set; }
        /// <summary>
        /// 机械手控制模式
        /// </summary>
        /// <remarks>
        /// 1: 客户端控制
        /// 2: 未知/其他
        /// 与 RobotRunMode 配合判断机器人的当前控制状态。
        /// </remarks>
        public int? RobotControlMode { get; set; }
        /// <summary>
        /// 机械手是否抓取物料,0-无物料,1-有物料
        /// 机械手手臂抓取对象状态
        /// </summary>
        /// <remarks>
        /// 0: 无物料(手臂空闲)
        /// 1: 有物料(已抓取货物)
        /// 用于判断机器人是否可以执行下一步动作。
        /// </remarks>
        public int? RobotArmObject { get; set; }
        /// <summary>
        /// 机械手设备信息
        /// 机械手设备基础信息
        /// </summary>
        /// <remarks>
        /// 包含设备的 DeviceCode、DeviceName、IPAddress 等基础信息。
        /// 在状态初始化时从 JobDetail.JobDataMap 获取并缓存。
        /// </remarks>
        public RobotCraneDevice? RobotCrane { get; set; }
        /// <summary>
        /// 当前动作
        /// 机械手当前正在执行的动作
        /// </summary>
        /// <remarks>
        /// 可能的值:
        /// - "Picking": 取货中
        /// - "Putting": 放货中
        /// - "PickFinished": 取货完成
        /// - "PutFinished": 放货完成
        /// - "AllPickFinished": 全部取货完成
        /// - "AllPutFinished": 全部放货完成
        /// </remarks>
        public string? CurrentAction { get; set; }
        /// <summary>
        /// 当前状态
        /// 机械手当前运行状态
        /// </summary>
        /// <remarks>
        /// 可能的值:
        /// - "Homing": 回零中
        /// - "Homed": 已回零
        /// - "Running": 运行中
        /// - "Pausing": 暂停中
        /// - "Warming": 预热中
        /// - "Emstoping": 急停中
        /// </remarks>
        public string? OperStatus { get; set; }
        /// <summary>
        /// 取货完成位置
        /// 最近一次取货完成的位置数组
        /// </summary>
        /// <remarks>
        /// 数组中的每个元素代表一个电池位置编号。
        /// 用于记录取货动作涉及的货位,供后续组盘/拆盘操作使用。
        /// </remarks>
        public int[]? LastPickPositions { get; set; }
        /// <summary>
        /// 放货完成位置
        /// 最近一次放货完成的位置数组
        /// </summary>
        /// <remarks>
        /// 数组中的每个元素代表一个电池位置编号。
        /// 用于记录放货动作涉及的货位。
        /// </remarks>
        public int[]? LastPutPositions { get; set; }
        /// <summary>
        /// 抓取位置条码
        /// 电池/货位条码列表
        /// </summary>
        /// <remarks>
        /// 在组盘操作时用于记录生成的托盘条码。
        /// 每个条码格式为 "TRAY" + 日期 + 时间 + 随机数。
        /// </remarks>
        public List<string> CellBarcode { get; set; } = new List<string>();
        /// <summary>
        /// 当前抓取任务
        /// 机械手当前正在执行的任务
        /// </summary>
        /// <remarks>
        /// 当任务下发到机器人后,该字段保存任务详情。
        /// 任务类型包括:组盘(500)、换盘(510)、拆盘(520)。
        /// </remarks>
        public Dt_RobotTask? CurrentTask { get; set; }
        /// <summary>
        /// 是否需要拆盘
        /// 是否需要执行拆盘任务
        /// </summary>
        /// <remarks>
        /// 当任务类型为 SplitPallet (520) 时设为 true。
        /// 拆盘任务将电池从托盘上取下并逐个放置到目标位置。
        /// </remarks>
        public bool IsSplitPallet { get; set; }
        /// <summary>
        /// 是否需要组盘
        /// 是否需要执行组盘任务
        /// </summary>
        /// <remarks>
        /// 当任务类型为 GroupPallet (500) 或 ChangePallet (510) 时设为 true。
        /// 组盘任务将多个电池组合到同一个托盘上。
        /// </remarks>
        public bool IsGroupPallet { get; set; }
        /// <summary>
        /// 任务总数
        /// 机器人已处理的任务总数
        /// </summary>
        /// <remarks>
        /// 累计记录机器人已完成处理的电池/货物数量。
        /// 当达到 MaxTaskTotalNum (48) 时,不再下发新任务。
        /// </remarks>
        public int RobotTaskTotalNum { get; set; }
    }
}