前言

最近在琢磨怎么优化现有的 WCS(仓库控制系统)。主要想达到这么几个效果:用户能直接在拖拽操作界面,把物料的流转路径配置好;选中某一段路径,系统就能自动生成对应的任务模板;等要创建具体任务的时候,选个模板就行,系统会照着模板生成任务;最后,任务排队、调度,统一由WCS 来调度管理。 趁着现在系统里已经有了一些实现,简单介绍一下开发过程中用到的几个设计模式。


命令模式在WCS中的应用

命令模式能够解耦请求发送者与接收者。在WCS系统设计中,有以下两方面的应用:设备参数变化的快速响应和任务步骤的灵活组装。

设备状态驱动的命令执行

实现机制:

  1. 设备监控服务实时采集设备参数(位置、电量、传感器状态等)
  2. 状态变更时查询命令注册表
  3. 执行匹配的命令对象
// 命令接口定义
public interface ICommand
{
    void Execute();
}

// 具体命令:传送带急停
public class EmergencyStopCommand : ICommand
{
    private readonly Conveyor _conveyor;
    
    public EmergencyStopCommand(Conveyor conveyor)
    {
        _conveyor = conveyor;
    }
    
    public void Execute()
    {
        _conveyor.Stop();
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 传送带 {_conveyor.Id} 已执行急停");
    }
}

// 设备监控服务
public class DeviceMonitorService
{
    private readonly Dictionary<string, ICommand> _commandRegistry = new();
    
    // 注册状态对应的命令
    public void RegisterStatusCommand(string statusCode, ICommand command)
    {
        _commandRegistry[statusCode] = command;
    }
    
    // 处理设备状态变更
    public void HandleStatusChange(string deviceId, string statusCode)
    {
        if (_commandRegistry.TryGetValue(statusCode, out var command))
        {
            command.Execute();
            LogAction(deviceId, statusCode);
        }
    }
    
    private void LogAction(string deviceId, string status)
    {
        Console.WriteLine($"设备 {deviceId} 状态变更: {status}");
    }
}

// 使用示例
var monitor = new DeviceMonitorService();
var conveyorA = new Conveyor("CV-001");

// 配置状态响应命令
monitor.RegisterStatusCommand("OBSTRUCTION_DETECTED", 
    new EmergencyStopCommand(conveyorA));

// 模拟传感器触发
monitor.HandleStatusChange("PHOTO_SENSOR_01", "OBSTRUCTION_DETECTED");

任务流程命令组合

实现机制:

  1. 原子操作封装为独立命令
  2. 任务流程(宏命令)组合多个原子命令
  3. 任务调度器执行任务序列
// 宏命令实现
public class MacroCommand : ICommand
{
    private readonly List<ICommand> _commands = new();
    
    public void AddCommand(ICommand command)
    {
        _commands.Add(command);
    }
    
    public void Execute()
    {
        foreach (var cmd in _commands)
        {
            cmd.Execute();
            Thread.Sleep(100); // 模拟执行间隔
        }
    }
}

// 原子操作命令
public class PickItemCommand : ICommand
{
    private readonly RobotArm _arm;
    private readonly string _itemId;
    
    public PickItemCommand(RobotArm arm, string itemId)
    {
        _arm = arm;
        _itemId = itemId;
    }
    
    public void Execute()
    {
        _arm.Pick(_itemId);
        Console.WriteLine($"已抓取货物: {_itemId}");
    }
}

public class MoveToCommand : ICommand
{
    private readonly AGV _agv;
    private readonly Location _target;
    
    public MoveToCommand(AGV agv, Location target)
    {
        _agv = agv;
        _target = target;
    }
    
    public void Execute()
    {
        _agv.NavigateTo(_target);
        Console.WriteLine($"AGV 已抵达: {_target}");
    }
}

// 任务构建与执行
public void CreateDeliveryTask()
{
    var agv = new AGV("AGV-01");
    var arm = new RobotArm("ARM-02");
    
    var task = new MacroCommand();
    task.AddCommand(new PickItemCommand(arm, "ITEM-1001"));
    task.AddCommand(new MoveToCommand(agv, new Location("ZONE-B")));
    task.AddCommand(new PlaceItemCommand(arm)); // 假设已实现
    
    // 提交到WCS任务队列
    TaskScheduler.Enqueue(task);
}
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐