#
Junjie
2024-03-28 61e30cbd7d5548ba4c94e105319c8bff878f88db
#
3个文件已添加
5个文件已修改
350 ■■■■■ 已修改文件
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/kernel/command/ShuttleCommandService.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/command/ShuttleCommand.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/command/ShuttleRedisCommand.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/enums/ShuttleCommandModeType.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/DeviceTimer.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/model/protocol/ShuttleProtocol.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/thread/impl/SurayShuttleThread.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/action/ShuttleAction.java
New file
@@ -0,0 +1,181 @@
package com.zy.asrs.wcs.core.action;
import com.alibaba.fastjson.JSON;
import com.zy.asrs.wcs.core.model.NavigateNode;
import com.zy.asrs.wcs.core.model.command.ShuttleAssignCommand;
import com.zy.asrs.wcs.core.model.command.ShuttleCommand;
import com.zy.asrs.wcs.core.model.command.ShuttleRedisCommand;
import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType;
import com.zy.asrs.wcs.core.utils.NavigateMapUtils;
import com.zy.asrs.wcs.core.utils.RedisUtil;
import com.zy.asrs.wcs.core.utils.Utils;
import com.zy.asrs.wcs.rcs.News;
import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant;
import com.zy.asrs.wcs.rcs.entity.Device;
import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType;
import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol;
import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ShuttleAction {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private NavigateMapUtils navigateMapUtils;
    public synchronized boolean assignWork(Device device, ShuttleAssignCommand assignCommand) {
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
        if (shuttleThread == null) {
            return false;
        }
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return false;
        }
        ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
        redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
        redisCommand.setCommandStep(0);//命令执行步序
        redisCommand.setAssignCommand(assignCommand);//命令
        //任务数据保存到redis
        if (redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand))) {
            shuttleProtocol.setTaskNo(assignCommand.getTaskNo().intValue());
            return true;
        }
        return false;
    }
    public synchronized boolean executeWork(Device device, Integer taskNo) {
        Object obj = redisUtil.get(DeviceRedisConstant.SHUTTLE_WORK_FLAG + taskNo);
        if (obj == null) {
            return false;
        }
        ShuttleRedisCommand redisCommand = JSON.parseObject(obj.toString(), ShuttleRedisCommand.class);
        if (redisCommand == null) {
            return false;
        }
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue());
        if (shuttleThread == null) {
            return false;
        }
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return false;
        }
        //四向穿梭车空闲、有任务、标记为true、存在任务指令,需要执行任务的下一条指令
        if (!shuttleProtocol.getIdle()
                || shuttleProtocol.getTaskNo() == 0
                || !shuttleProtocol.getPakMk()) {
            return false;
        }
        List<ShuttleCommand> commands = redisCommand.getAssignCommand().getCommands();
        if (commands.isEmpty()) {
            return false;
        }
        ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
        int commandStep = redisCommand.getCommandStep();
        // 完结上一条命令
        if (commandStep != 0) {
            ShuttleCommand command = commands.get(commandStep - 1);
            if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
                // 正常移动
                if (command.getTargetLocNo().equals(shuttleProtocol.getCurrentLocNo())) {
                    command.setComplete(true);
                    //解锁锁定路径,上一条路径
                    List<NavigateNode> nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class);//进行深度copy
                    if (nodes != null) {
                        NavigateNode targetNode = assignCommand.getNodes().get(assignCommand.getNodes().size() - 1);//最终节点
                        NavigateNode node = nodes.get(nodes.size() - 1);
                        if (!(targetNode.getX() == node.getX() && targetNode.getY() == node.getY())) {
                            nodes.remove(nodes.size() - 1);//剔除尾节点
                        }
                        boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(shuttleProtocol.getCurrentLocNo()), shuttleProtocol.getShuttleNo(), nodes, false);//解锁路径
                        if (!result) {
                            return false;//解锁失败
                        }
                    }
                }
            } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id) {
                // 托盘顶升
                //判断是否顶升到位
                if (shuttleProtocol.getHasLift()) {
                    //判断是否有物
                    if (shuttleProtocol.getHasPallet()) {
                        command.setComplete(true);
                    }
                }
            } else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {
                // 托盘下降命令
                // 判断是否下降到位
                if (!shuttleProtocol.getHasLift()) {
                    command.setComplete(true);
                }
            } else if (command.getMode() == ShuttleCommandModeType.CHARGE.id) {
                // 充电开关
                //判断小车充电状态
                if (shuttleProtocol.getHasCharge()) {
                    command.setComplete(true);
                }
            }else {
                command.setComplete(true);//其他命令默认认为完成
            }
            // 更新redis数据
            redisUtil.set(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
            if (!command.getComplete()) {
                return false;
            }
            //判断是否为最后一条命令且命令执行完成,抛出等待确认状态
            ShuttleCommand endCommand = commands.get(commands.size() - 1);
            if (endCommand.getComplete()) {
                News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands));
                // 系统任务
                if (assignCommand.getAuto()) {
                    if (!assignCommand.getCharge()) {
                        //对主线程抛出等待确认状态waiting
                        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                    }else {
                        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
                    }
                    News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                    // 手动任务
                } else {
                    //手动模式不抛出等待状态,直接复位空闲状态
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                    //任务号清零
                    shuttleProtocol.setTaskNo(0);
                    //标记复位
                    shuttleProtocol.setPakMk(true);
                    News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                }
                //删除redis
                redisUtil.del(DeviceRedisConstant.SHUTTLE_WORK_FLAG + redisCommand.getWrkNo());
                return false;//禁止再下发命令
            }
        }
        return true;
    }
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/kernel/command/ShuttleCommandService.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.asrs.framework.common.Cools;
import com.zy.asrs.framework.exception.CoolException;
import com.zy.asrs.wcs.core.action.ShuttleAction;
import com.zy.asrs.wcs.core.entity.Loc;
import com.zy.asrs.wcs.core.model.NavigateNode;
import com.zy.asrs.wcs.core.model.command.ShuttleAssignCommand;
@@ -50,6 +51,8 @@
    private LocService locService;
    @Autowired
    private NavigateMapUtils navigateMapUtils;
    @Autowired
    private ShuttleAction shuttleAction;
    // 计算
    public Boolean accept(Motion motion) {
@@ -365,16 +368,14 @@
        if (motion.getOrigin() != null && motion.getTarget() != null) {
            //所使用的路径进行锁定禁用
            boolean lockResult = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(motion.getTarget()), Integer.parseInt(shuttleProtocol.getShuttleNo()), assignCommand.getNodes(), true);//所使用的路径进行锁定禁用
            boolean lockResult = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(motion.getTarget()), shuttleProtocol.getShuttleNo(), assignCommand.getNodes(), true);//所使用的路径进行锁定禁用
            if (!lockResult) {
                return false;//锁定失败
            }
//            shuttleThread.assignWork(assignCommand);
        }else {
//            shuttleThread.assignWork(assignCommand);
        }
        return Boolean.TRUE;
        boolean result = shuttleAction.assignWork(shuttleThread.getDevice(), assignCommand);
        return result;
    }
    public Boolean finish(Motion motion) {
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/command/ShuttleCommand.java
@@ -1,6 +1,7 @@
package com.zy.asrs.wcs.core.model.command;
import com.zy.asrs.wcs.core.model.NavigateNode;
import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType;
import lombok.Data;
import java.util.List;
@@ -22,6 +23,16 @@
    private Integer taskNo = 0;
    /**
     * 命令类型
     */
    private Integer mode = ShuttleCommandModeType.NONE.id;
    /**
     * 目标库位
     */
    private String targetLocNo;
    /**
     * 报文内容
     */
    private String body;
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/command/ShuttleRedisCommand.java
New file
@@ -0,0 +1,28 @@
package com.zy.asrs.wcs.core.model.command;
import lombok.Data;
import java.io.Serializable;
/**
 * 四向穿梭车命令-存储在redis
 */
@Data
public class ShuttleRedisCommand implements Serializable {
    //四向穿梭车号
    private Short shuttleNo;
    //工作号
    private Short wrkNo;
    //命令执行步序
    private Integer commandStep;
    //命令
    private ShuttleAssignCommand assignCommand;
    //提升机安全锁定标记
    private Boolean liftSecurityMk = false;
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/enums/ShuttleCommandModeType.java
New file
@@ -0,0 +1,51 @@
package com.zy.asrs.wcs.core.model.enums;
/**
 * 四向穿梭车命令类型
 */
public enum ShuttleCommandModeType {
    NONE(-1, "未知类型"),
    MOVE(1, "移动"),
    IN_LIFT(2, "进提升机"),
    OUT_LIFT(3, "出提升机"),
    CHARGE(4, "充电"),
    PALLET_LIFT(5, "托盘顶升"),
    PALLET_DOWN(6, "托盘下降"),
    RESET(8, "复位"),
    ;
    public Integer id;
    public String desc;
    ShuttleCommandModeType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static ShuttleCommandModeType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ShuttleCommandModeType type : ShuttleCommandModeType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static ShuttleCommandModeType get(ShuttleCommandModeType type) {
        if (null == type) {
            return null;
        }
        for (ShuttleCommandModeType type1 : ShuttleCommandModeType.values()) {
            if (type1 == type) {
                return type1;
            }
        }
        return null;
    }
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/timer/DeviceTimer.java
@@ -1,10 +1,20 @@
package com.zy.asrs.wcs.core.timer;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.asrs.wcs.core.action.ShuttleAction;
import com.zy.asrs.wcs.core.utils.RedisUtil;
import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant;
import com.zy.asrs.wcs.rcs.entity.Device;
import com.zy.asrs.wcs.rcs.entity.DeviceType;
import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
import com.zy.asrs.wcs.rcs.service.DeviceService;
import com.zy.asrs.wcs.rcs.service.DeviceTypeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j
@Component
@@ -12,10 +22,37 @@
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DeviceTypeService deviceTypeService;
    @Autowired
    private ShuttleAction shuttleAction;
    @Scheduled(cron = "0/1 * * * * ? ")
    public synchronized void executeShuttle() {
        DeviceType deviceType = deviceTypeService.getOne(new LambdaQueryWrapper<DeviceType>()
                .eq(DeviceType::getFlag, String.valueOf(SlaveType.Shuttle))
                .eq(DeviceType::getStatus, 1));
        if (deviceType == null) {
            return;
        }
        List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
                .eq(Device::getStatus, 1)
                .eq(Device::getDeviceType, deviceType.getId()));
        for (Device device : list) {
            Object object = redisUtil.get(DeviceRedisConstant.SHUTTLE_FLAG + device.getDeviceNo());
            if (object == null) {
                continue;
            }
            Integer taskNo = Integer.valueOf(String.valueOf(object));
            if (taskNo != 0) {
                //存在任务需要执行
                shuttleAction.executeWork(device, taskNo);
            }
        }
    }
    @Scheduled(cron = "0/1 * * * * ? ")
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/model/protocol/ShuttleProtocol.java
@@ -29,7 +29,7 @@
    /**
     * 四向穿梭车号
     */
    private String shuttleNo;
    private Integer shuttleNo;
    /**
     * 任务号
@@ -89,6 +89,11 @@
     * 是否顶升
     */
    private Boolean hasLift;
    /**
     * 是否有托盘
     */
    private Boolean hasPallet;
    /**
     * 行驶方向
@@ -230,6 +235,14 @@
        return this.taskNo == null ? 0 : this.taskNo;
    }
    public void setTaskNo(Integer taskNo) {
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        if (null != redisUtil) {
            redisUtil.set(DeviceRedisConstant.SHUTTLE_FLAG + this.shuttleNo, taskNo);
            this.taskNo = taskNo;
        }
    }
    //通过当前二维码获取当前库位号
    public String getCurrentLocNo() {
        LocService locService = SpringUtils.getBean(LocService.class);
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/thread/impl/SurayShuttleThread.java
@@ -9,6 +9,7 @@
import com.zy.asrs.framework.exception.CoolException;
import com.zy.asrs.wcs.core.entity.Loc;
import com.zy.asrs.wcs.core.model.command.ShuttleCommand;
import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType;
import com.zy.asrs.wcs.core.service.LocService;
import com.zy.asrs.wcs.rcs.News;
import com.zy.asrs.wcs.rcs.cache.OutputQueue;
@@ -81,24 +82,29 @@
            if (data != null) {
                if (null == shuttleProtocol) {
                    shuttleProtocol = new ShuttleProtocol();
                    shuttleProtocol.setShuttleNo(device.getDeviceNo());
                    shuttleProtocol.setShuttleNo(Integer.valueOf(device.getDeviceNo()));
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                    shuttleProtocol.setDevice(device);
                }
                //----------读取四向穿梭车状态-----------
                //小车忙状态位
                shuttleProtocol.setDeviceStatus(data.getInteger("deviceStatus"));
                //小车设备状态
                Integer deviceStatus = data.getInteger("deviceStatus");
                shuttleProtocol.setDeviceStatus(deviceStatus);
                //当前二维码
                shuttleProtocol.setCurrentCode(data.getString("deviceLocation") == null ? "0" : data.getString("deviceLocation"));
                shuttleProtocol.setCurrentCode(data.getString("groundCode") == null ? "0" : data.getString("groundCode"));
                //电池电量
                shuttleProtocol.setBatteryPower(data.getString("battery") == null ? "0%" : data.getString("battery"));
                //是否顶升
                shuttleProtocol.setHasLift(data.getInteger("palletStatus") == 1 ? true : false);
                //是否有托盘
                shuttleProtocol.setHasPallet(data.getInteger("hasPallet") != 2 ? true : false);
                //行驶方向
                shuttleProtocol.setRunDirection(data.getString("direction") == null ? "none" : data.getString("direction"));
                //是否为充电状态
                shuttleProtocol.setHasCharge((deviceStatus == 5 || deviceStatus == 13) ? true : false);
                ///读取四向穿梭车状态-end
@@ -194,6 +200,8 @@
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(Integer.parseInt(this.device.getDeviceNo()));
        command.setBody(JSON.toJSONString(body));
        command.setMode(ShuttleCommandModeType.MOVE.id);
        command.setTargetLocNo(loc.getLocNo());
        return command;
    }