自动化立体仓库 - WCS系统
Junjie
2023-03-27 eb5eb35a7ef56a01a4c788a8c2efef9fc7b823e7
四向穿梭车线程完善
5个文件已添加
4个文件已修改
385 ■■■■ 已修改文件
src/main/java/com/zy/asrs/entity/BasShuttleOpt.java 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasShuttleOptMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasShuttleOptService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasShuttleOptServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ShuttleThread.java 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasShuttleOptMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasShuttleOpt.java
New file
@@ -0,0 +1,151 @@
package com.zy.asrs.entity;
import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.annotations.TableField;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.core.common.SpringUtils;
import com.zy.system.service.UserService;
import com.zy.system.entity.User;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.baomidou.mybatisplus.annotations.TableName;
import java.io.Serializable;
@Data
@TableName("asr_bas_shuttle_opt")
public class BasShuttleOpt implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value= "")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 任务号
     */
    @ApiModelProperty(value= "任务号")
    @TableField("wrk_no")
    private Integer wrkNo;
    /**
     * 穿梭车号
     */
    @ApiModelProperty(value= "穿梭车号")
    @TableField("shuttle_no")
    private Integer shuttleNo;
    /**
     * 下发时间
     */
    @ApiModelProperty(value= "下发时间")
    @TableField("send_time")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date sendTime;
    /**
     * 作业
     */
    @ApiModelProperty(value= "作业")
    private String mode;
    /**
     * 起点库位
     */
    @ApiModelProperty(value= "起点库位")
    @TableField("source_loc_no")
    private String sourceLocNo;
    /**
     * 目标库位
     */
    @ApiModelProperty(value= "目标库位")
    @TableField("dist_loc_no")
    private String distLocNo;
    /**
     * 修改时间
     */
    @ApiModelProperty(value= "修改时间")
    @TableField("update_time")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * 修改人员
     */
    @ApiModelProperty(value= "修改人员")
    @TableField("update_by")
    private Long updateBy;
    /**
     * 备注
     */
    @ApiModelProperty(value= "备注")
    private String memo;
    /**
     * 命令
     */
    @ApiModelProperty(value= "命令")
    private String command;
    public BasShuttleOpt() {}
    public BasShuttleOpt(Integer wrkNo,Integer shuttleNo,Date sendTime,String mode,String sourceLocNo,String distLocNo,Date updateTime,Long updateBy,String memo,String command) {
        this.wrkNo = wrkNo;
        this.shuttleNo = shuttleNo;
        this.sendTime = sendTime;
        this.mode = mode;
        this.sourceLocNo = sourceLocNo;
        this.distLocNo = distLocNo;
        this.updateTime = updateTime;
        this.updateBy = updateBy;
        this.memo = memo;
        this.command = command;
    }
//    BasShuttleOpt basShuttleOpt = new BasShuttleOpt(
//            null,    // 任务号
//            null,    // 穿梭车号
//            null,    // 下发时间
//            null,    // 作业
//            null,    // 起点库位
//            null,    // 目标库位
//            null,    // 修改时间
//            null,    // 修改人员
//            null,    // 备注
//            null    // 命令
//    );
    public String getSendTime$(){
        if (Cools.isEmpty(this.sendTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.sendTime);
    }
    public String getUpdateTime$(){
        if (Cools.isEmpty(this.updateTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
    }
    public String getUpdateBy$(){
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.selectById(this.updateBy);
        if (!Cools.isEmpty(user)){
            return String.valueOf(user.getUsername());
        }
        return null;
    }
}
src/main/java/com/zy/asrs/mapper/BasShuttleOptMapper.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.mapper;
import com.zy.asrs.entity.BasShuttleOpt;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BasShuttleOptMapper extends BaseMapper<BasShuttleOpt> {
}
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java
@@ -95,4 +95,6 @@
    List<WrkMast> selectAll(@Param("staNo")Integer staNo);
    WrkMast selectAllC();
    List<WrkMast> selectWorkWaiting(Integer workNo);
}
src/main/java/com/zy/asrs/service/BasShuttleOptService.java
New file
@@ -0,0 +1,8 @@
package com.zy.asrs.service;
import com.zy.asrs.entity.BasShuttleOpt;
import com.baomidou.mybatisplus.service.IService;
public interface BasShuttleOptService extends IService<BasShuttleOpt> {
}
src/main/java/com/zy/asrs/service/impl/BasShuttleOptServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.service.impl;
import com.zy.asrs.mapper.BasShuttleOptMapper;
import com.zy.asrs.entity.BasShuttleOpt;
import com.zy.asrs.service.BasShuttleOptService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("basShuttleOptService")
public class BasShuttleOptServiceImpl extends ServiceImpl<BasShuttleOptMapper, BasShuttleOpt> implements BasShuttleOptService {
}
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java
@@ -1,6 +1,7 @@
package com.zy.core.model.protocol;
import com.zy.core.enums.ShuttleStatusType;
import com.zy.core.model.command.ShuttleAssignCommand;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -22,6 +23,11 @@
    private Short taskNo = 0;
    /**
     * 任务指令
     */
    private ShuttleAssignCommand assignCommand;
    /**
     * 源库位
     */
    private String sourceLocNo;
src/main/java/com/zy/core/thread/ShuttleThread.java
@@ -7,7 +7,10 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasShuttleOpt;
import com.zy.asrs.service.BasShuttleOptService;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.CommonUtils;
import com.zy.common.utils.NavigatePositionConvert;
@@ -19,6 +22,7 @@
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.ShuttleRunDirection;
import com.zy.core.enums.ShuttleStatusType;
import com.zy.core.enums.ShuttleTaskModeType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.Task;
@@ -170,7 +174,7 @@
                //四向穿梭车空闲、有任务且标记为true,需要执行任务的下一条指令
                if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE && shuttleProtocol.getTaskNo() != 0 && shuttleProtocol.getPakMk()) {
                    //执行下一步指令
                    executeWork(shuttleProtocol.getTaskNo());
                    executeWork(shuttleProtocol.getAssignCommand());
                }
            }else {
@@ -178,6 +182,7 @@
                throw new CoolException(MessageFormat.format( "四向穿梭车plc状态信息失败 ===>> [id:{0}] [ip:{1}] [port:{2}]", slave.getId(), slave.getIp(), slave.getPort()));
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            initShuttle();
        }
@@ -286,91 +291,92 @@
    //分配任务
    private void assignWork(ShuttleAssignCommand assignCommand) {
        //将此map存入redis中
        HashMap<String, Object> map = new HashMap<>();
        //计算路径
        List<NavigateNode> calc = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getDistLocNo(), assignCommand.getTaskMode().intValue());
        if (calc != null) {
            //获取分段路径
            ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
            //路径数据
            map.put("path", data);
        }
        //工作号
        map.put("wrk_no", assignCommand.getTaskNo());
        //命令执行步序
        map.put("commandStep", 0);
        //命令
        map.put("assignCommand", assignCommand);
        shuttleProtocol.setTaskNo(assignCommand.getTaskNo());
        shuttleProtocol.setAssignCommand(assignCommand);
        //任务数据保存到redis
        redisUtil.set("wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(map));
        //执行下发任务
        executeWork(assignCommand);
    }
    //执行下发的指令
    private void executeWork(ShuttleAssignCommand assignCommand) {
        //读取redis数据
        Object o = redisUtil.get("wrk_no_" + assignCommand.getTaskNo());
        HashMap map = JSON.parseObject(o.toString(), HashMap.class);
        //当前步序
        int commandStep = Integer.parseInt(map.get("commandStep").toString());
        //path路径数目
        int size = 0;
        //下发命令
        ShuttleCommand command = new ShuttleCommand();
        switch (assignCommand.getTaskMode()) {
            case 1:
            case 2:
                //计算路径
                List<NavigateNode> calc = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getDistLocNo(), assignCommand.getTaskMode().intValue());
                if (calc != null) {
                    //获取分段路径
                    ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
                    //将此map存入redis中
                    HashMap<String, Object> map = new HashMap<>();
                    //命令执行步序
                    map.put("commandStep", 0);
                    //路径数据
                    map.put("path", data);
                    //工作号
                    map.put("wrk_no", assignCommand.getTaskNo());
                    //任务数据保存到redis
                    redisUtil.set("wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(map));
                    shuttleProtocol.setTaskNo(assignCommand.getTaskNo());
            case 1://入库
            case 2://出库
                //当前路径数据
                Object data = map.get("path");
                ArrayList pathList = JSON.parseObject(data.toString(), ArrayList.class);
                //取第一条路径
                Object o1 = pathList.get(commandStep);
                ArrayList path = JSON.parseObject(o1.toString(), ArrayList.class);
                    //执行下发任务
                    executeWork(assignCommand.getTaskNo());
                }
                size = path.size();
                //开始路径
                JSONObject startPath = JSON.parseObject(path.get(0).toString());
                //目标路径
                JSONObject endPath = JSON.parseObject(path.get(size - 1).toString());
                command.setCommandWord((short) 1);
                command.setStartCodeNum(NavigatePositionConvert.xyToPosition(startPath.getIntValue("x"), startPath.getIntValue("y")));
                command.setMiddleCodeNum((short) 0);
                command.setDistCodeNum(NavigatePositionConvert.xyToPosition(endPath.getIntValue("x"), endPath.getIntValue("y")));
                command.setStartToDistDistance(1000);
                command.setMiddleToDistDistance(1000);
                command.setRunDirection(ShuttleRunDirection.get(startPath.get("direction").toString()).id);
                command.setPalletLift((short) 1);
                command.setForceMoveDistance(1000);
                command.setChargeSwitch((short) 2);
                command.setIOControl((short) 0);
                command.setRunSpeed((short) 1000);
                command.setRadarTmp((short) 0);
                break;
            case 3:
            case 4:
            case 3://托盘顶升
            case 4://托盘下降
                command.setCommandWord((short) 2);
                command.setPalletLift(assignCommand.getTaskMode() == 3 ? (short)1 : (short)2);
                command.setCommandEnd((short) 1);
                write(command);
                break;
            case 5:
            case 6:
            case 7:
            case 8:
            case 5://强制左移
            case 6://强制右移
            case 7://强制上移
            case 8://强制下移
                command.setCommandWord((short) 3);
                command.setForceMoveDistance(1000);
                command.setRunDirection((short) (assignCommand.getTaskMode() - 4));
                command.setCommandEnd((short) 1);
                write(command);
                break;
        }
    }
    //执行下发的指令
    private void executeWork(Short taskNo) {
        //读取redis数据
        Object o = redisUtil.get("wrk_no_" + taskNo);
        HashMap map = JSON.parseObject(o.toString(), HashMap.class);
        //当前步序
        int commandStep = Integer.parseInt(map.get("commandStep").toString());
        //当前路径数据
        Object data = map.get("path");
        ArrayList pathList = JSON.parseObject(data.toString(), ArrayList.class);
        //取第一条路径
        Object o1 = pathList.get(commandStep);
        ArrayList path = JSON.parseObject(o1.toString(), ArrayList.class);
        int size = path.size();
        //开始路径
        JSONObject startPath = JSON.parseObject(path.get(0).toString());
        System.out.println(startPath);
        //目标路径
        JSONObject endPath = JSON.parseObject(path.get(size - 1).toString());
        System.out.println(endPath);
        //下发命令
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 1);
        command.setStartCodeNum(NavigatePositionConvert.xyToPosition(startPath.getIntValue("x"), startPath.getIntValue("y")));
        command.setMiddleCodeNum((short) 0);
        command.setDistCodeNum(NavigatePositionConvert.xyToPosition(endPath.getIntValue("x"), endPath.getIntValue("y")));
        command.setStartToDistDistance(1000);
        command.setMiddleToDistDistance(1000);
        command.setRunDirection(ShuttleRunDirection.get(startPath.get("direction").toString()).id);
        command.setPalletLift((short) 1);
        command.setForceMoveDistance(1000);
        command.setChargeSwitch((short) 2);
        command.setIOControl((short) 0);
        command.setRunSpeed((short) 1000);
        command.setRadarTmp((short) 0);
        command.setCommandEnd((short) 1);
        //下发命令
        if (!write(command)) {
            News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
@@ -391,12 +397,24 @@
            }else {
                //已执行完成
                //保存数据到数据库做流水
                BasShuttleOptService shuttleOptService = SpringUtils.getBean(BasShuttleOptService.class);
                if (shuttleOptService != null) {
                    BasShuttleOpt opt = new BasShuttleOpt(
                            assignCommand.getTaskNo().intValue(),
                            assignCommand.getShuttleNo().intValue(),
                            new Date(),
                            ShuttleTaskModeType.get(assignCommand.getTaskMode()).desc,
                            assignCommand.getSourceLocNo(),
                            assignCommand.getDistLocNo(),
                            null,
                            null,
                            null,
                            JSON.toJSONString(command)
                    );
                    shuttleOptService.insert(opt);
                }
                //删除redis
                redisUtil.del("wrk_no_" + map.get("wrk_no").toString());
                //。。。
                //1、命令下方需要判断小车空闲状态
                //2、
            }
        }
src/main/resources/mapper/BasShuttleOptMapper.xml
New file
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.asrs.mapper.BasShuttleOptMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.BasShuttleOpt">
        <id column="id" property="id" />
        <result column="wrk_no" property="wrkNo" />
        <result column="shuttle_no" property="shuttleNo" />
        <result column="send_time" property="sendTime" />
        <result column="mode" property="mode" />
        <result column="source_loc_no" property="sourceLocNo" />
        <result column="dist_loc_no" property="distLocNo" />
        <result column="update_time" property="updateTime" />
        <result column="update_by" property="updateBy" />
        <result column="memo" property="memo" />
        <result column="command" property="command" />
    </resultMap>
</mapper>
src/main/resources/mapper/WrkMastMapper.xml
@@ -234,5 +234,12 @@
            #{item}
        </foreach>
    </select>
    <select id="selectWorkWaiting" resultMap="BaseResultMap">
        select *
        from dbo.asr_wrk_mast
        where 1=1
        wrk_no=#{workNo} and wrk_sts in (4,7)
    </select>
</mapper>