Junjie
2023-03-31 87c4efe93e6fe31a9c989b4aa5cc0c8f559b845d
提升机代码,四向穿梭车线程优化
16个文件已修改
20个文件已添加
2835 ■■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/LiftController.java 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ShuttleController.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/LiftOperatorParam.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/LiftDataVo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/LiftMsgTableVo.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/LiftSensorDataVo.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/LiftStateTableVo.java 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/ShuttleSensorDataVo.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasLift.java 299 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasLiftOpt.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasLiftMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasLiftOptMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasLiftOptService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasLiftService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasLiftOptServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasLiftServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/CommonUtils.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/MainProcess.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/ServerBootstrap.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/cache/MessageQueue.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/LiftProtocolStatusType.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/LiftAssignCommand.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/LiftCommand.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/ShuttleAssignCommand.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/LiftProtocol.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/LiftThread.java 327 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ShuttleThread.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasLiftMapper.xml 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasLiftOptMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/css/lift.css 334 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/lift.html 484 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LiftController.java
New file
@@ -0,0 +1,216 @@
package com.zy.asrs.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.annotations.ManagerAuth;
import com.core.common.BaseRes;
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.domain.param.LiftOperatorParam;
import com.zy.asrs.domain.vo.*;
import com.zy.asrs.entity.BasLift;
import com.zy.asrs.service.BasLiftService;
import com.zy.asrs.service.WrkMastService;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.LiftSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.LiftAssignCommand;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.LiftThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
 * 提升机接口
 */
@Slf4j
@RestController
@RequestMapping("/lift")
public class LiftController {
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
    private BasLiftService basLiftService;
    @Autowired
    private WrkMastService wrkMastService;
    @PostMapping("/table/lift/state")
    @ManagerAuth(memo = "提升机信息表")
    public R liftStateTable(){
        List<LiftStateTableVo> list = new ArrayList<>();
        List<BasLift> lifts = basLiftService.selectList(new EntityWrapper<BasLift>().orderBy("lift_no"));
        for (BasLift basLift : lifts) {
            // 表格行
            LiftStateTableVo vo = new LiftStateTableVo();
            vo.setLiftNo(basLift.getLiftNo());   //提升机号
            list.add(vo);
            // 获取提升机信息
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, basLift.getLiftNo());
            if (liftThread == null) {
                continue;
            }
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null || liftProtocol.getLiftNo()==null) {
                continue;
            }
            vo.setTaskNo(liftProtocol.getTaskNo());  //  任务号
            vo.setProtocolStatus(liftProtocol.getProtocolStatusType().desc);
            vo.setLiftLock(liftProtocol.getLiftLock());
            vo.setPositionArrivalFeedback(liftProtocol.getPositionArrivalFeedback());
            vo.setReady(liftProtocol.getReady());
            vo.setRunning(liftProtocol.getRunning());
            vo.setMode(liftProtocol.getMode());
            vo.setLineFrontHasStock(liftProtocol.getLineFrontHasStock());
            vo.setForwardRotationFeedback(liftProtocol.getForwardRotationFeedback());
            vo.setReverseFeedback(liftProtocol.getReverseFeedback());
            vo.setMotorOverload(liftProtocol.getMotorOverload());
            vo.setLineEndHasStock(liftProtocol.getLineEndHasStock());
            vo.setInConveyLineCardTrayAlarm(liftProtocol.getInConveyLineCardTrayAlarm());
            vo.setOutConveyLineCardTrayAlarm(liftProtocol.getOutConveyLineCardTrayAlarm());
            vo.setPlatPositionDeviationAlarm(liftProtocol.getPlatPositionDeviationAlarm());
            vo.setPlatTorqueDeviationAlarm(liftProtocol.getPlatTorqueDeviationAlarm());
            vo.setPlatShuttleCheck(liftProtocol.getPlatShuttleCheck());
            vo.setNotReady(liftProtocol.getNotReady());
            vo.setServoError1(liftProtocol.getServoError1());
            vo.setServoError2(liftProtocol.getServoError2());
            vo.setServoError3(liftProtocol.getServoError3());
            vo.setServoError4(liftProtocol.getServoError4());
            vo.setLiftActualSpeed(liftProtocol.getLiftActualSpeed());
            vo.setPakMk(liftProtocol.getPakMk());
        }
        return R.ok().add(list);
    }
    @PostMapping("/table/lift/msg")
    @ManagerAuth(memo = "提升机数据表")
    public R liftMsgTable(){
        List<LiftMsgTableVo> list = new ArrayList<>();
        List<BasLift> lifts = basLiftService.selectList(new EntityWrapper<BasLift>().orderBy("lift_no"));
        for (BasLift basLift : lifts) {
            // 表格行
            LiftMsgTableVo vo = new LiftMsgTableVo();
            vo.setLiftNo(basLift.getLiftNo());   //  提升机号
            list.add(vo);
            // 获取提升机信息
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, basLift.getLiftNo());
            if (liftThread == null) {
                continue;
            }
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null) {
                continue;
            }
            vo.setWorkNo(liftProtocol.getTaskNo().intValue());//任务号
            vo.setPakMk(liftProtocol.getPakMk()?"Y" : "N");    // 作业标记
            vo.setLineFrontHasStock(liftProtocol.getLineFrontHasStock());
            vo.setForwardRotationFeedback(liftProtocol.getForwardRotationFeedback());
            vo.setReverseFeedback(liftProtocol.getReverseFeedback());
            vo.setMotorOverload(liftProtocol.getMotorOverload());
            vo.setLineEndHasStock(liftProtocol.getLineEndHasStock());
            vo.setInConveyLineCardTrayAlarm(liftProtocol.getInConveyLineCardTrayAlarm());
            vo.setOutConveyLineCardTrayAlarm(liftProtocol.getOutConveyLineCardTrayAlarm());
        }
        return R.ok().add(list);
    }
    @PostMapping("/output/lift")
    @ManagerAuth
    public R liftOutput(){
        StringBuilder str = new StringBuilder();
        String s;
        int i = 0;
        while((s = OutputQueue.LIFT.poll()) != null && i <=10) {
            str.append("\n").append(s);
            i++;
        }
        return R.ok().add(str.toString());
    }
    @GetMapping("/detl/{liftNo}")
    public R liftDetl(@PathVariable("liftNo") Integer liftNo){
        LiftDataVo vo = new LiftDataVo();
        for (LiftSlave liftSlave : slaveProperties.getLift()) {
            if (liftNo.equals(liftSlave.getId())) {
                vo.setLiftNo(liftSlave.getId());
                BasLift basLift = basLiftService.selectById(liftSlave.getId());
                if (!Cools.isEmpty(basLift)) {
                    vo.setWorkNo(basLift.getWrkNo());
                    vo.setPakMk(basLift.getPakMk());
                }
                break;
            }
        }
        return R.ok().add(vo);
    }
    @GetMapping("/sensor/detl/{liftNo}")
    public R liftSensorDetl(@PathVariable("liftNo") Integer liftNo){
        LiftSensorDataVo vo = new LiftSensorDataVo();
        for (LiftSlave liftSlave : slaveProperties.getLift()) {
            if (liftNo.equals(liftSlave.getId())) {
                vo.setLiftNo(liftSlave.getId());
                // 获取提升机信息
                LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, liftSlave.getId());
                if (liftThread == null) {
                    return R.error("设备不在线");
                }
                LiftProtocol liftProtocol = liftThread.getLiftProtocol();
                if (liftProtocol == null) {
                    return R.error("设备不在线");
                }
                break;
            }
        }
        return R.ok().add(vo);
    }
    /****************************************************************/
    /************************** 手动操作 ******************************/
    /****************************************************************/
    @ManagerAuth(memo = "手动操作")
    @PostMapping("/operator/lift")
    public R liftOperator(LiftOperatorParam param){
        if (Cools.isEmpty(param.getLiftNo())) {
            return R.parse(BaseRes.PARAM);
        }
        for (LiftSlave liftSlave : slaveProperties.getLift()) {
            if (param.getLiftNo().equals(liftSlave.getId())) {
                LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, liftSlave.getId());
                if (liftThread == null) {
                    throw new CoolException("提升机不在线");
                }
                LiftProtocol liftProtocol = liftThread.getLiftProtocol();
                if (liftProtocol == null) {
                    throw new CoolException("提升机不在线");
                }
                LiftAssignCommand assignCommand = new LiftAssignCommand();
                assignCommand.setLiftNo(liftSlave.getId().shortValue()); // 提升机编号
                assignCommand.setTaskNo((short) 9999);
                assignCommand.setTaskMode(param.getLiftTaskMode().shortValue());
                assignCommand.setAuto(false);//手动模式
                if (MessageQueue.offer(SlaveType.Lift, liftSlave.getId(), new Task(3, assignCommand))) {
                    return R.ok();
                } else {
                    throw new CoolException("命令下发失败");
                }
            }
        }
        return R.error();
    }
}
src/main/java/com/zy/asrs/controller/ShuttleController.java
@@ -30,7 +30,6 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
 * 四向穿梭车接口
@@ -246,8 +245,14 @@
            return R.parse(BaseRes.PARAM);
        }
        if (Cools.isEmpty(param.getSourceLocNo(), param.getDistLocNo())) {
            return R.parse(BaseRes.PARAM);
        ShuttleAssignCommand assignCommand = new ShuttleAssignCommand();
        if (param.getShuttleTaskMode() == 1 || param.getShuttleTaskMode() == 2) {
            if (Cools.isEmpty(param.getSourceLocNo(), param.getDistLocNo())) {
                return R.parse(BaseRes.PARAM);
            }
            assignCommand.setSourceLocNo(param.getSourceLocNo());
            assignCommand.setLocNo(param.getDistLocNo());
        }
        for (ShuttleSlave shuttleSlave : slaveProperties.getShuttle()) {
@@ -262,14 +267,12 @@
                }
                ShuttleTaskModeType shuttleTaskModeType = ShuttleTaskModeType.get(param.getShuttleTaskMode());
                ShuttleAssignCommand command = new ShuttleAssignCommand();
                command.setShuttleNo(shuttleSlave.getId().shortValue()); // 四向穿梭车编号
                command.setTaskMode(shuttleTaskModeType.id.shortValue());
                command.setSourceLocNo(param.getSourceLocNo());
                command.setLocNo(param.getDistLocNo());
                command.setTaskNo((short) 9999);
                assignCommand.setShuttleNo(shuttleSlave.getId().shortValue()); // 四向穿梭车编号
                assignCommand.setTaskMode(shuttleTaskModeType.id.shortValue());
                assignCommand.setTaskNo((short) 9999);
                assignCommand.setAuto(false);//手动模式
                if (MessageQueue.offer(SlaveType.Shuttle, shuttleSlave.getId(), new Task(3, command))) {
                if (MessageQueue.offer(SlaveType.Shuttle, shuttleSlave.getId(), new Task(3, assignCommand))) {
                    return R.ok();
                } else {
                    throw new CoolException("命令下发失败");
src/main/java/com/zy/asrs/domain/param/LiftOperatorParam.java
New file
@@ -0,0 +1,17 @@
package com.zy.asrs.domain.param;
import lombok.Data;
@Data
public class LiftOperatorParam {
    // 提升机号
    private Integer liftNo;
    // 任务号
    private Integer taskNo = 0;
    //操作模式
    private Integer liftTaskMode;
}
src/main/java/com/zy/asrs/domain/vo/LiftDataVo.java
New file
@@ -0,0 +1,16 @@
package com.zy.asrs.domain.vo;
import lombok.Data;
@Data
public class LiftDataVo {
    // 提升机号
    private Integer liftNo;
    // 工作号
    private Integer workNo;
    private Boolean pakMk;
}
src/main/java/com/zy/asrs/domain/vo/LiftMsgTableVo.java
New file
@@ -0,0 +1,87 @@
package com.zy.asrs.domain.vo;
import lombok.Data;
@Data
public class LiftMsgTableVo {
    // 提升机号
    private Integer liftNo;
    // 工作号
    private Integer workNo = 0;
    // 作业标记
    private String pakMk = "-";
    /**
     * 输送线前端光电有货
     * 有货为1,无货为0(前端指靠近货架侧)
     */
    private Boolean lineFrontHasStock;
    /**
     * 输送线正转反馈
     * 正转运行为1,否则为0
     */
    private Boolean forwardRotationFeedback;
    /**
     * 输送线反转反馈
     * 反转运行为1,否则为0
     */
    private Boolean reverseFeedback;
    /**
     * 输送线电机过载
     * 过载为0,正常为1
     */
    private Boolean motorOverload;
    /**
     * 输送线末端光电有货
     * 有货为1,无货为0
     */
    private Boolean lineEndHasStock;
    /**
     * 进输送线卡托盘报警
     * 报警为1,未报警为0
     */
    private Boolean inConveyLineCardTrayAlarm;
    /**
     * 出输送线卡托盘报警
     * 报警为1,未报警为0
     */
    private Boolean outConveyLineCardTrayAlarm;
    public String getLineFrontHasStock$() {
        return this.lineFrontHasStock ? "Y" : "N";
    }
    public String getForwardRotationFeedback$() {
        return this.forwardRotationFeedback ? "Y" : "N";
    }
    public String getReverseFeedback$() {
        return this.reverseFeedback ? "Y" : "N";
    }
    public String getMotorOverload$() {
        return this.motorOverload ? "Y" : "N";
    }
    public String getLineEndHasStock$() {
        return this.lineEndHasStock ? "Y" : "N";
    }
    public String getInConveyLineCardTrayAlarm$() {
        return this.inConveyLineCardTrayAlarm ? "Y" : "N";
    }
    public String getOutConveyLineCardTrayAlarm$() {
        return this.outConveyLineCardTrayAlarm ? "Y" : "N";
    }
}
src/main/java/com/zy/asrs/domain/vo/LiftSensorDataVo.java
New file
@@ -0,0 +1,13 @@
package com.zy.asrs.domain.vo;
import lombok.Data;
@Data
public class LiftSensorDataVo {
    /**
     * 提升机号
     */
    private Integer liftNo;
}
src/main/java/com/zy/asrs/domain/vo/LiftStateTableVo.java
New file
@@ -0,0 +1,223 @@
package com.zy.asrs.domain.vo;
import com.zy.core.enums.LiftProtocolStatusType;
import lombok.Data;
@Data
public class LiftStateTableVo {
    // 提升机号
    private Integer liftNo;
    /**
     * 任务号
     */
    private Short taskNo = 0;
    /**
     * 当前提升机状态(内部自我维护)
     */
    private String protocolStatus;
    /**
     * 提升机锁定
     */
    private Boolean liftLock;
    /**
     * 位置到达反馈
     */
    private Short positionArrivalFeedback;
    /**
     * 准备就绪
     * 就绪为1,未就绪为0
     */
    private Boolean ready;
    /**
     * 运行中
     * 运行中为1,未运行为0
     */
    private Boolean running;
    /**
     * 联机/单机
     * 联机为1,单机为0
     */
    private Boolean mode;
    /**
     * 输送线前端光电有货
     * 有货为1,无货为0(前端指靠近货架侧)
     */
    private Boolean lineFrontHasStock;
    /**
     * 输送线正转反馈
     * 正转运行为1,否则为0
     */
    private Boolean forwardRotationFeedback;
    /**
     * 输送线反转反馈
     * 反转运行为1,否则为0
     */
    private Boolean reverseFeedback;
    /**
     * 输送线电机过载
     * 过载为0,正常为1
     */
    private Boolean motorOverload;
    /**
     * 输送线末端光电有货
     * 有货为1,无货为0
     */
    private Boolean lineEndHasStock;
    /**
     * 进输送线卡托盘报警
     * 报警为1,未报警为0
     */
    private Boolean inConveyLineCardTrayAlarm;
    /**
     * 出输送线卡托盘报警
     * 报警为1,未报警为0
     */
    private Boolean outConveyLineCardTrayAlarm;
    /**
     * 平台位置偏差报警
     * 报警为1,未报警为0
     */
    private Boolean platPositionDeviationAlarm;
    /**
     * 平台扭矩偏差报警
     * 报警为1,未报警为0
     */
    private Boolean platTorqueDeviationAlarm;
    /**
     * 平台四向车检测
     * 有车为1,无车为0
     */
    private Boolean platShuttleCheck;
    /**
     * 未就绪状态
     * 1.    不在指定层
     * 2.    四轴不同步
     * 3.    平台前限光电被挡到(靠近货架)
     * 4.    平台后限光电被挡到(远离货架)
     * 5.    平台上限位报警
     * 6.    平台下限位报警
     * 7.    电柜急停报警
     * 8.    输送线前限位被挡到(靠近货架)
     * 9.    输送线后限位被挡到(远离货架)
     * 10.    触摸屏紧急停止被按下
     * 11.    四轴动力线断线
     * 12.    单机模式
     * 13.    四轴报警
     * 14.    位置偏差过大
     * 15.    扭矩偏差过大
     * 16.    输送线过载
     * 17.    进提升机卡托盘
     * 18.    出提升机卡托盘
     */
    private Short notReady;
    /**
     * 伺服1错误
     */
    private Short servoError1;
    /**
     * 伺服2错误
     */
    private Short servoError2;
    /**
     * 伺服3错误
     */
    private Short servoError3;
    /**
     * 伺服4错误
     */
    private Short servoError4;
    /**
     * 提升机实际速度反馈
     */
    private Short liftActualSpeed;
    /**
     * 作业标记
     */
    private Boolean pakMk = true;
    public String getLiftLock$() {
        return this.liftLock ? "Y" : "N";
    }
    public String getReady$() {
        return this.ready ? "Y" : "N";
    }
    public String getRunning$() {
        return this.running ? "Y" : "N";
    }
    public String getMode$() {
        return this.mode ? "Y" : "N";
    }
    public String getLineFrontHasStock$() {
        return this.lineFrontHasStock ? "Y" : "N";
    }
    public String getForwardRotationFeedback$() {
        return this.forwardRotationFeedback ? "Y" : "N";
    }
    public String getReverseFeedback$() {
        return this.reverseFeedback ? "Y" : "N";
    }
    public String getMotorOverload$() {
        return this.motorOverload ? "Y" : "N";
    }
    public String getLineEndHasStock$() {
        return this.lineEndHasStock ? "Y" : "N";
    }
    public String getInConveyLineCardTrayAlarm$() {
        return this.inConveyLineCardTrayAlarm ? "Y" : "N";
    }
    public String getOutConveyLineCardTrayAlarm$() {
        return this.outConveyLineCardTrayAlarm ? "Y" : "N";
    }
    public String getPlatPositionDeviationAlarm$() {
        return this.platPositionDeviationAlarm ? "Y" : "N";
    }
    public String getPlatTorqueDeviationAlarm$() {
        return this.platTorqueDeviationAlarm ? "Y" : "N";
    }
    public String getPlatShuttleCheck$() {
        return this.platShuttleCheck ? "Y" : "N";
    }
    public String getPakMk$() {
        return this.pakMk ? "Y" : "N";
    }
}
src/main/java/com/zy/asrs/domain/vo/ShuttleSensorDataVo.java
@@ -10,81 +10,4 @@
     */
    private Integer shuttleNo;
    // 任务信息 ---------------------------------------------------------
    /**
     * 96.入库任务中
     */
    private boolean pakInTask;
    /**
     * 97. 出库任务中
     */
    private boolean pakOutTask;
    /**
     * 98. 移库任务中
     */
    private boolean pakMoveTask;
    /**
     * 99. 回原点任务中
     */
    private boolean goHpTask;
    /**
     * 100. 去反原点任务中
     */
    private boolean goOHpTask;
    /**
     * 101. 去原点避让位
     */
    private boolean goHpAvoid;
    /**
     * 102. 去反原点避让位
     */
    private boolean goOHpAvoid;
    /**
     * 104. 入库取空结束
     */
    private boolean pakInEmpty;
    /**
     * 105. 入库正常结束
     */
    private boolean pakInFinish;
    /**
     * 106. 出库取空结束
     */
    private boolean pakOutEmpty;
    /**
     * 107. 出库正常结束
     */
    private boolean pakOutFinish;
    /**
     * 108. 去原点避让完成
     */
    private boolean goHpAvoidFinish;
    /**
     * 109. 去反原点避让完成
     */
    private boolean goOHpAvoidFinish;
    /**
     * 110. 去原点避让完成
     */
    private boolean goHpAvoidErr;
    /**
     * 111. 去反原点避让完成
     */
    private boolean goOHpAvoidErr;
}
src/main/java/com/zy/asrs/entity/BasLift.java
New file
@@ -0,0 +1,299 @@
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 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_lift")
public class BasLift implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 提升机号
     */
    @ApiModelProperty(value= "提升机号")
    @TableId(value = "lift_no", type = IdType.INPUT)
    @TableField("lift_no")
    private Integer liftNo;
    /**
     * 当前任务状态
     */
    @ApiModelProperty(value= "当前任务状态")
    @TableField("status")
    private Integer status;
    /**
     * 任务号
     */
    @ApiModelProperty(value= "任务号")
    @TableField("wrk_no")
    private Integer wrkNo;
    /**
     * 修改时间
     */
    @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= "作业标记")
    @TableField("pak_mk")
    private Boolean pakMk;
    /**
     * 提升机锁定
     */
    @ApiModelProperty(value= "提升机锁定")
    @TableField("lift_lock")
    private Boolean liftLock;
    /**
     * 位置到达反馈
     */
    @ApiModelProperty(value= "位置到达反馈")
    @TableField("position_arrival_feedback")
    private Integer positionArrivalFeedback;
    /**
     * 准备就绪
     */
    @ApiModelProperty(value= "准备就绪")
    private Boolean ready;
    /**
     * 运行中
     */
    @ApiModelProperty(value= "运行中")
    private Boolean running;
    /**
     * 联机/单机
     */
    @ApiModelProperty(value= "联机/单机")
    private Boolean mode;
    /**
     * 输送线前端光电有货
     */
    @ApiModelProperty(value= "输送线前端光电有货")
    @TableField("line_front_has_stock")
    private Boolean lineFrontHasStock;
    /**
     * 输送线正转反馈
     */
    @ApiModelProperty(value= "输送线正转反馈")
    @TableField("forward_rotation_feedback")
    private Boolean forwardRotationFeedback;
    /**
     * 输送线反转反馈
     */
    @ApiModelProperty(value= "输送线反转反馈")
    @TableField("reverse_feedback")
    private Boolean reverseFeedback;
    /**
     * 输送线电机过载
     */
    @ApiModelProperty(value= "输送线电机过载")
    @TableField("motor_overload")
    private Boolean motorOverload;
    /**
     * 输送线末端光电有货
     */
    @ApiModelProperty(value= "输送线末端光电有货")
    @TableField("line_end_has_stock")
    private Boolean lineEndHasStock;
    /**
     * 进输送线卡托盘报警
     */
    @ApiModelProperty(value= "进输送线卡托盘报警")
    @TableField("in_convey_line_card_tray_alarm")
    private Boolean inConveyLineCardTrayAlarm;
    /**
     * 出输送线卡托盘报警
     */
    @ApiModelProperty(value= "出输送线卡托盘报警")
    @TableField("out_convey_line_card_tray_alarm")
    private Boolean outConveyLineCardTrayAlarm;
    /**
     * 平台位置偏差报警
     */
    @ApiModelProperty(value= "平台位置偏差报警")
    @TableField("plat_position_deviation_alarm")
    private Boolean platPositionDeviationAlarm;
    /**
     * 平台扭矩偏差报警
     */
    @ApiModelProperty(value= "平台扭矩偏差报警")
    @TableField("plat_torque_deviation_alarm")
    private Boolean platTorqueDeviationAlarm;
    /**
     * 平台四向车检测
     */
    @ApiModelProperty(value= "平台四向车检测")
    @TableField("plat_shuttle_check")
    private Boolean platShuttleCheck;
    /**
     * 未就绪状态
     */
    @ApiModelProperty(value= "未就绪状态")
    @TableField("not_ready")
    private Integer notReady;
    /**
     * 伺服1错误
     */
    @ApiModelProperty(value= "伺服1错误")
    @TableField("servo_error1")
    private Integer servoError1;
    /**
     * 伺服2错误
     */
    @ApiModelProperty(value= "伺服2错误")
    @TableField("servo_error2")
    private Integer servoError2;
    /**
     * 伺服3错误
     */
    @ApiModelProperty(value= "伺服3错误")
    @TableField("servo_error3")
    private Integer servoError3;
    /**
     * 伺服4错误
     */
    @ApiModelProperty(value= "伺服4错误")
    @TableField("servo_error4")
    private Integer servoError4;
    /**
     * 提升机实际速度反馈
     */
    @ApiModelProperty(value= "提升机实际速度反馈")
    @TableField("lift_actual_speed")
    private Integer liftActualSpeed;
    public BasLift() {}
    public BasLift(Integer liftNo,Integer status,Integer wrkNo,Date updateTime,Long updateBy,String memo,Boolean pakMk,Boolean liftLock,Integer positionArrivalFeedback,Boolean ready,Boolean running,Boolean mode,Boolean lineFrontHasStock,Boolean forwardRotationFeedback,Boolean reverseFeedback,Boolean motorOverload,Boolean lineEndHasStock,Boolean inConveyLineCardTrayAlarm,Boolean outConveyLineCardTrayAlarm,Boolean platPositionDeviationAlarm,Boolean platTorqueDeviationAlarm,Boolean platShuttleCheck,Integer notReady,Integer servoError1,Integer servoError2,Integer servoError3,Integer servoError4,Integer liftActualSpeed) {
        this.liftNo = liftNo;
        this.status = status;
        this.wrkNo = wrkNo;
        this.updateTime = updateTime;
        this.updateBy = updateBy;
        this.memo = memo;
        this.pakMk = pakMk;
        this.liftLock = liftLock;
        this.positionArrivalFeedback = positionArrivalFeedback;
        this.ready = ready;
        this.running = running;
        this.mode = mode;
        this.lineFrontHasStock = lineFrontHasStock;
        this.forwardRotationFeedback = forwardRotationFeedback;
        this.reverseFeedback = reverseFeedback;
        this.motorOverload = motorOverload;
        this.lineEndHasStock = lineEndHasStock;
        this.inConveyLineCardTrayAlarm = inConveyLineCardTrayAlarm;
        this.outConveyLineCardTrayAlarm = outConveyLineCardTrayAlarm;
        this.platPositionDeviationAlarm = platPositionDeviationAlarm;
        this.platTorqueDeviationAlarm = platTorqueDeviationAlarm;
        this.platShuttleCheck = platShuttleCheck;
        this.notReady = notReady;
        this.servoError1 = servoError1;
        this.servoError2 = servoError2;
        this.servoError3 = servoError3;
        this.servoError4 = servoError4;
        this.liftActualSpeed = liftActualSpeed;
    }
//    BasLift basLift = new BasLift(
//            null,    // 提升机号[非空]
//            null,    // 当前提升机状态
//            null,    // 任务号
//            null,    // 修改时间
//            null,    // 修改人员
//            null,    // 备注
//            null,    // 作业标记
//            null,    // 提升机锁定
//            null,    // 位置到达反馈
//            null,    // 准备就绪
//            null,    // 运行中
//            null,    // 联机/单机
//            null,    // 输送线前端光电有货
//            null,    // 输送线正转反馈
//            null,    // 输送线反转反馈
//            null,    // 输送线电机过载
//            null,    // 输送线末端光电有货
//            null,    // 进输送线卡托盘报警
//            null,    // 出输送线卡托盘报警
//            null,    // 平台位置偏差报警
//            null,    // 平台扭矩偏差报警
//            null,    // 平台四向车检测
//            null,    // 未就绪状态
//            null,    // 伺服1错误
//            null,    // 伺服2错误
//            null,    // 伺服3错误
//            null,    // 伺服4错误
//            null    // 提升机实际速度反馈
//    );
    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/entity/BasLiftOpt.java
New file
@@ -0,0 +1,126 @@
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_lift_opt")
public class BasLiftOpt implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value= "")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 任务号
     */
    @ApiModelProperty(value= "任务号")
    @TableField("wrk_no")
    private Integer wrkNo;
    /**
     * 提升机号
     */
    @ApiModelProperty(value= "提升机号")
    @TableField("lift_no")
    private Integer liftNo;
    /**
     * 下发时间
     */
    @ApiModelProperty(value= "下发时间")
    @TableField("send_time")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date sendTime;
    /**
     * 修改时间
     */
    @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 BasLiftOpt() {}
    public BasLiftOpt(Integer wrkNo,Integer liftNo,Date sendTime,Date updateTime,Long updateBy,String memo,String command) {
        this.wrkNo = wrkNo;
        this.liftNo = liftNo;
        this.sendTime = sendTime;
        this.updateTime = updateTime;
        this.updateBy = updateBy;
        this.memo = memo;
        this.command = command;
    }
//    BasLiftOpt basLiftOpt = new BasLiftOpt(
//            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/BasLiftMapper.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.mapper;
import com.zy.asrs.entity.BasLift;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BasLiftMapper extends BaseMapper<BasLift> {
}
src/main/java/com/zy/asrs/mapper/BasLiftOptMapper.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.mapper;
import com.zy.asrs.entity.BasLiftOpt;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BasLiftOptMapper extends BaseMapper<BasLiftOpt> {
}
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java
@@ -99,4 +99,8 @@
    WrkMast selectRackInStep48(Short workNo,Integer sourceStaNo);
    WrkMast selectByWorkNo59(Integer workNo);
    WrkMast selectLiftStep6();
    WrkMast selectByWorkNo7(Integer workNo);
}
src/main/java/com/zy/asrs/service/BasLiftOptService.java
New file
@@ -0,0 +1,8 @@
package com.zy.asrs.service;
import com.zy.asrs.entity.BasLiftOpt;
import com.baomidou.mybatisplus.service.IService;
public interface BasLiftOptService extends IService<BasLiftOpt> {
}
src/main/java/com/zy/asrs/service/BasLiftService.java
New file
@@ -0,0 +1,8 @@
package com.zy.asrs.service;
import com.zy.asrs.entity.BasLift;
import com.baomidou.mybatisplus.service.IService;
public interface BasLiftService extends IService<BasLift> {
}
src/main/java/com/zy/asrs/service/impl/BasLiftOptServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.service.impl;
import com.zy.asrs.mapper.BasLiftOptMapper;
import com.zy.asrs.entity.BasLiftOpt;
import com.zy.asrs.service.BasLiftOptService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("basLiftOptService")
public class BasLiftOptServiceImpl extends ServiceImpl<BasLiftOptMapper, BasLiftOpt> implements BasLiftOptService {
}
src/main/java/com/zy/asrs/service/impl/BasLiftServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.service.impl;
import com.zy.asrs.mapper.BasLiftMapper;
import com.zy.asrs.entity.BasLift;
import com.zy.asrs.service.BasLiftService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("basLiftService")
public class BasLiftServiceImpl extends ServiceImpl<BasLiftMapper, BasLift> implements BasLiftService {
}
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -23,10 +23,7 @@
import com.zy.core.enums.*;
import com.zy.core.model.*;
import com.zy.core.model.command.*;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.model.protocol.SteProtocol;
import com.zy.core.model.protocol.*;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.*;
import lombok.extern.slf4j.Slf4j;
@@ -673,9 +670,8 @@
                            //入出库模式
                            assignCommand.setTaskMode(ShuttleTaskModeType.PAK_IN.id.shortValue());
                            //源库位(小车当前位置)
                            Short currentCode = shuttleProtocol.getCurrentCode();
                            LocMast currentLocMast = locMastService.queryByQrCode(currentCode.toString());
                            assignCommand.setSourceLocNo(currentLocMast.getLocNo());
                            String currentLocNo = shuttleProtocol.getCurrentLocNo();
                            assignCommand.setSourceLocNo(currentLocNo);
                            if (wrkMast.getWrkSts() == 8 || Boolean.parseBoolean(searchIdleShuttle.get("sameLay").toString())) {
                                //同一层
@@ -688,7 +684,6 @@
                                //不同层,将目标库位分配成提升机库位号
                                //小车当前层高
                                String currentLocNo = currentLocMast.getLocNo();
                                Integer currentLev = Integer.parseInt(currentLocNo.substring(currentLocNo.length() - 2, currentLocNo.length()));
                                //获取提升机
@@ -736,9 +731,7 @@
                continue;
            }
            Short currentCode = shuttleProtocol.getCurrentCode();//四向穿梭车当前位置二维码
            LocMast shuttleLocMast = locMastService.queryByQrCode(currentCode.toString());//找到二维码对应的库位记录
            String shuttleLocNo = shuttleLocMast.getLocNo();//二维码对应库位号
            String shuttleLocNo = shuttleProtocol.getCurrentLocNo();//二维码对应库位号
            String shuttleLocNoLay = shuttleLocNo.substring(shuttleLocNo.length() - 2, shuttleLocNo.length());//库位号对应层高
            if (lay.equals(shuttleLocNoLay)) {
                //当前四向穿梭车和工作档任务在同一层,则调配该车辆
@@ -752,9 +745,7 @@
                recentShuttle = shuttleThread;
            }else {
                ShuttleProtocol recentShuttleProtocol = recentShuttle.getShuttleProtocol();//目前最近穿梭车
                Short recentShuttleCurrentCode = recentShuttleProtocol.getCurrentCode();//目前最近穿梭车位置二维码
                LocMast recentShuttleLocMast = locMastService.queryByQrCode(recentShuttleCurrentCode.toString());//找到二维码对应的库位记录
                String recentShuttleLocNo = recentShuttleLocMast.getLocNo();//二维码对应库位号
                String recentShuttleLocNo = recentShuttleProtocol.getCurrentLocNo();//二维码对应库位号
                String recentShuttleLocNoLay = recentShuttleLocNo.substring(recentShuttleLocNo.length() - 2, recentShuttleLocNo.length());//库位号对应层高
                int recentShuttleLocNoLayInt = Integer.parseInt(recentShuttleLocNoLay);
@@ -838,7 +829,9 @@
                        shuttleProtocol.setLocNo(null);
                        //标记复位
                        shuttleProtocol.setPakMk(true);
                        News.info("四向穿梭车已确认且任务完成状态,复位。堆垛机号={}", shuttleProtocol.getShuttleNo());
                        //任务指令清零
                        shuttleProtocol.setAssignCommand(null);
                        News.info("四向穿梭车已确认且任务完成状态,复位。四向穿梭车号={}", shuttleProtocol.getShuttleNo());
                    } else {
                        News.error("四向穿梭车已确认且任务完成状态,复位失败,但未找到工作档。四向穿梭车号={},工作号={}", shuttleProtocol.getShuttleNo(), shuttleProtocol.getTaskNo());
                    }
@@ -849,6 +842,152 @@
    }
    /**
     * 提升机任务
     */
    public synchronized void liftIoExecute() {
        for (LiftSlave liftSlave : slaveProperties.getLift()) {
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, liftSlave.getId());
            if (liftThread == null) {
                continue;
            }
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null) {
                continue;
            }
            //判断提升机是否处于空闲状态
            if (!liftProtocol.isIdle()) {
                continue;
            }
            //搜索是否有待处理的任务
            WrkMast wrkMast = wrkMastMapper.selectLiftStep6();
            if (wrkMast == null) {
                continue;
            }
            //给提升机分配任务
            liftProtocol.setLiftLock(true);//锁定提升机
            liftProtocol.setTaskNo(wrkMast.getWrkNo().shortValue());//设置任务号
            liftProtocol.setShuttleNo(wrkMast.getShuttleNo().shortValue());//设置四向穿梭车号
            liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);//设置提升机状态为工作中
            //找到四向穿梭车的线程
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, liftProtocol.getShuttleNo().intValue());
            if (shuttleThread == null) {
                continue;
            }
            ShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol == null) {
                continue;
            }
            //命令list
            ArrayList<LiftCommand> commands = new ArrayList<>();
            //当前穿梭车库位号
            String currentLocNo = shuttleProtocol.getCurrentLocNo();
            //当前穿梭车楼层
            int currentLocNoLey = Integer.parseInt(currentLocNo.substring(currentLocNo.length() - 2, currentLocNo.length()));
            //工作档目标库位号
            String wrkMastLocNo = wrkMast.getLocNo();
            //工作档目标库位楼层
            int wrkMastLocNoLey = Integer.parseInt(wrkMastLocNo.substring(wrkMastLocNo.length() - 2, wrkMastLocNo.length()));
            //提升机当前楼层
            int liftLev = liftProtocol.getLev().intValue();
            if (liftLev != currentLocNoLey) {
                //不同楼层
                LiftCommand command1 = new LiftCommand();
                command1.setLiftNo(liftProtocol.getLiftNo());//提升机号
                command1.setTaskNo(liftProtocol.getTaskNo());//任务号
                command1.setRun((short) 1);//升降
                command1.setDistPosition((short) currentLocNoLey);//目标楼层(穿梭车所在楼层)
                command1.setLiftLock(true);//锁定提升机
                commands.add(command1);//将命令添加进list
            }
            //输送线将四向穿梭车移动进来
            LiftCommand command2 = new LiftCommand();
            command2.setLiftNo(liftProtocol.getLiftNo());//提升机号
            command2.setTaskNo(liftProtocol.getTaskNo());//任务号
            command2.setRun((short) 6);//输送线运作
            command2.setLiftLock(true);//锁定提升机
            commands.add(command2);//将命令添加进list
            //提升机搬运四向穿梭车
            LiftCommand command3 = new LiftCommand();
            command3.setLiftNo(liftProtocol.getLiftNo());//提升机号
            command3.setTaskNo(liftProtocol.getTaskNo());//任务号
            command3.setRun((short) 1);//升降
            command3.setDistPosition((short) wrkMastLocNoLey);//工作档目标楼层
            command3.setLiftLock(true);//锁定提升机
            commands.add(command3);//将命令添加进list
            //提升机到达指定楼层,输送线将四向穿梭车移出去
            //输送线将四向穿梭车移动进来
            LiftCommand command4 = new LiftCommand();
            command4.setLiftNo(liftProtocol.getLiftNo());//提升机号
            command4.setTaskNo(liftProtocol.getTaskNo());//任务号
            command4.setRun((short) 3);//输送线运作
            command4.setLiftLock(true);//锁定提升机
            commands.add(command4);//将命令添加进list
            wrkMast.setWrkSts(7L);//移动任务
            //所需命令组合完毕,更新数据库,提交到线程去工作
            LiftAssignCommand assignCommand = new LiftAssignCommand();
            assignCommand.setCommands(commands);
            assignCommand.setLiftNo(liftProtocol.getLiftNo());
            assignCommand.setTaskNo(liftProtocol.getTaskNo());
            if (wrkMastMapper.updateById(wrkMast) > 0) {
                //下发任务
                MessageQueue.offer(SlaveType.Lift, liftProtocol.getLiftNo().intValue(), new Task(3, assignCommand));
            }
        }
    }
    /**
     * 提升机任务完成
     */
    public synchronized void liftFinished() {
        for (LiftSlave liftSlave : slaveProperties.getLift()) {
            //获取提升机信息
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, liftSlave.getId());
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null) {
                continue;
            }
            //提升机为等待确认
            if (liftProtocol.getProtocolStatus() == LiftProtocolStatusType.WAITING.id && liftProtocol.getTaskNo() != 0) {
                //将任务档标记为完成
                WrkMast wrkMast = wrkMastMapper.selectByWorkNo7(liftProtocol.getTaskNo().intValue());
                if (wrkMast != null) {
                    wrkMast.setWrkSts(8L);
                    if (wrkMastMapper.updateById(wrkMast) > 0) {
                        //设置提升机为空闲状态
                        liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
                        //任务号清零
                        liftProtocol.setTaskNo((short) 0);
                        //标记复位
                        liftProtocol.setPakMk(true);
                        //任务指令清零
                        liftProtocol.setAssignCommand(null);
                        News.info("提升机已确认且任务完成状态,复位。提升机号={}", liftProtocol.getLiftNo());
                    } else {
                        News.error("提升机已确认且任务完成状态,复位失败,但未找到工作档。提升机号={},工作号={}", liftProtocol.getLiftNo(), liftProtocol.getTaskNo());
                    }
                }
            }
        }
    }
    /**
     * 入出库  ===>>  堆垛机入出库作业下发
     */
    public synchronized void crnIoExecute(){
src/main/java/com/zy/common/utils/CommonUtils.java
@@ -40,4 +40,8 @@
        return new short[]{byteToShort2, byteToShort};
    }
    public static boolean shortToBoolean(Short num) {
        return num != 0;
    }
}
src/main/java/com/zy/core/MainProcess.java
@@ -61,6 +61,10 @@
                    mainService.shuttleIoExecute();
                    //四向穿梭车任务完成
                    mainService.shuttleFinished();
                    //提升机任务
                    mainService.liftIoExecute();
                    //提升机任务完成
                    mainService.liftFinished();
                    // 入库  ===>> 执行堆垛机对工作档的完成操作
                    mainService.storeFinished();
                    // 入库 ===>> 执行穿梭车对工作档的完成操作
src/main/java/com/zy/core/ServerBootstrap.java
@@ -108,7 +108,7 @@
        // 初始化提升机
        News.info("初始化提升机........................................................");
        for (LiftSlave liftSlave : slaveProperties.getLift()) {
            LiftThread liftThread = new LiftThread(liftSlave);
            LiftThread liftThread = new LiftThread(liftSlave, redisUtil);
            new Thread(liftThread).start();
            SlaveConnection.put(SlaveType.Lift, liftSlave.getId(), liftThread);
        }
src/main/java/com/zy/core/cache/MessageQueue.java
@@ -31,6 +31,8 @@
    private static final Map<Integer, ConcurrentLinkedQueue<Task>> CAR_EXCHANGE = new ConcurrentHashMap<>();
    //四向穿梭车mq交换机
    private static final Map<Integer, ConcurrentLinkedQueue<Task>> SHUTTLE_EXCHANGE = new ConcurrentHashMap<>();
    //提升机mq交换机
    private static final Map<Integer, ConcurrentLinkedQueue<Task>> LIFT_EXCHANGE = new ConcurrentHashMap<>();
    /**
     * mq 交换机初始化
@@ -61,6 +63,9 @@
            case Shuttle:
                SHUTTLE_EXCHANGE.put(slave.getId(), new ConcurrentLinkedQueue<>());
                break;
            case Lift:
                LIFT_EXCHANGE.put(slave.getId(), new ConcurrentLinkedQueue<>());
                break;
            default:
                break;
        }
@@ -88,6 +93,8 @@
                return CAR_EXCHANGE.get(id).offer(task);
            case Shuttle:
                return SHUTTLE_EXCHANGE.get(id).offer(task);
            case Lift:
                return LIFT_EXCHANGE.get(id).offer(task);
            default:
                return false;
        }
@@ -115,6 +122,8 @@
                return CAR_EXCHANGE.get(id).poll();
            case Shuttle:
                return SHUTTLE_EXCHANGE.get(id).poll();
            case Lift:
                return LIFT_EXCHANGE.get(id).poll();
            default:
                return null;
        }
@@ -141,6 +150,8 @@
                return CAR_EXCHANGE.get(id).peek();
            case Shuttle:
                return SHUTTLE_EXCHANGE.get(id).peek();
            case Lift:
                return LIFT_EXCHANGE.get(id).peek();
            default:
                return null;
        }
@@ -172,6 +183,9 @@
            case Shuttle:
                SHUTTLE_EXCHANGE.get(id).clear();
                break;
            case Lift:
                LIFT_EXCHANGE.get(id).clear();
                break;
            default:
                break;
        }
src/main/java/com/zy/core/enums/LiftProtocolStatusType.java
New file
@@ -0,0 +1,40 @@
package com.zy.core.enums;
public enum LiftProtocolStatusType {
    IDLE(1, "空闲"),
    WORKING(2, "作业中"),
    WAITING(3, "等待确认"),
    ;
    public Integer id;
    public String desc;
    LiftProtocolStatusType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static LiftProtocolStatusType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (LiftProtocolStatusType type : LiftProtocolStatusType.values()) {
            if (type.id.equals(id.intValue())) {
                return type;
            }
        }
        return null;
    }
    public static LiftProtocolStatusType get(LiftProtocolStatusType type) {
        if (null == type) {
            return null;
        }
        for (LiftProtocolStatusType type2 : LiftProtocolStatusType.values()) {
            if (type2 == type) {
                return type2;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/model/command/LiftAssignCommand.java
New file
@@ -0,0 +1,40 @@
package com.zy.core.model.command;
import lombok.Data;
import java.util.List;
@Data
public class LiftAssignCommand {
    /**
     * 提升机号
     */
    private Short liftNo = 0;
    /**
     * 任务号
     */
    private Short taskNo = 0;
    /**
     * 命令list
     */
    private List<LiftCommand> commands;
    /**
     * 作业类型
     * 1: 上升一层
     * 2: 下降一层
     * 3: 有货正转
     * 4: 有货反转
     * 5: 复位
     */
    private Short taskMode = 0;
    /**
     * 是否自动,true:自动模式,false:手动模式
     */
    private Boolean auto = true;
}
src/main/java/com/zy/core/model/command/LiftCommand.java
@@ -12,22 +12,12 @@
    /**
     * 提升机号
     */
    private Integer liftNo = 0;
    private Short liftNo = 0;
    /**
     * 任务号
     */
    private Integer taskNo = 0;
    /**
     * 作业类型
     */
    private Short taskMode = 0;
    /**
     * 任务确认 false:未确认 true:已确认
     */
    private Boolean complete = Boolean.FALSE;
    private Short taskNo = 0;
    /**
     * 开始运行
@@ -65,6 +55,9 @@
    private Boolean liftLock;
    public Short getLiftLockShortValue() {
        if (liftLock == null) {
            return (short) 0;
        }
        return liftLock ? (short) 1 : (short) 0;
    }
src/main/java/com/zy/core/model/command/ShuttleAssignCommand.java
@@ -2,6 +2,9 @@
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class ShuttleAssignCommand {
@@ -38,4 +41,14 @@
     */
    private String locNo;
    /**
     * 命令list
     */
    private List<ShuttleCommand> commands = new ArrayList<>();
    /**
     * 是否自动,true:自动模式,false:手动模式
     */
    private Boolean auto = true;
}
src/main/java/com/zy/core/model/protocol/LiftProtocol.java
@@ -1,5 +1,13 @@
package com.zy.core.model.protocol;
import com.core.common.SpringUtils;
import com.zy.asrs.service.BasShuttleService;
import com.zy.core.News;
import com.zy.core.enums.LiftProtocolStatusType;
import com.zy.core.enums.ShuttleErrorCodeType;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.ShuttleStatusType;
import com.zy.core.model.command.LiftAssignCommand;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -19,6 +27,21 @@
     * 任务号
     */
    private Short taskNo = 0;
    /**
     * 四向穿梭车号
     */
    private Short shuttleNo = 0;
    /**
     * 当前提升机状态(内部自我维护)
     */
    private Integer protocolStatus = 1;
    /**
     * 当前提升机状态枚举
     */
    private LiftProtocolStatusType protocolStatusType = LiftProtocolStatusType.IDLE;
    /**
     * 层
@@ -161,8 +184,51 @@
     */
    private Short liftActualSpeed;
    /**
     * 作业标记
     */
    private Boolean pakMk = true;
    /**
     * 任务命令
     */
    private LiftAssignCommand assignCommand;
    public Short getLiftLockShortValue() {
        return liftLock ? (short) 1 : (short) 0;
    }
    /**
     * 设置提升机状态
     */
    public void setProtocolStatus(Integer status) {
        this.protocolStatus = status;
        this.protocolStatusType = LiftProtocolStatusType.get(status);
    }
    /**
     * 设置提升机状态
     */
    public void setProtocolStatus(LiftProtocolStatusType status) {
        this.protocolStatus = status.id;
        this.protocolStatusType = status;
    }
    // 是否处于空闲待命状态
    public Boolean isIdle() {
        boolean res = this.taskNo == 0
                && !this.liftLock
                && this.ready
                && !this.running
                && this.mode
                && this.pakMk.equals(true)
                ;
        return res;
    }
    public void setPositionArrivalFeedback(Short position) {
        this.lev = position;//层高
        this.positionArrivalFeedback = position;//位置到达反馈
    }
}
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java
@@ -1,7 +1,9 @@
package com.zy.core.model.protocol;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.core.News;
import com.zy.core.enums.ShuttleErrorCodeType;
import com.zy.core.enums.ShuttleProtocolStatusType;
@@ -228,4 +230,18 @@
        }
    }
    //通过当前二维码获取当前库位号
    public String getCurrentLocNo() {
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        if (locMastService == null) {
            return null;
        }
        //源库位(小车当前位置)
        LocMast currentLocMast = locMastService.queryByQrCode(this.currentCode.toString());
        if (currentLocMast == null) {
            return null;
        }
        return currentLocMast.getLocNo();
    }
}
src/main/java/com/zy/core/thread/LiftThread.java
@@ -5,22 +5,40 @@
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.ModBus.ModbusTcpNet;
import com.alibaba.fastjson.JSON;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasLift;
import com.zy.asrs.entity.BasLiftOpt;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.BasShuttleOpt;
import com.zy.asrs.service.BasLiftOptService;
import com.zy.asrs.service.BasLiftService;
import com.zy.asrs.service.BasShuttleOptService;
import com.zy.asrs.service.BasShuttleService;
import com.zy.common.utils.CommonUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.ThreadHandler;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.SlaveType;
import com.zy.core.enums.*;
import com.zy.core.model.LiftSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.LiftAssignCommand;
import com.zy.core.model.command.LiftCommand;
import com.zy.core.model.command.ShuttleAssignCommand;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.protocol.LiftProtocol;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
 * 提升机线程
@@ -32,9 +50,11 @@
    private ModbusTcpNet modbusTcpNet;
    private LiftSlave slave;
    private LiftProtocol liftProtocol;
    private RedisUtil redisUtil;
    public LiftThread(LiftSlave slave) {
    public LiftThread(LiftSlave slave,RedisUtil redisUtil) {
        this.slave = slave;
        this.redisUtil = redisUtil;
    }
    @Override
@@ -56,6 +76,10 @@
                    case 2:
                        write((LiftCommand) task.getData());
                        break;
                    //分配任务
                    case 3:
                        assignWork((LiftAssignCommand) task.getData());
                        break;
                    default:
                        break;
                }
@@ -70,7 +94,7 @@
    public boolean connect() {
        boolean result = false;
        //-------------------------提升机连接方法------------------------//
        modbusTcpNet = new ModbusTcpNet(slave.getIp(), slave.getPort(), (byte) 0x01);
        modbusTcpNet = new ModbusTcpNet(slave.getIp(), slave.getPort(), (byte) 0x02);
        // 当你需要指定格式的数据解析时,就需要设置下面的这个信息
        modbusTcpNet.setDataFormat(DataFormat.ABCD);
        OperateResult connect = modbusTcpNet.ConnectServer();
@@ -94,7 +118,7 @@
    private void readStatus() {
        try {
            OperateResultExOne<byte[]> result = modbusTcpNet.Read("29", (short) 17);
            OperateResultExOne<byte[]> result = modbusTcpNet.Read("29", (short) 50);
            if (result.IsSuccess) {
                if (null == liftProtocol) {
                    liftProtocol = new LiftProtocol();
@@ -105,55 +129,106 @@
                //获取数据
                byte[] content = result.Content;
                //提升机锁定
                liftProtocol.setLiftLock(modbusTcpNet.getByteTransform().TransBool(content,0));
                liftProtocol.setLiftLock(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content, 0)));
                //位置到达反馈
                liftProtocol.setPositionArrivalFeedback(modbusTcpNet.getByteTransform().TransInt16(content,2));
                //准备就绪
                liftProtocol.setReady(modbusTcpNet.getByteTransform().TransBool(content,3));
                liftProtocol.setReady(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content,4)));
                //运行中
                liftProtocol.setRunning(modbusTcpNet.getByteTransform().TransBool(content,4));
                liftProtocol.setRunning(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content,6)));
                //联机/单机
                liftProtocol.setMode(modbusTcpNet.getByteTransform().TransBool(content,5));
                liftProtocol.setMode(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content,8)));
                //以下参数并未进行调整(需要后续针对实机进行获取和调试)
                //输送线前端光电有货
                liftProtocol.setLineFrontHasStock(modbusTcpNet.getByteTransform().TransBool(content,6));
                liftProtocol.setLineFrontHasStock(modbusTcpNet.getByteTransform().TransBool(content,10));
                //输送线正转反馈
                liftProtocol.setForwardRotationFeedback(modbusTcpNet.getByteTransform().TransBool(content,7));
                liftProtocol.setForwardRotationFeedback(modbusTcpNet.getByteTransform().TransBool(content,12));
                //输送线反转反馈
                liftProtocol.setReverseFeedback(modbusTcpNet.getByteTransform().TransBool(content,8));
                liftProtocol.setReverseFeedback(modbusTcpNet.getByteTransform().TransBool(content,14));
                //输送线电机过载
                liftProtocol.setMotorOverload(modbusTcpNet.getByteTransform().TransBool(content,9));
                liftProtocol.setMotorOverload(modbusTcpNet.getByteTransform().TransBool(content,16));
                //输送线末端光电有货
                liftProtocol.setLineEndHasStock(modbusTcpNet.getByteTransform().TransBool(content,10));
                liftProtocol.setLineEndHasStock(modbusTcpNet.getByteTransform().TransBool(content,18));
                //进输送线卡托盘报警
                liftProtocol.setInConveyLineCardTrayAlarm(modbusTcpNet.getByteTransform().TransBool(content,11));
                liftProtocol.setInConveyLineCardTrayAlarm(modbusTcpNet.getByteTransform().TransBool(content,20));
                //出输送线卡托盘报警
                liftProtocol.setOutConveyLineCardTrayAlarm(modbusTcpNet.getByteTransform().TransBool(content,12));
                liftProtocol.setOutConveyLineCardTrayAlarm(modbusTcpNet.getByteTransform().TransBool(content,22));
                //平台位置偏差报警
                liftProtocol.setPlatPositionDeviationAlarm(modbusTcpNet.getByteTransform().TransBool(content,13));
                liftProtocol.setPlatPositionDeviationAlarm(modbusTcpNet.getByteTransform().TransBool(content,24));
                //平台扭矩偏差报警
                liftProtocol.setPlatTorqueDeviationAlarm(modbusTcpNet.getByteTransform().TransBool(content,14));
                liftProtocol.setPlatTorqueDeviationAlarm(modbusTcpNet.getByteTransform().TransBool(content,26));
                //平台四向车检测
                liftProtocol.setPlatShuttleCheck(modbusTcpNet.getByteTransform().TransBool(content,15));
                liftProtocol.setPlatShuttleCheck(modbusTcpNet.getByteTransform().TransBool(content,28));
                //未就绪状态
                liftProtocol.setNotReady(modbusTcpNet.getByteTransform().TransInt16(content,16));
                liftProtocol.setNotReady(modbusTcpNet.getByteTransform().TransInt16(content,30));
                //伺服1错误
                liftProtocol.setServoError1(modbusTcpNet.getByteTransform().TransInt16(content,17));
                liftProtocol.setServoError1(modbusTcpNet.getByteTransform().TransInt16(content,32));
                //伺服2错误
                liftProtocol.setServoError2(modbusTcpNet.getByteTransform().TransInt16(content,18));
                liftProtocol.setServoError2(modbusTcpNet.getByteTransform().TransInt16(content,34));
                //伺服3错误
                liftProtocol.setServoError3(modbusTcpNet.getByteTransform().TransInt16(content,19));
                liftProtocol.setServoError3(modbusTcpNet.getByteTransform().TransInt16(content,36));
                //伺服4错误
                liftProtocol.setServoError4(modbusTcpNet.getByteTransform().TransInt16(content,20));
                liftProtocol.setServoError4(modbusTcpNet.getByteTransform().TransInt16(content,38));
                //提升机实际速度反馈
                liftProtocol.setLiftActualSpeed(modbusTcpNet.getByteTransform().TransInt16(content,21));
                liftProtocol.setLiftActualSpeed(modbusTcpNet.getByteTransform().TransInt16(content,40));
                ///读取提升机状态-end
                OutputQueue.LIFT.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
//                log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
                //小车处于运行状态,将标记置为true
                if (liftProtocol.getRunning()) {
                    liftProtocol.setPakMk(true);
                }
                // 根据实时信息更新数据库
                //.....
                //提升机处于锁定、未运行、就绪、标记true、有任务号
                if (liftProtocol.getLiftLock()
                        && !liftProtocol.getRunning()
                        && liftProtocol.getReady()
                        && liftProtocol.getPakMk()
                        && liftProtocol.getTaskNo() != 0
                        && liftProtocol.getAssignCommand() != null) {
                    //还有未完成的命令
                    executeWork(liftProtocol.getAssignCommand());
                }
                //将提升机状态保存至数据库
                BasLiftService liftService = SpringUtils.getBean(BasLiftService.class);
                BasLift basLift = liftService.selectById(liftProtocol.getLiftNo());
                if (basLift == null) {
                    basLift = new BasLift();
                    //提升机号
                    basLift.setLiftNo(slave.getId());
                    liftService.insert(basLift);
                }
                basLift.setStatus(liftProtocol.getProtocolStatus());
                basLift.setWrkNo(liftProtocol.getTaskNo().intValue());
                basLift.setUpdateTime(new Date());
                basLift.setPakMk(liftProtocol.getPakMk());
                basLift.setLiftLock(liftProtocol.getLiftLock());
                basLift.setPositionArrivalFeedback(liftProtocol.getPositionArrivalFeedback().intValue());
                basLift.setReady(liftProtocol.getReady());
                basLift.setRunning(liftProtocol.getRunning());
                basLift.setMode(liftProtocol.getMode());
                basLift.setLineFrontHasStock(liftProtocol.getLineFrontHasStock());
                basLift.setForwardRotationFeedback(liftProtocol.getForwardRotationFeedback());
                basLift.setReverseFeedback(liftProtocol.getReverseFeedback());
                basLift.setMotorOverload(liftProtocol.getMotorOverload());
                basLift.setLineEndHasStock(liftProtocol.getLineEndHasStock());
                basLift.setInConveyLineCardTrayAlarm(liftProtocol.getInConveyLineCardTrayAlarm());
                basLift.setOutConveyLineCardTrayAlarm(liftProtocol.getOutConveyLineCardTrayAlarm());
                basLift.setPlatPositionDeviationAlarm(liftProtocol.getPlatPositionDeviationAlarm());
                basLift.setPlatTorqueDeviationAlarm(liftProtocol.getPlatTorqueDeviationAlarm());
                basLift.setPlatShuttleCheck(liftProtocol.getPlatShuttleCheck());
                basLift.setNotReady(liftProtocol.getNotReady().intValue());
                basLift.setServoError1(liftProtocol.getServoError1().intValue());
                basLift.setServoError2(liftProtocol.getServoError2().intValue());
                basLift.setServoError3(liftProtocol.getServoError3().intValue());
                basLift.setServoError4(liftProtocol.getServoError4().intValue());
                basLift.setLiftActualSpeed(liftProtocol.getLiftActualSpeed().intValue());
                if (liftService.updateById(basLift)) {
                    OutputQueue.LIFT.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
//                    log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
                }
            }else {
                OutputQueue.LIFT.offer(MessageFormat.format("【{0}】{1}提升机plc状态信息失败", DateUtils.convert(new Date()), slave.getId()));
@@ -171,23 +246,35 @@
            return false;
        }
        command.setLiftNo(slave.getId());
        command.setLiftNo(slave.getId().shortValue());
        // 开始任务
        short[] array = new short[30];
        //开始运行
        array[0] = command.getRun();
        //目标位置
        array[1] = command.getDistPosition();
        //运行速度
        array[2] = command.getSpeed();
        //二层高度设定
        array[3] = command.getHeight2();
        //三层高度设定
        array[4] = command.getHeight3();
        //四层高度设定
        array[5] = command.getHeight4();
        //提升机锁定
        array[29] = command.getLiftLockShortValue();
        if (command.getDistPosition() != null) {
            //目标位置
            array[1] = command.getDistPosition();
        }
        if (command.getSpeed() != null) {
            //运行速度
            array[2] = command.getSpeed();
        }
        if (command.getHeight2() != null) {
            //二层高度设定
            array[3] = command.getHeight2();
        }
        if (command.getHeight3() != null) {
            //三层高度设定
            array[4] = command.getHeight3();
        }
        if (command.getHeight4() != null) {
            //四层高度设定
            array[5] = command.getHeight4();
        }
        if (command.getLiftLockShortValue() != null) {
            //提升机锁定
            array[29] = command.getLiftLockShortValue();
        }
        OperateResult result = modbusTcpNet.Write("0", array);;
        if (result != null && result.IsSuccess) {
@@ -199,6 +286,138 @@
            News.error("写入提升机plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
            return false;
        }
    }
    //分配任务
    private void assignWork(LiftAssignCommand assignCommand) {
        //将此map存入redis中
        HashMap<String, Object> map = new HashMap<>();
        //提升机号
        map.put("lift_no", assignCommand.getLiftNo());
        //工作号
        map.put("wrk_no", assignCommand.getTaskNo());
        //命令执行步序
        map.put("commandStep", 0);
        //命令
        map.put("assignCommand", assignCommand);
        //任务数据保存到redis
        redisUtil.set("lift_wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(map));
        liftProtocol.setAssignCommand(assignCommand);
        liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);
        //执行下发任务
        executeWork(assignCommand);
    }
    //执行任务
    private boolean executeWork(LiftAssignCommand assignCommand) {
        //读取redis数据
        if (assignCommand == null) {
            return false;
        }
        //将标记置为false(防止重发)
        liftProtocol.setPakMk(false);
        //手动模式指令
        if (!assignCommand.getAuto()) {
            LiftCommand command = new LiftCommand();
            //提升机当前楼层
            Short lev = liftProtocol.getLev();
            List<LiftCommand> commands = assignCommand.getCommands();
            if (commands == null) {
                commands = new ArrayList<LiftCommand>();
            }
            liftProtocol.setTaskNo(assignCommand.getTaskNo());
            switch (assignCommand.getTaskMode()) {
                case 1://上升一层
                    command.setRun((short) 1);//升降
                    command.setDistPosition(++lev);
                    break;
                case 2://下降一层
                    command.setRun((short) 1);//下降
                    command.setDistPosition(--lev);
                    break;
                case 3://有货正转
                    command.setRun((short) 6);
                    break;
                case 4://有货反转
                    command.setRun((short) 3);
                    break;
                case 5://复位
                    command.setRun((short) 0);
                    command.setLiftLock(false);
                    liftProtocol.setTaskNo((short) 0);
                    liftProtocol.setShuttleNo((short) 0);
                    liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
                    liftProtocol.setPakMk(true);
                    break;
                default:
            }
            commands.add(command);
            assignCommand.setCommands(commands);
        }
        Object o = redisUtil.get("lift_wrk_no_" + assignCommand.getTaskNo());
        if (o == null) {
            return false;
        }
        HashMap map = JSON.parseObject(o.toString(), HashMap.class);
        List<LiftCommand> commands = assignCommand.getCommands();
        //当前步序
        int commandStep = Integer.parseInt(map.get("commandStep").toString());
        //总步序
        int size = commands.size();
        //取出命令
        LiftCommand command = commands.get(commandStep);
        //下发命令
        if (!write(command)) {
            News.error("提升机命令下发失败,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
            return false;
        }else {
            News.info("提升机命令下发成功,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
            //判断数据是否执行完成
            if (commandStep < size - 1) {
                //更新redis数据
                //步序增加
                commandStep++;
                map.put("commandStep", commandStep);
                //任务数据保存到redis
                redisUtil.set("lift_wrk_no_" + map.get("wrk_no").toString(), JSON.toJSONString(map));
            }else {
                //已执行完成
                //保存数据到数据库做流水
                BasLiftOptService liftOptService = SpringUtils.getBean(BasLiftOptService.class);
                if (liftOptService != null) {
                    BasLiftOpt opt = new BasLiftOpt(
                            assignCommand.getTaskNo().intValue(),
                            assignCommand.getLiftNo().intValue(),
                            new Date(),
                            null,
                            null,
                            null,
                            JSON.toJSONString(assignCommand)
                    );
                    liftOptService.insert(opt);
                }
                //删除redis
                redisUtil.del("lift_wrk_no_" + map.get("wrk_no").toString());
                if (assignCommand.getAuto()) {
                    //对主线程抛出等待确认状态waiting
                    liftProtocol.setProtocolStatus(LiftProtocolStatusType.WAITING);
                    News.info("提升机任务执行完成等待确认中,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
                }else {
                    //手动模式不抛出等待状态
                    News.info("提升机手动任务执行完成,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
                }
            }
        }
        return true;
    }
    /**
@@ -218,19 +437,19 @@
        slave.setId(1);
        slave.setIp("192.168.4.24");
        slave.setPort(502);
        LiftThread thread = new LiftThread(slave);
        thread.connect();
        thread.readStatus();
        LiftCommand command = new LiftCommand();
        command.setRun((short) 0);
        command.setDistPosition((short) 12);
        command.setSpeed((short) 300);
        command.setHeight2((short) 100);
        command.setHeight3((short) 200);
        command.setHeight4((short) 303);
        command.setLiftLock(true);
        thread.write(command);
//        LiftThread thread = new LiftThread(slave,);
//        thread.connect();
//        thread.readStatus();
//
//        LiftCommand command = new LiftCommand();
//        command.setRun((short) 1);
//        command.setDistPosition((short) 12);
//        command.setSpeed((short) 300);
//        command.setHeight2((short) 100);
//        command.setHeight3((short) 200);
//        command.setHeight4((short) 303);
//        command.setLiftLock(true);
//        thread.write(command);
    }
src/main/java/com/zy/core/thread/ShuttleThread.java
@@ -10,7 +10,6 @@
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.BasShuttleOpt;
import com.zy.asrs.mapper.BasShuttleMapper;
import com.zy.asrs.service.BasShuttleOptService;
import com.zy.asrs.service.BasShuttleService;
import com.zy.common.model.NavigateNode;
@@ -168,8 +167,11 @@
                    shuttleProtocol.setPakMk(true);
                }
                //四向穿梭车空闲、有任务且标记为true,需要执行任务的下一条指令
                if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE && shuttleProtocol.getTaskNo() != 0 && shuttleProtocol.getPakMk()) {
                //四向穿梭车空闲、有任务、标记为true、存在任务指令,需要执行任务的下一条指令
                if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE
                        && shuttleProtocol.getTaskNo() != 0
                        && shuttleProtocol.getPakMk()
                        && shuttleProtocol.getAssignCommand() != null) {
                    //执行下一步指令
                    executeWork(shuttleProtocol.getAssignCommand());
                }
@@ -347,19 +349,23 @@
        //将此map存入redis中
        HashMap<String, Object> map = new HashMap<>();
        //计算路径
        List<NavigateNode> calc = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getLocNo(), assignCommand.getTaskMode().intValue());
        if (calc != null) {
            //获取分段路径
            ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
            //路径数据
            map.put("path", data);
            //路径次数
            map.put("pathSize", data.size());
        }else {
            if (assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_IN.id.shortValue() || assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_OUT.id.shortValue()) {
                //属于入库出库,必须要计算路径,则抛出异常
                throw new Exception("未能找到运行路径");
        if (assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_IN.id.shortValue()
                || assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_OUT.id.shortValue()) {
            //入库或出库模式,计算路径
            //计算路径
            List<NavigateNode> calc = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getLocNo(), assignCommand.getTaskMode().intValue());
            if (calc != null) {
                //获取分段路径
                ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
                //路径数据
                map.put("path", data);
                //路径次数
                map.put("pathSize", data.size());
            }else {
                if (assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_IN.id.shortValue() || assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_OUT.id.shortValue()) {
                    //属于入库出库,必须要计算路径,则抛出异常
                    throw new Exception("未能找到运行路径");
                }
            }
        }
@@ -373,6 +379,7 @@
        map.put("assignCommand", assignCommand);
        shuttleProtocol.setTaskNo(assignCommand.getTaskNo());
        shuttleProtocol.setAssignCommand(assignCommand);
        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
        //任务数据保存到redis
        redisUtil.set("wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(map));
        //执行下发任务
@@ -385,7 +392,14 @@
        if (assignCommand == null) {
            return false;
        }
        //将标记置为false(防止重发)
        shuttleProtocol.setPakMk(false);
        Object o = redisUtil.get("wrk_no_" + assignCommand.getTaskNo());
        if (o == null) {
            return false;
        }
        HashMap map = JSON.parseObject(o.toString(), HashMap.class);
        //当前步序
        int commandStep = Integer.parseInt(map.get("commandStep").toString());
@@ -453,6 +467,8 @@
                shuttleProtocol.setTaskNo((short) 0);
                //标记复位
                shuttleProtocol.setPakMk(true);
                //任务指令清零
                shuttleProtocol.setAssignCommand(null);
                break;
            default:
        }
@@ -464,9 +480,6 @@
            return false;
        } else {
            News.info("四向穿梭车命令下发成功,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
            //将标记置为false(防止重发)
            shuttleProtocol.setPakMk(false);
            //判断数据是否执行完成
            if (commandStep < size - 1) {
@@ -491,17 +504,22 @@
                            null,
                            null,
                            null,
                            JSON.toJSONString(command)
                            JSON.toJSONString(assignCommand)
                    );
                    shuttleOptService.insert(opt);
                }
                //删除redis
                redisUtil.del("wrk_no_" + map.get("wrk_no").toString());
                //对主线程抛出等待确认状态waiting
                shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                if (!assignCommand.getAuto()) {
                    //手动模式不抛出等待状态,直接复位
                    News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                }else {
                    //对主线程抛出等待确认状态waiting
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                    News.info("四向穿梭车任务执行完成等待确认中,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                }
                News.info("四向穿梭车任务执行完成等待确认中,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
            }
        }
src/main/resources/mapper/BasLiftMapper.xml
New file
@@ -0,0 +1,38 @@
<?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.BasLiftMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.BasLift">
        <result column="lift_no" property="liftNo" />
        <result column="lift_status" property="liftStatus" />
        <result column="wrk_no" property="wrkNo" />
        <result column="update_time" property="updateTime" />
        <result column="update_by" property="updateBy" />
        <result column="memo" property="memo" />
        <result column="pak_mk" property="pakMk" />
        <result column="lift_lock" property="liftLock" />
        <result column="position_arrival_feedback" property="positionArrivalFeedback" />
        <result column="ready" property="ready" />
        <result column="running" property="running" />
        <result column="mode" property="mode" />
        <result column="line_front_has_stock" property="lineFrontHasStock" />
        <result column="forward_rotation_feedback" property="forwardRotationFeedback" />
        <result column="reverse_feedback" property="reverseFeedback" />
        <result column="motor_overload" property="motorOverload" />
        <result column="line_end_has_stock" property="lineEndHasStock" />
        <result column="in_convey_line_card_tray_alarm" property="inConveyLineCardTrayAlarm" />
        <result column="out_convey_line_card_tray_alarm" property="outConveyLineCardTrayAlarm" />
        <result column="plat_position_deviation_alarm" property="platPositionDeviationAlarm" />
        <result column="plat_torque_deviation_alarm" property="platTorqueDeviationAlarm" />
        <result column="plat_shuttle_check" property="platShuttleCheck" />
        <result column="not_ready" property="notReady" />
        <result column="servo_error1" property="servoError1" />
        <result column="servo_error2" property="servoError2" />
        <result column="servo_error3" property="servoError3" />
        <result column="servo_error4" property="servoError4" />
        <result column="lift_actual_speed" property="liftActualSpeed" />
    </resultMap>
</mapper>
src/main/resources/mapper/BasLiftOptMapper.xml
New file
@@ -0,0 +1,19 @@
<?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.BasLiftOptMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.BasLiftOpt">
        <id column="id" property="id" />
        <result column="wrk_no" property="wrkNo" />
        <result column="lift_no" property="liftNo" />
        <result column="send_time" property="sendTime" />
        <result column="mode" property="mode" />
        <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
@@ -247,6 +247,21 @@
    </select>
    <select id="selectByWorkNo59" resultMap="BaseResultMap">
        select top 1 * from dbo.asr_wrk_mast where wrk_no=#{workNo} and wrk_sts in (5,9)
        select top 1 * from dbo.asr_wrk_mast
        where wrk_no=#{workNo}
        and wrk_sts in (5,9)
    </select>
    <select id="selectLiftStep6" resultMap="BaseResultMap">
        select top 1 * from dbo.asr_wrk_mast
        where wrk_sts in (6)
        and shuttle_no is not null
        order by io_pri desc,wrk_sts desc
    </select>
    <select id="selectByWorkNo7" resultMap="BaseResultMap">
        select top 1 * from dbo.asr_wrk_mast
        where wrk_no=#{workNo}
        and wrk_sts in (7)
    </select>
</mapper>
src/main/webapp/static/css/lift.css
New file
@@ -0,0 +1,334 @@
body {
    background-color: #6CA7A8;
}
.button-window {
    float: left;
    width: 100%;
    height: 100%;
    padding: 10px;
    background-color: #6CA7A8;
    border-radius: 5px;
    box-shadow: 0 0 3px rgba(0 0 0 .3);
}
/* -------------------- 第一模块 -------------------- */
.log-board {
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 0 3px rgba(0,0,0,.3);
    height: 25%;
}
/* 左 */
.command-log {
    float: left;
    height: 100%;
    width: 20%;
    text-align: center;
}
.command-log h2 {
    padding: 10px;
}
.lift-command-item {
    padding: 4px 0;
    margin-top: 5px;
}
.lift-command-item label {
    font-size: 20px;
    font-weight: bold;
    vertical-align: middle;
}
.demoBtn {
    vertical-align: middle;
    /*width: 30%;*/
    height: 30px;
    left: 0;
    top: 0;
    padding: 5px 15px;
    text-shadow: inherit;
    font-size: 15px;
    margin-left: 5px;
    margin-right: 5px;
    display: inline-block;
    background-color: #FF5722;
    border: none;
    color: #FFF;
    box-shadow: 1px 1px 5px #B6B6B6;
    border-radius: 3px;
    cursor: pointer;
}
.demoBtn:hover {
    opacity: 0.8
}
.demoBtn:focus {
    outline: 0;
}
/* 右 */
.lift-state {
    float: left;
    height: 100%;
    width: 80%;
    overflow: auto;
}
/* 穿梭车状态表 */
#lift-state-table {
    font-size: 12px;
    border-collapse: collapse;
    margin: 0 auto;
    text-align: center;
}
#lift-state-table td, #lift-state-table th {
    border: 1px solid #cad9ea;
    color: #666;
    height: 25px;
}
#lift-state-table thead th {
    background-color: #CCE8EB;
    width: 300px;
}
#lift-state-table tr:nth-child(odd) {
    background: #fff;
}
#lift-state-table tr:nth-child(even) {
    background: #F5FAFA;
}
/* -------------------- 第二模块 -------------------- */
.lift-msg {
    /*overflow: auto;*/
    margin-top: 10px;
    height: 23%;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 0 3px rgba(0,0,0,.3);
}
/* 堆垛机状态信息表 */
#lift-msg-table {
    font-size: 12px;
    border-collapse: collapse;
    margin: 0 auto;
    text-align: center;
}
#lift-msg-table td, #lift-msg-table th {
    border: 1px solid #f1f1f1;
    color: #666;
    height: 30px;
}
#lift-msg-table thead th {
    background-color: #fff;
    width: 400px;
}
#lift-msg-table tr:nth-child(odd) {
    background: #fff;
}
#lift-msg-table tr:nth-child(even) {
    background: #fff;
}
/* -------------------- 第三模块 -------------------- */
.lift-operation {
    position: relative;
    margin-top: 10px;
    height: 25%;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 0 3px rgba(0,0,0,.3);
}
/* 任务设备选择框 */
.task-select {
    width: 13%;
    height: 100%;
    overflow: hidden;
    display: inline-block;
    padding: 20px 0 10px 20px;
    /*clear: right;*/
}
.operator-item {
    display: inline-block;
    height: 100%;
    text-align: center;
    position: relative;
    vertical-align: middle;
    padding: 0 20px;
}
.operator-item .select-title {
    display: inline-block;
    position: absolute;
    top: -11px;
    left: 50%;
    transform: translate(-50%, 0);
    background-color: #fff;
    color: #2e95d3;
    font-size: 12px;
    border: 1px solid #8d8d8d;
    border-radius: 5px;
    padding: 5px;
    z-index: 999;
}
.operator-item .select-container {
    padding: 30px 0;
    height: 100%;
    border: 1px solid #8d8d8d;
    border-radius: 5px;
}
#lift-select .select-container label {
    display: block;
    padding: 5px 40px;
    vertical-align: middle; margin-top:-2px; margin-bottom:1px;
}
.select-container input {
    display: inline-block;
    font-size: 12px;
    vertical-align: middle; margin-top:-2px; margin-bottom:1px;
}
.select-container-item {
    display: inline-block;
    padding: 0 10px;
}
.select-container-item input {
    height: 20px;
    border: 1px solid #8D8D8D;
    border-radius: 3px;
    width: 80px;
    outline: none;
}
/* 任务作业选择框 */
.task-operator {
    width: 86%;
    height: 100%;
    overflow: hidden;
    padding: 5px 0 10px 20px;
    display: inline-block;
    margin-right: 10px;
}
.task-operator fieldset {
    padding: 15px 20px 5px 50px;
    /*border-width: 1px;*/
    /*border-style: solid;*/
    height: 100%;
    border: 1px solid #8d8d8d;
    border-radius: 5px;
}
.task-operator legend {
    background-color: #fff;
    color: #2e95d3;
    font-size: 12px;
    border: 1px solid #8d8d8d;
    border-radius: 5px;
    padding: 5px;
    z-index: 999;
}
button.item {
    margin-top: 5px;
    border: 1px solid #333;
    font-size: 13px;
    padding: 1px 1px 1px 1px;
    width: 100px;
    height: 40px;
    outline: none;
    cursor: pointer;
    color: #333;
    background-color: transparent;
    margin-right: 5px;
    border-radius: 5px;
}
button.item:hover {
    background-color: #333;
    color: #fff;
}
/* 手动操作遮罩 */
.lift-operation-shade {
    position: absolute;
    height: 100%;
    width: 100%;
    z-index: 1000;
    text-align: center;
    padding: 80px 0;
}
.lift-operation-shade-span {
    font-size: xx-large;
    font-weight: bold;
    color: red;
}
/* -------------------- 第四模块 -------------------- */
.lift-output-board {
    margin-top: 10px;
    height: 20%;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 0 3px rgba(0,0,0,.3);
}
#lift-output {
    border-left: none;
    border-right: none;
    border-top: 1px solid #9d9d9d;
    border-bottom: 1px solid #333;
    width: 100%;
    height: 100%;
    overflow: auto;
    resize:none;
    color: #666;
}
/* 详情弹出层 */
#lift-detl {
    padding: 30px 10px 0 25px;
    overflow: hidden;
}
#lift-detl form {
    overflow: hidden;
}
.form-item {
    margin-bottom: 10px;
}
.form-label {
    display: inline-block;
    width: 130px;
    text-align: right;
}
.form-input {
    display: inline-block;
    padding-left: 15px;
}
.form-input input {
    outline-style: none ;
    border: 1px solid #ccc;
    border-radius: 3px;
    padding: 5px 8px;
    width: 150px;
    height: 30px;
    font-size: 14px;
    font-weight: bolder;
}
.form-input input:focus{
    border-color: #66afe9;
    outline: 0;
    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
    box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)
}
.form-button-container {
    text-align: center;
}
.form-button {
    margin: 10px 10px;
    width: 50px;
    height: 30px;
    color:white;
    background-color:cornflowerblue;
    border-radius: 3px;
    border-width: 0;
    outline: none;
    font-size: 15px;
    text-align: center;
    cursor: pointer;
}
.form-button:hover {
    opacity: 0.7;
}
src/main/webapp/views/index.html
@@ -20,7 +20,7 @@
        <ul class="cl-effect-4">
            <li><a id="console" onclick="nav(this.id)" class="nav-select" href="#">主控图</a></li>
            <li><a id="pipeline" onclick="nav(this.id)" class="nav-unselect" href="#">输送设备</a></li>
<!--            <li><a id="crn" onclick="nav(this.id)" class="nav-unselect" href="#">堆垛机</a></li>-->
            <li><a id="lift" onclick="nav(this.id)" class="nav-unselect" href="#">提升机</a></li>
<!--            <li><a id="ste" onclick="nav(this.id)" class="nav-unselect" href="#">穿梭车</a></li>-->
            <li><a id="shuttle" onclick="nav(this.id)" class="nav-unselect" href="#">四向穿梭车</a></li>
        </ul>
src/main/webapp/views/lift.html
New file
@@ -0,0 +1,484 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>提升机监控管理</title>
    <link rel="stylesheet" type="text/css" href="../static/css/normalize.css">
    <link rel="stylesheet" type="text/css" href="../static/css/common.css">
    <link rel="stylesheet" type="text/css" href="../static/layui/css/layui.css">
    <link rel="stylesheet" href="../static/css/lift.css">
    <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
    <script type="text/javascript" src="../static/js/layer/layer.js"></script>
    <script type="text/javascript" src="../static/layui/layui.js"></script>
    <script type="text/javascript" src="../static/js/common.js"></script>
</head>
<body>
<div style="padding: 10px;height: 100%;float: left;width: 6%">
    <div class="button-window"></div>
</div>
<div style="height: 100%;padding-left: 6%">
    <div style="padding: 10px;height: 100%">
        <!-- 日志监控板 -->
        <div class="log-board">
            <div class="command-log" id="commandLogId">
            </div>
            <div class="lift-state">
                <table id="lift-state-table">
                    <thead>
                    <tr>
                        <th>提升机</th>
                        <th>工作号</th>
                        <th>任务状态</th>
                        <th>提升机锁定</th>
                        <th>位置到达反馈</th>
                        <th>准备就绪</th>
                        <th>运行中</th>
                        <th>联机/单机</th>
                        <th>平台位置偏差报警</th>
                        <th>平台扭矩偏差报警</th>
                        <th>平台四向车检测</th>
                        <th>未就绪状态</th>
                        <th>伺服1错误</th>
                        <th>伺服2错误</th>
                        <th>伺服3错误</th>
                        <th>伺服4错误</th>
                        <th>提升机实际速度反馈</th>
                    </tr>
                    </thead>
                    <tbody>
                    </tbody>
                </table>
            </div>
        </div>
        <!-- 提升机状态 -->
        <div class="lift-msg">
            <table id="lift-msg-table">
                <thead>
                <tr>
                    <th>提升机</th>
                    <th>工作号</th>
                    <th>输送线前端光电有货</th>
                    <th>输送线正转反馈</th>
                    <th>输送线反转反馈</th>
                    <th>输送线电机过载</th>
                    <th>输送线末端光电有货</th>
                    <th>进输送线卡托盘报警</th>
                    <th>出输送线卡托盘报警</th>
                    <th>作业标记</th>
                </tr>
                </thead>
                <tbody>
                </tbody>
            </table>
        </div>
        <!-- 手动操作 -->
        <div class="lift-operation">
            <!-- 遮罩层 -->
            <div class="lift-operation-shade">
                    <span class="lift-operation-shade-span">
                        WCS 系统运行中,请停止后操作
                    </span>
            </div>
            <!-- 设备任务选择 -->
            <div class="task-select">
                <!-- 选择 -->
                <div id="lift-select" class="operator-item">
                    <span class="select-title">提升机号</span>
                    <div class="select-container" id="liftRadioBoxId">
                        <!--                            <label><input type="radio" name="liftSelect" value="1" checked>&nbsp;1号提升机</label>-->
                    </div>
                </div>
            </div>
            <!-- 设备任务操作 -->
            <div class="task-operator">
                <fieldset>
                    <legend>手动操作</legend>
                    <div class="button-group">
                        <button class="item" onclick="liftOperator(1)">上升一层</button>
                        <button class="item" onclick="liftOperator(2)">下降一层</button>
                        <button class="item" onclick="liftOperator(3)">有货正转</button>
                        <button class="item" onclick="liftOperator(4)">有货反转</button>
                        <button class="item" onclick="liftOperator(5)">复位</button>
                    </div>
                </fieldset>
            </div>
        </div>
        <!-- 提升机日志输出 -->
        <div class="lift-output-board">
            <textarea id="lift-output"></textarea>
        </div>
    </div>
</div>
</body>
</html>
<script>
    // 空白行数
    var liftStateTableBlankRows = 0;
    var liftMsgTableBlankRows = 0;
    // 实际行数
    var liftStateTableFullRows = 0;
    var liftMsgTableFullRows = 0;
    // 初始化
    var liftOutputDom = document.getElementById("lift-output");
    $(document).ready(function() {
        initliftStateTable();
        getliftStateInfo();
        initliftMsgTable();
        getliftMsgInfo();
        operatorBlockShow();
        setliftRadio();
    });
    setInterval(function () {
        getliftStateInfo()
        getliftMsgInfo();
    },1000)
    setInterval(function () {
        getliftOutput();
        operatorBlockShow();
    },500);
    // 判断手动操作模块是否可用
    function operatorBlockShow() {
        if (parent.systemRunning) {
            $('.lift-operation').css("opacity", "0.5");
            $('.lift-operation-shade').show();
            $('.lift-operation-shade-span').show();
        }  else {
            $('.lift-operation').css("opacity", "1");
            $('.lift-operation-shade').hide();
            $('.lift-operation-shade-span').hide();
        }
    }
    var layerIdx;
    $(document).on('click ','.pos-btn', function () {
        let liftNo = Number($(this).parent().attr("data-liftNo"));
        layerIdx = layer.open({
            type: 1,
            title: false,
            shadeClose: true,
            offset: [$(this).offset().top + 30 + 'px', $(this).offset().left + 'px'],
            anim: 5,
            shade: [0],
            area: ['310px', '370px'],
            closeBtn: 0,
            content: $("#lift-detl"),
            success: function(layero, index){
                http.get(baseUrl+ "/lift/detl/"+liftNo, null, function (res) {
                    $('#liftNo').val(liftNo);
                    $('#workNo').val(res.data.workNo);
                    $('#row').val(res.data.row);
                    $('#bay').val(res.data.bay);
                    $('#lev').val(res.data.lev);
                    $('#crnNo').val(res.data.crnNo);
                    $('#pakMk').val(res.data.pakMk);
                })
            },
            end: function () {
                $('#liftNo').val("");
                $('#workNo').val("");
                $('#row').val("");
                $('#bay').val("");
                $('#lev').val("");
                $('#crnNo').val("");
                $('#pakMk').val("");
            }
        })
    })
    var layerIdx0;
    $(document).on('click ','.mode-btn', function () {
        let liftNo = Number($(this).parent().attr("data-liftNo"));
        layerIdx0 = layer.open({
            type: 1,
            title: false,
            shadeClose: true,
            offset: [$(this).offset().top + 30 + 'px', $(this).offset().left + 'px'],
            anim: 5,
            shade: [0],
            area: ['70%', '85%'],
            closeBtn: 0,
            content: $("#lift-detl2"),
            success: function(layero, index){
                console.log(liftNo)
                http.get(baseUrl+ "/lift/sensor/detl/"+liftNo, null, function (res) {
                    $('#liftNo1').val(res.data.liftNo);
                    getColor(res.data.pakInTask,'#pakInTask');
                    getColor(res.data.pakOutTask,'#pakOutTask');
                    getColor(res.data.pakMoveTask,'#pakMoveTask');
                    getColor(res.data.goHpTask,'#goHpTask');
                    getColor(res.data.goOHpTask,'#goOHpTask');
                    getColor(res.data.goHpAvoid,'#goHpAvoid');
                    getColor(res.data.goOHpAvoid,'#goOHpAvoid');
                    getColor(res.data.pakInEmpty,'#pakInEmpty');
                    getColor(res.data.pakInFinish,'#pakInFinish');
                    getColor(res.data.pakOutEmpty,'#pakOutEmpty');
                    getColor(res.data.pakOutFinish,'#pakOutFinish');
                    getColor(res.data.goHpAvoidFinish,'#goHpAvoidFinish');
                    getColor(res.data.goOHpAvoidFinish,'#goOHpAvoidFinish');
                    getColor(res.data.goHpAvoidErr,'#goHpAvoidErr');
                    getColor(res.data.goOHpAvoidErr,'#goOHpAvoidErr');
                })
            },
            end: function () {
                $('#liftNo').val("");
            }
        })
    })
    function getColor(res,e){
        $(e).val(res?"✔":"—");
        if (res){
            $(e).attr("style", "color: #FD482C;");
        }else {
            $(e).attr("style", "color: #00FF00;");
        }
    }
    $(document).on('click ','#save', function () {
        http.post(baseUrl+ "/lift/detl/update", {
            liftNo: $('#liftNo').val(),
            workNo: $('#workNo').val(),
            row:  $('#row').val(),
            bay: $('#bay').val(),
            lev:  $('#lev').val(),
            crnNo: $('#crnNo').val(),
            pakMk: $('#pakMk').val(),
        }, function (res) {
            layer.msg("修改成功", {icon: 1,});
            layer.close(layerIdx);
        })
    })
    $(document).on('click ','#cancel', function () {
        layer.close(layerIdx);
    })
    function setliftRadio() {
        $.ajax({
            url: baseUrl+ "/lift/table/lift/state",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                if (res.code === 200){
                    let table = res.data;
                    for (let i=1;i<=table.length;i++){
                        //渲染提升机选项html
                        let liftRadioBox = '<label><input type="radio" name="liftSelect" ';
                        if (i === 1) {
                            liftRadioBox += 'checked '
                        }
                        liftRadioBox += 'value="' + table[i - 1].liftNo + '">&nbsp;' + table[i - 1].liftNo + '号提升机</label>'
                        $("#liftRadioBoxId").append(liftRadioBox)
                        //渲染提升机数据维护和设备信息html
                        let liftCommandLogBox = '<div class="lift-command-item" data-liftNo="' + table[i - 1].liftNo + '">\n' +
                            '<label>' + table[i - 1].liftNo + '#</label>\n' +
                            '</div>'
                        $("#commandLogId").append(liftCommandLogBox);
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
                }  else {
                    console.log(res.msg);
                }
            }
        });
    }
    // 提升机信息表获取 ---- 表一
    function getliftStateInfo() {
        let tableEl = $('#lift-state-table');
        $.ajax({
            url: baseUrl+ "/lift/table/lift/state",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                if (res.code === 200){
                    let table = res.data;
                    if (table.length > liftStateTableBlankRows && table.length !== liftStateTableFullRows) {
                        initliftStateTable(table.length-liftStateTableBlankRows);
                        liftStateTableFullRows = table.length;
                    }
                    for (let i=1;i<=table.length;i++){
                        // $("#mode-"+table[i-1].liftNo).html(table[i-1].statusVal===0?'联机':'脱机');
                        let tr = tableEl.find("tr").eq(i);
                        setVal(tr.children("td").eq(0), table[i-1].liftNo);
                        setVal(tr.children("td").eq(1), table[i-1].taskNo);
                        setVal(tr.children("td").eq(2), table[i-1].protocolStatus);
                        setVal(tr.children("td").eq(3), table[i-1].liftLock$);
                        setVal(tr.children("td").eq(4), table[i-1].positionArrivalFeedback$);
                        setVal(tr.children("td").eq(5), table[i-1].ready$);
                        setVal(tr.children("td").eq(6), table[i-1].running$);
                        setVal(tr.children("td").eq(7), table[i-1].mode$);
                        setVal(tr.children("td").eq(8), table[i-1].platPositionDeviationAlarm$);
                        setVal(tr.children("td").eq(9), table[i-1].platTorqueDeviationAlarm$);
                        setVal(tr.children("td").eq(10), table[i-1].platShuttleCheck$);
                        setVal(tr.children("td").eq(11), table[i-1].notReady$);
                        setVal(tr.children("td").eq(12), table[i-1].servoError1);
                        setVal(tr.children("td").eq(13), table[i-1].servoError2);
                        setVal(tr.children("td").eq(14), table[i-1].servoError3);
                        setVal(tr.children("td").eq(14), table[i-1].servoError4);
                        setVal(tr.children("td").eq(14), table[i-1].liftActualSpeed);
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
                }  else {
                    console.log(res.msg);
                }
            }
        });
    }
    // 提升机数据表获取 ---- 表二
    function getliftMsgInfo() {
        let tableEl = $('#lift-msg-table');
        $.ajax({
            url: baseUrl+ "/lift/table/lift/msg",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                if (res.code === 200){
                    var table = res.data;
                    if (table.length > liftMsgTableBlankRows && table.length !== liftMsgTableFullRows) {
                        initliftMsgTable(table.length-liftMsgTableBlankRows);
                        liftMsgTableFullRows = table.length;
                    }
                    for (var i=1;i<=table.length;i++){
                        var tr = tableEl.find("tr").eq(i);
                        setVal(tr.children("td").eq(0), table[i-1].liftNo);
                        setVal(tr.children("td").eq(1), table[i-1].workNo);
                        setVal(tr.children("td").eq(2), table[i-1].lineFrontHasStock$);
                        setVal(tr.children("td").eq(3), table[i-1].forwardRotationFeedback$);
                        setVal(tr.children("td").eq(4), table[i-1].reverseFeedback$);
                        setVal(tr.children("td").eq(5), table[i-1].motorOverload$);
                        setVal(tr.children("td").eq(6), table[i-1].lineEndHasStock$);
                        setVal(tr.children("td").eq(7), table[i-1].inConveyLineCardTrayAlarm$);
                        setVal(tr.children("td").eq(8), table[i-1].outConveyLineCardTrayAlarm$);
                        setVal(tr.children("td").eq(9), table[i-1].pakMk);
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
                }  else {
                    console.log(res.msg);
                }
            }
        });
    }
    // 提升机日志输出 -----------------------------------------------------------------------
    function getliftOutput() {
        $.ajax({
            url: baseUrl + "/lift/output/lift",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                if (res.code === 200) {
                    liftOutput(res.data);
                } else if (res.code === 403) {
                    window.location.href = baseUrl + "/login";
                } else {
                    console.log(res.msg);
                }
            }
        })
    }
    // 任务指令下发
    function liftOperator(liftTaskMode) {
        http.post(baseUrl+"/lift/operator/lift", {
            liftNo: $('input[name="liftSelect"]:checked').val(),
            liftTaskMode: liftTaskMode,
        }, function (res) {
            layer.msg(res.msg, {icon: 1});
        });
    }
    // ------------------------------------------------------------------------------------------------
    // 提升机信息表获取  ----- 表一
    function initliftStateTable(row) {
        let line;
        if (row === undefined){
            let one = $('#lift-state-table thead').height();
            let total = $('.lift-state').height();
            let count = total / one;
            count = parseInt(count) - 1;
            liftStateTableBlankRows = count;
            line = count;
        } else {
            line = row;
        }
        let html = "";
        for (let i = 0; i < line; i ++){
            html += " <tr>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "     </tr>\n";
        }
        $('#lift-state-table tbody').after(html);
    }
    // 提升机数据表获取  ----- 表二
    function initliftMsgTable(row) {
        let line;
        if (row === undefined){
            let one = $('#lift-msg-table thead').height();
            let total = $('.lift-msg').height();
            let count = total / one;
            count = parseInt(count) - 1;
            liftMsgTableBlankRows = count;
            line = count;
        } else {
            line = row;
        }
        let html = "";
        for (let i = 0; i < line; i ++){
            html += " <tr>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "       <td></td>\n" +
                "     </tr>\n";
        }
        $('#lift-msg-table tbody').after(html);
    }
    // 日志输出框
    function liftOutput(content){
        liftOutputDom.value += content;
        liftOutputDom.scrollTop = liftOutputDom.scrollHeight;
    }
</script>