#
Junjie
2025-11-20 4e005e4936039fca16bfd1679942daa416a21986
#
7个文件已添加
20个文件已修改
1039 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/RgvController.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/RgvCommandMoveParam.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/RgvCommandTaskCompleteParam.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/RgvCommandTransportParam.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/RgvStateTableVo.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasRgv.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/CodeBuilder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateSolution.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateUtils.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RgvModeType.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RgvTaskModeType.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/RgvCommand.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/ZyCrnConnectDriver.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/ZyRgvConnectDriver.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/ZyStationConnectDriver.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/entity/ZyRgvStatusEntity.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/fake/ZyCrnFakeConnect.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/fake/ZyRgvFakeConnect.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/real/ZyCrnRealConnect.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/real/ZyRgvRealConnect.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/real/ZyStationRealConnect.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/RgvThread.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZyRgvThread.java 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZyStationThread.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/components/WatchRgvCard.js 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/watch/console.html 73 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/RgvController.java
New file
@@ -0,0 +1,159 @@
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.zy.asrs.domain.param.RgvCommandMoveParam;
import com.zy.asrs.domain.param.RgvCommandTaskCompleteParam;
import com.zy.asrs.domain.param.RgvCommandTransportParam;
import com.zy.asrs.domain.vo.RgvStateTableVo;
import com.zy.asrs.entity.BasRgv;
import com.zy.asrs.entity.BasRgvErr;
import com.zy.asrs.service.BasRgvService;
import com.zy.asrs.service.BasRgvErrService;
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.RgvStatusType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.Task;
import com.zy.core.model.command.RgvCommand;
import com.zy.core.model.protocol.RgvProtocol;
import com.zy.core.thread.RgvThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@Slf4j
@RestController
@RequestMapping("/rgv")
public class RgvController {
    @Autowired
    private BasRgvService basRgvService;
    @Autowired
    private BasRgvErrService basRgvErrService;
    @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());
            list.add(vo);
            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, basRgv.getRgvNo());
            if (rgvThread == null) {
                continue;
            }
            RgvProtocol rgvProtocol = rgvThread.getStatus();
            if (rgvProtocol == null) {
                continue;
            }
            vo.setTaskNo(rgvProtocol.getTaskNo());
            RgvModeType modeType = RgvModeType.get(rgvProtocol.getMode());
            vo.setMode(modeType == null ? "" : modeType.desc);
            RgvStatusType statusType = RgvStatusType.get(rgvProtocol.getStatus() == null ? null : rgvProtocol.getStatus());
            vo.setStatus(statusType == null ? "" : statusType.desc);
            vo.setLoading(rgvProtocol.getLoaded() != null && rgvProtocol.getLoaded() == 1 ? "有物" : "无物");
            vo.setTrackSiteNo(String.valueOf(rgvProtocol.getRgvPos()));
            String deviceStatus = "";
            if (modeType == RgvModeType.AUTO) {
                deviceStatus = "AUTO";
            }
            if (rgvProtocol.getTaskNo() != null && rgvProtocol.getTaskNo() > 0) {
                deviceStatus = "WORKING";
            }
            if(rgvProtocol.getAlarm() > 0) {
                deviceStatus = "ERROR";
            }
            vo.setDeviceStatus(deviceStatus);
            vo.setWarnCode(String.valueOf(rgvProtocol.getAlarm()));
            if (rgvProtocol.getAlarm() != null && rgvProtocol.getAlarm() > 0) {
                BasRgvErr err = basRgvErrService.selectById(rgvProtocol.getAlarm());
                vo.setAlarm(err == null ? "未知异常" : err.getErrName());
                vo.setDeviceStatus("ERROR");
            }
        }
        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());
    }
    @PostMapping("/command/transport")
    public R rgvCommandTransport(@RequestBody RgvCommandTransportParam param) {
        if (Cools.isEmpty(param) || param.getRgvNo() == null || param.getTargetPos() == null) {
            return R.error("缺少参数");
        }
        Integer rgvNo = param.getRgvNo();
        Integer sourcePos = param.getSourcePos();
        Integer targetPos = param.getTargetPos();
        RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvNo);
        if (rgvThread == null) {
            return R.error("线程不存在");
        }
        RgvCommand command = rgvThread.getTransportCommand(9999, rgvNo, sourcePos, targetPos);
        MessageQueue.offer(SlaveType.Rgv, rgvNo, new Task(2, command));
        return R.ok();
    }
    @PostMapping("/command/move")
    public R rgvCommandMove(@RequestBody RgvCommandMoveParam param) {
        if (Cools.isEmpty(param) || param.getRgvNo() == null || param.getTargetPos() == null) {
            return R.error("缺少参数");
        }
        Integer rgvNo = param.getRgvNo();
        Integer targetPos = param.getTargetPos();
        RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvNo);
        if (rgvThread == null) {
            return R.error("线程不存在");
        }
        RgvCommand command = rgvThread.getMoveCommand(9999, rgvNo, targetPos);
        MessageQueue.offer(SlaveType.Rgv, rgvNo, new Task(2, command));
        return R.ok();
    }
    @PostMapping("/command/taskComplete")
    public R rgvCommandTaskComplete(@RequestBody RgvCommandTaskCompleteParam param) {
        if (Cools.isEmpty(param) || param.getRgvNo() == null) {
            return R.error("缺少参数");
        }
        Integer rgvNo = param.getRgvNo();
        RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvNo);
        if (rgvThread == null) {
            return R.error("线程不存在");
        }
        RgvCommand command = rgvThread.getResetCommand(rgvNo);
        MessageQueue.offer(SlaveType.Rgv, rgvNo, new Task(2, command));
        return R.ok();
    }
}
src/main/java/com/zy/asrs/domain/param/RgvCommandMoveParam.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.domain.param;
import lombok.Data;
@Data
public class RgvCommandMoveParam {
    private Integer rgvNo;
    private Integer targetPos;
}
src/main/java/com/zy/asrs/domain/param/RgvCommandTaskCompleteParam.java
New file
@@ -0,0 +1,10 @@
package com.zy.asrs.domain.param;
import lombok.Data;
@Data
public class RgvCommandTaskCompleteParam {
    private Integer rgvNo;
}
src/main/java/com/zy/asrs/domain/param/RgvCommandTransportParam.java
New file
@@ -0,0 +1,14 @@
package com.zy.asrs.domain.param;
import lombok.Data;
@Data
public class RgvCommandTransportParam {
    private Integer rgvNo;
    private Integer sourcePos;
    private Integer targetPos;
}
src/main/java/com/zy/asrs/domain/vo/RgvStateTableVo.java
New file
@@ -0,0 +1,26 @@
package com.zy.asrs.domain.vo;
import lombok.Data;
@Data
public class RgvStateTableVo {
    private Integer rgvNo;
    private Integer taskNo;
    private String mode;
    private String status;
    private String loading;
    private String trackSiteNo;
    private String deviceStatus;
    private String warnCode;
    private String alarm;
}
src/main/java/com/zy/asrs/entity/BasRgv.java
@@ -24,7 +24,7 @@
     * 编号
     */
    @ApiModelProperty(value= "编号")
    @TableId(value = "rgv_no", type = IdType.AUTO)
    @TableId(value = "rgv_no", type = IdType.INPUT)
    @TableField("rgv_no")
    private Integer rgvNo;
src/main/java/com/zy/common/CodeBuilder.java
@@ -12,10 +12,10 @@
        CoolGenerator generator = new CoolGenerator();
        // mysql
        generator.sqlOsType = SqlOsType.MYSQL;
        generator.url="localhost:3306/wcs";
        generator.url="192.168.4.11:3306/wcs";
        generator.username="root";
        generator.password="root";
        generator.table="asr_bas_devp";
        generator.table="asr_bas_rgv_opt";
        // sqlserver
//        generator.sqlOsType = SqlOsType.SQL_SERVER;
//        generator.url="127.0.0.1:1433;databasename=tzskasrs";
src/main/java/com/zy/common/utils/NavigateSolution.java
@@ -63,6 +63,51 @@
        return navigateNodeList;
    }
    public List<List<NavigateNode>> getRgvTrackMap() {
        BasMapService basMapService = SpringUtils.getBean(BasMapService.class);
        BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", 1));
        if (basMap == null) {
            throw new CoolException("地图不存在");
        }
        List<List<JSONObject>> dataList = JSON.parseObject(basMap.getData(), List.class);
        List<List<NavigateNode>> navigateNodeList = new ArrayList<>();
        for (int i = 0; i < dataList.size(); i++) {
            List<JSONObject> row = dataList.get(i);
            List<NavigateNode> navigateNodeRow = new ArrayList<>();
            for (int j = 0; j < row.size(); j++) {
                JSONObject map = row.get(j);
                NavigateNode navigateNode = new NavigateNode(i, j);
                String nodeType = map.getString("type");
                if(nodeType == null) {
                    navigateNode.setValue(MapNodeType.DISABLE.id);
                }else if(nodeType.equals("rgv")){
                    navigateNode.setValue(MapNodeType.NORMAL_PATH.id);
                    JSONObject valueObj = JSON.parseObject(map.getString("value"));
                    //RGV暂不控制行走方向,默认上下左右都可走
                    List<String> directionList = new ArrayList<>();
                    directionList.add("top");
                    directionList.add("bottom");
                    directionList.add("left");
                    directionList.add("right");
                    navigateNode.setDirectionList(directionList);
                }else {
                    navigateNode.setValue(MapNodeType.DISABLE.id);
                }
                navigateNode.setNodeType(nodeType);
                navigateNode.setNodeValue(map.getString("value"));
                navigateNodeRow.add(navigateNode);
            }
            navigateNodeList.add(navigateNodeRow);
        }
        return navigateNodeList;
    }
    public NavigateNode astarSearchJava(List<List<NavigateNode>> map, NavigateNode start, NavigateNode end) {
        // 清理上次搜索的状态,防止复用实例导致记录残留
        this.Open.clear();
@@ -184,6 +229,21 @@
        return null;
    }
    public NavigateNode findTrackSiteNoNavigateNode(List<List<NavigateNode>> map, int trackSiteNo) {
        for(int x = 0; x < map.size(); x++) {
            for(int y = 0; y < map.get(0).size(); y++) {
                NavigateNode node = map.get(x).get(y);
                if("rgv".equals(node.getNodeType())) {
                    JSONObject valueObj = JSON.parseObject(node.getNodeValue());
                    if(valueObj.getInteger("trackSiteNo") == trackSiteNo) {
                        return node;
                    }
                }
            }
        }
        return null;
    }
    //------------------A*启发函数------------------//
    //计算通过现在的结点的位置和最终结点的位置计算H值(曼哈顿法:坐标分别取差值相加)
src/main/java/com/zy/common/utils/NavigateUtils.java
@@ -66,4 +66,56 @@
        return fitlerList;
    }
    public synchronized List<NavigateNode> calcByTrackSiteNo(Integer startTrackSiteNo, Integer endTrackSiteNo) {
        NavigateSolution navigateSolution = new NavigateSolution();
        List<List<NavigateNode>> rgvTrackMap = navigateSolution.getRgvTrackMap();
        NavigateNode startNode = navigateSolution.findTrackSiteNoNavigateNode(rgvTrackMap, startTrackSiteNo);
        if (startNode == null){
            throw new CoolException("未找到该 起点 对应的节点");
        }
        NavigateNode endNode = navigateSolution.findTrackSiteNoNavigateNode(rgvTrackMap, endTrackSiteNo);
        if (endNode == null){
            throw new CoolException("未找到该 终点 对应的节点");
        }
        NavigateNode res_node = navigateSolution.astarSearchJava(rgvTrackMap, startNode, endNode);
        if (res_node == null) {
            throw new CoolException("未找到该路径");
        }
        ArrayList<NavigateNode> list = new ArrayList<>();
        // 使用 visited 集合防止父链出现环导致死循环,同时设置安全步数上限
        HashSet<NavigateNode> visited = new HashSet<>();
        int maxSteps = rgvTrackMap.size() * rgvTrackMap.get(0).size() + 5; // 安全上限
        int steps = 0;
        while (res_node != null && visited.add(res_node) && steps++ < maxSteps) {
            list.add(res_node);
            res_node = res_node.getFather();//迭代操作
        }
        if (steps >= maxSteps) {
            throw new CoolException("路径回溯超出安全上限,疑似存在父链循环");
        }
        Collections.reverse(list);
        //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多)
        for (NavigateNode navigateNode : list) {
            //父节点设置为null,不影响计算结果,不影响后续操作。
            //此操作仅为后续排查处理提供视觉方便。
            navigateNode.setFather(null);
        }
        //去重
        HashSet<Integer> set = new HashSet<>();
        List<NavigateNode> fitlerList = new ArrayList<>();
        for(NavigateNode navigateNode : list){
            JSONObject valuObject = JSON.parseObject(navigateNode.getNodeValue());
            if(set.add(valuObject.getInteger("trackSiteNo"))){
                fitlerList.add(navigateNode);
            }
        }
        return fitlerList;
    }
}
src/main/java/com/zy/core/enums/RgvModeType.java
@@ -3,9 +3,9 @@
public enum RgvModeType {
    NONE(-1, "离线"),
    STOP(0, "关机"),
    HAND(1, "手动"),
    HALF_AUTO(2, "半自动"),
    HAND(0, "手动"),
    COMPUTER(1, "电脑模式"),
    STOP(2, "停机"),
    AUTO(3, "自动"),
    OTHER(100, "其它"),
    ;
src/main/java/com/zy/core/enums/RgvTaskModeType.java
New file
@@ -0,0 +1,46 @@
package com.zy.core.enums;
public enum RgvTaskModeType {
    NONE(0),    // 无
    FETCH(1),    // 取货
    PUT(2),    // 放货
    FETCH_PUT(3),    // 取放货
    X_MOVE(4),    // 站位移转
//    Y_MOVE(5),    // 站位移转
//    XY_MOVE(6),    // 站位移转
    GO_ORIGIN(7),    // 回原点
//    BACK_ORIGIN(8),      // 回反原点
//    CLEAR(9),       // 清错
    ;
    public Integer id;
    RgvTaskModeType(Integer id) {
        this.id = id;
    }
    public static RgvTaskModeType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (RgvTaskModeType type : RgvTaskModeType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static RgvTaskModeType get(RgvTaskModeType type) {
        if (null == type) {
            return null;
        }
        for (RgvTaskModeType rgvTaskModeType : RgvTaskModeType.values()) {
            if (rgvTaskModeType == type) {
                return rgvTaskModeType;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/model/command/RgvCommand.java
@@ -5,15 +5,18 @@
@Data
public class RgvCommand {
    private Integer rgvNo = 0;
    private Integer rgvNo;
    private Short ackFinish = 0;
    // 任务完成确认位
    private Integer ackFinish = 0;
    private Short taskNo = 0;
    private Integer taskNo;
    private Short taskMode = 0;
    private Integer taskMode;
    private Short targetPos = 0;
    private Integer sourcePos;
    private Integer targetPos;
    
    private Short command = 0;
    private Integer command;
}
src/main/java/com/zy/core/network/ZyCrnConnectDriver.java
@@ -18,12 +18,10 @@
public class ZyCrnConnectDriver implements ThreadHandler{
    private boolean connected = false;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    private ZyCrnConnectApi zyCrnConnectApi;
    public ZyCrnConnectDriver(SiemensS7Net siemensS7Net, DeviceConfig deviceConfig) {
        this.siemensNet = siemensS7Net;
    public ZyCrnConnectDriver(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
@@ -46,7 +44,7 @@
    @Override
    public boolean connect() {
        if (deviceConfig.getFake() == 0) {
            zyCrnConnectApi = new ZyCrnRealConnect(siemensNet, deviceConfig);
            zyCrnConnectApi = new ZyCrnRealConnect(deviceConfig);
        }else {
            zyCrnConnectApi = new ZyCrnFakeConnect(deviceConfig);
        }
src/main/java/com/zy/core/network/ZyRgvConnectDriver.java
@@ -1,6 +1,5 @@
package com.zy.core.network;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.core.ThreadHandler;
import com.zy.core.model.CommandResponse;
@@ -14,12 +13,10 @@
@Slf4j
public class ZyRgvConnectDriver implements ThreadHandler {
    private boolean connected = false;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    private ZyRgvConnectApi zyRgvConnectApi;
    public ZyRgvConnectDriver(SiemensS7Net siemensS7Net, DeviceConfig deviceConfig) {
        this.siemensNet = siemensS7Net;
    public ZyRgvConnectDriver(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
@@ -41,7 +38,7 @@
    @Override
    public boolean connect() {
        if (deviceConfig.getFake() == 0) {
            zyRgvConnectApi = new ZyRgvRealConnect(siemensNet, deviceConfig);
            zyRgvConnectApi = new ZyRgvRealConnect(deviceConfig);
        } else {
            zyRgvConnectApi = new ZyRgvFakeConnect(deviceConfig);
        }
src/main/java/com/zy/core/network/ZyStationConnectDriver.java
@@ -19,12 +19,10 @@
public class ZyStationConnectDriver implements ThreadHandler {
    private boolean connected = false;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    private ZyStationConnectApi zyStationConnectApi;
    public ZyStationConnectDriver(SiemensS7Net siemensS7Net, DeviceConfig deviceConfig) {
        this.siemensNet = siemensS7Net;
    public ZyStationConnectDriver(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
@@ -46,7 +44,7 @@
    @Override
    public boolean connect() {
        if (deviceConfig.getFake() == 0) {
            zyStationConnectApi = new ZyStationRealConnect(siemensNet, deviceConfig);
            zyStationConnectApi = new ZyStationRealConnect(deviceConfig);
        } else {
            zyStationConnectApi = new ZyStationFakeConnect(deviceConfig);
        }
src/main/java/com/zy/core/network/entity/ZyRgvStatusEntity.java
@@ -5,6 +5,8 @@
@Data
public class ZyRgvStatusEntity {
    private Integer rgvNo;
    private Integer mode;
    private Integer taskNo;
@@ -12,7 +14,14 @@
    private Integer status;
    private Integer rgvPos;
    /**
     * 走行在定位
     * 0 = 在定位
     * 1 = 不在定位
     */
    public Integer walkPos;
    private Integer loaded;
    private Integer alarm;
src/main/java/com/zy/core/network/fake/ZyCrnFakeConnect.java
@@ -141,7 +141,7 @@
        }
    }
        private void sleep(long ms) {
    private void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
src/main/java/com/zy/core/network/fake/ZyRgvFakeConnect.java
@@ -1,15 +1,26 @@
package com.zy.core.network.fake;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.NavigateUtils;
import com.zy.core.enums.RgvModeType;
import com.zy.core.enums.RgvStatusType;
import com.zy.core.enums.RgvTaskModeType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.RgvCommand;
import com.zy.core.network.api.ZyRgvConnectApi;
import com.zy.core.network.entity.ZyRgvStatusEntity;
import com.zy.core.network.entity.ZyStationStatusEntity;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ZyRgvFakeConnect implements ZyRgvConnectApi {
    private ZyRgvStatusEntity status;
    private final DeviceConfig deviceConfig;
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
@@ -38,18 +49,124 @@
    @Override
    public CommandResponse sendCommand(RgvCommand command) {
        CommandResponse response = new CommandResponse(true);
        executor.submit(() -> {
            if (command.getTaskMode() != null && command.getTaskMode() == 1) {
                status.setTaskNo((int) command.getTaskNo());
                status.setStatus(1);
                try { Thread.sleep(300); } catch (InterruptedException ignored) {}
                status.setRgvPos((int) command.getTargetPos());
                status.setStatus(0);
            } else if (command.getTaskMode() != null && command.getTaskMode() == 0) {
                status.setTaskNo(0);
                status.setStatus(0);
            }
        });
        if (command.getTaskMode() == RgvTaskModeType.FETCH_PUT.id) {
            //取放货
            executor.submit(() -> commandTake(command));
        } else if (command.getTaskMode() == RgvTaskModeType.X_MOVE.id) {
            //移动
            executor.submit(() -> commandMove(command));
        }else if (command.getTaskMode() == RgvTaskModeType.NONE.id) {
            //复位
            executor.submit(() -> commandTaskComplete(command));
        }
        return response;
    }
    private void commandTake(RgvCommand command) {
        int taskNo = command.getTaskNo();
        int taskMode = command.getTaskMode();
        int sourcePos = command.getSourcePos();
        int targetPos = command.getTargetPos();
        NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class);
        if (navigateUtils == null) {
            return;
        }
        List<NavigateNode> navigateNodes = null;
        try {
            navigateNodes = navigateUtils.calcByTrackSiteNo(status.getRgvPos(), sourcePos);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (navigateNodes == null) {
            return;
        }
        List<NavigateNode> targetNavigateNodes = null;
        try {
            targetNavigateNodes = navigateUtils.calcByTrackSiteNo(sourcePos, targetPos);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (targetNavigateNodes == null) {
            return;
        }
        status.setTaskNo(taskNo);
        status.setStatus(RgvStatusType.FETCHING.id);
        for (int i = 0; i < navigateNodes.size(); i++) {
            NavigateNode navigateNode = navigateNodes.get(i);
            JSONObject valueObject = JSON.parseObject(navigateNode.getNodeValue());
            Integer currentTrackSiteNo = valueObject.getInteger("trackSiteNo");
            status.setRgvPos(currentTrackSiteNo);
            sleep(1000);
        }
        status.setStatus(RgvStatusType.PUTTING.id);
        status.setLoaded(1);
        sleep(1000);
        for (int i = 0; i < targetNavigateNodes.size(); i++) {
            NavigateNode navigateNode = targetNavigateNodes.get(i);
            JSONObject valueObject = JSON.parseObject(navigateNode.getNodeValue());
            Integer currentTrackSiteNo = valueObject.getInteger("trackSiteNo");
            status.setRgvPos(currentTrackSiteNo);
            sleep(1000);
        }
        sleep(1000);
        status.setStatus(RgvStatusType.WAITING.id);
    }
    private void commandMove(RgvCommand command) {
        int taskNo = command.getTaskNo();
        int taskMode = command.getTaskMode();
        int targetPos = command.getTargetPos();
        NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class);
        if (navigateUtils == null) {
            return;
        }
        List<NavigateNode> navigateNodes = null;
        try {
            navigateNodes = navigateUtils.calcByTrackSiteNo(status.getRgvPos(), targetPos);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (navigateNodes == null) {
            return;
        }
        status.setTaskNo(taskNo);
        status.setStatus(RgvStatusType.WORKING.id);
        for (int i = 0; i < navigateNodes.size(); i++) {
            NavigateNode navigateNode = navigateNodes.get(i);
            JSONObject valueObject = JSON.parseObject(navigateNode.getNodeValue());
            Integer currentTrackSiteNo = valueObject.getInteger("trackSiteNo");
            status.setRgvPos(currentTrackSiteNo);
            sleep(1000);
        }
        status.setStatus(RgvStatusType.WAITING.id);
    }
    private void commandTaskComplete(RgvCommand command) {
        status.setTaskNo(0);
        status.setStatus(RgvStatusType.IDLE.id);
    }
    private void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
src/main/java/com/zy/core/network/real/ZyCrnRealConnect.java
@@ -2,6 +2,7 @@
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.core.common.DateUtils;
@@ -25,13 +26,13 @@
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    public ZyCrnRealConnect(SiemensS7Net siemensS7Net, DeviceConfig deviceConfig) {
        this.siemensNet = siemensS7Net;
    public ZyCrnRealConnect(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
    public boolean connect() {
        boolean connected = false;
        siemensNet = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
        OperateResult connect = siemensNet.ConnectServer();
        if(connect.IsSuccess){
            connected = true;
@@ -220,7 +221,7 @@
                    null,    // 修改人员
                    null,    // 备注
                    JSON.toJSONString(command),    // 指令
                    JSON.toJSONString(command),    // 系统状态
                    JSON.toJSONString(getStatus()),    // 系统状态
                    1,    // 下发状态{0:未下发,1:已下发}
                    JSON.toJSONString(response)    // 响应
            );
src/main/java/com/zy/core/network/real/ZyRgvRealConnect.java
@@ -1,38 +1,146 @@
package com.zy.core.network.real;
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import java.text.MessageFormat;
import java.util.Date;
import com.alibaba.fastjson.JSON;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasCrnpOpt;
import com.zy.asrs.entity.BasRgv;
import com.zy.asrs.entity.BasRgvOpt;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.entity.DeviceDataLog;
import com.zy.asrs.service.BasCrnpOptService;
import com.zy.asrs.service.BasRgvOptService;
import com.zy.asrs.service.BasRgvService;
import com.zy.asrs.service.DeviceDataLogService;
import com.zy.asrs.utils.Utils;
import com.zy.core.News;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.RgvStatusType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.RgvCommand;
import com.zy.core.model.protocol.RgvProtocol;
import com.zy.core.network.api.ZyRgvConnectApi;
import com.zy.core.network.entity.ZyRgvStatusEntity;
public class ZyRgvRealConnect implements ZyRgvConnectApi {
    private final SiemensS7Net siemensNet;
    private final DeviceConfig deviceConfig;
    public ZyRgvRealConnect(SiemensS7Net siemensNet, DeviceConfig deviceConfig) {
        this.siemensNet = siemensNet;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    public ZyRgvRealConnect(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
    @Override
    public boolean connect() {
        return true;
        boolean result = false;
        siemensNet = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
        OperateResult connect = siemensNet.ConnectServer();
        if(connect.IsSuccess){
            result = true;
            OutputQueue.RGV.offer(MessageFormat.format( "【{0}】RGV plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort()));
            News.info("RGV plc连接成功 ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort());
        } else {
            OutputQueue.RGV.offer(MessageFormat.format("【{0}】RGV plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort()));
            News.error("RGV plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort());
        }
//        siemensNet.ConnectClose();
        return result;
    }
    @Override
    public boolean disconnect() {
        siemensNet.ConnectClose();
        return true;
    }
    @Override
    public ZyRgvStatusEntity getStatus() {
        try {
            OperateResultExOne<byte[]> result = siemensNet.Read("DB101.0", (short) 30);
            if (result.IsSuccess) {
                ZyRgvStatusEntity zyRgvStatusEntity = new ZyRgvStatusEntity();
                zyRgvStatusEntity.setRgvNo(deviceConfig.getDeviceNo());
                zyRgvStatusEntity.setMode((int) siemensNet.getByteTransform().TransInt16(result.Content, 0));
                zyRgvStatusEntity.setStatus((int) siemensNet.getByteTransform().TransInt16(result.Content, 2));
                zyRgvStatusEntity.setTaskNo((int) siemensNet.getByteTransform().TransInt16(result.Content, 4));
                // zyRgvStatusEntity.setStatus((int) siemensNet.getByteTransform().TransInt16(result.Content, 6));
                zyRgvStatusEntity.setLoaded((int) siemensNet.getByteTransform().TransInt16(result.Content, 8));
                zyRgvStatusEntity.setRgvPos((int) siemensNet.getByteTransform().TransInt16(result.Content, 10));
                zyRgvStatusEntity.setWalkPos((int) siemensNet.getByteTransform().TransInt16(result.Content, 12));
                zyRgvStatusEntity.setAlarm((int) siemensNet.getByteTransform().TransInt16(result.Content, 14));
                OutputQueue.RGV.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功", DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
                return zyRgvStatusEntity;
            } else {
                OutputQueue.RGV.offer(MessageFormat.format("【{0}】读取RGV plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort()));
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.RGV.offer(MessageFormat.format("【{0}】读取RGV plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort()));
        }
        return null;
    }
    @Override
    public CommandResponse sendCommand(RgvCommand command) {
        return new CommandResponse(false, "not implemented");
        CommandResponse response = new CommandResponse(false);
        try {
            if (null == command) {
                response.setMessage("RGV写入命令为空");
                return response;
            }
            short[] array = new short[5];
            array[0] = command.getAckFinish().shortValue();
            array[1] = command.getTaskNo().shortValue();
            array[2] = command.getTaskMode().shortValue();
            array[3] = command.getSourcePos().shortValue();
            array[4] = command.getTargetPos().shortValue();
            OperateResult result = siemensNet.Write("DB100.0", array);
            if (result != null && result.IsSuccess) {
                News.info("RGV 命令下发[id:{}] >>>>> {}", deviceConfig.getDeviceNo(), JSON.toJSON(command));
                OutputQueue.RGV.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), JSON.toJSON(command)));
                response.setResult(true);
                return response;
            } else {
                OutputQueue.RGV.offer(MessageFormat.format("【{0}】写入RGV plc数据失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort()));
                News.error("写入RGV plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getId(), deviceConfig.getIp(), deviceConfig.getPort());
                response.setMessage("写入RGV plc数据失败");
                return response;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 日志记录
            BasRgvOptService bean = SpringUtils.getBean(BasRgvOptService.class);
            BasRgvOpt basRgvOpt = new BasRgvOpt(
                    command.getTaskNo(),    // 任务号
                    command.getRgvNo(),    // RGV[非空]
                    new Date(),    // 下发时间
                    String.valueOf(command.getTaskMode()),    // 模式
                    String.valueOf(command.getSourcePos()), //源库位
                    String.valueOf(command.getTargetPos()), //目标库位
                    null,    // 修改时间
                    null,    // 修改人员
                    null,    // 备注
                    JSON.toJSONString(command),    // 指令
                    JSON.toJSONString(getStatus()),    // 系统状态
                    1,    // 下发状态{0:未下发,1:已下发}
                    JSON.toJSONString(response)    // 响应
            );
            bean.insert(basRgvOpt);
        }
        return response;
    }
}
src/main/java/com/zy/core/network/real/ZyStationRealConnect.java
@@ -2,6 +2,7 @@
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import lombok.extern.slf4j.Slf4j;
@@ -33,17 +34,17 @@
    private List<ZyStationStatusEntity> statusList;
    private List<ZyStationStatusEntity> barcodeStatusList;
    private final SiemensS7Net siemensNet;
    private final DeviceConfig deviceConfig;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    public ZyStationRealConnect(SiemensS7Net siemensNet, DeviceConfig deviceConfig) {
        this.siemensNet = siemensNet;
    public ZyStationRealConnect(DeviceConfig deviceConfig) {
        this.deviceConfig = deviceConfig;
    }
    @Override
    public boolean connect() {
        boolean connected = false;
        siemensNet = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
        OperateResult connect = siemensNet.ConnectServer();
        if (connect.IsSuccess) {
            connected = true;
src/main/java/com/zy/core/thread/RgvThread.java
@@ -9,6 +9,8 @@
    RgvProtocol getStatus();
    RgvCommand getTransportCommand(Integer taskNo, Integer rgvNo, Integer sourcePos, Integer targetPos);
    RgvCommand getMoveCommand(Integer taskNo, Integer rgvNo, Integer targetPos);
    RgvCommand getResetCommand(Integer rgvNo);
src/main/java/com/zy/core/thread/impl/ZyRgvThread.java
@@ -3,13 +3,18 @@
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasRgv;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.entity.DeviceDataLog;
import com.zy.asrs.service.BasRgvService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.RgvTaskModeType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.Task;
@@ -28,6 +33,7 @@
@Data
@Slf4j
public class ZyRgvThread implements Runnable, RgvThread {
    private DeviceConfig deviceConfig;
    private RedisUtil redisUtil;
    private ZyRgvConnectDriver zyRgvConnectDriver;
@@ -72,7 +78,7 @@
            rgvProtocol = new RgvProtocol();
            rgvProtocol.setRgvNo(deviceConfig.getDeviceNo());
        }
        rgvProtocol.setMode(-1);
        rgvProtocol.setMode(0);
        rgvProtocol.setTaskNo(0);
        rgvProtocol.setStatus(-1);
        rgvProtocol.setRgvPos(0);
@@ -82,8 +88,7 @@
    @Override
    public boolean connect() {
        SiemensS7Net siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
        zyRgvConnectDriver = new ZyRgvConnectDriver(siemensS7Net, deviceConfig);
        zyRgvConnectDriver = new ZyRgvConnectDriver(deviceConfig);
        new Thread(zyRgvConnectDriver).start();
        DeviceConnectPool.put(SlaveType.Rgv, deviceConfig.getDeviceNo(), zyRgvConnectDriver);
        return true;
@@ -122,6 +127,18 @@
            redisUtil.set(RedisKeyType.DEVICE_LOG_KEY.key + System.currentTimeMillis(), deviceDataLog, 60 * 60 * 24);
            rgvProtocol.setDeviceDataLog(System.currentTimeMillis());
        }
        BasRgvService basRgvService = SpringUtils.getBean(BasRgvService.class);
        if (basRgvService != null) {
            BasRgv basRgv = basRgvService.selectOne(new EntityWrapper<BasRgv>().eq("rgv_no", deviceConfig.getDeviceNo()));
            if(basRgv == null) {
                basRgv = new BasRgv();
                basRgv.setRgvNo(deviceConfig.getDeviceNo());
                basRgv.setStatus(1);
                basRgv.setCreateTime(new Date());
                basRgvService.insert(basRgv);
            }
        }
    }
    @Override
@@ -135,13 +152,25 @@
    }
    @Override
    public RgvCommand getTransportCommand(Integer taskNo, Integer rgvNo, Integer sourcePos, Integer targetPos) {
        RgvCommand cmd = new RgvCommand();
        cmd.setRgvNo(rgvNo);
        cmd.setTaskNo(taskNo);
        cmd.setTaskMode(RgvTaskModeType.FETCH_PUT.id);
        cmd.setSourcePos(sourcePos);
        cmd.setTargetPos(targetPos);
        cmd.setCommand(1);
        return cmd;
    }
    @Override
    public RgvCommand getMoveCommand(Integer taskNo, Integer rgvNo, Integer targetPos) {
        RgvCommand cmd = new RgvCommand();
        cmd.setRgvNo(rgvNo);
        cmd.setTaskNo(taskNo.shortValue());
        cmd.setTaskMode((short) 1);
        cmd.setTargetPos(targetPos.shortValue());
        cmd.setCommand((short) 1);
        cmd.setTaskNo(taskNo);
        cmd.setTaskMode(RgvTaskModeType.X_MOVE.id);
        cmd.setTargetPos(targetPos);
        cmd.setCommand(1);
        return cmd;
    }
@@ -149,10 +178,10 @@
    public RgvCommand getResetCommand(Integer rgvNo) {
        RgvCommand cmd = new RgvCommand();
        cmd.setRgvNo(rgvNo);
        cmd.setTaskNo((short) 0);
        cmd.setAckFinish((short) 1);
        cmd.setTaskMode((short) 0);
        cmd.setCommand((short) 1);
        cmd.setTaskNo(0);
        cmd.setAckFinish(1);
        cmd.setTaskMode(0);
        cmd.setCommand(1);
        return cmd;
    }
src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java
@@ -1,7 +1,5 @@
package com.zy.core.thread.impl;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.DateUtils;
@@ -109,8 +107,7 @@
    @Override
    public boolean connect() {
        SiemensS7Net siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
        zyCrnConnectDriver = new ZyCrnConnectDriver(siemensS7Net, deviceConfig);
        zyCrnConnectDriver = new ZyCrnConnectDriver(deviceConfig);
        new Thread(zyCrnConnectDriver).start();
        DeviceConnectPool.put(SlaveType.Crn, deviceConfig.getDeviceNo(), zyCrnConnectDriver);
        return true;
src/main/java/com/zy/core/thread/impl/ZyStationThread.java
@@ -1,7 +1,5 @@
package com.zy.core.thread.impl;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zy.asrs.entity.BasDevp;
@@ -143,8 +141,7 @@
    @Override
    public boolean connect() {
        SiemensS7Net siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
        zyStationConnectDriver = new ZyStationConnectDriver(siemensS7Net, deviceConfig);
        zyStationConnectDriver = new ZyStationConnectDriver(deviceConfig);
        new Thread(zyStationConnectDriver).start();
        DeviceConnectPool.put(SlaveType.Devp, deviceConfig.getDeviceNo(), zyStationConnectDriver);
        return true;
src/main/webapp/components/WatchRgvCard.js
New file
@@ -0,0 +1,188 @@
Vue.component("watch-rgv-card", {
  template: `
    <div>
        <div style="display: flex;margin-bottom: 10px;">
            <div style="width: 100%;">RGV监控</div>
            <div style="width: 100%;text-align: right;display: flex;">
              <el-input size="mini" v-model="searchRgvNo" placeholder="请输入RGV号"></el-input>
              <el-button @click="getRgvStateInfo" size="mini">查询</el-button>
            </div>
        </div>
        <div style="margin-bottom: 10px;">
            <div style="margin-bottom: 5px;">
               <el-button v-if="showControl" @click="openControl" size="mini">关闭控制中心</el-button>
               <el-button v-else @click="openControl" size="mini">打开控制中心</el-button>
            </div>
            <div v-if="showControl" style="display: flex;justify-content: space-between;flex-wrap: wrap;">
                <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.rgvNo" placeholder="RGV号"></el-input></div>
                <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.sourcePos" placeholder="源点"></el-input></div>
                <div style="margin-bottom: 10px;width: 33%;"><el-input size="mini" v-model="controlParam.targetPos" placeholder="目标点"></el-input></div>
                <div style="margin-bottom: 10px;"><el-button @click="controlCommandTransport()" size="mini">取放货</el-button></div>
                <div style="margin-bottom: 10px;"><el-button @click="controlCommandMove()" size="mini">移动</el-button></div>
                <div style="margin-bottom: 10px;"><el-button @click="controlCommandTaskComplete()" size="mini">任务完成</el-button></div>
            </div>
        </div>
        <el-collapse v-model="activeNames">
          <el-collapse-item v-for="(item) in rgvList" :name="item.rgvNo">
            <template slot="title">
                <div style="width: 100%;display: flex;">
                   <div style="width: 50%;">{{ item.rgvNo }}号RGV</div>
                   <div style="width: 50%;text-align: right;">
                      <el-tag v-if="item.deviceStatus === 'AUTO'" type="success" size="small">自动</el-tag>
                      <el-tag v-else-if="item.deviceStatus === 'WORKING'" size="small">作业中</el-tag>
                      <el-tag v-else-if="item.deviceStatus === 'ERROR'" type="danger" size="small">报警</el-tag>
                      <el-tag v-else type="warning" size="small">离线</el-tag>
                   </div>
                </div>
            </template>
            <el-descriptions border direction="vertical">
                <el-descriptions-item label="编号">{{ item.rgvNo }}</el-descriptions-item>
                <el-descriptions-item label="工作号">{{ item.taskNo }}</el-descriptions-item>
                <el-descriptions-item label="模式">{{ item.mode }}</el-descriptions-item>
                <el-descriptions-item label="状态">{{ item.status }}</el-descriptions-item>
                <el-descriptions-item label="轨道位">{{ item.trackSiteNo }}</el-descriptions-item>
                <el-descriptions-item label="是否有物">{{ item.loading }}</el-descriptions-item>
                <el-descriptions-item label="故障代码">{{ item.warnCode }}</el-descriptions-item>
                <el-descriptions-item label="故障描述">{{ item.alarm }}</el-descriptions-item>
            </el-descriptions>
          </el-collapse-item>
        </el-collapse>
    </div>
    `,
  props: ["param"],
  data() {
    return {
      rgvList: [],
      activeNames: "",
      searchRgvNo: "",
      showControl: true,
      controlParam: {
        rgvNo: "",
        sourcePos: "",
        targetPos: ""
      }
    };
  },
  created() {
    setInterval(() => {
      this.getRgvStateInfo();
    }, 1000);
  },
  watch: {
    param: {
      handler(newVal) {
        if (newVal && newVal.rgvNo != 0) {
          this.activeNames = newVal.rgvNo;
        }
      },
      deep: true,
      immediate: true
    },
  },
  methods: {
    getRgvStateInfo() {
      let that = this;
      $.ajax({
        url: baseUrl + "/rgv/table/rgv/state",
        headers: {
          token: localStorage.getItem("token"),
        },
        method: "post",
        success: (res) => {
          if (res.code == 200) {
            let list = res.data || [];
            if (that.searchRgvNo == "") {
              that.rgvList = list;
            } else {
              let tmp = [];
              list.forEach((item) => {
                if (item.rgvNo == that.searchRgvNo) {
                  tmp.push(item);
                }
              });
              that.rgvList = tmp;
            }
          }
        },
      });
    },
    openControl() {
      this.showControl = !this.showControl;
    },
    controlCommandTransport() {
      let that = this;
      $.ajax({
        url: baseUrl + "/rgv/command/transport",
        headers: {
          token: localStorage.getItem("token"),
        },
        contentType: "application/json",
        method: "post",
        data: JSON.stringify(that.controlParam),
        success: (res) => {
          if (res.code == 200) {
            that.$message({
              message: res.msg,
              type: "success",
            });
          } else {
            that.$message({
              message: res.msg,
              type: "warning",
            });
          }
        },
      });
    },
    controlCommandMove() {
      let that = this;
      $.ajax({
        url: baseUrl + "/rgv/command/move",
        headers: {
          token: localStorage.getItem("token"),
        },
        contentType: "application/json",
        method: "post",
        data: JSON.stringify(that.controlParam),
        success: (res) => {
          if (res.code == 200) {
            that.$message({
              message: res.msg,
              type: "success",
            });
          } else {
            that.$message({
              message: res.msg,
              type: "warning",
            });
          }
        },
      });
    },
    controlCommandTaskComplete() {
      let that = this;
      $.ajax({
        url: baseUrl + "/rgv/command/taskComplete",
        headers: {
          token: localStorage.getItem("token"),
        },
        contentType: "application/json",
        method: "post",
        data: JSON.stringify(that.controlParam),
        success: (res) => {
          if (res.code == 200) {
            that.$message({
              message: res.msg,
              type: "success",
            });
          } else {
            that.$message({
              message: res.msg,
              type: "warning",
            });
          }
        },
      });
    },
  },
});
src/main/webapp/views/watch/console.html
@@ -24,7 +24,9 @@
                        <el-tab-pane label="输送站" name="devp">
                            <devp-card :param="devpParam"></devp-card>
                        </el-tab-pane>
                        <el-tab-pane label="RGV" name="rgv">RGV</el-tab-pane>
                        <el-tab-pane label="RGV" name="rgv">
                            <watch-rgv-card :param="rgvParam"></watch-rgv-card>
                        </el-tab-pane>
                        <el-tab-pane label="地图配置" name="mapSetting">
                            <map-setting-card :param="mapSettingParam"></map-setting-card>
                        </el-tab-pane>
@@ -75,6 +77,7 @@
        <script src="../../components/WatchCrnCard.js"></script>
        <script src="../../components/DevpCard.js"></script>
        <script src="../../components/MapSettingCard.js"></script>
        <script src="../../components/WatchRgvCard.js"></script>
        <script>
            var app = new Vue({
                el: '#app',
@@ -94,6 +97,9 @@
                    },
                    devpParam: {
                        stationId: 0
                    },
                    rgvParam: {
                        rgvNo: 0
                    }
                },
                created() {
@@ -150,30 +156,8 @@
                        this.activateCard = 'crn';
                    },
                    openRgv(id) {
                        this.rgvWindow = true; //打开RGV信息弹窗
                        $(".detailed").empty();
                        $('.detailed').append(id + '号RGV');
                        $.ajax({
                            url: baseUrl + "/console/rgv/detail",
                            headers: {
                                'token': localStorage.getItem('token')
                            },
                            data: {
                                rgvNo: id
                            },
                            method: 'post',
                            success: function(res) {
                                for (var val in res.data) {
                                    var find = $("#rgvWindow").find(":input[name='" + val + "']");
                                    if (find[0].type === 'text') {
                                        find.val(res.data[val]);
                                    } else if (find[0].type === 'checkbox') {
                                        find.attr("checked", res.data[val] === 'Y');
                                    }
                                }
                            }
                        })
                        this.rgvParam.rgvNo = id;
                        this.activateCard = 'rgv';
                    },
                    openSite(id) {
                        this.devpParam.stationId = id;
@@ -303,38 +287,13 @@
                                        let trackSiteNo = rgvs[i].trackSiteNo;
                                        let trackSiteEl = $("#rgvTrackSiteNo-" + trackSiteNo);
                                        let flag = false;
                                        that.rgvPosition.forEach((item) => {
                                            if (item.id == rgvs[i].rgvNo) {
                                                if (item.trackSiteNo != trackSiteNo) {
                                                    flag = true
                                                }
                                            }
                                        })
                                        if (flag) {
                                            let finalOffset = 0;
                                            let targetPosition = trackSiteEl.parent().parent().position().left;
                                            let rgvPosition = rgvEl.position().left;
                                            let calcResult = targetPosition - rgvPosition
                                            if (calcResult > 0) {
                                                finalOffset = targetPosition + trackSiteEl.width();
                                            }else {
                                                finalOffset = targetPosition;
                                            }
                                            rgvEl.animate({left: finalOffset + "px"}, 500);
                                            let position = []
                                            that.rgvPosition.forEach((item) => {
                                                if (item.id == rgvs[i].rgvNo) {
                                                    item.trackSiteNo = trackSiteNo
                                                }
                                                position.push(item)
                                            })
                                            that.rgvPosition = position
                                        }
                                        let parentLeft = rgvEl.offsetParent().offset().left;
                                        let targetPosition = trackSiteEl.parent().parent().offset().left - parentLeft;
                                        let rgvPosition = rgvEl.position().left;
                                        let zoomFactor = that.mapSettingParam.zoom ? (that.mapSettingParam.zoom / 100) : 1;
                                        if (zoomFactor <= 0) { zoomFactor = 1; }
                                        let finalOffset = targetPosition / zoomFactor;
                                        rgvEl.animate({left: finalOffset + "px"}, 500);
                                    }
                                } else if (res.code === 403) {
                                    parent.location.href = baseUrl + "/login";