IProtocolService.cs 8.46 KB
using Rcs.Application.Common;
using Rcs.Domain.Entities;
using Rcs.Domain.Models.VDA5050;

namespace Rcs.Application.Services.Protocol;

/// <summary>
/// 协议服务接口。
/// 定义机器人通信协议的统一抽象,支持 VDA5050 和自定义协议。
/// @author zzy
/// </summary>
public interface IProtocolService
{
    /// <summary>
    /// 当前协议类型。
    /// </summary>
    ProtocolType ProtocolType { get; }

    /// <summary>
    /// 根据任务准备并发送订单指令。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="task">任务实体。</param>
    /// <param name="ct">取消令牌。</param>
    Task<ApiResponse> PrepareSendOrderAsync(Robot robot, RobotTask task, CancellationToken ct = default);

    /// <summary>
    /// 发送订单指令(直接指定目标节点)。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="priority">优先级。</param>
    /// <param name="endNodeId">终点节点。</param>
    /// <param name="containerId">容器号。</param>
    /// <param name="ct">取消令牌。</param>
    Task<ApiResponse> SendOrderAsync(
        Robot robot,
        int priority,
        Guid endNodeId,
        string? containerId,
        CancellationToken ct = default);

    /// <summary>
    /// 发送带任务上下文的订单(支持仅传递上下文ID,ID可为空)。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="priority">优先级。</param>
    /// <param name="endNodeId">终点节点ID。</param>
    /// <param name="containerId">容器ID。</param>
    /// <param name="taskId">任务ID(可空)。</param>
    /// <param name="subTaskId">子任务ID(可空)。</param>
    /// <param name="taskTemplateId">任务模板ID(可空)。</param>
    /// <param name="subTaskSequence">子任务序号(可空)。</param>
    /// <param name="taskCode">任务编码(可空)。</param>
    /// <param name="mapId">地图ID(可空,空时使用机器人当前地图)。</param>
    /// <param name="ct">取消令牌。</param>
    Task<ApiResponse> SendOrderWithTaskContextAsync(
        Robot robot,
        int priority,
        Guid endNodeId,
        string? containerId,
        Guid? taskId = null,
        Guid? subTaskId = null,
        Guid? taskTemplateId = null,
        int? subTaskSequence = null,
        string? taskCode = null,
        Guid? mapId = null,
        CancellationToken ct = default);

    /// <summary>
    /// 取消指定订单。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="orderId">订单ID。</param>
    /// <param name="ct">取消令牌。</param>
    Task CancelOrderAsync(Robot robot, string? orderId, CancellationToken ct = default);

    /// <summary>
    /// 取消机器人所有任务。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="ct">取消令牌。</param>
    Task CancelRobotTasksAsync(Robot robot, CancellationToken ct = default);

    /// <summary>
    /// 发送即时动作指令。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="actions">即时动作。</param>
    /// <param name="ct">取消令牌。</param>
    Task SendInstantActionAsync(Robot robot, InstantAction actions, CancellationToken ct = default);

    /// <summary>
    /// 复位机器人。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="ct">取消令牌。</param>
    Task ResetRobotAsync(Robot robot, CancellationToken ct = default);

    /// <summary>
    /// 确认异常。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="ct">取消令牌。</param>
    Task ConfirmExceptionAsync(Robot robot, CancellationToken ct = default);

    /// <summary>
    /// 开始充电。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="actionName">充电动作名称。</param>
    /// <param name="ct">取消令牌。</param>
    Task<ApiResponse> StartChargingAsync(Robot robot, string actionName, CancellationToken ct = default);

    /// <summary>
    /// 停止充电。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="ct">取消令牌。</param>
    Task<ApiResponse> StopChargingAsync(Robot robot, CancellationToken ct = default);

    /// <summary>
    /// 暂停机器人。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="ct">取消令牌。</param>
    Task RobotPauseAsync(Robot robot, CancellationToken ct = default);

    /// <summary>
    /// 取消暂停机器人。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="ct">取消令牌。</param>
    Task RobotUnPauseAsync(Robot robot, CancellationToken ct = default);

    /// <summary>
    /// 机器人重定位。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="mapCode">地图编码。</param>
    /// <param name="x">X 坐标。</param>
    /// <param name="y">Y 坐标。</param>
    /// <param name="theta">角度。</param>
    /// <param name="ct">取消令牌。</param>
    Task<ApiResponse> ReLocationAsync(Robot robot, string mapCode, double x, double y, double theta, CancellationToken ct = default);

    /// <summary>
    /// 发送下一段路径指令。
    /// 用于分段下发场景,将路径拆分为多段依次发送给机器人。
    /// </summary>
    /// <param name="robot">机器人实体。</param>
    /// <param name="currentSubTask">当前子任务。</param>
    /// <param name="ct">取消令牌。</param>
    /// <param name="reExec">是否重新执行。</param>
    /// <returns>操作响应。</returns>
    Task<ApiResponse> SendNextSegmentAsync(Robot robot, RobotSubTask currentSubTask, CancellationToken ct = default, bool reExec = false);

    /// <summary>
    /// 发送下一段路径指令(通过机器人标识查找)。
    /// </summary>
    /// <param name="robotManufacturer">机器人厂商。</param>
    /// <param name="robotSerialNumber">机器人序列号。</param>
    /// <param name="ct">取消令牌。</param>
    /// <param name="reExec">是否重新执行。</param>
    /// <returns>操作响应。</returns>
    Task<ApiResponse> SendNextSegmentAsync(string robotManufacturer, string robotSerialNumber,
        CancellationToken ct = default, bool reExec = false);

    /// <summary>
    /// 判断是否所有段已发送完毕。
    /// 用于分段下发场景,检查当前任务的所有路径段是否均已下发。
    /// </summary>
    /// <param name="robotManufacturer">机器人厂商。</param>
    /// <param name="robotSerialNumber">机器人序列号。</param>
    /// <param name="ct">取消令牌。</param>
    /// <returns>是否全部发送完毕。</returns>
    Task<bool> IsAllSegmentsSentAsync(string robotManufacturer, string robotSerialNumber, CancellationToken ct = default);

    /// <summary>
    /// 判断机器人当前是否行驶在已下发路径集合中的最后一段路径上。
    /// 用于决定是否需要继续下发下一段路径。
    /// </summary>
    /// <param name="robotManufacturer">机器人厂商。</param>
    /// <param name="robotSerialNumber">机器人序列号。</param>
    /// <param name="ct">取消令牌。</param>
    /// <returns>是否在最后一段路径上。</returns>
    Task<bool> IsOnLastSentSegmentAsync(string robotManufacturer, string robotSerialNumber, CancellationToken ct = default);

    /// <summary>
    /// 根据 VDA5050 State 消息判断订单是否完成。
    /// 通过解析机器人上报的状态信息,自动识别订单完成条件并标记完成。
    /// </summary>
    /// <param name="robotManufacturer">机器人厂商。</param>
    /// <param name="robotSerialNumber">机器人序列号。</param>
    /// <param name="stateInfo">VDA5050 状态信息。</param>
    /// <param name="ct">取消令牌。</param>
    /// <returns>是否已完成订单。</returns>
    Task<bool> TryCompleteOrderFromStateAsync(
        string robotManufacturer, string robotSerialNumber,
        State stateInfo, CancellationToken ct = default);

    /// <summary>
    /// 清除指定机器人的所有 VDA 路径缓存。
    /// </summary>
    /// <param name="robotId">机器人ID。</param>
    /// <returns>异步任务。</returns>
    Task ClearAllVdaPathCacheAsync(Guid robotId);
}