zjj
2024-05-07 ab18ecb1c25613535c2047467cf8c14d3b41b047
#空桶入库完成
18个文件已修改
13个文件已添加
2595 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/RgvController.java 319 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/enums/RgvStatusType.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/RgvOperatorParam.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/RgvMsgTableVo.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/RgvStateTableVo.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/EmptyBarrelIn.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/FullStoreParam.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/EmptyBarrelInMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/EmptyBarrelInService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WrkMastService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/EmptyBarrelInServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 351 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WrkMastServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/CodeBuilder.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/MainProcess.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/cache/MessageQueue.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RgvModeType.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RgvStatusType.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RgvTaskModeType.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/RgvSlave.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/RgvCommand.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/RgvProtocol.java 253 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/StaProtocol.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/SiemensDevpThread.java 81 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ZyRgvThread.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 81 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/EmptyBarrelInMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/css/rgv.css 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/rgv.html 598 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/RgvController.java
New file
@@ -0,0 +1,319 @@
package com.zy.asrs.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.annotations.ManagerAuth;
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.domain.enums.RgvStatusType;
import com.zy.asrs.domain.param.RgvOperatorParam;
import com.zy.asrs.domain.vo.RgvMsgTableVo;
import com.zy.asrs.domain.vo.RgvStateTableVo;
import com.zy.asrs.entity.BasRgv;
import com.zy.asrs.entity.BasRgvErr;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.mapper.BasRgvErrMapper;
import com.zy.asrs.service.BasRgvService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.service.impl.MainServiceImpl;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.RgvModeType;
import com.zy.core.enums.RgvTaskModeType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.RgvSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.RgvCommand;
import com.zy.core.model.protocol.RgvProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.ZyRgvThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
 * RGV接口
 * Created by vincent on 2020-06-01
 */
@Slf4j
@RestController
@RequestMapping("/rgv")
public class RgvController {
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private BasRgvErrMapper basRgvErrMapper;
    @Autowired
    private BasRgvService basRgvService;
    @Autowired
    private MainServiceImpl mainService;
    @Autowired
    private LocMastService locMastService;
    @PostMapping("/table/rgv/state")
    @ManagerAuth(memo = "RGV信息表")
    public R rgvStateTable(){
        List<RgvStateTableVo> list = new ArrayList<>();
        List<BasRgv> rgvs = basRgvService.selectList(new EntityWrapper<BasRgv>().orderBy("rgv_no"));
        for (BasRgv basRgv : rgvs) {
            // 表格行
            RgvStateTableVo vo = new RgvStateTableVo();
            vo.setRgvNo(basRgv.getRgvNo());   //  RGV号
            list.add(vo);
            // 获取RGV信息
            ZyRgvThread rgvThread = (ZyRgvThread) SlaveConnection.get(SlaveType.Rgv, basRgv.getRgvNo());
            if (rgvThread == null) {
                continue;
            }
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol == null) {
                continue;
            }
            vo.setStatusType(rgvProtocol.modeType.desc);   //  模式状态
            vo.setStatus(rgvProtocol.getStatusType().desc);     //  状态
            vo.setWorkNo1(rgvProtocol.getTaskNo1());  //  工位1任务号
            vo.setLoading1(rgvProtocol.getLoaded1()==1?"有物":"无物");  // 工位1有物
//            vo.setRgvPos(rgvProtocol.getRgvPos());
            vo.setRgvPos1(rgvProtocol.getRgvPosI());
//            vo.setWalkPos(rgvProtocol.getWalkPos()==1?"在定位":"不在定位");
            vo.setWorkNo2(rgvProtocol.getTaskNo2());  //  工位2任务号
//            vo.setStatus2(rgvProtocol.getStatusType2().desc);  // 工位2状态
//            vo.setLoading2(rgvProtocol.getLoaded2()==1?"有物":"无物");  // 工位2有物
            vo.setWarnCode(String.valueOf(rgvProtocol.getAlarm()));
            if (rgvProtocol.getAlarm() > 0) {
                BasRgvErr rgvErr = basRgvErrMapper.selectById(rgvProtocol.getAlarm());
                vo.setAlarm(rgvErr==null?"未知异常":rgvErr.getErrName());
            }
        }
        return R.ok().add(list);
    }
    @PostMapping("/table/rgv/msg")
    @ManagerAuth(memo = "RGV数据表")
    public R rgvMsgTable(){
        List<RgvMsgTableVo> list = new ArrayList<>();
        List<BasRgv> rgvs = basRgvService.selectList(new EntityWrapper<BasRgv>().orderBy("rgv_no"));
        for (BasRgv basRgv : rgvs) {
            // 表格行
            RgvMsgTableVo vo = new RgvMsgTableVo();
            vo.setRgvNo(basRgv.getRgvNo());   //  RGV号
            list.add(vo);
            // 获取RGV信息
            ZyRgvThread rgvThread = (ZyRgvThread) SlaveConnection.get(SlaveType.Rgv, basRgv.getRgvNo());
            if (rgvThread == null) {
                continue;
            }
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol == null) {
                continue;
            }
            vo.setWorkNo(rgvProtocol.getTaskNo1());  //  任务号
            if (rgvProtocol.getTaskNo1()>0) {
                WrkMast wrkMast = wrkMastService.selectById(rgvProtocol.getTaskNo1());
                if (wrkMast != null) {
                    vo.setStatus(RgvStatusType.process(wrkMast.getIoType()).getDesc());   //  模式状态
                    vo.setSourceStaNo(wrkMast.getSourceStaNo$());    //  源站
                    vo.setStaNo(wrkMast.getStaNo$());   //  目标站
                    vo.setSourceLocNo(wrkMast.getSourceLocNo());    //  源库位
                    vo.setLocNo(wrkMast.getLocNo());    //  目标库位
                }
            } else {
                vo.setStatus(rgvProtocol.modeType.equals(RgvModeType.AUTO)? rgvProtocol.modeType.desc: RgvModeType.HAND.desc);   //  模式状态
            }
            vo.setXspeed(rgvProtocol.getXSpeed());  //  走行速度(m/min)
            vo.setXdistance(rgvProtocol.getXDistance());  //  走行距离(Km)
            vo.setXduration(rgvProtocol.getXDuration());    //  走行时长(H)
        }
        return R.ok().add(list);
    }
    @PostMapping("/output/site")
    @ManagerAuth(memo = "RGV报文日志输出")
    public R rgvOutput(){
        StringBuilder str = new StringBuilder();
        String s;
        int i = 0;
        while((s = OutputQueue.RGV.poll()) != null && i <=10) {
            str.append("\n").append(s);
            i++;
        }
        return R.ok().add(str.toString());
    }
    /****************************************************************/
    /************************** 手动操作 ******************************/
    /****************************************************************/
    @ManagerAuth(memo = "取放货")
    @PostMapping("/operator/put")
    public R rgvFetchPut(RgvOperatorParam param){
        RgvCommand command = new RgvCommand();
        command.setRgvNo(param.getRgvNo()); // RGV编号
        //工位1
        command.setTaskNo1(0); // 工作号
        command.setSourceStaNo1(param.getSourceStaNo1()); // 源站
        command.setDestinationStaNo1(param.getStaNo1());  // 目标站
        command.setAckFinish1(false);  // 任务完成确认位
        //工位2
        command.setTaskNo2(0); // 工作号
        command.setSourceStaNo2(param.getSourceStaNo2()); // 源站
        command.setDestinationStaNo2(param.getStaNo2());  // 目标站
        command.setAckFinish2(false);  // 任务完成确认位
        if (Cools.isEmpty(param.getSourceStaNo1()) || param.getStaNo1() == 0){
            command.setTaskMode(RgvTaskModeType.FETCH_PUT2); // 任务模式: 取放货
        } else if (Cools.isEmpty(param.getSourceStaNo2()) || param.getStaNo2() == 0) {
            command.setTaskMode(RgvTaskModeType.FETCH_PUT1); // 任务模式: 取放货
        }else {
            command.setTaskMode(RgvTaskModeType.FETCH_PUT_ALL); // 任务模式: 取放货
        }
        command.setCommand(false);
        return rgvControl(command)? R.ok(): R.error();
    }
    @ManagerAuth(memo = "工位1任务完成")
    @PostMapping("/operator/taskComplete1")
    public R rgvTaskComplete1(RgvOperatorParam param){
        RgvCommand command = new RgvCommand();
        command.setRgvNo(param.getRgvNo()); // RGV编号
        //工位1
        command.setTaskNo1(0); // 工作号
        command.setSourceStaNo1((short) 0); // 源站
        command.setDestinationStaNo1((short) 0);  // 目标站
        command.setAckFinish1(true);  // 任务完成确认位
        //工位2
        command.setTaskNo2(0); // 工作号
        command.setSourceStaNo2((short) 0); // 源站
        command.setDestinationStaNo2((short) 0);  // 目标站
        command.setAckFinish2(false);  // 任务完成确认位
        command.setTaskMode(RgvTaskModeType.NONE); // 任务模式: 取放货
        command.setCommand(false);
        return rgvControlAsk1(command)? R.ok(): R.error();
    }
    @ManagerAuth(memo = "工位2任务完成")
    @PostMapping("/operator/taskComplete2")
    public R rgvTaskComplete2(RgvOperatorParam param){
        RgvCommand command = new RgvCommand();
        command.setRgvNo(param.getRgvNo()); // RGV编号
        //工位1
        command.setTaskNo1(0); // 工作号
        command.setSourceStaNo1((short) 0); // 源站
        command.setDestinationStaNo1((short) 0);  // 目标站
        command.setAckFinish1(false);  // 任务完成确认位
        //工位2
        command.setTaskNo2(0); // 工作号
        command.setSourceStaNo2((short) 0); // 源站
        command.setDestinationStaNo2((short) 0);  // 目标站
        command.setAckFinish2(true);  // 任务完成确认位
        command.setTaskMode(RgvTaskModeType.NONE); // 任务模式: 取放货
        command.setCommand(false);
        return rgvControlAsk2(command)? R.ok(): R.error();
    }
    private boolean rgvControl(RgvCommand command){
        if (command.getRgvNo() == null) {
            throw new CoolException("请选择RGV");
        }
        for (RgvSlave rgv : slaveProperties.getRgv()) {
            // 获取RGV信息
            if (command.getRgvNo().equals(rgv.getId())) {
                ZyRgvThread rgvThread = (ZyRgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
                if (rgvThread == null) {
                    throw new CoolException("RGV不在线");
                }
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    throw new CoolException("RGV不在线");
                }
                if (MessageQueue.offer(SlaveType.Rgv, rgv.getId(), new Task(2, command))) {
                    return true;
                } else {
                    throw new CoolException("命令下发失败");
                }
            }
        }
        return false;
    }
    private boolean rgvControlAsk1(RgvCommand command){
        if (command.getRgvNo() == null) {
            throw new CoolException("请选择RGV");
        }
        for (RgvSlave rgv : slaveProperties.getRgv()) {
            // 获取RGV信息
            if (command.getRgvNo().equals(rgv.getId())) {
                ZyRgvThread rgvThread = (ZyRgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
                if (rgvThread == null) {
                    throw new CoolException("RGV不在线");
                }
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    throw new CoolException("RGV不在线");
                }
                if (MessageQueue.offer(SlaveType.Rgv, rgv.getId(), new Task(3, command))) {
                    return true;
                } else {
                    throw new CoolException("命令下发失败");
                }
            }
        }
        return false;
    }
    private boolean rgvControlAsk2(RgvCommand command){
        if (command.getRgvNo() == null) {
            throw new CoolException("请选择RGV");
        }
        for (RgvSlave rgv : slaveProperties.getRgv()) {
            // 获取RGV信息
            if (command.getRgvNo().equals(rgv.getId())) {
                ZyRgvThread rgvThread = (ZyRgvThread) SlaveConnection.get(SlaveType.Rgv, rgv.getId());
                if (rgvThread == null) {
                    throw new CoolException("RGV不在线");
                }
                RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
                if (rgvProtocol == null) {
                    throw new CoolException("RGV不在线");
                }
                if (MessageQueue.offer(SlaveType.Rgv, rgv.getId(), new Task(4, command))) {
                    return true;
                } else {
                    throw new CoolException("命令下发失败");
                }
            }
        }
        return false;
    }
}
src/main/java/com/zy/asrs/domain/enums/RgvStatusType.java
New file
@@ -0,0 +1,43 @@
package com.zy.asrs.domain.enums;
/**
 * RGV状态枚举
 */
public enum RgvStatusType {
    // 入库
    MACHINE_PAKIN("入库"),
    // 出库
    MACHINE_PAKOUT("出库"),
    // 异常
    MACHINE_ERROR("异常"),
    // 自动
    MACHINE_AUTO("自动"),
    // 非自动/手动
    MACHINE_UN_AUTO("非自动"),
    ;
    private String desc;
    RgvStatusType(String desc){
        this.desc = desc;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public static RgvStatusType process(Integer ioType){
        if (ioType>100) {
            return MACHINE_PAKOUT;
        } else if (ioType < 100 && ioType!=3 && ioType!=6 && ioType!=11) {
            return MACHINE_PAKIN;
        } else {
            return MACHINE_ERROR;
        }
    }
}
src/main/java/com/zy/asrs/domain/param/RgvOperatorParam.java
New file
@@ -0,0 +1,25 @@
package com.zy.asrs.domain.param;
import lombok.Data;
/**
 * Created by vincent on 2020-06-02
 */
@Data
public class RgvOperatorParam {
    // RGV号
    private Integer rgvNo;
    // 工位1源站
    private Short sourceStaNo1;
    // 工位1目标站
    private Short staNo1;
    // 工位2源站
    private Short sourceStaNo2;
    // 工位2目标站
    private Short staNo2;
}
src/main/java/com/zy/asrs/domain/vo/RgvMsgTableVo.java
New file
@@ -0,0 +1,62 @@
package com.zy.asrs.domain.vo;
import com.zy.asrs.utils.Utils;
import lombok.Data;
/**
 * Created by vincent on 2020-06-02
 */
@Data
public class RgvMsgTableVo {
        // RGV号
    private Integer rgvNo;
    // 工作号
    private Integer workNo = 0;
    // 状态
    private String status = "-";
    // 源站
    private String sourceStaNo = "-";
    // 目标站
    private String staNo = "-";
    // 源库位
    private String sourceLocNo = "-";
    // 目标库位
    private String locNo = "-";
    // 异常
    private String error = "";
    // 原点
    private String origin = "";
    // 命令
    private String command = "";
    // 走行速度(m/min)
    private Float xspeed = 0.0F;
    // 走行距离(Km)
    private Float xdistance = 0.0F;
    // 走行时长(H)
    private Float xduration = 0.0F;
    public void setXspeed(Float xspeed) {
        this.xspeed = Utils.scale(xspeed);
    }
    public void setXdistance(Float xdistance) {
        this.xdistance = Utils.scale(xdistance);
    }
    public void setXduration(Float xduration) {
        this.xduration = Utils.scale(xduration);
    }
}
src/main/java/com/zy/asrs/domain/vo/RgvStateTableVo.java
New file
@@ -0,0 +1,53 @@
package com.zy.asrs.domain.vo;
import lombok.Data;
/**
 * Created by vincent on 2020-06-02
 */
@Data
public class RgvStateTableVo {
    // RGV号
    private Integer RgvNo;
    // 模式
    private String statusType = "-";
    // 状态
    private String status = "-";
    // 任务号
    private Integer workNo1 = 0;
    // 状态
    private String status1 = "-";
    // 有物
    private String loading1 = "-";
    // RGV位置
    private Integer RgvPos = 0;
    // 走行定位
    private String walkPos = "-";
    // 任务号
    private Integer workNo2 = 0;
    // 状态
    private String status2 = "-";
    // 有物
    private String loading2 = "-";
    //异常
    private String warnCode;
    // 异常码描述
    private String alarm = "-";
    private Integer RgvPos1 = 0;
    private String pakMk="-";
}
src/main/java/com/zy/asrs/entity/EmptyBarrelIn.java
New file
@@ -0,0 +1,45 @@
package com.zy.asrs.entity;
import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.enums.IdType;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.baomidou.mybatisplus.annotations.TableName;
import java.io.Serializable;
@Data
@TableName("man_emptyBarrel_in")
public class EmptyBarrelIn implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value= "")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty(value= "")
    private String matnr;
    @ApiModelProperty(value= "")
    private String batch;
    @ApiModelProperty(value= "")
    private String maktx;
    public EmptyBarrelIn() {}
    public EmptyBarrelIn(String matnr,String batch,String maktx) {
        this.matnr = matnr;
        this.batch = batch;
        this.maktx = maktx;
    }
//    EmptyBarrelIn emptyBarrelIn = new EmptyBarrelIn(
//            null,    //
//            null,    //
//            null    //
//    );
}
src/main/java/com/zy/asrs/entity/FullStoreParam.java
New file
@@ -0,0 +1,36 @@
package com.zy.asrs.entity;
import lombok.Data;
import java.util.List;
/**
 * Created by vincent on 2020/6/11
 */
@Data
public class FullStoreParam {
    // 托盘条码
    private String barcode;
    // 站点编号
    private Integer devpNo;
    // 物料列表数据
    private List<MatCodeStore> list;
    @Data
    public static class MatCodeStore {
        // 物料编号
        private String matnr;
        // 序列码
        private String batch;
        // 物料数量
        private Double anfme;
    }
}
src/main/java/com/zy/asrs/mapper/EmptyBarrelInMapper.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.mapper;
import com.zy.asrs.entity.EmptyBarrelIn;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface EmptyBarrelInMapper extends BaseMapper<EmptyBarrelIn> {
}
src/main/java/com/zy/asrs/service/EmptyBarrelInService.java
New file
@@ -0,0 +1,8 @@
package com.zy.asrs.service;
import com.zy.asrs.entity.EmptyBarrelIn;
import com.baomidou.mybatisplus.service.IService;
public interface EmptyBarrelInService extends IService<EmptyBarrelIn> {
}
src/main/java/com/zy/asrs/service/WrkMastService.java
@@ -19,4 +19,6 @@
    WrkMast selectpj(Integer staNo,String barcode);
    List<WrkMast> selectLaneWrkMast(Integer lane, Boolean pakIn);//查询指定巷道任务
    WrkMast selectByworkNo(Short workNo);
}
src/main/java/com/zy/asrs/service/impl/EmptyBarrelInServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.service.impl;
import com.zy.asrs.mapper.EmptyBarrelInMapper;
import com.zy.asrs.entity.EmptyBarrelIn;
import com.zy.asrs.service.EmptyBarrelInService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service("emptyBarrelInService")
public class EmptyBarrelInServiceImpl extends ServiceImpl<EmptyBarrelInMapper, EmptyBarrelIn> implements EmptyBarrelInService {
}
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -24,6 +24,7 @@
import com.zy.common.utils.News;
import com.zy.core.CrnThread;
import com.zy.core.DevpThread;
import com.zy.core.RgvThread;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
@@ -46,6 +47,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
@@ -86,9 +88,13 @@
    private BasErrLogService basErrLogService;
    @Autowired
    private BasCrnErrorMapper basCrnErrorMapper;
    @Autowired
    private EmptyBarrelInService emptyBarrelInService;
    @Value("${wms.url}")
    private String wmsUrl;
    public int workNo = 9900;
    /**
     * 组托
@@ -491,6 +497,9 @@
     */
    public synchronized void crnStnToOutStn() {
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            if (crnSlave.getId() ==5){
                continue;
            }
            // 遍历堆垛机出库站
            for (CrnSlave.CrnStn crnStn : crnSlave.getCrnOutStn()) {
                // 获取堆垛机出库站信息
@@ -561,6 +570,9 @@
     */
    public synchronized void crnIoExecute() {
        for (CrnSlave crn : slaveProperties.getCrn()) {
            if (crn.getId() == 5){
                continue;
            }
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
@@ -2189,7 +2201,29 @@
            if (crnProtocol.getStatusType() == CrnStatusType.IDLE && crnProtocol.getTaskNo() == 0 && crnProtocol.getModeType() == CrnModeType.AUTO
                    && crnProtocol.getLoaded() == 0 && crnProtocol.getForkPos() == 0) {
                Crn5InTaskSta(crnSlave,crnProtocol);
//                Crn5InTaskSta(crnSlave,crnProtocol);
                // 如果最近一次是入库模式
                if (crnProtocol.getLastIo().equals("I")) {
                    if (basCrnp.getInEnable().equals("Y")) {
                        this.Crn5InTaskSta(crnSlave,crnProtocol);
                        crnProtocol.setLastIo("O");
                    } else if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrn5Stn(crnSlave, crnProtocol); //  出库
                        crnProtocol.setLastIo("I");
                    }
                }
                // 如果最近一次是出库模式
                else if (crnProtocol.getLastIo().equals("O")) {
                    if (basCrnp.getOutEnable().equals("Y")) {
                        this.locToCrn5Stn(crnSlave, crnProtocol); //  出库
                        crnProtocol.setLastIo("I");
                    } else if (basCrnp.getInEnable().equals("Y")) {
                        this.Crn5InTaskSta(crnSlave,crnProtocol);
                        crnProtocol.setLastIo("O");
                    }
                }
            }
@@ -2249,4 +2283,319 @@
    }
    public synchronized void crn5StnToOutStn() {
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            if (crnSlave.getId() != 5){
                continue;
            }
            // 遍历堆垛机出库站
            for (CrnSlave.CrnStn crnStn : crnSlave.getCrnOutStn()) {
                // 获取堆垛机出库站信息
                DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
                if (staProtocol == null) {
                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()) {
                    // 查询工作档
                    WrkMast wrkMast = wrkMastMapper.selectPakOutStep2(crnStn.getStaNo());
                    if (wrkMast == null) {
                        continue;
                    }
                    // 判断工作档条件
                    if (wrkMast.getIoType() < 100 || wrkMast.getStaNo() == null || wrkMast.getSourceStaNo() == null) {
                        continue;
                    }
                    // 判断吊车是否实际已完成,且电脑状态在move中,以备电脑进行更新工作档
                    CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, wrkMast.getCrnNo());
                    CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                    if (crnProtocol.statusType == CrnStatusType.FETCHING || crnProtocol.statusType == CrnStatusType.PUTTING) {
                        // 移动中
                        continue;
                    }
                    //  判断堆垛机状态等待确认
                    if (crnProtocol.modeType == CrnModeType.AUTO && crnProtocol.getTaskNo().equals(wrkMast.getWrkNo().shortValue())
                            && crnProtocol.statusType == CrnStatusType.WAITING
                            && crnProtocol.forkPosType == CrnForkPosType.HOME) {
                            // 更新工作档状态为14
                            wrkMast.setWrkSts(14L);
                        wrkMast.setCrnEndTime(new Date());
                        if (wrkMastMapper.updateById(wrkMast) != 0) {
                            // 复位堆垛机
                            crnThread.setResetFlag(true);
                        } else {
                            log.error("更新工作档的工作状态为14失败!!! [工作号:{}]", wrkMast.getWrkNo());
                        }
                    }
                }
            }
        }
    }
    public synchronized void locToCrn5Stn(CrnSlave slave, CrnProtocol crnProtocol) {
        for (CrnSlave.CrnStn crnStn : slave.getCrnOutStn()) {
            // 获取工作状态为11(生成出库ID)的出库工作档
//            WrkMast wrkMast = wrkMastMapper.selectPakOutStep1(slave.getId(), crnStn.getStaNo());
            List<WrkMast> wrkMasts = wrkMastMapper.selectPakOutStep11(slave.getId(), crnStn.getStaNo());
            //            获取工作状态为14的工作档
            WrkMast wrkMast1 = wrkMastMapper.selectPakOutStep14(slave.getId(), crnStn.getStaNo());
            if ( wrkMast1 !=null) {
                continue;
            }
            for (WrkMast wrkMast : wrkMasts) {
                if (wrkMast == null) {
                    continue;
                }
                // 工作档状态判断
                if (wrkMast.getIoType() < 100 || wrkMast.getSourceStaNo() == null) {
                    log.error("查询工作档数据不符合条件--入出类型/站点, 工作号={},源库位={},入出类型={}", wrkMast.getWrkNo(), wrkMast.getSourceLocNo(), wrkMast.getIoType());
                    continue;
                }
                // 获取源库位信息
                LocMast locMast = locMastService.selectById(wrkMast.getSourceLocNo());
                if (!locMast.getLocSts().equals("R") && !locMast.getLocSts().equals("P")) {
                    log.error("出库操作库位状态不符合--状态, 库位号={},库位状态={}", wrkMast.getLocNo(), locMast.getLocSts());
                    continue;
                }
                // 获取堆垛机出库站信息
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
                if (staProtocol == null) {
                    break;
//                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                // 查询站点详细信息
                BasDevp staDetl = basDevpService.selectById(crnStn.getStaNo());
                if (staDetl == null) {
                    log.error("出库 ===>> 堆垛机站点在数据库不存在, 站点编号={}", crnStn.getStaNo());
                    break;
//                    continue;
                }
                // 判断堆垛机出库站状态
                if (staProtocol.isAutoing() && !staProtocol.isLoading() && staProtocol.isOutEnable()) {
                    // 命令下发区 --------------------------------------------------------------------------
                    // 堆垛机控制过滤
                    if (!crnProtocol.getStatusType().equals(CrnStatusType.IDLE) || crnProtocol.getTaskNo() != 0) {
//                        continue;
                        break;
                    }
                    // 已经存在吊车执行任务时,则过滤
                    if (wrkMastMapper.selectWorking(slave.getId()) != null) {
                        break;
//                        return;
                    }
                    // 1.堆垛机开始移动
                    CrnCommand crnCommand = new CrnCommand();
                    crnCommand.setCrnNo(slave.getId()); // 堆垛机编号
                    crnCommand.setTaskNo(wrkMast.getWrkNo().shortValue()); // 工作号
                    crnCommand.setAckFinish((short) 0);  // 任务完成确认位
                    crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE); // 任务模式:  库位移转
                    crnCommand.setSourcePosX(locMast.getRow1()==9?(short)4:(short)5);     // 源库位排
                    crnCommand.setSourcePosY(locMast.getBay1().shortValue());     // 源库位列
                    crnCommand.setSourcePosZ(locMast.getLev1().shortValue());     // 源库位层
                    crnCommand.setDestinationPosX(crnStn.getRow().shortValue());     // 目标库位排
                    crnCommand.setDestinationPosY(crnStn.getBay().shortValue());     // 目标库位列
                    crnCommand.setDestinationPosZ(crnStn.getLev().shortValue());     // 目标库位层
                    crnCommand.setLocType1(locMast.getLocType1().shortValue());     // 货物类型
                    if (!MessageQueue.offer(SlaveType.Crn, wrkMast.getCrnNo(), new Task(2, crnCommand))) {
                        log.error("堆垛机命令下发失败,堆垛机号={},任务数据={}", wrkMast.getCrnNo(), JSON.toJSON(crnCommand));
                    } else {
                        // 修改工作档状态 11.生成出库ID => 12.吊车出库中
                        Date now = new Date();
                        wrkMast.setWrkSts(12L);
                        wrkMast.setCrnStrTime(now);
                        wrkMast.setModiTime(now);
                        if (wrkMastMapper.updateById(wrkMast) == 0) {
                            log.error("修改工作档状态 11.生成出库ID => 12.吊车出库中 失败!!,工作号={}", wrkMast.getWrkNo());
                        }
                        break;
                    }
                }
            }
        }
    }
    public synchronized void crn5TaskCreate() throws IOException {
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            if (crnSlave.getId() != 5){
                continue;
            }
            for (CrnSlave.CrnStn crnStn : crnSlave.getCrnInStn()) {
                // 获取堆垛机出库站信息
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, crnStn.getDevpPlcId());
                StaProtocol staProtocol = devpThread.getStation().get(crnStn.getStaNo());
                if (staProtocol == null) {
                    break;
//                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable() && staProtocol.isPakMk()){
                    EmptyBarrelIn emptyBarrelIn = emptyBarrelInService.selectOne(new EntityWrapper<>());
                    if (Cools.isEmpty(emptyBarrelIn)){
                        continue;
                    }
                    FullStoreParam fullStoreParam = new FullStoreParam();
                    fullStoreParam.setDevpNo(crnStn.getStaNo());
                    FullStoreParam.MatCodeStore matCodeStore = new FullStoreParam.MatCodeStore();
                    matCodeStore.setMatnr(emptyBarrelIn.getMatnr());
                    matCodeStore.setBatch(emptyBarrelIn.getBatch());
                    if (staProtocol.isForce()){
                        log.info("空桶强制入库:"+staProtocol.getAmount());
                        matCodeStore.setAnfme(Double.valueOf(staProtocol.getAmount()));
                    }else {
                        matCodeStore.setAnfme(8d) ;
                    }
                    ArrayList<FullStoreParam.MatCodeStore> matCodeStores = new ArrayList<>();
                    matCodeStores.add(matCodeStore);
                    fullStoreParam.setList(matCodeStores);
                    try {
                        String response = new HttpHandler.Builder()
                                .setUri(wmsUrl)
                                .setPath("/full/store/put/start")
                                .setJson(JSON.toJSONString(fullStoreParam))
                                .build()
                                .doPost();
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject.getInteger("code").equals(200)) {
                            devpThread.setPakMk(crnStn.getStaNo(),false);
                        }
                    }catch (CoolException e){
                    }
                }
            }
        }
    }
    public synchronized void RGVTaskPut(){
        for (RgvSlave rgvSlave:slaveProperties.getRgv()){
            ZyRgvThread rgvThread = (ZyRgvThread)SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
            if (rgvProtocol.getModeType() != RgvModeType.AUTO){
                continue;
            }
            int workNo1 = 0;
            int workNo2 = 0;
            short souSta1 = 0;
            short sta1 = 0;
            short souSta2 = 0;
            short sta2 = 0;
            //工位一任务
            for (RgvSlave.Sta inStn :  rgvSlave.getInStn()){
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, inStn.getSourcePlcId());
                StaProtocol staProtocol = devpThread.getStation().get(inStn.getSourceStaNo());
                if (staProtocol == null) {
                    break;
//                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (staProtocol.isLoading() && staProtocol.isLoading() && staProtocol.isInEnable()){
                    if (staProtocol.getWorkNo() > 0 && staProtocol.getWorkNo() <9900){
                        WrkMast wrkMast = wrkMastService.selectByworkNo(staProtocol.getWorkNo());
                        if (Cools.isEmpty(wrkMast)){
                            log.error("未找到工作档");
                            continue;
                        }
                        workNo1 = wrkMast.getWrkNo();
                        souSta1 = inStn.getSourceStaNo().shortValue();
                        sta1 = Utils.getRgvEndStaNo(rgvSlave.getId(),wrkMast.getStaNo());
                        break;
                    }
                    workNo1 = workNo++;
                    souSta1 = inStn.getSourceStaNo().shortValue();
                    sta1 = inStn.getStaNo().shortValue();
                    break;
                }
            }
            //工位二任务
            for (RgvSlave.Sta inStn :  rgvSlave.getInStn()){
                if (souSta1 == inStn.getSourceStaNo()){
                    continue;
                }
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, inStn.getSourcePlcId());
                StaProtocol staProtocol = devpThread.getStation().get(inStn.getSourceStaNo());
                if (staProtocol == null) {
                    break;
//                    continue;
                } else {
                    staProtocol = staProtocol.clone();
                }
                if (staProtocol.isLoading() && staProtocol.isLoading() && staProtocol.isInEnable()){
                    if (staProtocol.getWorkNo() > 0 && staProtocol.getWorkNo() <9900){
                        WrkMast wrkMast = wrkMastService.selectByworkNo(staProtocol.getWorkNo());
                        if (Cools.isEmpty(wrkMast)){
                            log.error("未找到工作档");
                            continue;
                        }
                        workNo2 = wrkMast.getWrkNo();
                        souSta2 = inStn.getSourceStaNo().shortValue();
                        sta2 = Utils.getRgvEndStaNo(rgvSlave.getId(),wrkMast.getStaNo());
                        break;
                    }
                    workNo2 = workNo++;
                    souSta2 = inStn.getSourceStaNo().shortValue();
                    sta2 = inStn.getStaNo().shortValue();
                    break;
                }
            }
            //rgv任务下发--------------------------------------------------------------
            RgvCommand command = new RgvCommand();
            command.setRgvNo(rgvSlave.getId()); // RGV编号
            //工位1
            command.setTaskNo1(workNo1); // 工作号
            command.setSourceStaNo1(souSta1); // 源站
            command.setDestinationStaNo1(sta1);  // 目标站
            command.setAckFinish1(false);  // 任务完成确认位
            //工位2
            command.setTaskNo2(workNo2); // 工作号
            command.setSourceStaNo2(souSta2); // 源站
            command.setDestinationStaNo2(sta2);  // 目标站
            command.setAckFinish2(false);  // 任务完成确认位
            if (workNo1 != 0 && workNo2 ==0){
                command.setTaskMode(RgvTaskModeType.FETCH_PUT2); // 任务模式: 取放货
            } else if (workNo1 == 0 && workNo2 !=0) {
                command.setTaskMode(RgvTaskModeType.FETCH_PUT1); // 任务模式: 取放货
            }else {
                command.setTaskMode(RgvTaskModeType.FETCH_PUT_ALL); // 任务模式: 取放货
            }
            command.setCommand(false);
            MessageQueue.offer(SlaveType.Rgv, rgvSlave.getId(), new Task(2, command));
            log.info("rgv任务下发:"+JSON.toJSONString(command));
        }
    }
    public synchronized void RGVTaskOver() {
    }
}
src/main/java/com/zy/asrs/service/impl/WrkMastServiceImpl.java
@@ -62,4 +62,9 @@
        }
        return list;
    }
    @Override
    public WrkMast selectByworkNo(Short workNo) {
        return this.baseMapper.selectByWrkNo(Integer.valueOf(workNo));
    }
}
src/main/java/com/zy/asrs/utils/Utils.java
@@ -8,6 +8,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * Created by vincent on 2020/8/27
@@ -16,6 +17,21 @@
    private static final DecimalFormat fmt = new DecimalFormat("##0.00");
    public static short getRgvEndStaNo(Integer rgvNo,Integer staNo){
        Map<Integer, Short> rgv1Map = new HashMap<>();
        Map<Integer, Short> rgv2Map = new HashMap<>();
        Map<Integer, Short> rgv3Map = new HashMap<>();
        switch (rgvNo){
            case 1:
                return rgv1Map.get(staNo);
            case 2:
                return rgv2Map.get(staNo);
            case 3:
                return rgv3Map.get(staNo);
        }
        return 0;
    }
    public static float scale(Float f){
        if (f == null || f == 0f || Float.isNaN(f)) {
            return 0f;
src/main/java/com/zy/common/CodeBuilder.java
@@ -20,7 +20,7 @@
        generator.url="127.0.0.1:1433;databasename=mdqdasrs";
        generator.username="sa";
        generator.password="sa@123";
        generator.table="asr_wrk_mast_sta";
        generator.table="man_emptyBarrel_in";
        generator.packagePath="com.zy.asrs";
        generator.html = false;
        generator.htmlDetail = false;
src/main/java/com/zy/core/MainProcess.java
@@ -37,16 +37,10 @@
                    // 间隔
                    Thread.sleep(1000);
                    // 系统运行状态判断
                    if (!SystemProperties.WCS_RUNNING_STATUS.get()) {
                        continue;
                    }
                    // 演示
                    //mainService.crnDemoOfLocMove1();
//                    // 演示 所有库位轮询
//                    mainService.crnDemoOfLocMove2();
                    // 入库  ===>> 入库站到堆垛机站,根据条码扫描生成入库工作档
                    mainService.generateStoreWrkFile(); // 组托
//                    mainService.generateStoreWrkFile0(); // WMS入库
@@ -56,13 +50,8 @@
                    mainService.crnStnToOutStn();
                    // 入出库  ===>>  堆垛机入出库作业下发
                    mainService.crnIoExecute();
                    //空桶库入库
                    mainService.crn5InTask();
                    // 入库  ===>> 执行对工作档的完成操作
                    mainService.storeFinished();
                    // 堆垛机异常信息记录
                    mainService.recCrnErr();
                    // 入库  ===>> 空栈板初始化入库,叉车入库站放货
@@ -77,6 +66,19 @@
                    //扫描拆盘机自动出库空托盘
                    mainService.autoEmptyOut();
                    //二期
                    //空桶库任务生成
                    mainService.crn5TaskCreate();
                    //空桶库入库
                    mainService.crn5InTask();
                    //空桶出库完成
                    mainService.crn5StnToOutStn();
                    //rgv任务
                    mainService.RGVTaskPut();
                    //rgv任务完成
                    mainService.RGVTaskOver();
                } catch (Exception e) {
                    e.printStackTrace();
                }
src/main/java/com/zy/core/cache/MessageQueue.java
@@ -28,6 +28,8 @@
    // 台车mq交换机
    private static final Map<Integer, ConcurrentLinkedQueue<Task>> CAR_EXCHANGE = new ConcurrentHashMap<>();
    private static final Map<Integer, LinkedBlockingQueue<Task>> RGV_EXCHANGE = new ConcurrentHashMap<>();
    /**
     * mq 交换机初始化
     */
@@ -35,6 +37,9 @@
        switch (type) {
            case Crn:
                CRN_EXCHANGE.put(slave.getId(), new LinkedBlockingQueue<>(1));
                break;
            case Rgv:
                RGV_EXCHANGE.put(slave.getId(), new LinkedBlockingQueue<>(1));
                break;
            case Devp:
                DEVP_EXCHANGE.put(slave.getId(), new ConcurrentLinkedQueue<>());
@@ -64,6 +69,8 @@
        switch (type) {
            case Crn:
                return CRN_EXCHANGE.get(id).offer(task);
            case Rgv:
                return RGV_EXCHANGE.get(id).offer(task);
            case Devp:
                return DEVP_EXCHANGE.get(id).offer(task);
            case Barcode:
@@ -87,6 +94,8 @@
        switch (type) {
            case Crn:
                return CRN_EXCHANGE.get(id).poll();
            case Rgv:
                return RGV_EXCHANGE.get(id).poll();
            case Devp:
                return DEVP_EXCHANGE.get(id).poll();
            case Barcode:
@@ -109,6 +118,8 @@
        switch (type) {
            case Crn:
                return CRN_EXCHANGE.get(id).peek();
            case Rgv:
                return RGV_EXCHANGE.get(id).peek();
            case Devp:
                return DEVP_EXCHANGE.get(id).peek();
            case Barcode:
@@ -130,6 +141,9 @@
                
                CRN_EXCHANGE.get(id).clear();
                break;
            case Rgv:
                RGV_EXCHANGE.get(id).clear();
                break;
            case Devp:
                DEVP_EXCHANGE.get(id).clear();
                break;
src/main/java/com/zy/core/enums/RgvModeType.java
@@ -5,16 +5,17 @@
 */
public enum RgvModeType {
    STOP((short) 0, "停机模式"),
    MANUAL((short) 1, "手动模式"),
    AUTO((short) 2, "自动模式"),
    COMPUTER((short) 3, "电脑模式"),
    NONE(-1, "离线"),
    STOP(0, "关机"),
    HAND(1, "手动"),
    HALF_AUTO(2, "半自动"),
    AUTO(3, "自动"),
    AUTO2(100, "其它"),
    ;
    public Short id;
    public Integer id;
    public String desc;
    RgvModeType(Short id, String desc) {
    RgvModeType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
@@ -24,7 +25,7 @@
            return null;
        }
        for (RgvModeType type : RgvModeType.values()) {
            if (type.id.equals(id)) {
            if (type.id.equals(id.intValue())) {
                return type;
            }
        }
@@ -35,9 +36,9 @@
        if (null == type) {
            return null;
        }
        for (RgvModeType type1 : RgvModeType.values()) {
            if (type1 == type) {
                return type1;
        for (RgvModeType rgvModeType : RgvModeType.values()) {
            if (rgvModeType == type) {
                return rgvModeType;
            }
        }
        return null;
src/main/java/com/zy/core/enums/RgvStatusType.java
@@ -14,7 +14,8 @@
    RELEASE_WAIT((short) 5, "放货等待"),
    RELEASE_WORKING((short) 6, "放货中"),
    WALKING((short) 9, "走行中"),
    WAITING((short) 90, "任务完成等待WCS确认"),
    WAITING((short) 90, "工位一任务完成等待WCS确认"),
    WAITING2((short) 91, "工位二任务完成等待WCS确认"),
    ALARM((short) 99, "报警"),
    OTHER((short) 100, "其他"),
    ;
src/main/java/com/zy/core/enums/RgvTaskModeType.java
@@ -2,26 +2,32 @@
public enum RgvTaskModeType {
    NONE((short) 0, "无"),
    PICK((short) 1, "取货"),
    RELEASE((short) 2, "放货"),
    PICK_RELEASE((short) 3, "取放货"),
    MOVE((short) 4, "移动(发工位1任务即可)"),
    NONE(0),    // 无
    FETCH(1),    // 取货
    PUT(2),    // 放货
    FETCH_PUT_ALL(1),    // 取放货
    FETCH_PUT1(8),    // 取放货
    FETCH_PUT2(9),    // 取放货
    X_MOVE(4),    // 站位移转
    //    Y_MOVE(5),    // 站位移转
//    XY_MOVE(6),    // 站位移转
    GO_ORIGIN(7),    // 回原点
//    BACK_ORIGIN(8),      // 回反原点
//    CLEAR(9),       // 清错
    ;
    public Short id;
    public String desc;
    RgvTaskModeType(Short id, String desc) {
    public Integer id;
    RgvTaskModeType(Integer id) {
        this.id = id;
        this.desc = desc;
    }
    public static RgvTaskModeType get(Short id) {
        if (null == id) {
            return null;
        }
        for (RgvTaskModeType type : RgvTaskModeType.values()) {
            if (type.id.equals(id)) {
            if (type.id.equals(id.intValue())) {
                return type;
            }
        }
@@ -32,9 +38,9 @@
        if (null == type) {
            return null;
        }
        for (RgvTaskModeType type1 : RgvTaskModeType.values()) {
            if (type1 == type) {
                return type1;
        for (RgvTaskModeType rgvTaskModeType : RgvTaskModeType.values()) {
            if (rgvTaskModeType == type) {
                return rgvTaskModeType;
            }
        }
        return null;
src/main/java/com/zy/core/model/RgvSlave.java
@@ -21,12 +21,11 @@
    @Data
    public static class Sta {
        private Integer sourceStaNo;//源站
        private Integer sourcePlcId;
        private Integer staNo;//目标站
        private Integer sourceStaNo;//源站
        private Integer devpPlcId;
        private Integer staPlcId;
    }
src/main/java/com/zy/core/model/command/RgvCommand.java
@@ -13,40 +13,17 @@
    // RGV编号
    private Integer rgvNo = 0;
    // 任务完成确认位
    private boolean ackFinish = false;
    //**************工位1**************
    // 工位1工作号
    private Integer taskNo1 = 0;
    /**
     * 任务模式:
     * 0 = 无
     * 1 = 取货
     * 2 = 放货
     * 3 = 取放货
     * 4 = 移动(发工位1任务即可)
     */
    private Short taskMode1 = 0;
    @JSONField(serialize = false)
    private RgvTaskModeType taskModeType1;
    // 工位1源站
    private Short sourceStaNo1 = 0;
    // 工位1目标站
    private Short destinationStaNo1 = 0;
    //**************工位1**************
    // 工位2源站
    private Short sourceStaNo2 = 0;
    //**************工位2**************
    // 工位2工作号
    private Short taskNo2 = 0;
    // 工位2目标站
    private Short destinationStaNo2 = 0;
    /**
     * 任务模式:
@@ -56,40 +33,41 @@
     * 3 = 取放货
     * 4 = 移动(发工位1任务即可)
     */
    private Short taskMode2 = 0;
    private Short taskMode = 0;
    // 工位1工作号
    private Integer taskNo1 = 0;
    // 工位2工作号
    private Integer taskNo2 = 0;
    // 任务确认 0:未确认 1:已确认
    private boolean command = false;
    // 任务完成确认位
    private boolean ackFinish1 = false;
    // 任务完成确认位
    private boolean ackFinish2 = false;
    @JSONField(serialize = false)
    private RgvTaskModeType taskModeType2;
    private RgvTaskModeType taskModeType;
    // 工位1源站
    private Short sourceStaNo2 = 0;
    // 工位1目标站
    private Short destinationStaNo2 = 0;
    //**************工位2**************
    // 任务确认 0:未确认 1:已确认
    private Short command = 0;
    public void setTaskMode1(Short taskMode){
        this.taskMode1 = taskMode;
        this.taskModeType1 = RgvTaskModeType.get(taskMode);
    public void setTaskMode(Short taskMode){
        this.taskMode = taskMode;
        this.taskModeType = RgvTaskModeType.get(taskMode);
    }
    public void setTaskMode1(RgvTaskModeType type) {
        this.taskModeType1 = type;
        this.taskMode1 = RgvTaskModeType.get(type).id;
    public void setTaskMode(RgvTaskModeType type) {
        this.taskModeType = type;
        this.taskMode = RgvTaskModeType.get(type).id.shortValue();
    }
    public void setTaskMode2(Short taskMode){
        this.taskMode2 = taskMode;
        this.taskModeType2 = RgvTaskModeType.get(taskMode);
    }
    public void setTaskMode2(RgvTaskModeType type) {
        this.taskModeType2 = type;
        this.taskMode2 = RgvTaskModeType.get(type).id;
    }
}
src/main/java/com/zy/core/model/protocol/RgvProtocol.java
@@ -1,98 +1,195 @@
package com.zy.core.model.protocol;
import com.zy.asrs.entity.BasRgv;
import com.zy.core.enums.RgvModeType;
import com.zy.core.enums.RgvStatusType;
import com.zy.core.enums.RgvWalkPosType;
import lombok.Data;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Data
public class RgvProtocol {
    //RGV编号
    private Integer rgvNo;
    private Integer RgvNo;
    //模式
    private Short mode;
    /**
     * 1 = 手动模式
     * 2 = 自动模式
     * 3 = 电脑模式
     */
    public Short mode;
    //RGV模式枚举
    private RgvModeType modeType;
    public RgvModeType modeType;
    //RGV状态
    private Short status;
    /**
     * 工位1任务号
     */
    public Integer taskNo1 = 0;
    /**
     * 工位2任务号
     */
    public Integer taskNo2 = 0;
    //RGV状态枚举
    private RgvStatusType statusType;
    /**
     * RGV当前状态
     * 0:空闲,无任务
     * 1:作业中
     * 2:报警
     */
    public Short status;
    //工位1工作号
    private Integer taskNo1;
    /**
     * 状态枚举
     */
    public RgvStatusType statusType;
    /**
     * 当前列号
     */
    public Short columnNumber;
    //工位1有物信号
    private Short loaded1;
    /**
     * RGV当前位置
     */
    public Integer RgvPos;
    //RGV当前位置
    private Short rgvPos;
    /**
     * 工位1有物
     */
    public Short loaded1;
    //走行在定位 0:在定位,1:不在定位
    private Short walkPos;
    //RGV走行枚举
    private RgvWalkPosType walkPosType;
    /**
     * 异常码
     */
    public Short alarm;
    //工位2工作号
    private Short taskNo2;
    /**
     * X行走行速度m/min
     */
    private Float xSpeed;
    //工位2有物信号
    private Short loaded2;
    /**
     * 堆垛机累计走行距离km
     */
    public Float xDistance;
    //工位1任务完成信号
    private Short taskFinish1;
    /**
     * 堆垛机累计走行时长h
     */
    public Float xDuration;
    //工位2任务完成信号
    private Short taskFinish2;
    //异常码
    private Short alarm;
    //心跳
    private Short heart;
    //备用1
    private Integer temp1;
    //备用2
    /**
     * RGV工位1当前状态
     * 0:空闲,无任务
     * 11:取货中
     * 12:放货中
     * 10:任务完成等待WCS确认
     */
    public Short status1;
    /**
     * 状态枚举
     */
    public RgvStatusType statusType1;
    /**
     * 走行在定位
     * 0 = 在定位
     * 1 = 不在定位
     */
    public Short walkPos;
    /**
     * RGV工位2当前状态
     * 0:空闲,无任务
     * 11:取货中
     * 12:放货中
     * 10:任务完成等待WCS确认
     */
    public Short status2;
    /**
     * 状态枚举
     */
    public RgvStatusType statusType2;
    /**
     * 工位2有物
     */
    public Short loaded2;
    /**
     * 心跳指令 1-2每秒切换一次
     */
    public Short heart;
    private Short temp1;
    private Short temp2;
    //备用3
    private Short temp3;
    //备用4
    private Short temp4;
    //备用5
    private Short temp5;
    //工位1任务模式
    private Short taskMode1;
    //工位1源站
    private Short sourceStn1;
    //工位1目标站
    private Short destinationPos1;
    public void setMode(Short mode) {
        this.mode = mode;
        this.modeType = RgvModeType.get(mode);
    }
    //工位2任务模式
    private Short taskMode2;
    public void setMode(RgvModeType type) {
        this.modeType = type;
        this.mode = RgvModeType.get(type).id.shortValue();
    }
    //工位2源站
    private Short sourceStn2;
    public void setStatus(Short status){
        this.status = status;
        this.statusType = RgvStatusType.get(status);
    }
    //工位2目标站
    private Short destinationPos2;
    public void setStatus(RgvStatusType type){
        this.statusType = type;
        this.status = RgvStatusType.get(type).id.shortValue();
    }
    //工位1下发时间
    private Long task1SendTime;
    public void setStatus1(Short status1){
        this.status1 = status1;
        this.statusType1 = RgvStatusType.get(status1);
    }
    public void setStatus1(RgvStatusType type1){
        this.statusType1 = type1;
        this.status1 = RgvStatusType.get(type1).id.shortValue();
    }
    public void setStatus2(Short status2){
        this.status2 = status2;
        this.statusType2 = RgvStatusType.get(status2);
    }
    public void setStatus2(RgvStatusType type2){
        this.statusType2 = type2;
        this.status2 = RgvStatusType.get(type2).id.shortValue();
    }
    /**
     * 最近一次入出库类型
@@ -101,34 +198,50 @@
     */
    private String lastIo = "I";
    public void setMode(Short mode) {
        this.mode = mode;
        this.modeType = RgvModeType.get(mode);
    public BasRgv toSqlModel(BasRgv basRgv){
        if (alarm!=null) {
            basRgv.setRgvErr(alarm.longValue());
        }
        basRgv.setWrkNo1(taskNo1.intValue());
//        basRgv.setWrkNo2(taskNo2.intValue());
        return basRgv;
    }
    public void setMode(RgvModeType type) {
        this.mode = type.id;
        this.modeType = type;
    public void setxSpeed(float xSpeed) {
        this.xSpeed = xSpeed;
    }
    public void setStatus(Short status) {
        this.status = status;
        this.statusType = RgvStatusType.get(status);
    public void setxDistance(float xDistance) {
        this.xDistance = xDistance;
    }
    public void setStatus(RgvStatusType type) {
        this.status = type.id;
        this.statusType = type;
    public void setxDuration(float xDuration) {
        this.xDuration = xDuration;
    }
    public void setWalkPos(Short walkPos) {
        this.walkPos = walkPos;
        this.walkPosType = RgvWalkPosType.get(walkPos);
    public Integer getRgvPosI(){
        //需要根据现场改造  根据读到的值获取对应站点位置
        Map<Short,Integer> map = new HashMap<>();
        map.put((short) 1,100);map.put((short) 2,101);
        map.put((short) 3,106);map.put((short) 4,107);
        map.put((short) 5,112);map.put((short) 6,113);
        map.put((short) 7,119);map.put((short) 8,124);
        map.put((short) 9,149);map.put((short) 10,153);
        map.put((short) 11,157);map.put((short) 12,161);
        if (RgvPos==null) return 0;
        return map.get(RgvPos);
    }
    public void setWalkPos(RgvWalkPosType type) {
        this.walkPos = type.id;
        this.walkPosType = type;
    @Override
    public RgvProtocol clone() {
        try {
            return (RgvProtocol) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
src/main/java/com/zy/core/model/protocol/StaProtocol.java
@@ -85,6 +85,9 @@
    // 扫码失败
    private boolean barcodeErr = false;
    private boolean force = false;
    private short amount = 0;
    public Boolean isErr(){
        if (frontErr || backErr || highErr || leftErr || rightErr || weightErr || barcodeErr){
            return true;
@@ -104,7 +107,7 @@
        basDevp.setLocType1((short) 0);  // 高低类型{0:未知,1:低库位,2:高库位}
        basDevp.setLocType2((short) 0);  // 宽窄类型{0:未知,1:窄库位,2:宽库位}
        basDevp.setLocType3((short) 0);  // 轻重类型{0:未知,1:轻库位,2:重库位}
        basDevp.setLocType1(high != low && low ? (short) 1 : (short) 2);
        basDevp.setLocType1(high != low && high ? (short) 2 : (short) 1);
//        basDevp.
        return basDevp;
    }
src/main/java/com/zy/core/thread/SiemensDevpThread.java
@@ -59,9 +59,7 @@
    }};
    public static final ArrayList<Integer> staNos3 = new ArrayList<Integer>() {{
        add(2007);add(2008);add(2009);add(2010);add(2011);add(2012);add(2013);
        add(2108);add(2109);add(2110);add(2111);add(2112);add(2113);add(2114);
        add(2401);add(2402);add(2403);
        add(5001);add(5002);
    }};
    public static final ArrayList<Integer> staNos4 = new ArrayList<Integer>() {{
@@ -88,15 +86,13 @@
    }};
    public static final ArrayList<Integer> writeStaNos2 = new ArrayList<Integer>() {{
        add(2001);add(2002);add(2003);
        add(2101);add(2102);add(2103);
        add(2301);
        add(2001);add(2002);add(2101);add(2102);add(2301);add(2302);
        add(2303);add(2304);add(2305);add(2306);add(2003);add(2004);add(2005);
        add(2006);add(2103);add(2104);add(2105);add(2106);add(2107);
    }};
    public static final ArrayList<Integer> writeStaNos3 = new ArrayList<Integer>() {{
        add(2013);
        add(2114);
        add(2401);add(2402);
        add(5001);add(5002);
    }};
    public static final ArrayList<Integer> writeStaNos4 = new ArrayList<Integer>() {{
@@ -209,7 +205,12 @@
                switch (step) {
                    // 读数据
                    case 1:
                        read();
                        if (slave.getId() ==3){
                            read30();
                        }else {
                            read();
                        }
                        break;
                    // 写数据 ID+目标站
                    case 2:
@@ -356,6 +357,66 @@
        }
    }
    private void read30() throws InterruptedException {
        ArrayList<Integer> staNos = getStaNo();
        int staNoSize = staNos.size();
        OperateResultExOne<byte[]> result = siemensS7Net.Read("DB101.0", (short) (getStaNo().size() * 8));
        result = siemensS7Net.Read("DB101.0", (short) (getStaNo().size()*4));
        if (result.IsSuccess) {
            for (int i = 0; i < staNoSize; i++) {
                Integer siteId = staNos.get(i); // 站点编号
                boolean[] status = siemensS7Net.getByteTransform().TransBool(result.Content, i*4, 1);
                short count = siemensS7Net.getByteTransform().TransInt16(result.Content, i * 4 + 2);
                StaProtocol staProtocol = station.get(siteId);
                if (null == staProtocol) {
                    staProtocol = new StaProtocol();
                    staProtocol.setSiteId(siteId);
                    station.put(siteId, staProtocol);
                }
                staProtocol.setAutoing(status[0]);  // 自动
                staProtocol.setLoading(status[1]);  // 有物
                staProtocol.setInEnable(status[2]); // 可入
                staProtocol.setOutEnable(status[3]);// 可出
                staProtocol.setForce(status[4]);
                staProtocol.setAmount(count);
                if (!staProtocol.isPakMk() && !staProtocol.isLoading()) {
                    staProtocol.setPakMk(true);
                }
            }
        }
        if (result.IsSuccess) {
            OutputQueue.DEVP.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
            // 根据实时信息更新数据库
            try {
                List<BasDevp> basDevps = new ArrayList<>();
                for (Integer siteId : staNos) {
                    StaProtocol staProtocol = station.get(siteId);
                    basDevps.add(staProtocol.toSqlModel());
                }
                BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
                if (null != basDevpService && !basDevpService.updateBatchById(basDevps)) {
                    throw new Exception("更新数据库数据失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
                OutputQueue.DEVP.offer(MessageFormat.format("【{0}】更新数据库数据失败 ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
                log.error("更新数据库数据失败 ===>> [id:{}] [ip:{}] [port:{}] [rack:{}] [slot:{}]", slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot());
            }
        } else {
            OutputQueue.DEVP.offer(MessageFormat.format("【{0}】读取输送线plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
//            log.error("读取输送线plc状态信息失败 ===>> [id:{}] [ip:{}] [port:{}] [rack:{}] [slot:{}]", slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot());
        }
    }
    /**
     * 写入 ID+目标站 =====> 单站点写入
     */
src/main/java/com/zy/core/thread/ZyRgvThread.java
@@ -64,23 +64,13 @@
                    case 2:
                        write((RgvCommand) task.getData());
                        break;
                    // 复位
                    // 工位1复位
                    case 3:
                        RgvCommand command = (RgvCommand) task.getData();
                        if (null == command) {
                            command = new RgvCommand();
                        }
                        command.setRgvNo(slave.getId()); // 堆垛机编号
                        command.setTaskNo1(0); // 工作号
                        command.setTaskMode1(RgvTaskModeType.NONE); // 任务模式
                        command.setSourceStaNo1((short) 0);//源站
                        command.setDestinationStaNo1((short) 0);//目标站
                        command.setTaskNo2((short) 0); // 工作号
                        command.setTaskMode2(RgvTaskModeType.NONE); // 任务模式
                        command.setSourceStaNo2((short) 0);//源站
                        command.setDestinationStaNo2((short) 0);//目标站
                        command.setAckFinish(true);  // 任务完成确认位
                        write(command);
                        writeAckFinish1((RgvCommand) task.getData());
                        break;
                        //工位2复位
                    case 4:
                        writeAckFinish2((RgvCommand) task.getData());
                        break;
                    default:
@@ -88,7 +78,7 @@
                }
                Thread.sleep(500);
            } catch (Exception e) {
//                e.printStackTrace();
                e.printStackTrace();
            }
        }
@@ -103,10 +93,10 @@
        OperateResult connect = siemensNet.ConnectServer();
        if(connect.IsSuccess){
            result = true;
            OutputQueue.CRN.offer(MessageFormat.format( "【{0}】RGV plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
            OutputQueue.RGV.offer(MessageFormat.format( "【{0}】RGV plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
            log.info("RGV plc连接成功 ===>> [id:{}] [ip:{}] [port:{}] [rack:{}] [slot:{}]", slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot());
        } else {
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】RGV plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
            OutputQueue.RGV.offer(MessageFormat.format("【{0}】RGV plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
            log.error("RGV plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}] [rack:{}] [slot:{}]", slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot());
            initRgv();
        }
@@ -118,7 +108,7 @@
     */
    private void readStatus(){
        try {
            OperateResultExOne<byte[]> result = siemensNet.Read("DB101.0", (short) 30);
            OperateResultExOne<byte[]> result = siemensNet.Read("DB101.0", (short) 34);
            if (result.IsSuccess) {
                if (null == rgvProtocol) {
                    rgvProtocol = new RgvProtocol();
@@ -126,17 +116,18 @@
                }
                rgvProtocol.setMode(siemensNet.getByteTransform().TransInt16(result.Content, 0));//模式
                rgvProtocol.setTaskNo1(siemensNet.getByteTransform().TransInt32(result.Content, 2));//工位1工作号
                rgvProtocol.setStatus(siemensNet.getByteTransform().TransInt16(result.Content, 6));//RGV状态
                rgvProtocol.setRgvPos(siemensNet.getByteTransform().TransInt16(result.Content, 8));//RGV当前位置
                rgvProtocol.setWalkPos(siemensNet.getByteTransform().TransInt16(result.Content, 10));//走行在定位
                rgvProtocol.setTemp1(siemensNet.getByteTransform().TransInt32(result.Content, 12));//备用1
                rgvProtocol.setLoaded1(siemensNet.getByteTransform().TransInt16(result.Content, 16));//工位1有物
                rgvProtocol.setAlarm(siemensNet.getByteTransform().TransInt16(result.Content, 18));//异常码
                rgvProtocol.setTemp2(siemensNet.getByteTransform().TransInt16(result.Content, 20));//备用2
                rgvProtocol.setTemp3(siemensNet.getByteTransform().TransInt16(result.Content, 24));//备用3
                rgvProtocol.setTemp4(siemensNet.getByteTransform().TransInt16(result.Content, 28));//备用4
                rgvProtocol.setTaskNo2(siemensNet.getByteTransform().TransInt32(result.Content, 6));//工位1工作号
                rgvProtocol.setStatus(siemensNet.getByteTransform().TransInt16(result.Content, 10));//RGV状态
                rgvProtocol.setColumnNumber(siemensNet.getByteTransform().TransInt16(result.Content, 12));//RGV当前位置
                rgvProtocol.setWalkPos(siemensNet.getByteTransform().TransInt16(result.Content, 14));//走行在定位
                rgvProtocol.setRgvPos(siemensNet.getByteTransform().TransInt32(result.Content, 16));//RGV当前位置
                rgvProtocol.setLoaded1(siemensNet.getByteTransform().TransInt16(result.Content, 20));//工位1有物
                rgvProtocol.setAlarm(siemensNet.getByteTransform().TransInt16(result.Content, 22));//异常码
                rgvProtocol.setxSpeed(siemensNet.getByteTransform().TransSingle(result.Content, 24));//备用2
                rgvProtocol.setxDistance(siemensNet.getByteTransform().TransSingle(result.Content, 28));//备用3
                rgvProtocol.setxDuration(siemensNet.getByteTransform().TransInt16(result.Content, 32));//备用4
                OutputQueue.CRN.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
                OutputQueue.RGV.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
                // 复位信号
                if (rgvProtocol.getStatusType().equals(RgvStatusType.WAITING)) {
@@ -172,16 +163,33 @@
            } else {
                initRgv();
                OutputQueue.CRN.offer(MessageFormat.format("【{0}】读取RGV plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
                OutputQueue.RGV.offer(MessageFormat.format("【{0}】读取RGV plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}] [rack:{4}] [slot:{5}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot()));
                log.error("读取RGV plc状态信息失败 ===>> [id:{}] [ip:{}] [port:{}] [rack:{}] [slot:{}]", slave.getId(), slave.getIp(), slave.getPort(), slave.getRack(), slave.getSlot());
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】读取RGV plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            OutputQueue.RGV.offer(MessageFormat.format("【{0}】读取RGV plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            log.error("读取RGV plc状态信息失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
            initRgv();
        }
    }
    private boolean writeAckFinish1(RgvCommand command) throws InterruptedException {
        OperateResult write = siemensNet.Write("DB100.22.1", true);
        if (!write.IsSuccess){
            log.error("任务1确认完成写入RGVplc数据失败,重新添加任务到队列 ===> [id:{}]",slave.getId());
            MessageQueue.offer(SlaveType.Rgv, slave.getId(), new Task(3, command));
        }
        return write.IsSuccess;
    }
    private boolean writeAckFinish2(RgvCommand command) throws InterruptedException {
        OperateResult write = siemensNet.Write("DB100.22.2", true);
        if (!write.IsSuccess){
            log.error("任务2确认完成写入RGVplc数据失败,重新添加任务到队列 ===> [id:{}]",slave.getId());
            MessageQueue.offer(SlaveType.Rgv, slave.getId(), new Task(4, command));
        }
        return write.IsSuccess;
    }
    /**
     * 写入数据
@@ -198,11 +206,21 @@
        array[1] = command.getSourceStaNo2();
        array[2] = command.getDestinationStaNo1();
        array[3] = command.getDestinationStaNo2();
        array[4] = command.getTaskMode1();
        array[4] = command.getTaskMode();
        int[] array2 = new int[3];
        array2[0] = command.getTaskNo1();
        array2[1] = command.getTaskNo2();
        array2[2] = 0;
        boolean[] array3 = new boolean[3];
        array3[0] = command.isCommand();
        array3[1] = command.isAckFinish1();
        array3[2] = command.isAckFinish2();
        OperateResult result1 = siemensNet.Write("DB100.0",array);
        OperateResult result2 = siemensNet.Write("DB100.10",command.getTaskNo1());
        OperateResult result3 = siemensNet.Write("DB100.18.1",command.isAckFinish());
        OperateResult result2 = siemensNet.Write("DB100.10",array2);
        OperateResult result3 = siemensNet.Write("DB100.22",array3);
        if (!result1.IsSuccess && !result2.IsSuccess && !result3.IsSuccess){
            log.error("写入RGVplc数据失败,重新添加任务到队列 ===> [id:{}],{}",slave.getId(),JSON.toJSON(command));
@@ -215,23 +233,33 @@
        //RGV任务写入后,回读一次,看是否成功
        Thread.sleep(400);
        try {
            OperateResultExOne<byte[]> resultRead = siemensNet.Read("DB100.0", (short) 20);
            OperateResultExOne<byte[]> resultReadAck = siemensNet.Read("DB100.18.1", (short) 1);
            if (resultRead.IsSuccess){
            OperateResultExOne<byte[]> resultRead = siemensNet.Read("DB100.0", (short) 24);
            OperateResultExOne<byte[]> readAck1 = siemensNet.Read("DB100.0", (short) 22.1);
            OperateResultExOne<byte[]> readAck2 = siemensNet.Read("DB100.0", (short) 22.2);
            if (resultRead.IsSuccess && readAck1.IsSuccess && readAck2.IsSuccess){
                RgvCommand one = new RgvCommand();
                one.setAckFinish(siemensNet.getByteTransform().TransBool(resultReadAck.Content, 0));
                one.setSourceStaNo1(siemensNet.getByteTransform().TransInt16(resultRead.Content, 0));
                one.setSourceStaNo2(siemensNet.getByteTransform().TransInt16(resultRead.Content, 2));
                one.setDestinationStaNo1(siemensNet.getByteTransform().TransInt16(resultRead.Content, 4));
                one.setDestinationStaNo2(siemensNet.getByteTransform().TransInt16(resultRead.Content, 6));
                one.setTaskMode1(siemensNet.getByteTransform().TransInt16(resultRead.Content, 8));
                one.setTaskMode(siemensNet.getByteTransform().TransInt16(resultRead.Content, 8));
                one.setTaskNo1(siemensNet.getByteTransform().TransInt32(resultRead.Content, 10));
                one.setTaskNo2(siemensNet.getByteTransform().TransInt32(resultRead.Content, 14));
                one.setCommand(siemensNet.getByteTransform().TransBool(resultRead.Content, 22));
                one.setAckFinish1(siemensNet.getByteTransform().TransBool(readAck1.Content, 0));
                one.setAckFinish2(siemensNet.getByteTransform().TransBool(readAck2.Content, 0));
//                one.setDestinationStaNo1(siemensNet.getByteTransform().TransInt16(resultRead.Content, 8));
                if (    !command.isAckFinish() == one.isAckFinish() ||
                if (    !command.isAckFinish1() == one.isAckFinish1() ||
                        !command.isAckFinish2() == one.isAckFinish2() ||
                        !command.isCommand() == one.isCommand() ||
                        !command.getTaskNo1().equals(one.getTaskNo1()) ||
                        !command.getTaskMode1().equals(one.getTaskMode1()) ||
                        !command.getTaskNo2().equals(one.getTaskNo2()) ||
                        !command.getTaskMode().equals(one.getTaskMode()) ||
                        !command.getSourceStaNo1().equals(one.getSourceStaNo1()) ||
                        !command.getDestinationStaNo1().equals(one.getDestinationStaNo1())
                        !command.getDestinationStaNo1().equals(one.getDestinationStaNo1()) ||
                        !command.getSourceStaNo2().equals(one.getSourceStaNo2()) ||
                        !command.getDestinationStaNo2().equals(one.getDestinationStaNo2())
                ){
                    try{
                        log.error("RGV命令地址写入后回读失败[id:{}] >>>>> 写入[{}],===>>回读[{}]", slave.getId(), JSON.toJSON(command),JSON.toJSON(one));
@@ -250,12 +278,15 @@
                }else {
                    log.info("RGV命令地址写入后回读成功[id:{}] >>>>> 写入[{}],===>>回读[{}]", slave.getId(), JSON.toJSON(command),JSON.toJSON(one));
                }
            }else {
                log.error("RGV命令地址写入后回读出错,重新加入队列");
                MessageQueue.offer(SlaveType.Rgv, slave.getId(), new Task(2, command));
            }
        }catch (Exception e){
            log.error("RGV命令地址写入后回读出错");
        }
        if (!command.isAckFinish()) {
        if (!command.isAckFinish1() && !command.isAckFinish2()) {
            if (result1.IsSuccess) {
                Thread.sleep(300);
                //任务下发次数
@@ -263,11 +294,11 @@
                do {
                    writeCount2++;
                    result1 = siemensNet.Write("DB100.18", true);
                    result1 = siemensNet.Write("DB100.22", true);
                    if(result1.IsSuccess){
                        //RGV任务写入后,回读一次,看是否成功
                        Thread.sleep(200);
                        OperateResultExOne<byte[]> resultRead = siemensNet.Read("DB100.18", (short) 2);
                        OperateResultExOne<byte[]> resultRead = siemensNet.Read("DB100.22", (short) 2);
                        if (resultRead.IsSuccess) {
                            boolean commandFinish=siemensNet.getByteTransform().TransBool(resultRead.Content, 0);
                            if (!commandFinish){
@@ -309,9 +340,18 @@
        if (null == rgvProtocol) {
            rgvProtocol = new RgvProtocol();
        }
        rgvProtocol.setMode((short) 0);
        rgvProtocol.setStatus((short) -1);
        rgvProtocol.setWalkPos((short) 1);
        rgvProtocol.setMode((short) 0);//模式
        rgvProtocol.setTaskNo1(0);//工位1工作号
        rgvProtocol.setTaskNo2(0);//工位1工作号
        rgvProtocol.setStatus((short) 0);//RGV状态
        rgvProtocol.setColumnNumber((short) 0);//RGV当前位置
        rgvProtocol.setWalkPos((short) 0);//走行在定位
        rgvProtocol.setRgvPos(0);//RGV当前位置
        rgvProtocol.setLoaded1((short) 0);//工位1有物
        rgvProtocol.setAlarm((short) 0);//异常码
        rgvProtocol.setxSpeed( 0);//备用2
        rgvProtocol.setxDistance(0);//备用3
        rgvProtocol.setxDuration( 0);//备用4
    }
    @Override
src/main/resources/application.yml
@@ -8,7 +8,7 @@
    name: @pom.build.finalName@
  datasource:
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    url: jdbc:sqlserver://127.0.0.1:1433;databasename=mdqdasrs
    url: jdbc:sqlserver://10.10.10.212:1433;databasename=mdqdasrs
    username: sa
    password: sa@123
  mvc:
@@ -34,7 +34,7 @@
  enable: false
wms:
  url: localhost:8080/mdqdwms
  url: localhost:8082/mdqdwms
# 下位机配置
wcs-slave:
@@ -132,15 +132,15 @@
    demo: false
    # 堆垛机入库站1
    crnInStn[0]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 1013
      devpPlcId: ${wcs-slave.devp[2].id}
      staNo: 5001
      row: 4
      bay: 2
      lev: 1
    # 堆垛机出库站点1
    crnOutStn[0]:
      devpPlcId: ${wcs-slave.devp[0].id}
      staNo: 1010
      devpPlcId: ${wcs-slave.devp[2].id}
      staNo: 5002
      row: 4
      bay: 1
      lev: 1
@@ -225,45 +225,42 @@
    port: 102
    rack: 0
    slot: 0
    rgvSta[0]:
      staNo: 4007
    rgvSta[1]:
      staNo: 4001
    rgvSta[2]:
      staNo: 4016
    rgvSta[3]:
      staNo: 4010
    rgvSta[4]:
      staNo: 2003
    rgvSta[5]:
      staNo: 2103
    rgvSta[6]:
      staNo: 2301
    rgvSta[7]:
      staNo: 2002
    rgvSta[8]:
      staNo: 2102
#    # 输送线3
#  devp[2]:
#    id: 1
#    ip: 10.10.10.20
#    port: 102
#    rack: 0
#    slot: 0
#  # 输送线4
#  devp[3]:
#    id: 1
#    ip: 10.10.10.20
#    port: 102
#    rack: 0
#    slot: 0
  # RGV1
  rgv[0]:
    id: 1
    ip: 10.10.10.120
    # 输送线3
  devp[2]:
    id: 3
    ip: 10.10.10.30
    port: 102
    rack: 0
    slot: 0
  # 输送线4
  devp[3]:
    id: 4
    ip: 10.10.10.33
    port: 102
    rack: 0
    slot: 0
#  # 输送线5
#  devp[4]:
#    id: 5
#    ip: 10.10.10.33
#    port: 102
#    rack: 0
#    slot: 0
#  # RGV1
  rgv[0]:
    id: 1
    ip: 10.10.10.130
    port: 102
    rack: 0
    slot: 0
    inStn[0]:
      sourceStaNo: 4007
      sourcePlcId: 4
      staNo: 2103
      staPlcId: 2
    outStn[0]:
      sourceStaNo: 4007
      sourcePlcId: 4
#  # RGV2
#  rgv[1]:
#    id: 2
src/main/resources/mapper/EmptyBarrelInMapper.xml
New file
@@ -0,0 +1,14 @@
<?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.EmptyBarrelInMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.EmptyBarrelIn">
        <id column="id" property="id" />
        <result column="matnr" property="matnr" />
        <result column="batch" property="batch" />
        <result column="maktx" property="maktx" />
    </resultMap>
</mapper>
src/main/webapp/static/css/rgv.css
New file
@@ -0,0 +1,252 @@
body {
    background-color: #6CA7A8;
}
.button-window {
    float: left;
    width: 100%;
    height: 100%;
    padding: 10px;
    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: 28%;
}
/* 左 */
.command-log {
    float: left;
    height: 100%;
    width: 20%;
    text-align: center;
}
.command-log h2 {
    padding: 10px;
}
.rgv-command-item {
    padding: 4px 0;
}
.rgv-command-item label {
    font-size: 20px;
    font-weight: bold;
    vertical-align: middle;
}
.rgv-command-item span {
    display: inline-block;
    width: 20px;
    height: 20px;
    background-color: #2e9926;
    border-radius: 5px;
    vertical-align: middle;
}
.rgv-command-item input {
    vertical-align: middle;
    outline: none;
    width: 60%;
}
/* 右 */
.rgv-state {
    float: left;
    height: 100%;
    width: 100%;
    overflow: auto;
}
/* 堆垛机状态表 */
#rgv-state-table {
    font-size: 12px;
    border-collapse: collapse;
    margin: 0 auto;
    text-align: center;
}
#rgv-state-table td, #rgv-state-table th {
    border: 1px solid #cad9ea;
    color: #666;
    height: 25px;
}
#rgv-state-table thead th {
    background-color: #CCE8EB;
    width: 300px;
}
#rgv-state-table tr:nth-child(odd) {
    background: #fff;
}
#rgv-state-table tr:nth-child(even) {
    background: #F5FAFA;
}
/* -------------------- 第二模块 -------------------- */
.rgv-msg {
    /*overflow: auto;*/
    margin-top: 10px;
    height: 23%;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 0 3px rgba(0,0,0,.3);
}
/* 堆垛机状态信息表 */
#rgv-msg-table {
    font-size: 12px;
    border-collapse: collapse;
    margin: 0 auto;
    text-align: center;
}
#rgv-msg-table td, #rgv-msg-table th {
    border: 1px solid #f1f1f1;
    color: #666;
    height: 30px;
}
#rgv-msg-table thead th {
    background-color: #fff;
    width: 400px;
}
#rgv-msg-table tr:nth-child(odd) {
    background: #fff;
}
#rgv-msg-table tr:nth-child(even) {
    background: #fff;
}
/* -------------------- 第三模块 -------------------- */
.rgv-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 {
    height: 50%;
    overflow: hidden;
    padding: 20px 0 10px 20px;
}
.operator-item {
    display: inline-block;
    height: 100%;
    width: 20%;
    text-align: center;
    position: relative;
    vertical-align: middle;
    padding: 10px 0px 10px 50px;
}
.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: 10px 0;
    height: 100%;
    border: 1px solid #8d8d8d;
    border-radius: 5px;
}
#rgv-select .select-container label {
    display: inline-block;
    padding: 0 20px;
    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: block;
    margin: 0px auto;
    padding: 0;
}
.select-container-item input {
    height: 20px;
    border: 1px solid #8D8D8D;
    border-radius: 3px;
    width: 80px;
    outline: none;
}
/* 任务作业选择框 */
.task-operator {
    height: 50%;
    overflow: hidden;
    padding: 0 20px 10px 20px;
}
.task-operator fieldset {
    padding: 15px 20px 5px 50px;
    border-width: 1px;
    border-style: solid;
    height: 100%;
}
.task-operator legend {
    margin-left: 20px;
    padding: 0 10px;
    font-size: 16px;
    font-weight: 300;
}
button.item {
    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;
}
/* 手动操作遮罩 */
.rgv-operation-shade {
    position: absolute;
    height: 100%;
    width: 100%;
    z-index: 1000;
    text-align: center;
    padding: 80px 0;
}
.rgv-operation-shade-span {
    font-size: xx-large;
    font-weight: bold;
    color: red;
}
/* -------------------- 第四模块 -------------------- */
.rgv-output-board {
    margin-top: 10px;
    height: 15%;
    background-color: #fff;
    border-radius: 5px;
    box-shadow: 0 0 3px rgba(0,0,0,.3);
}
#rgv-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;
}
src/main/webapp/views/index.html
@@ -17,6 +17,7 @@
            <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="rgv" onclick="nav(this.id)" class="nav-unselect" href="#">RGV</a></li>
        </ul>
    </div>
</div>
src/main/webapp/views/rgv.html
New file
@@ -0,0 +1,598 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>RGV监控管理</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <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/css/rgv.css">
    <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
    <script type="text/javascript" src="../static/js/common.js"></script>
    <script type="text/javascript" src="../static/js/layer/layer.js"></script>
    <style>
        .demoBtn {
            vertical-align: middle;
            width: 20%;
            height: 25px;
            left: 0;
            top: 0;
            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;
        }
    </style>
</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">-->
<!--                <h3>执行中的命令</h3>-->
<!--                <div class="crn-command-item">-->
<!--                    <label>1#</label>-->
<!--                    <button id="demoBtn-1" class="demoBtn" onclick="demoSwitch(this.id)"> - </button>-->
<!--                    &lt;!&ndash;            <span>&nbsp;</span>&ndash;&gt;-->
<!--                    <input id="crn1" disabled="disabled">-->
<!--                </div>-->
<!--                <div class="crn-command-item">-->
<!--                    <label>2#</label>-->
<!--                    <button id="demoBtn-2" class="demoBtn" onclick="demoSwitch(this.id)"> - </button>-->
<!--                    &lt;!&ndash;            <span>&nbsp;</span>&ndash;&gt;-->
<!--                    <input id="crn2" disabled="disabled">-->
<!--                </div>-->
<!--                <div class="crn-command-item">-->
<!--                    <label>3#</label>-->
<!--                    <button id="demoBtn-3" class="demoBtn" onclick="demoSwitch(this.id)"> - </button>-->
<!--                    &lt;!&ndash;            <span>&nbsp;</span>&ndash;&gt;-->
<!--                    <input id="crn3" disabled="disabled">-->
<!--                </div>-->
<!--                <div class="crn-command-item">-->
<!--                    <label>4#</label>-->
<!--                    <button id="demoBtn-4" class="demoBtn" onclick="demoSwitch(this.id)"> - </button>-->
<!--                    &lt;!&ndash;            <span>&nbsp;</span>&ndash;&gt;-->
<!--                    <input id="crn4" disabled="disabled">-->
<!--                </div>-->
<!--                <div class="crn-command-item">-->
<!--                    <label>5#</label>-->
<!--                    <button id="demoBtn-5" class="demoBtn" onclick="demoSwitch(this.id)"> - </button>-->
<!--                    &lt;!&ndash;            <span>&nbsp;</span>&ndash;&gt;-->
<!--                    <input id="crn5" disabled="disabled">-->
<!--                </div>-->
<!--            </div>-->
            <!-- RGV状态位信息 -->
            <div class="rgv-state">
                <table id="rgv-state-table">
                    <thead>
                    <tr>
                        <th>RGV</th>
                        <th>当前模式</th>
                        <th>当前状态</th>
                        <th>工位1任务号</th>
                        <th>工作状态</th>
                        <th>有物</th>
                        <th>RGV位置</th>
                        <th>走行定位</th>
<!--                        <th>任务号2</th>-->
<!--                        <th>状态2</th>-->
<!--                        <th>有物2</th>-->
                        <th>故障代码</th>
                        <th>故障描述</th>
<!--                        <th>锁定状态</th>-->
                    </tr>
                    </thead>
                    <tbody>
                    </tbody>
                </table>
            </div>
        </div>
        <!-- RGV状态 -->
        <div class="rgv-msg">
            <table id="rgv-msg-table">
                <thead>
                <tr>
                    <th>RGV</th>
                    <th>工作号</th>
                    <th>状态</th>
                    <th>源站</th>
                    <th>目标站</th>
                    <th>源库位</th>
                    <th>目标库位</th>
<!--                    <th>走行速度(m/min)</th>-->
<!--                    <th>升降速度(m/min)</th>-->
<!--                    <th>叉牙速度(m/min)</th>-->
<!--                    <th>走行距离(Km)</th>-->
<!--                    <th>升降距离(Km)</th>-->
<!--                    <th>走行时长(H)</th>-->
<!--                    <th>升降时长(H)</th>-->
                </tr>
                </thead>
                <tbody>
                </tbody>
            </table>
        </div>
        <!-- 手动操作 -->
        <div class="rgv-operation">
            <!-- 遮罩层 -->
            <div class="rgv-operation-shade">
        <span class="rgv-operation-shade-span">
            WCS 系统运行中,请停止后操作
        </span>
            </div>
            <!-- 设备任务选择 -->
            <div class="task-select">
                <!-- 堆垛机选择 -->
                <div id="rgv-select" class="operator-item" style="width: 55%">
                    <span class="select-title">RGV号</span>
                    <div class="select-container" style="padding: 20px 0;">
                        <label><input type="radio" name="rgvSelect" value="1" checked>&nbsp;1号RGV</label>
                        <label><input type="radio" name="rgvSelect" value="2">&nbsp;2号RGV</label>
                        <label><input type="radio" name="rgvSelect" value="3">&nbsp;3号RGV</label>
                    </div>
                </div>
                <!-- 源站/源库位 选择 -->
                <div id="source-select" class="operator-item">
                    <span class="select-title">源站</span>
                    <div class="select-container">
                        <div class="select-container-item">
                            <span>工位1源站</span>
                            <label><input id="sourceStaNo" type="number" name="points" min="0" value="0"/></label>
                        </div>
<!--                        <div class="select-container-item">-->
<!--                            <span>排</span>-->
<!--                            <label><input id="sourceRow" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>-->
<!--                        </div>-->
                        <div class="select-container-item">
                            <span>工位2源站</span>
                            <label><input id="sourceBay" type="number" name="points" min="0" style="background-color: #a9eeff" value="0" /></label>
                        </div>
<!--                        <div class="select-container-item">-->
<!--                            <span>层</span>-->
<!--                            <label><input id="sourceLev" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>-->
<!--                        </div>-->
                    </div>
                </div>
                <!-- 目标站/目标库位 选择 -->
                <div id="target-select" class="operator-item">
                    <span class="select-title">目标站</span>
                    <div class="select-container">
                        <div class="select-container-item">
                            <span>工位1目标站</span>
                            <label><input id="staNo" type="number" name="points" min="0" value="0"/></label>
                        </div>
<!--                        <div class="select-container-item">-->
<!--                            <span>排</span>-->
<!--                            <label><input id="row" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>-->
<!--                        </div>-->
                        <div class="select-container-item">
                            <span>工位2目标站</span>
                            <label><input id="bay" type="number" name="points" min="0" style="background-color: #a9eeff" value="0" /></label>
                        </div>
<!--                        <div class="select-container-item">-->
<!--                            <span>层</span>-->
<!--                            <label><input id="lev" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>-->
<!--                        </div>-->
                    </div>
                </div>
            </div>
            <!-- 设备任务操作 -->
            <div class="task-operator">
                <fieldset>
                    <legend>手动操作</legend>
                    <div class="button-group">
                        <button class="item" onclick="put()">取放货</button>
<!--                        <button class="item" onclick="take()">取货</button>-->
<!--                        <button class="item" onclick="stockMove()">放货</button>-->
<!--                        <button class="item" onclick="siteMove()">站到站</button>-->
                        <!--                <button class="item" onclick="bacOrigin()">回原点</button>-->
                        <!--                <button class="item" onclick="reverseOrigin()">反原点</button>-->
                        <!--                <button class="item" onclick="coorMove()">坐标移行</button>-->
                        <button class="item" onclick="taskComplete1()">工位1任务完成</button>
                        <button class="item" onclick="taskComplete2()">工位2任务完成</button>
                        <!--                <button class="item" onclick="pause()">暂停</button>-->
                        <!--                <button class="item" onclick="boot()">启动</button>-->
<!--                        <button class="item" onclick="clearCommand()">清除命令</button>-->
<!--                        <button class="item" onclick="handleReset()">复位</button>-->
                    </div>
                </fieldset>
            </div>
        </div>
        <!-- 堆垛机日志输出 -->
        <div class="rgv-output-board">
            <textarea id="rgv-output"></textarea>
        </div>
    </div>
</div>
</body>
<script>
    // 空白行数
    var rgvStateTableBlankRows = 0;
    var rgvMsgTableBlankRows = 0;
    // 实际行数
    var rgvStateTableFullRows = 0;
    var rgvMsgTableFullRows = 0;
    // 初始化
    var rgvOutputDom = document.getElementById("rgv-output");
    $(document).ready(function() {
        // getCommandLog();
        initRgvStateTable();
        getRgvStateInfo();
        initRgvMsgTable();
        getRgvMsgInfo();
        operatorBlockShow();
    });
    // 数据更新
    setInterval(function () {
        getRgvStateInfo();
        getRgvMsgInfo();
        // getCommandLog();
    },1000);
    setInterval(function () {
        getRgvOutput();
        operatorBlockShow();
        // initDemo();
    },500);
    // 判断手动操作模块是否可用
    function operatorBlockShow() {
        if (parent.systemRunning) {
            $('.rgv-operation').css("opacity", "0.5");
            $('.rgv-operation-shade').show();
            $('.rgv-operation-shade-span').show();
        }  else {
            $('.rgv-operation').css("opacity", "1");
            $('.rgv-operation-shade').hide();
            $('.rgv-operation-shade-span').hide();
        }
    }
    // 获取RGV执行中的命令
    function getCommandLog() {
        $.ajax({
            url: baseUrl + "/rgv/command/ongoing",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                if (res.code === 200) {
                    var commands = res.data;
                    for (var i=0; i<commands.length;i++){
                        $("#rgv"+commands[i].rgvNo).val(commands[i].command);
                    }
                } else if (res.code === 403) {
                    window.location.href = baseUrl + "/login";
                } else {
                    console.log(res.msg);
                }
            }
        })
    }
    // 堆垛机信息表获取 ---- 表一
    function getRgvStateInfo() {
        var tableEl = $('#rgv-state-table');
        $.ajax({
            url: baseUrl+ "/rgv/table/rgv/state",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                console.log(res)
                if (res.code === 200){
                    var table = res.data;
                    if (table.length > rgvStateTableBlankRows && table.length !== rgvStateTableFullRows) {
                        initRgvStateTable(table.length-rgvStateTableBlankRows);
                        rgvStateTableFullRows = 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].rgvNo);
                        setVal(tr.children("td").eq(1), table[i-1].statusType);
                        setVal(tr.children("td").eq(2), table[i-1].status);
                        setVal(tr.children("td").eq(3), table[i-1].workNo1);
                        setVal(tr.children("td").eq(4), table[i-1].status1);
                        setVal(tr.children("td").eq(5), table[i-1].loading1);
                        setVal(tr.children("td").eq(6), table[i-1].rgvPos1);
                        setVal(tr.children("td").eq(7), table[i-1].walkPos);
                        // setVal(tr.children("td").eq(8), table[i-1].workNo2);
                        // setVal(tr.children("td").eq(9), table[i-1].status2);
                        // setVal(tr.children("td").eq(10), table[i-1].loading2);
                        setVal(tr.children("td").eq(8), table[i-1].warnCode);
                        setVal(tr.children("td").eq(9), table[i-1].alarm);
                        // setVal(tr.children("td").eq(10), table[i-1].pakMk);
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
                }  else {
                    console.log(res.msg);
                }
            }
        });
    }
    // 堆垛机数据表获取 ---- 表二
    function getRgvMsgInfo() {
        var tableEl = $('#rgv-msg-table');
        $.ajax({
            url: baseUrl+ "/rgv/table/rgv/msg",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                if (res.code === 200){
                    var table = res.data;
                    if (table.length > rgvStateTableBlankRows && table.length !== rgvMsgTableFullRows) {
                        initRgvStateTable(table.length-rgvStateTableBlankRows);
                        rgvMsgTableFullRows = 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].rgvNo);
                        setVal(tr.children("td").eq(1), table[i-1].workNo);
                        setVal(tr.children("td").eq(2), table[i-1].status);
                        setVal(tr.children("td").eq(3), table[i-1].sourceStaNo);
                        setVal(tr.children("td").eq(4), table[i-1].staNo);
                        setVal(tr.children("td").eq(5), table[i-1].sourceLocNo);
                        setVal(tr.children("td").eq(6), table[i-1].locNo);
                        // setVal(tr.children("td").eq(7), table[i-1].xspeed);
                        // setVal(tr.children("td").eq(8), table[i-1].yspeed);
                        // setVal(tr.children("td").eq(9), table[i-1].zspeed);
                        // setVal(tr.children("td").eq(10), table[i-1].xdistance);
                        // setVal(tr.children("td").eq(11), table[i-1].ydistance);
                        // setVal(tr.children("td").eq(12), table[i-1].xduration);
                        // setVal(tr.children("td").eq(13), table[i-1].yduration);
                    }
                } else if (res.code === 403){
                    window.location.href = baseUrl+"/login";
                }  else {
                    console.log(res.msg);
                }
            }
        });
    }
    // 堆垛机手动操作区 -----------------------------------------------------------------------
    function getReqParam() {
        var rgvNo = $('input[name="rgvSelect"]:checked').val();
        var sourceStaNo = $('#sourceStaNo').val();
        var sourceRow = $('#sourceRow').val();
        var sourceBay = $('#sourceBay').val();
        var sourceLev = $('#sourceLev').val();
        var staNo = $('#staNo').val();
        var row = $('#row').val();
        var bay = $('#bay').val();
        var lev = $('#lev').val();
        return {
            rgvNo: rgvNo,
            sourceStaNo1: sourceStaNo,
            sourceRow: sourceRow,
            sourceStaNo2: sourceBay,
            sourceLev: sourceLev,
            staNo1: staNo,
            row: row,
            staNo2: bay,
            lev: lev
        };
    }
    // 入库
    function put() {
        http.post(baseUrl+"/rgv/operator/put", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 出库
    function take() {
        http.post(baseUrl+"/rgv/operator/take", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 库位转移
    function stockMove() {
        http.post(baseUrl+"/rgv/operator/stockMove", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 站到站
    function siteMove() {
        http.post(baseUrl+"/rgv/operator/siteMove", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 坐标移动
    function coorMove() {
        http.post(baseUrl+"/rgv/operator/coorMove", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 回原点
    function bacOrigin() {
        http.post(baseUrl+"/rgv/operator/bacOrigin", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 回原点
    function reverseOrigin() {
        http.post(baseUrl+"/rgv/operator/reverseOrigin", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 任务完成
    function taskComplete1() {
        http.post(baseUrl+"/rgv/operator/taskComplete1", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 任务完成
    function taskComplete2() {
        http.post(baseUrl+"/rgv/operator/taskComplete2", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    function lock() {
        http.post(baseUrl+"/rgv/lock", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 暂停
    function pause() {
        http.post(baseUrl+"/rgv/operator/pause", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 启动
    function boot() {
        http.post(baseUrl+"/rgv/operator/boot", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 清除命令
    function clearCommand() {
        http.post(baseUrl+"/rgv/operator/clearCommand", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 手动复位
    function handleReset() {
        http.post(baseUrl+"/rgv/operator/handleReset", getReqParam(), function (res) {
            layer.msg(res.msg);
        });
    }
    // 输送设备日志输出 -----------------------------------------------------------------------
    function getRgvOutput() {
        $.ajax({
            url: baseUrl + "/rgv/output/site",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                console.log(res)
                if (res.code === 200) {
                    rgvOutput(res.data);
                } else if (res.code === 403) {
                    window.location.href = baseUrl + "/login";
                } else {
                    console.log(res.msg);
                }
            }
        })
    }
    // ------------------------------------------------------------------------------------------------
    // 堆垛机信息表获取  ----- 表一
    function initRgvStateTable(row) {
        var line;
        if (row === undefined){
            var one = $('#rgv-state-table thead').height();
            var total = $('.rgv-state').height();
            var count = total / one;
            count = parseInt(count) - 1;
            rgvStateTableBlankRows = count;
            line = count;
        } else {
            line = row;
        }
        var html = "";
        for (var 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" +
                "     </tr>\n";
        }
        $('#rgv-state-table tbody').after(html);
    }
    // 堆垛机数据表获取  ----- 表二
    function initRgvMsgTable(row) {
        var line;
        if (row === undefined){
            var one = $('#rgv-msg-table thead').height();
            var total = $('.rgv-msg').height();
            var count = total / one;
            count = parseInt(count) - 1;
            rgvMsgTableBlankRows = count;
            line = count;
        } else {
            line = row;
        }
        var html = "";
        for (var 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" +
                "     </tr>\n";
        }
        $('#rgv-msg-table tbody').after(html);
    }
    // 日志输出框
    function rgvOutput(content){
        rgvOutputDom.value += content;
        rgvOutputDom.scrollTop = rgvOutputDom.scrollHeight;
    }
</script>
</html>