#
Junjie
2023-09-20 fb8419ef141e16b8ec8b1d9802fa0d5a46768794
#
13个文件已修改
3个文件已添加
973 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/LiftController.java 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ShuttleController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/LiftOperatorParam.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkMastLog.java 504 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkMastLocMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 146 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/ShuttleDispatchUtils.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/NyShuttleProtocol.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/LiftThread.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/NyShuttleThread.java 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/SiemensDevpThread.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastLogMapper.xml 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/lift.html 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/shuttle.html 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LiftController.java
@@ -12,16 +12,19 @@
import com.zy.asrs.entity.BasLift;
import com.zy.asrs.service.BasLiftService;
import com.zy.common.service.CommonService;
import com.zy.common.utils.NyLiftUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.LiftProtocolStatusType;
import com.zy.core.enums.NyLiftTaskModelType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.LiftSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.*;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.model.protocol.LiftStaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.LiftThread;
import lombok.extern.slf4j.Slf4j;
@@ -189,18 +192,86 @@
                    throw new CoolException("提升机不在线");
                }
                LiftAssignCommand assignCommand = new LiftAssignCommand();
                assignCommand.setLiftNo(liftSlave.getId().shortValue()); // 提升机编号
                assignCommand.setTaskNo((short) commonService.getWorkNo(3));//获取任务号
                assignCommand.setTaskMode(param.getLiftTaskMode().shortValue());
                assignCommand.setAuto(false);//手动模式
                assignCommand.setLev(param.getLev());//移动楼层
                if (param.getLiftTaskMode() == 1) {
                    //提升机升降楼层
                    int workNo = commonService.getWorkNo(3);//获取任务号
                if (MessageQueue.offer(SlaveType.Lift, liftSlave.getId(), new Task(3, assignCommand))) {
                    return R.ok();
                    Integer startSta = null;
                    Integer targetSta = null;
                    for (LiftStaProtocol liftStaProtocol : liftThread.getLiftStaProtocols()) {
                        if (liftStaProtocol.getLev() == liftProtocol.getLev().intValue()) {
                            startSta = liftStaProtocol.getStaNo();
                        }
                        if (liftStaProtocol.getLev() == param.getLev()) {
                            targetSta = liftStaProtocol.getStaNo();
                        }
                    }
                    if (startSta == null || targetSta == null) {
                        throw new CoolException("起点或目标点不存在");
                    }
                    //获取提升机命令
                    NyLiftCommand liftCommand = NyLiftUtils.getLiftCommand(liftProtocol.getLiftNo().intValue(), NyLiftTaskModelType.MOVE_CAR.id, startSta, targetSta, workNo);
                    ArrayList<NyLiftCommand> commands = new ArrayList<>();
                    commands.add(liftCommand);
                    //提交到线程去工作
                    LiftAssignCommand assignCommand = new LiftAssignCommand();
                    assignCommand.setCommands(commands);
                    assignCommand.setLiftNo(liftProtocol.getLiftNo());
                    assignCommand.setTaskNo((short) workNo);
                    assignCommand.setAuto(false);//手动模式
                    assignCommand.setTaskMode(NyLiftTaskModelType.MOVE_CAR.id.shortValue());
                    if (MessageQueue.offer(SlaveType.Lift, liftSlave.getId(), new Task(3, assignCommand))) {
                        return R.ok();
                    } else {
                        throw new CoolException("命令下发失败");
                    }
                } else if (param.getLiftTaskMode() == 2) {
                    //移动托盘
                    int workNo = commonService.getWorkNo(3);//获取任务号
                    Integer startSta = null;
                    Integer targetSta = null;
                    for (LiftStaProtocol liftStaProtocol : liftThread.getLiftStaProtocols()) {
                        if (liftStaProtocol.getStaNo() == param.getSourceStaNo()) {
                            startSta = liftStaProtocol.getStaNo();
                        }
                        if (liftStaProtocol.getLev() == param.getStaNo()) {
                            targetSta = liftStaProtocol.getStaNo();
                        }
                    }
                    if (startSta == null || targetSta == null) {
                        throw new CoolException("起点或目标点不存在");
                    }
                    //获取提升机命令
                    NyLiftCommand liftCommand = NyLiftUtils.getLiftCommand(liftProtocol.getLiftNo().intValue(), NyLiftTaskModelType.MOVE_TRAY.id, startSta, targetSta, workNo);
                    ArrayList<NyLiftCommand> commands = new ArrayList<>();
                    commands.add(liftCommand);
                    //提交到线程去工作
                    LiftAssignCommand assignCommand = new LiftAssignCommand();
                    assignCommand.setCommands(commands);
                    assignCommand.setLiftNo(liftProtocol.getLiftNo());
                    assignCommand.setTaskNo((short) workNo);
                    assignCommand.setAuto(false);//手动模式
                    assignCommand.setTaskMode(NyLiftTaskModelType.MOVE_TRAY.id.shortValue());
                    if (MessageQueue.offer(SlaveType.Lift, liftSlave.getId(), new Task(3, assignCommand))) {
                        return R.ok();
                    } else {
                        throw new CoolException("命令下发失败");
                    }
                } else {
                    throw new CoolException("命令下发失败");
                    throw new CoolException("未知命令");
                }
            }
        }
        return R.error();
src/main/java/com/zy/asrs/controller/ShuttleController.java
@@ -21,6 +21,7 @@
import com.zy.common.utils.NyHttpUtils;
import com.zy.common.utils.NyShuttleOperaUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.common.utils.ShuttleDispatchUtils;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
@@ -62,6 +63,8 @@
    private CommonService commonService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ShuttleDispatchUtils shuttleDispatchUtils;
    @PostMapping("/table/shuttle/state")
    @ManagerAuth(memo = "四向穿梭车信息表")
@@ -339,6 +342,10 @@
                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
                    commands.add(suspendCommand);
                    assignCommand.setCommands(commands);
                } else if (shuttleTaskModeType == ShuttleTaskModeType.MOVE_LOC_NO_WRK_MAST) {
                    //移动到目标库位(生成移动任务)
                    shuttleDispatchUtils.dispatchShuttle(commonService.getWorkNo(3), param.getDistLocNo(), param.getShuttleNo());
                    return R.ok();
                } else {
                    throw new CoolException("未知命令");
                }
src/main/java/com/zy/asrs/domain/param/LiftOperatorParam.java
@@ -17,4 +17,10 @@
    //提升机楼层
    private Integer lev;
    //源站
    private Integer sourceStaNo;
    //目标站
    private Integer staNo;
}
src/main/java/com/zy/asrs/entity/WrkMastLog.java
New file
@@ -0,0 +1,504 @@
package com.zy.asrs.entity;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkMastService;
import com.zy.system.entity.User;
import com.zy.system.service.UserService;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
@Data
@TableName("asr_wrk_mast_log")
public class WrkMastLog 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("inv_wh")
    private String invWh;
    @ApiModelProperty(value= "")
    private Date ymd;
    @ApiModelProperty(value= "")
    private String mk;
    @ApiModelProperty(value= "")
    @TableField("whs_type")
    private Integer whsType;
    /**
     * 工作状态
     */
    @ApiModelProperty(value= "工作状态")
    @TableField("wrk_sts")
    private Long wrkSts;
    /**
     * 入出库类型
     */
    @ApiModelProperty(value= "入出库类型")
    @TableField("io_type")
    private Integer ioType;
    /**
     * 堆垛机号
     */
    @ApiModelProperty(value= "堆垛机号")
    @TableField("crn_no")
    private Integer crnNo;
    /**
     * 穿梭车
     */
    @ApiModelProperty(value= "穿梭车")
    @TableField("ste_no")
    private Integer steNo;
    /**
     * 边缘库位
     */
    @ApiModelProperty(value= "边缘库位")
    @TableField("out_most")
    private Integer outMost;
    @ApiModelProperty(value= "")
    @TableField("sheet_no")
    private String sheetNo;
    /**
     * 优先级
     */
    @ApiModelProperty(value= "优先级")
    @TableField("io_pri")
    private Double ioPri;
    @ApiModelProperty(value= "")
    @TableField("wrk_date")
    private Date wrkDate;
    /**
     * 目标库位
     */
    @ApiModelProperty(value= "目标库位")
    @TableField("loc_no")
    private String locNo;
    /**
     * 目标站
     */
    @ApiModelProperty(value= "目标站")
    @TableField("sta_no")
    private Integer staNo;
    /**
     * 源站
     */
    @ApiModelProperty(value= "源站")
    @TableField("source_sta_no")
    private Integer sourceStaNo;
    /**
     * 源库位
     */
    @ApiModelProperty(value= "源库位")
    @TableField("source_loc_no")
    private String sourceLocNo;
    @ApiModelProperty(value= "")
    @TableField("loc_sts")
    private String locSts;
    /**
     * 拣料
     */
    @ApiModelProperty(value= "拣料")
    private String picking;
    @ApiModelProperty(value= "")
    @TableField("link_mis")
    private String linkMis;
    @ApiModelProperty(value= "")
    @TableField("online_yn")
    private String onlineYn;
    @ApiModelProperty(value= "")
    @TableField("upd_mk")
    private String updMk;
    /**
     * 退出
     */
    @ApiModelProperty(value= "退出")
    @TableField("exit_mk")
    private String exitMk;
    @ApiModelProperty(value= "")
    @TableField("plt_type")
    private Integer pltType;
    /**
     * 空板
     */
    @ApiModelProperty(value= "空板")
    @TableField("empty_mk")
    private String emptyMk;
    /**
     * 工作时间
     */
    @ApiModelProperty(value= "工作时间")
    @TableField("io_time")
    private Date ioTime;
    @ApiModelProperty(value= "")
    @TableField("ctn_type")
    private Integer ctnType;
    @ApiModelProperty(value= "")
    private String packed;
    @ApiModelProperty(value= "")
    @TableField("ove_mk")
    private String oveMk;
    @ApiModelProperty(value= "")
    @TableField("mtn_type")
    private Double mtnType;
    @ApiModelProperty(value= "")
    @TableField("user_no")
    private String userNo;
    /**
     * 堆垛机启动时间
     */
    @ApiModelProperty(value= "堆垛机启动时间")
    @TableField("crn_str_time")
    private Date crnStrTime;
    /**
     * 堆垛机停止时间
     */
    @ApiModelProperty(value= "堆垛机停止时间")
    @TableField("crn_end_time")
    private Date crnEndTime;
    /**
     * 拣料时间
     */
    @ApiModelProperty(value= "拣料时间")
    @TableField("plc_str_time")
    private Date plcStrTime;
    @ApiModelProperty(value= "")
    @TableField("crn_pos_time")
    private Date crnPosTime;
    @ApiModelProperty(value= "")
    @TableField("load_time")
    private Double loadTime;
    @ApiModelProperty(value= "")
    @TableField("exp_time")
    private Double expTime;
    @ApiModelProperty(value= "")
    @TableField("ref_wrkno")
    private Double refWrkno;
    @ApiModelProperty(value= "")
    @TableField("ref_iotime")
    private Date refIotime;
    /**
     * 修改人员
     */
    @ApiModelProperty(value= "修改人员")
    @TableField("modi_user")
    private Long modiUser;
    /**
     * 修改时间
     */
    @ApiModelProperty(value= "修改时间")
    @TableField("modi_time")
    private Date modiTime;
    /**
     * 创建者
     */
    @ApiModelProperty(value= "创建者")
    @TableField("appe_user")
    private Long appeUser;
    /**
     * 添加时间
     */
    @ApiModelProperty(value= "添加时间")
    @TableField("appe_time")
    private Date appeTime;
    @ApiModelProperty(value= "")
    @TableField("pause_mk")
    private String pauseMk;
    @ApiModelProperty(value= "")
    @TableField("error_time")
    private Date errorTime;
    @ApiModelProperty(value= "")
    @TableField("error_memo")
    private String errorMemo;
    @ApiModelProperty(value= "")
    @TableField("ctn_kind")
    private Integer ctnKind;
    @ApiModelProperty(value= "")
    @TableField("manu_type")
    private String manuType;
    @ApiModelProperty(value= "")
    @TableField("memo_m")
    private String memoM;
    @ApiModelProperty(value= "")
    @TableField("sc_weight")
    private Double scWeight;
    @ApiModelProperty(value= "")
    @TableField("log_mk")
    private String logMk;
    @ApiModelProperty(value= "")
    @TableField("log_err_time")
    private Date logErrTime;
    @ApiModelProperty(value= "")
    @TableField("log_err_memo")
    private String logErrMemo;
    /**
     * 条码
     */
    @ApiModelProperty(value= "条码")
    private String barcode;
    @ApiModelProperty(value= "")
    @TableField("Pdc_type")
    private String PdcType;
    @ApiModelProperty(value= "")
    @TableField("ctn_no")
    private String ctnNo;
    /**
     * 满板
     */
    @ApiModelProperty(value= "满板")
    @TableField("full_plt")
    private String fullPlt;
    /**
     * 先入品 / 双重入库
     */
    @ApiModelProperty(value= "先入品")
    @TableField("pre_have")
    private String preHave;
    /**
     * 空操作 / 取货无箱
     */
    @ApiModelProperty(value= "空操作")
    @TableField("take_none")
    private String takeNone;
    public WrkMastLog() {}
    public String getWrkNo$(){
        WrkMastService service = SpringUtils.getBean(WrkMastService.class);
        WrkMast wrkMast = service.selectById(this.wrkNo);
        if (!Cools.isEmpty(wrkMast)){
            return String.valueOf(wrkMast.getWrkNo());
        }
        return null;
    }
    public String getYmd$(){
        if (Cools.isEmpty(this.ymd)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.ymd);
    }
    public String getCrnNo$(){
        BasCrnpService service = SpringUtils.getBean(BasCrnpService.class);
        BasCrnp basCrnp = service.selectById(this.crnNo);
        if (!Cools.isEmpty(basCrnp)){
            return String.valueOf(basCrnp.getCrnNo());
        }
        return null;
    }
    public String getWrkDate$(){
        if (Cools.isEmpty(this.wrkDate)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.wrkDate);
    }
    public String getLocNo$(){
        LocMastService service = SpringUtils.getBean(LocMastService.class);
        LocMast locMast = service.selectById(this.locNo);
        if (!Cools.isEmpty(locMast)){
            return String.valueOf(locMast.getLocNo());
        }
        return null;
    }
    public String getStaNo$(){
        BasDevpService service = SpringUtils.getBean(BasDevpService.class);
        BasDevp basDevp = service.selectById(this.staNo);
        if (!Cools.isEmpty(basDevp)){
            return String.valueOf(basDevp.getDevNo());
        }
        return null;
    }
    public String getSourceStaNo$(){
        BasDevpService service = SpringUtils.getBean(BasDevpService.class);
        BasDevp basDevp = service.selectById(this.sourceStaNo);
        if (!Cools.isEmpty(basDevp)){
            return String.valueOf(basDevp.getDevNo());
        }
        return null;
    }
    public String getSourceLocNo$(){
        LocMastService service = SpringUtils.getBean(LocMastService.class);
        LocMast locMast = service.selectById(this.sourceLocNo);
        if (!Cools.isEmpty(locMast)){
            return String.valueOf(locMast.getLocNo());
        }
        return null;
    }
    public String getIoTime$(){
        if (Cools.isEmpty(this.ioTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.ioTime);
    }
    public String getCrnStrTime$(){
        if (Cools.isEmpty(this.crnStrTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.crnStrTime);
    }
    public String getCrnEndTime$(){
        if (Cools.isEmpty(this.crnEndTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.crnEndTime);
    }
    public String getPlcStrTime$(){
        if (Cools.isEmpty(this.plcStrTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.plcStrTime);
    }
    public String getCrnPosTime$(){
        if (Cools.isEmpty(this.crnPosTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.crnPosTime);
    }
    public String getRefIotime$(){
        if (Cools.isEmpty(this.refIotime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.refIotime);
    }
    public String getModiUser$(){
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.selectById(this.modiUser);
        if (!Cools.isEmpty(user)){
            return String.valueOf(user.getUsername());
        }
        return null;
    }
    public String getModiTime$(){
        if (Cools.isEmpty(this.modiTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.modiTime);
    }
    public String getAppeUser$(){
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.selectById(this.appeUser);
        if (!Cools.isEmpty(user)){
            return String.valueOf(user.getUsername());
        }
        return null;
    }
    public String getAppeTime$(){
        if (Cools.isEmpty(this.appeTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.appeTime);
    }
    public String getErrorTime$(){
        if (Cools.isEmpty(this.errorTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.errorTime);
    }
    public String getLogErrTime$(){
        if (Cools.isEmpty(this.logErrTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.logErrTime);
    }
}
src/main/java/com/zy/asrs/mapper/WrkMastLocMapper.java
New file
@@ -0,0 +1,16 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.WrkMastLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface WrkMastLocMapper extends BaseMapper<WrkMastLog> {
    @Insert("insert into asr_wrk_mast_log select * from asr_wrk_mast where wrk_no=#{workNo}")
    int save(Integer workNo);
}
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -99,6 +99,9 @@
    private ShuttleDispatchUtils shuttleDispatchUtils;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private WrkMastLocMapper wrkMastLocMapper;
    /**
     * 组托
@@ -928,6 +931,16 @@
                            if (shuttleProtocol.getToken() == wrkMast.getWrkNo()) {
                                //释放小车令牌
                                shuttleProtocol.setToken(0);
                            }
                            break;
                        case 111:
                            // 保存工作主档历史档
                            if (wrkMastLocMapper.save(wrkMast.getWrkNo()) <= 0) {
                                log.info("保存工作历史档[workNo={0}]失败", wrkMast.getWrkNo());
                            }
                            // 删除工作主档
                            if (!wrkMastService.deleteById(wrkMast)) {
                                log.info("删除工作主档[workNo={0}]失败", wrkMast.getWrkNo());
                            }
                            break;
                        default:
@@ -2156,6 +2169,8 @@
                continue;
            }
//            this.shuttleMoveExecuteStepClearWrkMast(wrkMast);//清理111.小车移动完成
        }
    }
@@ -2181,7 +2196,7 @@
            }
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge()) {
            if (!shuttleProtocol.isIdleNoCharge(wrkMast.getWrkNo())) {
                return false;
            }
@@ -2358,6 +2373,8 @@
            wrkMast.setWrkSts(104L);//小车移动到提升机中  103.小车移动至站点完成 ==> 104.小车迁入提升机中
            wrkMast.setModiTime(now);
            wrkMast.setLiftNo(liftThread.getSlave().getId());//锁定提升机防止被占用
            liftProtocol.setToken(wrkMast.getShuttleNo());//提升机令牌绑定当前小车
            if (wrkMastMapper.updateById(wrkMast) > 0) {
                //下发任务
                MessageQueue.offer(SlaveType.Shuttle, assignCommand.getShuttleNo().intValue(), new Task(3, assignCommand));
@@ -2552,15 +2569,6 @@
        //小车移动到目标库位中  109.小车迁出提升机完成 ==> 110.小车移动中
        if (wrkMast.getWrkSts() == 109) {
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, wrkMast.getLiftNo());
            if (liftThread == null) {
                return false;
            }
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null) {
                return false;
            }
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, wrkMast.getShuttleNo());
            if (shuttleThread == null) {
@@ -2572,34 +2580,34 @@
            }
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge()) {
            if (!shuttleProtocol.isIdleNoCharge(wrkMast.getWrkNo())) {
                return false;
            }
            //判断小车令牌是否为当前任务
            if (shuttleProtocol.getToken() != wrkMast.getWrkNo()) {
            if (shuttleProtocol.getToken() != 0 && shuttleProtocol.getToken() != wrkMast.getWrkNo()) {
                return false;
            }
            //获取目标站对应的输送站点
            BasDevp targetBasDevp = basDevpService.selectByLevAndLiftNo(Utils.getLev(wrkMast.getLocNo()), wrkMast.getLiftNo());
            if (targetBasDevp == null) {
                return false;//缺少站点信息
            }
//            //获取目标站对应的输送站点
//            BasDevp targetBasDevp = basDevpService.selectByLevAndLiftNo(Utils.getLev(wrkMast.getLocNo()), wrkMast.getLiftNo());
//            if (targetBasDevp == null) {
//                return false;//缺少站点信息
//            }
//
//            //获取提升机数据
//            BasLift basLift = basLiftService.selectById(targetBasDevp.getLiftNo());
//            if (basLift == null) {
//                return false;//没有提升机数据
//            }
//            if (basLift.getPoint() == null) {
//                return false;//没有设置提升机点位坐标
//            }
//            NavigateNode liftNode = new NavigateNode(basLift.getPoint$().getX(), basLift.getPoint$().getY());
//            liftNode.setZ(basLift.getPoint$().getZ());
            //获取提升机数据
            BasLift basLift = basLiftService.selectById(targetBasDevp.getLiftNo());
            if (basLift == null) {
                return false;//没有提升机数据
            }
            if (basLift.getPoint() == null) {
                return false;//没有设置提升机点位坐标
            }
            NavigateNode liftNode = new NavigateNode(basLift.getPoint$().getX(), basLift.getPoint$().getY());
            liftNode.setZ(basLift.getPoint$().getZ());
            //获取小车从输送站到目标库位命令
            NyShuttleOperaResult result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleThread.getSlave().getId(), wrkMast.getWrkNo(), targetBasDevp.getLocNo(), wrkMast.getLocNo());
            //获取小车到目标库位命令
            NyShuttleOperaResult result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleThread.getSlave().getId(), wrkMast.getWrkNo(), shuttleProtocol.getCurrentLocNo(), wrkMast.getLocNo());
            if (result == null) {
                return false;//路径计算失败
            }
@@ -2616,7 +2624,20 @@
            wrkMast.setWrkSts(110L);//小车移动到目标库位中  109.小车迁出提升机完成 ==> 110.小车移动中
            wrkMast.setLiftNo(null);//释放提升机
            wrkMast.setModiTime(now);
            liftProtocol.setToken(0);//释放提升机令牌
            if (wrkMast.getLiftNo() != null) {
                LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, wrkMast.getLiftNo());
                if (liftThread == null) {
                    return false;
                }
                LiftProtocol liftProtocol = liftThread.getLiftProtocol();
                if (liftProtocol == null) {
                    return false;
                }
                if (liftProtocol.getToken() == shuttleProtocol.getShuttleNo().intValue()) {
                    liftProtocol.setToken(0);//释放提升机令牌
                }
            }
            if (wrkMastMapper.updateById(wrkMast) > 0) {
                //下发任务
                MessageQueue.offer(SlaveType.Shuttle, assignCommand.getShuttleNo().intValue(), new Task(3, assignCommand));
@@ -2626,6 +2647,69 @@
    }
    /**
     * 小车迁移-清理111.小车移动完成
     */
    private boolean shuttleMoveExecuteStepClearWrkMast(WrkMast wrkMast) {
        if (wrkMast.getWrkSts() == 111) {
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, wrkMast.getShuttleNo());
            if (shuttleThread == null) {
                return false;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol == null) {
                return false;
            }
            //小车处于空闲状态
            if (!shuttleProtocol.isIdleNoCharge(wrkMast.getWrkNo())) {
                return false;
            }
            Object o = redisUtil.get("shuttle_wrk_no_" + shuttleProtocol.getTaskNo());
            if (o != null) {
                ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
                ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
                int size = assignCommand.getCommands().size();
                NyShuttleHttpCommand command = assignCommand.getCommands().get(size - 1);//获取最后一段命令
                if (!command.getComplete()) {
                    return false;//最后一段命令还未完成,不做操作
                }
                NavigateMapData navigateMapData = new NavigateMapData(Utils.getLev(shuttleProtocol.getCurrentLocNo()));
                navigateMapData.writeNavigateNodeToRedisMap(assignCommand.getNodes(), false);//解锁路径
                //删除redis
                redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
            }
            // 保存工作主档历史档
            if (wrkMastLocMapper.save(wrkMast.getWrkNo()) <= 0) {
                log.info("保存工作历史档[workNo={0}]失败", wrkMast.getWrkNo());
            }
            // 删除工作主档
            if (!wrkMastService.deleteById(wrkMast)) {
                log.info("删除工作主档[workNo={0}]失败", wrkMast.getWrkNo());
            }
            //设置四向穿梭车为空闲状态
            shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
            //源库位清零
            shuttleProtocol.setSourceLocNo(null);
            //目标库位清零
            shuttleProtocol.setLocNo(null);
            //任务指令清零
            shuttleProtocol.setAssignCommand(null);
            //工作号清零
            shuttleProtocol.setTaskNo(0);
            //清除令牌
            shuttleProtocol.setToken(0);
            News.info("四向穿梭车已确认且移动任务完成状态,复位。四向穿梭车号={}", shuttleProtocol.getShuttleNo());
        }
        return true;
    }
    /**
     * 出入库模式切换
     */
    public synchronized void outAndIn() {
src/main/java/com/zy/common/utils/ShuttleDispatchUtils.java
@@ -189,7 +189,7 @@
        }
        Integer staNo = null;
        if (Utils.getLev(locNo) == shuttleProtocol.getPoint().getZ()) {
        if (Utils.getLev(locNo) != shuttleProtocol.getPoint().getZ()) {
            //目标库位和小车库位处于不同一楼层,需要通过提升机调度
            //获取穿梭车最近且空闲的提升机输送站点
            BasDevp liftSta = this.getRecentLiftSta(shuttleNo);
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java
@@ -25,6 +25,7 @@
    SHUTTLE_LOC_TO_LOC(20, "库位移转"),
    SHUTTLE_CONTROL(21, "小车管制"),
    SHUTTLE_CANCEL_CONTROL(22, "小车取消管制"),
    MOVE_LOC_NO_WRK_MAST(23, "移动到目标库位(生成移动任务)"),
    ;
    public Integer id;
src/main/java/com/zy/core/model/protocol/NyShuttleProtocol.java
@@ -494,6 +494,17 @@
        return res;
    }
    // 是否处于空闲待命状态
    public Boolean isIdleNoCharge(int taskNo) {
        boolean res = this.free == ShuttleStatusType.IDLE.id
                && !this.pakMk
                && this.errState == 0
                && (this.taskNo == 0 || this.taskNo == taskNo)
                && this.protocolStatus == ShuttleProtocolStatusType.IDLE.id
                ;
        return res;
    }
    // 是否满足充电状态
    public Boolean isRequireCharge() {
        if (this.free == null || this.pakMk == null || this.errState == null || this.taskNo == null) {
src/main/java/com/zy/core/thread/LiftThread.java
@@ -141,7 +141,7 @@
    private void readStatus() {
        try {
            //获取提升机数据
            OperateResultExOne<byte[]> result1 = siemensS7Net.Read("DB4.0", (short) 10);
            OperateResultExOne<byte[]> result1 = siemensS7Net.Read("DB82.4.0", (short) 10);
            if (result1.IsSuccess) {
                if (null == liftProtocol) {
                    liftProtocol = new LiftProtocol();
@@ -154,7 +154,7 @@
                //模式
                liftProtocol.setModel(status1[0]);
                //忙闲
                liftProtocol.setBusy(status1[1]);
                liftProtocol.setBusy(!status1[1]);
                //前超限
                liftProtocol.setFrontOverrun(status1[4]);
                //后超限
@@ -220,7 +220,7 @@
            Thread.sleep(200);
            //获取提升机站点数据
            OperateResultExOne<byte[]> result2 = siemensS7Net.Read("DB14.0", (short) (10 * liftStaProtocols.size()));
            OperateResultExOne<byte[]> result2 = siemensS7Net.Read("DB82.14.0", (short) (10 * liftStaProtocols.size()));
            if (result1.IsSuccess) {
                for (int i = 0; i < slave.getSta().size(); i++) {
                    LiftStaProtocol liftStaProtocol = liftStaProtocols.get(i);
@@ -233,7 +233,7 @@
                    //模式
                    liftStaProtocol.setModel(status1[0]);
                    //忙闲
                    liftStaProtocol.setBusy(status1[1]);
                    liftStaProtocol.setBusy(!status1[1]);
                    //有托盘
                    liftStaProtocol.setHasTray(status1[2]);
                    //前超限
@@ -273,7 +273,7 @@
        command.setLiftNo(slave.getId().shortValue());
        short[] array = getCommandArr(command);//获取命令报文
        OperateResult result = siemensS7Net.Write("41088", array);
        OperateResult result = siemensS7Net.Write("DB83.0", array);
        if (result != null && result.IsSuccess) {
            News.info("提升机命令下发[id:{}] >>>>> {}", slave.getId(), JSON.toJSON(command));
            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), slave.getId(), JSON.toJSON(command)));
src/main/java/com/zy/core/thread/NyShuttleThread.java
@@ -176,20 +176,6 @@
                //小车处于运行中,将标记置为true
                if (shuttleProtocol.getFree() == 0) {
                    shuttleProtocol.setPakMk(true);
                }else {
                    //小车处于等待确认且空闲状态,如有工作号则清空路径
                    if (shuttleProtocol.getTaskNo() != 0 && shuttleProtocol.getProtocolStatusType() == ShuttleProtocolStatusType.WAITING) {
                        Object o = redisUtil.get("shuttle_wrk_no_" + shuttleProtocol.getTaskNo());
                        if (o != null) {
                            ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
                            ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
                            NavigateMapData navigateMapData = new NavigateMapData(Utils.getLev(shuttleProtocol.getCurrentLocNo()));
                            navigateMapData.writeNavigateNodeToRedisMap(assignCommand.getNodes(), false);//解锁路径
                            //删除redis
                            redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
                        }
                    }
                }
                //将四向穿梭车状态保存至数据库
@@ -396,6 +382,23 @@
                //上一条任务未完成,禁止下发命令
                return false;
            }
            //判断是否为最后一条命令且命令执行完成,抛出等待确认状态
            NyShuttleHttpCommand endCommand = commands.get(commands.size() - 1);
            if (endCommand.getComplete()) {
                //删除redis
                redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
                if (!assignCommand.getCharge()) {
                    //对主线程抛出等待确认状态waiting
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                }else {
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
                }
                News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                return false;//禁止再下发命令
            }
        }
        List<NavigateNode> nextNodes = null;//下一步命令行走路径
@@ -471,20 +474,21 @@
        }else {
            //已执行完成
            //最后一段命令为移动命令,则暂缓删除redis等待清除路径时一次性删除
            //最后一段命令为不是移动命令,则删除redis
            if (!command.getRequest().getBody().get("requestType").equals("move")) {
                //删除redis
                redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
            }
            if (!assignCommand.getCharge()) {
                //对主线程抛出等待确认状态waiting
                shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
            }else {
                shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
            }
            News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
            commandStep++;
//            //最后一段命令为移动命令,则暂缓删除redis等待清除路径时一次性删除
//            //最后一段命令为不是移动命令,则删除redis
//            if (!command.getRequest().getBody().get("requestType").equals("move")) {
//                //删除redis
//                redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
//            }
//
//            if (!assignCommand.getCharge()) {
//                //对主线程抛出等待确认状态waiting
//                shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
//            }else {
//                shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
//            }
//            News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
        }
        return true;
@@ -629,6 +633,7 @@
            if (checkPathIsAvailable) {
                return true;//可行走
            }
            return false;
        }else {
            boolean checkPathIsAvailable2 = NavigateUtils.checkPathIsAvailable(nextNodes, shuttleProtocol.getShuttleNo().intValue(), Utils.getLev(shuttleProtocol.getCurrentLocNo()));
            if (checkPathIsAvailable && checkPathIsAvailable2) {
src/main/java/com/zy/core/thread/SiemensDevpThread.java
@@ -41,7 +41,7 @@
    private SiemensS7Net siemensS7Net;
    private Map<Integer, StaProtocol> station = new ConcurrentHashMap<>();
    private short heartBeatVal = 1;
    private int barcodeSize = 1;
    private int barcodeSize = 9;
    public static final ArrayList<Integer> staNos = new ArrayList<Integer>() {{
        add(100);add(101);
        add(102);add(103);
@@ -170,32 +170,15 @@
        //读条码
        Thread.sleep(100);
        OperateResultExOne<byte[]> result2 = siemensS7Net.Read("DB100.200",(short)24);
        OperateResultExOne<byte[]> result2 = siemensS7Net.Read("DB1000.200", (short) 72);
        if (result2.IsSuccess) {
            for (int i = 0; i <= barcodeSize; i++) {
//                byte[] bytes = siemensS7Net.getByteTransform().TransByte(result2.Content, i * 8, 8);
//                String barcode = CommonUtils.bytesToBarcode(bytes);
            for (int i = 0; i < barcodeSize; i++) {
                String barcode = siemensS7Net.getByteTransform().TransString(result2.Content,i*8,8, "UTF-8");
                BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, i + 1);
                if(!Cools.isEmpty(barcodeThread) && !barcodeThread.getBarcode().equals(barcode)) {
                    barcodeThread.setBarcode(barcode);
                }
            }
        }
        // 充电信号位1
        Thread.sleep(50);
        OperateResultExOne<byte[]> result32 = siemensS7Net.Read("DB102.109", (short)1);
        if (result32.IsSuccess) {
            boolean[] status = siemensS7Net.getByteTransform().TransBool(result32.Content, 0, 1);
            charge0 = status[0];  //1:可以充电   0:可能离线 可能在充电
        }
        // 充电信号位2
        Thread.sleep(50);
        OperateResultExOne<byte[]> result31 = siemensS7Net.Read("DB100.201", (short)1);
        if (result31.IsSuccess) {
            boolean[] status = siemensS7Net.getByteTransform().TransBool(result31.Content, 0, 1);
            charge1 = status[0];
        }
        // 外形检测 - 102
src/main/resources/mapper/WrkMastLogMapper.xml
New file
@@ -0,0 +1,69 @@
<?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.WrkMastLogMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.WrkMastLog">
        <id column="id" property="id" />
        <result column="wrk_no" property="wrkNo" />
        <result column="inv_wh" property="invWh" />
        <result column="ymd" property="ymd" />
        <result column="mk" property="mk" />
        <result column="whs_type" property="whsType" />
        <result column="wrk_sts" property="wrkSts" />
        <result column="io_type" property="ioType" />
        <result column="crn_no" property="crnNo" />
        <result column="ste_no" property="steNo" />
        <result column="out_most" property="outMost" />
        <result column="sheet_no" property="sheetNo" />
        <result column="io_pri" property="ioPri" />
        <result column="wrk_date" property="wrkDate" />
        <result column="loc_no" property="locNo" />
        <result column="sta_no" property="staNo" />
        <result column="source_sta_no" property="sourceStaNo" />
        <result column="source_loc_no" property="sourceLocNo" />
        <result column="loc_sts" property="locSts" />
        <result column="picking" property="picking" />
        <result column="link_mis" property="linkMis" />
        <result column="online_yn" property="onlineYn" />
        <result column="upd_mk" property="updMk" />
        <result column="exit_mk" property="exitMk" />
        <result column="plt_type" property="pltType" />
        <result column="empty_mk" property="emptyMk" />
        <result column="io_time" property="ioTime" />
        <result column="ctn_type" property="ctnType" />
        <result column="packed" property="packed" />
        <result column="ove_mk" property="oveMk" />
        <result column="mtn_type" property="mtnType" />
        <result column="user_no" property="userNo" />
        <result column="crn_str_time" property="crnStrTime" />
        <result column="crn_end_time" property="crnEndTime" />
        <result column="plc_str_time" property="plcStrTime" />
        <result column="crn_pos_time" property="crnPosTime" />
        <result column="load_time" property="loadTime" />
        <result column="exp_time" property="expTime" />
        <result column="ref_wrkno" property="refWrkno" />
        <result column="ref_iotime" property="refIotime" />
        <result column="modi_user" property="modiUser" />
        <result column="modi_time" property="modiTime" />
        <result column="appe_user" property="appeUser" />
        <result column="appe_time" property="appeTime" />
        <result column="pause_mk" property="pauseMk" />
        <result column="error_time" property="errorTime" />
        <result column="error_memo" property="errorMemo" />
        <result column="ctn_kind" property="ctnKind" />
        <result column="manu_type" property="manuType" />
        <result column="memo_m" property="memoM" />
        <result column="sc_weight" property="scWeight" />
        <result column="log_mk" property="logMk" />
        <result column="log_err_time" property="logErrTime" />
        <result column="log_err_memo" property="logErrMemo" />
        <result column="barcode" property="barcode" />
        <result column="Pdc_type" property="PdcType" />
        <result column="ctn_no" property="ctnNo" />
        <result column="full_plt" property="fullPlt" />
        <result column="pre_have" property="preHave" />
        <result column="take_none" property="takeNone" />
    </resultMap>
</mapper>
src/main/resources/mapper/WrkMastMapper.xml
@@ -195,7 +195,7 @@
    <select id="selectShuttleMoveWrk" resultMap="BaseResultMap">
        select * from dbo.asr_wrk_mast
        where 1=1
        and wrk_sts in (101,103,105,107)
        and wrk_sts in (101,103,105,107,109,111)
        and io_type = 200
        order by io_pri desc,io_time,wrk_no asc
    </select>
src/main/webapp/views/lift.html
@@ -93,13 +93,28 @@
                    <div class="button-group">
                        <select id="liftLev">
                            <option value="1" selected>1F</option>
                            <option value="3">2F</option>
                            <option value="4">3F</option>
                            <option value="5">4F</option>
                            <option value="2">输送线位置</option>
                            <option value="2">2F</option>
                            <option value="3">3F</option>
                            <option value="4">4F</option>
                            <option value="5">5F</option>
                            <option value="6">6F</option>
                            <option value="7">7F</option>
                            <option value="8">8F</option>
                            <option value="9">9F</option>
                            <option value="10">10F</option>
                        </select>
                        <button class="item" onclick="liftOperator(1)">移动提升机</button>
                        <button class="item" onclick="liftOperator(0)">复位</button>
                        <div class="select-container-item">
                            <span>源站</span>
                            <label><input id="sourceStaNo" type="text" name="sourceStaNo" /></label>
                        </div>
                        <div class="select-container-item">
                            <span>目标站</span>
                            <label><input id="staNo" type="text" name="staNo" /></label>
                        </div>
                        <button class="item" onclick="liftOperator(2)">移动托盘</button>
<!--                        <button class="item" onclick="liftOperator(0)">复位</button>-->
                    </div>
                </fieldset>
            </div>
src/main/webapp/views/shuttle.html
@@ -120,6 +120,7 @@
                                        <div style="margin-top: 10px;">
                                            <button class="item" onclick="shuttleOperator(18)">搬运货物</button>
                                            <button class="item" onclick="shuttleOperator(14)">移动到目标库位</button>
                                            <button class="item" onclick="shuttleOperator(23)">移动到目标库位(任务)</button>
                                            <button class="item" onclick="shuttleOperator(16)">移动到提升机</button>
                                        </div>
                                    </div>