using System; using System.Diagnostics.CodeAnalysis; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_QuartzJob.Models; using WIDESEAWCS_QuartzJob.Service; using WIDESEAWCS_Tasks.StackerCraneJob; namespace WIDESEAWCS_Tasks { /// /// 堆垛机命令构建器:封装任务到命令对象的转换与地址解析。 /// public class StackerCraneCommandBuilder { private readonly ITaskService _taskService; private readonly IRouterService _routerService; private readonly StackerCraneCommandConfig _config; public StackerCraneCommandBuilder( ITaskService taskService, IRouterService routerService, StackerCraneCommandConfig config) { _taskService = taskService; _routerService = routerService; _config = config; } public object? ConvertToStackerCraneTaskCommand([NotNull] Dt_Task task) { string commandType = GetCommandType(task.Roadway); return commandType switch { "Formation" => BuildCommand(task, CreateFormationCommand(task)), _ => BuildCommand(task, CreateStandardCommand(task)) }; } private string GetCommandType(string roadway) { foreach (var mapping in _config.RoadwayCommandMapping) { if (roadway.Contains(mapping.Key)) { return mapping.Value; } } return _config.DefaultCommandType; } private static StackerCraneTaskCommand CreateStandardCommand(Dt_Task task) { return new StackerCraneTaskCommand { TaskNum = task.TaskNum, WorkType = 1, WorkAction = 1 }; } private static FormationStackerCraneTaskCommand CreateFormationCommand(Dt_Task task) { return new FormationStackerCraneTaskCommand { Barcode = task.PalletCode, TaskNum = task.TaskNum, WorkType = 1, WorkAction = 1, FireAlarm = 0, HeartBeat = 0, FieldName = string.Empty }; } private T? BuildCommand(Dt_Task task, T command) where T : class { TaskTypeGroup taskTypeGroup = task.TaskType.GetTaskTypeGroup(); return taskTypeGroup switch { TaskTypeGroup.InboundGroup => BuildInboundCommand(task, command), TaskTypeGroup.OutbondGroup => BuildOutboundCommand(task, command), TaskTypeGroup.RelocationGroup => BuildRelocationCommand(task, command), _ => command }; } private T? BuildInboundCommand(Dt_Task task, T command) where T : class { int taskType = 0; if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty) { taskType = 100; } else taskType = task.TaskType; Dt_Router? router = _routerService.QueryNextRoute(task.CurrentAddress, task.Roadway, taskType); if (router == null) { _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.CurrentAddress}】信息,无法获取对应的堆垛机取货站台信息"); return null; } SetCommandProperty(command, "StartRow", Convert.ToInt16(router.SrmRow)); SetCommandProperty(command, "StartColumn", Convert.ToInt16(router.SrmColumn)); SetCommandProperty(command, "StartLayer", Convert.ToInt16(router.SrmLayer)); if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer)) { _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"入库任务终点错误,终点:【{task.NextAddress}】"); return null; } SetCommandProperty(command, "EndRow", endRow); SetCommandProperty(command, "EndColumn", endColumn); SetCommandProperty(command, "EndLayer", endLayer); return command; } private T? BuildOutboundCommand(Dt_Task task, T command) where T : class { int taskType = 0; if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty) { taskType = 100; } else taskType = task.TaskType; Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.TargetAddress, taskType); if (router == null) { _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.TargetAddress}】信息,无法获取对应的堆垛机放货站台信息"); return null; } SetCommandProperty(command, "EndRow", Convert.ToInt16(router.SrmRow)); SetCommandProperty(command, "EndColumn", Convert.ToInt16(router.SrmColumn)); SetCommandProperty(command, "EndLayer", Convert.ToInt16(router.SrmLayer)); if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer)) { _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"出库任务起点错误,起点:【{task.CurrentAddress}】"); return null; } SetCommandProperty(command, "StartRow", startRow); SetCommandProperty(command, "StartColumn", startColumn); SetCommandProperty(command, "StartLayer", startLayer); return command; } private T? BuildRelocationCommand(Dt_Task task, T command) where T : class { if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer)) { _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务终点错误,终点:【{task.NextAddress}】"); return null; } SetCommandProperty(command, "EndRow", endRow); SetCommandProperty(command, "EndColumn", endColumn); SetCommandProperty(command, "EndLayer", endLayer); if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer)) { _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务起点错误,起点:【{task.CurrentAddress}】"); return null; } SetCommandProperty(command, "StartRow", startRow); SetCommandProperty(command, "StartColumn", startColumn); SetCommandProperty(command, "StartLayer", startLayer); return command; } private static void SetCommandProperty(T command, string propertyName, object value) where T : class { var property = typeof(T).GetProperty(propertyName); property?.SetValue(command, value); } private static bool TryParseAddress(string address, out short row, out short column, out short layer) { row = column = layer = 0; string[] parts = address.Split("-"); if (parts.Length != 3) { return false; } return short.TryParse(parts[0], out row) && short.TryParse(parts[1], out column) && short.TryParse(parts[2], out layer); } } }