#
Junjie
2025-11-05 8b4f5b2b23023986db813242cd04f4650537decd
#
11个文件已添加
9个文件已删除
5个文件已修改
4995 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/ConsoleController.java 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/enums/CrnStatusType.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/CrnDetailVo.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/CrnLatestDataVo.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/ServerBootstrap.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/cache/OutputQueue.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/CrnTaskModeType.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/CrnCommand.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnProtocol.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/DeviceConnectPool.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/ZyCrnConnectThread.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/api/ZyCrnConnectApi.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/entity/ZyCrnStatusEntity.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/network/real/ZyCrnRealConnect.java 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/CrnThread.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ShuttleThread.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/NyShuttleThread.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/lift.html 456 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/lift_old.html 507 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/shuttle.html 617 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/shuttle2.html 657 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/shuttleNew.html 677 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/shuttle_zs.html 595 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/trafficControl.html 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ConsoleController.java
@@ -1,12 +1,36 @@
package com.zy.asrs.controller;
import com.alibaba.fastjson.JSON;
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.CrnStatusType;
import com.zy.asrs.domain.param.SystemSwitchParam;
import com.zy.asrs.domain.vo.CrnDetailVo;
import com.zy.asrs.domain.vo.CrnLatestDataVo;
import com.zy.asrs.entity.BasCrnpErr;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasCrnpErrService;
import com.zy.asrs.service.DeviceConfigService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.CodeRes;
import com.zy.core.Slave;
import com.zy.core.ThreadHandler;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.CrnModeType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.properties.SystemProperties;
import com.zy.core.thread.CrnThread;
import com.zy.core.thread.impl.ZySiemensCrnThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
/**
 * 主控图接口
@@ -16,6 +40,13 @@
@RestController
@RequestMapping("/console")
public class ConsoleController {
    @Autowired
    private DeviceConfigService deviceConfigService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private BasCrnpErrService basCrnpErrService;
    @PostMapping("/system/running/status")
    @ManagerAuth(memo = "系统运行状态")
@@ -42,4 +73,158 @@
        return R.ok().add(Cools.add("status", SystemProperties.WCS_RUNNING_STATUS.get()));
    }
//    @PostMapping("/latest/data/site")
//    @ManagerAuth(memo = "站点实时数据")
//    public R siteLatestData(){
//        List<SiteLatestDataVo> vos = new ArrayList<>();
//        Map<Integer, StaProtocol> stations = new HashMap<>();
//        for (DevpSlave devp : slaveProperties.getDevp()) {
//            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
//            if (null != devpThread) {
//                stations.putAll(devpThread.getStation());
//            }
//        }
//        for (Map.Entry<Integer, StaProtocol> entry : stations.entrySet()) {
//            SiteLatestDataVo vo = new SiteLatestDataVo();
//            StaProtocol staProtocol = entry.getValue();
//            vo.setSiteId(String.valueOf(entry.getKey())); // 站点编号
//            vo.setWorkNo(staProtocol.getWorkNo()); // 工作号
//            vo.setSiteStatus(SiteStatusType.process(staProtocol));  // 状态
//            vos.add(vo);
//        }
//        return R.ok().add(vos);
//    }
    @PostMapping("/latest/data/crn")
    @ManagerAuth(memo = "堆垛机实时数据")
    public R crnLatestData(){
        List<CrnLatestDataVo> vos = new ArrayList<>();
        List<DeviceConfig> crnList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                .eq("device_type", String.valueOf(SlaveType.Crn)));
        for (DeviceConfig deviceConfig : crnList) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, deviceConfig.getDeviceNo());
            if (crnThread == null) {
                continue;
            }
            CrnProtocol crnProtocol = crnThread.getStatus();
            if (crnProtocol == null) {
                continue;
            }
            CrnLatestDataVo vo = new CrnLatestDataVo();
            vo.setCrnId(crnProtocol.getCrnNo());   //  堆垛机编号
            vo.setOffset((double) new Random().nextInt(560));     //  堆垛机偏移量
            vo.setBay(crnProtocol.getBay());    //  当前列
            /**
             * 堆垛机状态判断
             */
            if (crnProtocol.getAlarm() > 0) {
                vo.setCrnStatus(CrnStatusType.MACHINE_ERROR);
            } else {
                if (crnProtocol.getTaskNo()>0) {
                    WrkMast wrkMast = wrkMastService.selectById(crnProtocol.getTaskNo());
                    if (wrkMast != null) {
                        vo.setCrnStatus(CrnStatusType.process(wrkMast.getIoType()));
                    } else {
                        vo.setCrnStatus(crnProtocol.modeType.equals(CrnModeType.AUTO)? CrnStatusType.MACHINE_AUTO: CrnStatusType.MACHINE_UN_AUTO);
                    }
                } else {
                    vo.setCrnStatus(crnProtocol.modeType.equals(CrnModeType.AUTO)? CrnStatusType.MACHINE_AUTO: CrnStatusType.MACHINE_UN_AUTO);
                }
            }
            vos.add(vo);
        }
        return R.ok().add(vos);
    }
//    @PostMapping("/latest/data/rgv")
//    @ManagerAuth(memo = "RGV实时数据")
//    public R rgvLatestData(){
//        List<RgvLatestDataVo> vos = new ArrayList<>();
//        for (RgvSlave rgvSlave : slaveProperties.getRgv()) {
//            // 获取堆垛机信息
//            RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, rgvSlave.getId());
//            if (rgvThread == null) {
//                continue;
//            }
//            RgvProtocol rgvProtocol = rgvThread.getRgvProtocol();
//            if (rgvProtocol == null) {
//                continue;
//            }
//            RgvLatestDataVo vo = new RgvLatestDataVo();
//            vo.setRgvId(rgvProtocol.getRgvNo());   //  RGV编号
//            vo.setTrackSiteNo(String.valueOf(rgvProtocol.getRgvPos()));
//            vo.setRgvStatus(rgvProtocol.getStatusType());
//            vos.add(vo);
//
//        }
//        Object object = redisUtil.get("rgvLatestData");
//        List<Object> siteLatestDataVos = JSON.parseArray(object.toString());
//        return R.ok().add(siteLatestDataVos);
//    }
//    @PostMapping("/latest/data/barcode")
//    @ManagerAuth(memo = "条码扫描仪实时数据")
//    public R barcodeLatestData(){
//        List<BarcodeDataVo> list = new ArrayList<>();
//        for (Slave barcode : slaveProperties.getBarcode()) {
//            BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, barcode.getId());
//            if (null == barcodeThread) {
//                continue;
//            }
//            BarcodeDataVo vo = new BarcodeDataVo();
//            vo.setBarcodeId(barcode.getId());
//            vo.setCodeValue(barcodeThread.getBarcode());
//            list.add(vo);
//        }
//        return R.ok().add(list);
//    }
    @PostMapping("/crn/detail")
    @ManagerAuth(memo = "堆垛机设备数据详情")
    public R crnDetail(@RequestParam Integer crnNo){
        if (Cools.isEmpty(crnNo)){
            return R.parse(CodeRes.EMPTY);
        }
        CrnDetailVo vo = new CrnDetailVo();
        DeviceConfig deviceConfig = deviceConfigService.selectOne(new EntityWrapper<DeviceConfig>()
                .eq("device_type", String.valueOf(SlaveType.Crn))
                .eq("device_no", crnNo)
        );
        if (deviceConfig == null) {
            return R.error("设备不存在");
        }
        CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crnNo);
        CrnProtocol crnProtocol = crnThread.getStatus();
        vo.setCrnNo(crnNo);
        vo.setWorkNo(crnProtocol.getTaskNo());
        vo.setCrnStatus(crnProtocol.getStatusType().desc);
        if (crnProtocol.getAlarm() > 0) {
            BasCrnpErr crnError = basCrnpErrService.selectById(crnProtocol.getAlarm());
            vo.setError(crnError == null ? "未知异常" : crnError.getErrName());
        }
        if (crnProtocol.getTaskNo() > 0) {
            WrkMast wrkMast = wrkMastService.selectById(crnProtocol.getTaskNo());
            if (wrkMast != null) {
                vo.setSourceStaNo(String.valueOf(wrkMast.getSourceStaNo()));
                vo.setStaNo(String.valueOf(wrkMast.getStaNo()));
                vo.setWrkSts(wrkMast.getWrkSts$());   // 工作状态
                vo.setIoType(wrkMast.getIoType$());   //  入出库类型
                vo.setSourceLocNo(wrkMast.getSourceLocNo$());
                vo.setLocNo(wrkMast.getLocNo$());
                vo.setCrnStatus(crnProtocol.getStatusType().desc);
                vo.setError("");    // todo
            }
        }
        return R.ok().add(vo);
    }
}
src/main/java/com/zy/asrs/domain/enums/CrnStatusType.java
New file
@@ -0,0 +1,53 @@
package com.zy.asrs.domain.enums;
/**
 * 堆垛机状态枚举
 */
public enum CrnStatusType {
    // 入库
    MACHINE_PAKIN("入库"),
    // 出库
    MACHINE_PAKOUT("出库"),
    // 库到库
    MACHINE_STOCK_MOVE("库到库"),
    // 站到站
    MACHINE_SITE_MOVE("站到站"),
    // p to p
    MACHINE_P_MOVE("PToP"),
    // 异常
    MACHINE_ERROR("异常"),
    // 自动
    MACHINE_AUTO("自动"),
    // 非自动/手动
    MACHINE_UN_AUTO("非自动"),
    ;
    private String desc;
    CrnStatusType(String desc){
        this.desc = desc;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public static CrnStatusType process(Integer ioType){
        if (ioType>100) {
            return MACHINE_PAKOUT;
        } else if (ioType < 100 && ioType!=3 && ioType!=6 && ioType!=11) {
            return MACHINE_PAKIN;
        } else if (ioType == 3) {
            return MACHINE_SITE_MOVE;
        } else if (ioType == 11) {
            return MACHINE_STOCK_MOVE;
        } else {
            return MACHINE_ERROR;
        }
    }
}
src/main/java/com/zy/asrs/domain/vo/CrnDetailVo.java
New file
@@ -0,0 +1,42 @@
package com.zy.asrs.domain.vo;
import lombok.Data;
/**
 * 堆垛机详情视图对象
 * Created by vincent on 2020-06-03
 */
@Data
public class CrnDetailVo {
    // 堆垛机号
    private Integer crnNo;
    // 工作号
    private Integer workNo;
    // 源站
    private String sourceStaNo = "";
    // 目标站
    private String staNo = "";
    // 工作状态
    private String wrkSts = "";
    // 出入类型
    private String ioType = "";
    // 源库位
    private String sourceLocNo = "";
    // 目标库位
    private String locNo = "";
    // 堆垛机状态
    private String crnStatus = "";
    // 异常
    private String error = "";
}
src/main/java/com/zy/asrs/domain/vo/CrnLatestDataVo.java
New file
@@ -0,0 +1,28 @@
package com.zy.asrs.domain.vo;
import com.zy.asrs.domain.enums.CrnStatusType;
import lombok.Data;
/**
 * 堆垛机最新数据视图对象
 * Created by vincent on 2020-06-01
 */
@Data
public class CrnLatestDataVo {
    // 堆垛机编号
    private Integer crnId;
    // 偏移量
    private Double offset;
    // 当前列
    private Integer bay;
    private CrnStatusType crnStatus;
    public String getCrnStatus(){
        return crnStatus.toString().toLowerCase().replaceAll("_", "-");
    }
}
src/main/java/com/zy/core/ServerBootstrap.java
@@ -1,11 +1,14 @@
package com.zy.core;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.exception.CoolException;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.service.DeviceConfigService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.thread.impl.ZySiemensCrnThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
@@ -77,31 +80,20 @@
    }
    private void initThread(){
//        News.info("初始化堆垛机........................................................");
//        List<DeviceConfig> crnList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
//                .eq("device_type", String.valueOf(SlaveType.Crn)));
//        for (DeviceConfig deviceConfig : crnList) {
//            BasLift basLift = basLiftService.selectOne(new EntityWrapper<BasLift>().eq("lift_no", deviceConfig.getDeviceNo()));
//            if (basLift == null) {
//                throw new CoolException("未配置货叉提升机数据");
//            }
//
//            ThreadHandler thread = null;
//            if (deviceConfig.getThreadImpl().equals("ZyForkLiftThread")) {
//                thread = new ZyForkLiftThread(deviceConfig, basLift.getStationList$(), redisUtil);
//            } else {
//                throw new CoolException("未知的线程实现");
//            }
//
//            new Thread(thread).start();
//            SlaveConnection.put(SlaveType.ForkLift, deviceConfig.getDeviceNo(), thread);
//
//            if (deviceConfig.getFake() == 1) {
//                fakeDevices.add(deviceConfig);
//            }else {
//                allDevices.add(deviceConfig);
//            }
//        }
        News.info("初始化堆垛机........................................................");
        List<DeviceConfig> crnList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                .eq("device_type", String.valueOf(SlaveType.Crn)));
        for (DeviceConfig deviceConfig : crnList) {
            ThreadHandler thread = null;
            if (deviceConfig.getThreadImpl().equals("ZySiemensCrnThread")) {
                thread = new ZySiemensCrnThread(deviceConfig, redisUtil);
            } else {
                throw new CoolException("未知的线程实现");
            }
            new Thread(thread).start();
            SlaveConnection.put(SlaveType.Crn, deviceConfig.getDeviceNo(), thread);
        }
    }
src/main/java/com/zy/core/cache/OutputQueue.java
@@ -9,11 +9,13 @@
 */
public class OutputQueue {
    //四向穿梭车输出日志
    public static ArrayBlockingQueue<String> SHUTTLE = new ArrayBlockingQueue<>(32);
    //提升机输出日志
    public static ArrayBlockingQueue<String> LIFT = new ArrayBlockingQueue<>(32);
    //货叉提升机输出日志
    public static ArrayBlockingQueue<String> FORKLIFT = new ArrayBlockingQueue<>(32);
    // 堆垛机输出日志
    public static ArrayBlockingQueue<String> CRN = new ArrayBlockingQueue<>(32);
    // 输送线输出日志
    public static ArrayBlockingQueue<String> DEVP = new ArrayBlockingQueue<>(32);
    // 条码器输出日志
    public static ArrayBlockingQueue<JSONObject> BARCODE = new ArrayBlockingQueue<>(32);
    // rgv输出日志
    public static ArrayBlockingQueue<String> RGV = new ArrayBlockingQueue<>(32);
}
src/main/java/com/zy/core/enums/CrnTaskModeType.java
New file
@@ -0,0 +1,46 @@
package com.zy.core.enums;
public enum CrnTaskModeType {
    NONE(0),    // 无
    PAKIN(1),    // 入库
    PAKOUT(2),    // 出库
    LOC_MOVE(3),    // 库位移转
    X_MOVE(4),    // 站位移转
    Y_MOVE(5),    // 站位移转
    XY_MOVE(6),    // 站位移转
    CRN_MOVE(7),    // 堆垛机移动XYZ
    BACK_ORIGIN(8),      // 回反原点
    CLEAR(9),       // 清错
    ;
    public Integer id;
    CrnTaskModeType(Integer id) {
        this.id = id;
    }
    public static CrnTaskModeType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (CrnTaskModeType type : CrnTaskModeType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static CrnTaskModeType get(CrnTaskModeType type) {
        if (null == type) {
            return null;
        }
        for (CrnTaskModeType crnTaskModeType : CrnTaskModeType.values()) {
            if (crnTaskModeType == type) {
                return crnTaskModeType;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/model/command/CrnCommand.java
New file
@@ -0,0 +1,68 @@
package com.zy.core.model.command;
import lombok.Data;
/**
 * 堆垛机命令报文
 * Created by vincent on 2020/8/11
 */
@Data
public class CrnCommand {
    // 堆垛机号
    private Integer crnNo = 0;
    // 任务完成确认位
    private Short ackFinish = 0;
    // 任务号
    private Short taskNo = 0;
    /**
     * 任务模式:
     * 0 = 无
     * 1 = 入库   源和目标都发
     * 2 = 出库   源和目标都发
     * 3 = 库位移转 源和目标都发
     * 4 = 站位移转 源和目标都发
     * 5 = 回原点  不用发
     * 6 = 去反原点 目标发
     * 7 = 坐标移行 取货发
     * 90 = 设置时间
     * 99 = 取消当前任务
     */
    private Short taskMode = 0;
    // 源位置排号
    private Short sourcePosX = 0;
    // 源位置列号
    private Short sourcePosY = 0;
    // 源位置层号
    private Short sourcePosZ = 0;
    // 源站
    private Short sourceStaNo = 0;
    // 源巷道
    private Short sourceLane = 0;
    // 目标位置排号
    private Short destinationPosX = 0;
    // 目标位置列号
    private Short destinationPosY = 0;
    // 目标位置层号
    private Short destinationPosZ = 0;
    // 目标站
    private Short destinationStaNo = 0;
    // 目标巷道
    private Short destinationLane = 0;
    // 任务确认 0:未确认 1:已确认
    private Short command = 0;
}
src/main/java/com/zy/core/model/protocol/CrnProtocol.java
@@ -24,11 +24,6 @@
    public CrnModeType modeType;
    /**
     * 1 = 急停
     */
    public Integer eStop;
    /**
     * 异常码
     */
    public Integer alarm;
@@ -110,37 +105,37 @@
    /**
     * X行走线速度m/min
     */
    private Float xSpeed;
    private Integer xSpeed;
    /**
     * Y行走线速度m/min
     */
    private Float ySpeed;
    private Integer ySpeed;
    /**
     * Z行走线速度m/min
     */
    private Float zSpeed;
    private Integer zSpeed;
    /**
     * 堆垛机累计走行距离km
     */
    public Float xDistance;
    public Integer xDistance;
    /**
     * 堆垛机累计升降距离km
     */
    public Float yDistance;
    public Integer yDistance;
    /**
     * 堆垛机累计走行时长h
     */
    public Float xDuration;
    public Integer xDuration;
    /**
     * 堆垛机累计升降时长h
     */
    public Float yDuration;
    public Integer yDuration;
    /**
     * 最近一次入出库类型
src/main/java/com/zy/core/network/DeviceConnectPool.java
New file
@@ -0,0 +1,36 @@
package com.zy.core.network;
import com.zy.core.ThreadHandler;
import com.zy.core.enums.SlaveType;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DeviceConnectPool {
    private static final String _LINK = "_";
    private static final Map<String, ThreadHandler> conContain = new ConcurrentHashMap<>();
    public static void put(SlaveType type, Integer id, ThreadHandler thread) {
        String key = toKey(type, id);
        remove(type, id);
        conContain.put(key, thread);
    }
    public static ThreadHandler get(SlaveType type, Integer id) {
        return conContain.get(toKey(type, id));
    }
    public static void remove(SlaveType type, Integer id) {
        Object object = get(type, id);
        if (null == object) {
            return;
        }
        conContain.remove(toKey(type, id));
    }
    private static String toKey(SlaveType type, Integer id){
        return type.toString() + _LINK + id;
    }
}
src/main/java/com/zy/core/network/ZyCrnConnectThread.java
New file
@@ -0,0 +1,69 @@
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;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.network.api.ZyCrnConnectApi;
import com.zy.core.network.entity.ZyCrnStatusEntity;
import com.zy.core.network.real.ZyCrnRealConnect;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ZyCrnConnectThread implements ThreadHandler{
    private boolean connected = false;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    private ZyCrnConnectApi zyCrnConnectApi;
    public ZyCrnConnectThread(SiemensS7Net siemensS7Net, DeviceConfig deviceConfig) {
        this.siemensNet = siemensS7Net;
        this.deviceConfig = deviceConfig;
    }
    @Override
    @SuppressWarnings("InfiniteLoopStatement")
    public void run() {
        while (true) {
            try {
                if (!connected) {
                    connect();
                }
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public boolean connect() {
        if (deviceConfig.getFake() == 0) {
            zyCrnConnectApi = new ZyCrnRealConnect(siemensNet, deviceConfig);
        }
        boolean connect = zyCrnConnectApi.connect();
        connected = connect;
        return connect;
    }
    @Override
    public void close() {
        zyCrnConnectApi.disconnect();
        zyCrnConnectApi = null;
        connected = false;
    }
    public ZyCrnStatusEntity getStatus() {
        return zyCrnConnectApi.getStatus();
    }
    public CommandResponse sendCommand(CrnCommand command) {
        return zyCrnConnectApi.sendCommand(command);
    }
}
src/main/java/com/zy/core/network/api/ZyCrnConnectApi.java
New file
@@ -0,0 +1,17 @@
package com.zy.core.network.api;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.network.entity.ZyCrnStatusEntity;
public interface ZyCrnConnectApi {
    boolean connect();
    boolean disconnect();
    ZyCrnStatusEntity getStatus();//设备状态
    CommandResponse sendCommand(CrnCommand command);//下发命令
}
src/main/java/com/zy/core/network/entity/ZyCrnStatusEntity.java
New file
@@ -0,0 +1,125 @@
package com.zy.core.network.entity;
import lombok.Data;
@Data
public class ZyCrnStatusEntity {
    /**
     * 堆垛机号
     */
    private Integer crnNo;
    /**
     * 1 = 手动模式
     * 2 = 自动模式
     * 3 = 电脑模式
     */
    public Integer mode;
    /**
     * 异常码
     */
    public Integer alarm;
    /**
     * 任务号
     */
    public Integer taskNo = 0;
    /**
     * 堆垛机当前状态
     * 0:空闲,无任务
     * 1:取货定位中
     * 2:取货中
     * 3:取货完成,放货定位中
     * 4:放货中
     * 5:回原点中
     * 6:反原点
     * 7:库位移位
     * 90:任务完成等待WCS确认
     * 99:报警
     */
    public Integer status;
    /**
     * 堆垛机当前列号
     */
    public Integer bay;
    /**
     * 堆垛机当前层号
     */
    public Integer level;
    /**
     * 当前货叉位置
     * 0 = 货叉原位
     * 1 = 货叉在左侧
     * 2 = 货叉在右侧
     */
    public Integer forkPos;
    /**
     * 当前载货台位置
     * 0 = 下定位
     * 1 = 上定位
     */
    public Integer liftPos;
    /**
     * 走行在定位
     * 0 = 在定位
     * 1 = 不在定位
     */
    public Integer walkPos;
    /**
     * 载货台有物
     */
    public Integer loaded;
    /**
     * X行走线速度m/min
     */
    private Integer xSpeed;
    /**
     * Y行走线速度m/min
     */
    private Integer ySpeed;
    /**
     * Z行走线速度m/min
     */
    private Integer zSpeed;
    /**
     * 堆垛机累计走行距离km
     */
    public Integer xDistance;
    /**
     * 堆垛机累计升降距离km
     */
    public Integer yDistance;
    /**
     * 堆垛机累计走行时长h
     */
    public Integer xDuration;
    /**
     * 堆垛机累计升降时长h
     */
    public Integer yDuration;
    private Integer temp1;
    private Integer temp2;
    private Integer temp3;
    private Integer temp4;
}
src/main/java/com/zy/core/network/real/ZyCrnRealConnect.java
New file
@@ -0,0 +1,231 @@
package com.zy.core.network.real;
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
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.DeviceConfig;
import com.zy.asrs.service.BasCrnpOptService;
import com.zy.asrs.utils.Utils;
import com.zy.core.News;
import com.zy.core.cache.OutputQueue;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.network.api.ZyCrnConnectApi;
import com.zy.core.network.entity.ZyCrnStatusEntity;
import java.text.MessageFormat;
import java.util.Date;
public class ZyCrnRealConnect implements ZyCrnConnectApi {
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    public ZyCrnRealConnect(SiemensS7Net siemensS7Net, DeviceConfig deviceConfig) {
        this.siemensNet = siemensS7Net;
        this.deviceConfig = deviceConfig;
    }
    public boolean connect() {
        boolean connected = false;
        OperateResult connect = siemensNet.ConnectServer();
        if(connect.IsSuccess){
            connected = true;
            OutputQueue.CRN.offer(MessageFormat.format( "【{0}】堆垛机plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()));
            News.info("SiemensCrn"+" - 1"+" - 堆垛机plc连接成功 ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort());
        } else {
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】堆垛机plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()));
            News.error("SiemensCrn"+" - 2"+" - 堆垛机plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort());
        }
//        siemensNet.ConnectClose();
        return connected;
    }
    @Override
    public boolean disconnect() {
        siemensNet.ConnectClose();
        return true;
    }
    @Override
    public ZyCrnStatusEntity getStatus() {
        try {
            OperateResultExOne<byte[]> result = siemensNet.Read("DB101.0", (short) 56);
            if (result.IsSuccess) {
                ZyCrnStatusEntity crnStatus = new ZyCrnStatusEntity();
                crnStatus.setCrnNo(deviceConfig.getDeviceNo());
                crnStatus.setMode((int) siemensNet.getByteTransform().TransInt16(result.Content, 0));
                crnStatus.setTaskNo((int) siemensNet.getByteTransform().TransInt16(result.Content, 2));
                crnStatus.setStatus((int) siemensNet.getByteTransform().TransInt16(result.Content, 4));
                crnStatus.setBay((int) siemensNet.getByteTransform().TransInt16(result.Content, 6));
                crnStatus.setLevel((int) siemensNet.getByteTransform().TransInt16(result.Content, 8));
                crnStatus.setForkPos((int) siemensNet.getByteTransform().TransInt16(result.Content, 10));
                crnStatus.setLiftPos((int) siemensNet.getByteTransform().TransInt16(result.Content, 12));
                crnStatus.setWalkPos((int) siemensNet.getByteTransform().TransInt16(result.Content, 14));
                crnStatus.setLoaded((int) siemensNet.getByteTransform().TransInt16(result.Content, 16));
                crnStatus.setAlarm((int) siemensNet.getByteTransform().TransInt16(result.Content, 18));
                crnStatus.setTemp1((int) siemensNet.getByteTransform().TransInt16(result.Content, 20));
                crnStatus.setTemp2((int) siemensNet.getByteTransform().TransInt16(result.Content, 22));
                crnStatus.setTemp3((int) siemensNet.getByteTransform().TransInt16(result.Content, 24));
                crnStatus.setTemp4((int) siemensNet.getByteTransform().TransInt16(result.Content, 26));
                crnStatus.setXSpeed((int) siemensNet.getByteTransform().TransInt16(result.Content, 28));
                crnStatus.setYSpeed((int) siemensNet.getByteTransform().TransInt16(result.Content, 32));
                crnStatus.setZSpeed((int) siemensNet.getByteTransform().TransInt16(result.Content, 36));
                crnStatus.setXDistance((int) siemensNet.getByteTransform().TransInt16(result.Content, 40));
                crnStatus.setYDistance((int) siemensNet.getByteTransform().TransInt16(result.Content, 44));
                crnStatus.setXDuration((int) siemensNet.getByteTransform().TransInt16(result.Content, 48));
                crnStatus.setYDuration((int) siemensNet.getByteTransform().TransInt16(result.Content, 52));
                return crnStatus;
            } else {
                OutputQueue.CRN.offer(MessageFormat.format("【{0}】读取堆垛机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()));
                News.error("SiemensCrn"+" - 4"+" - 读取堆垛机plc状态信息失败 ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort());
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】读取堆垛机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()));
            News.error("SiemensCrn"+" - 5"+" - 读取堆垛机plc状态信息失败 ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort());
        }
        return null;
    }
    @Override
    public CommandResponse sendCommand(CrnCommand command) {
        CommandResponse response = new CommandResponse(false);
        try {
            if (null == command) {
                News.error("堆垛机写入命令为空");
                response.setMessage("堆垛机写入命令为空");
                return response;
            }
            int writeAck = 0;
            boolean ackResult = false;
            do {
                OperateResult resultAck = siemensNet.Write("DB100.0", (short) 0);
                if (resultAck.IsSuccess) {
                    Thread.sleep(200);
                    OperateResultExOne<byte[]> resultRead = siemensNet.Read("DB100.0", (short) 2);
                    short ack = siemensNet.getByteTransform().TransInt16(resultRead.Content, 0);
                    if (ack != 0) {
                        writeAck++;
                    } else {
                        News.info("堆垛机命令下发[id:{}] >>>>> {}", command.getCrnNo(), "ack复位完成");
                        ackResult = true;
                        break;
                    }
                }
            } while (writeAck < 5);
            if (!ackResult) {
                response.setMessage("堆垛机命令下发[id:{}] >>>>> {}" + command.getCrnNo() + "ack复位失败");
                return response;
            }
            short[] array = new short[10];
            array[0] = command.getAckFinish();
            array[1] = command.getTaskNo();
            array[2] = command.getTaskMode();
            array[3] = command.getSourcePosX();
            array[4] = command.getSourcePosY();
            array[5] = command.getSourcePosZ();
            array[6] = command.getDestinationPosX();
            array[7] = command.getDestinationPosY();
            array[8] = command.getDestinationPosZ();
            array[9] = command.getCommand();
            OperateResult result = null;
            int idx = 0;
            do {
                OperateResultExOne<byte[]> resultRead = siemensNet.Read("DB100.0", (short) 20);
                if (resultRead.IsSuccess) {
                    if (command.getAckFinish() == 0) {
                        short taskNo = siemensNet.getByteTransform().TransInt16(resultRead.Content, 2);
                        short taskMode = siemensNet.getByteTransform().TransInt16(resultRead.Content, 4);
                        short sourcePosX = siemensNet.getByteTransform().TransInt16(resultRead.Content, 6);
                        short sourcePosY = siemensNet.getByteTransform().TransInt16(resultRead.Content, 8);
                        short sourcePosZ = siemensNet.getByteTransform().TransInt16(resultRead.Content, 10);
                        short destinationPosX = siemensNet.getByteTransform().TransInt16(resultRead.Content, 12);
                        short destinationPosY = siemensNet.getByteTransform().TransInt16(resultRead.Content, 14);
                        short destinationPosZ = siemensNet.getByteTransform().TransInt16(resultRead.Content, 16);
                        if (taskNo == 0 || taskMode == 0 || sourcePosX == 0 || sourcePosY == 0 || sourcePosZ == 0 || destinationPosX == 0 || destinationPosY == 0 || destinationPosZ == 0) {
                            result = siemensNet.Write("DB100.0", array);
                        } else {
                            break;
                        }
                    } else {
                        short ackFinish = siemensNet.getByteTransform().TransInt16(resultRead.Content, 0);
                        if (ackFinish != command.getAckFinish()) {
                            result = siemensNet.Write("DB100.0", array);
                        } else {
                            break;
                        }
                    }
                }
                idx++;
                Thread.sleep(500L);
            } while (idx < 5);
            if (command.getAckFinish() == 0) {
                short commandFinish = 1;
                int i = 0;
                do {
                    OperateResultExOne<byte[]> resultRead = siemensNet.Read("DB100.0", (short) 4);
                    OperateResultExOne<byte[]> resultReadConfirm = siemensNet.Read("DB100.18", (short) 2);
                    if (resultRead.IsSuccess && resultReadConfirm.IsSuccess) {
                        short taskNo = siemensNet.getByteTransform().TransInt16(resultRead.Content, 2);
                        short confirm = siemensNet.getByteTransform().TransInt16(resultReadConfirm.Content, 0);
                        if (taskNo != 0 && confirm == 0) {
                            result = siemensNet.Write("DB100.18", commandFinish);
                        }
                    }
                    i++;
                    Thread.sleep(500L);
                } while (i < 5);
            }
            if (result != null && result.IsSuccess) {
                News.info("SiemensCrn" + " - 7" + " - 堆垛机命令下发[id:{}] >>>>> {}", command.getCrnNo(), JSON.toJSON(command));
                OutputQueue.CRN.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), command.getCrnNo(), JSON.toJSON(command)));
                response.setResult(true);
                response.setMessage("命令下发成功");
            } else {
                News.error("SiemensCrn" + " - 8" + " - 写入堆垛机plc数据失败 ===>> [id:{}]", command.getCrnNo());
                OutputQueue.CRN.offer(MessageFormat.format("【{0}】写入堆垛机plc数据失败 ===>> [id:{1}]", DateUtils.convert(new Date()), command.getCrnNo()));
                response.setResult(false);
                response.setMessage("命令下发失败");
            }
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            String sourceLocNo = Utils.getLocNo(command.getSourcePosX(), command.getSourcePosY(), command.getSourcePosZ());
            String targetLocNo = Utils.getLocNo(command.getDestinationPosX(), command.getDestinationPosY(), command.getDestinationPosZ());
            // 日志记录
            BasCrnpOptService bean = SpringUtils.getBean(BasCrnpOptService.class);
            BasCrnpOpt basCrnpOpt = new BasCrnpOpt(
                    command.getTaskNo().intValue(),    // 任务号
                    command.getCrnNo(),    // 堆垛机[非空]
                    new Date(),    // 下发时间
                    String.valueOf(command.getTaskMode()),    // 模式
                    sourceLocNo, //源库位
                    targetLocNo, //目标库位
                    null,    // 修改时间
                    null,    // 修改人员
                    null,    // 备注
                    JSON.toJSONString(command),    // 指令
                    JSON.toJSONString(command),    // 系统状态
                    1,    // 下发状态{0:未下发,1:已下发}
                    JSON.toJSONString(response)    // 响应
            );
            bean.insert(basCrnpOpt);
        }
        return response;
    }
}
src/main/java/com/zy/core/thread/CrnThread.java
@@ -1,10 +1,20 @@
package com.zy.core.thread;
import com.zy.core.ThreadHandler;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.protocol.CrnProtocol;
public interface CrnThread extends ThreadHandler {
    CrnProtocol getCrnProtocol();
    CrnProtocol getStatus();
    CrnCommand getPickAndPutCommand(String sourceLocNo, String targetLocNo, Integer taskNo, Integer crnNo);//取放货
    CrnCommand getMoveCommand(String sourceLocNo, String targetLocNo, Integer taskNo, Integer crnNo);//移动
    CrnCommand getResetCommand(Integer crnNo);//复位
    CommandResponse sendCommand(CrnCommand command);//下发命令
}
src/main/java/com/zy/core/thread/ShuttleThread.java
File was deleted
src/main/java/com/zy/core/thread/impl/NyShuttleThread.java
File was deleted
src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java
New file
@@ -0,0 +1,254 @@
package com.zy.core.thread.impl;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.entity.DeviceDataLog;
import com.zy.asrs.service.DeviceDataLogService;
import com.zy.asrs.utils.Utils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.ThreadHandler;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.CrnTaskModeType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.Task;
import com.zy.core.model.command.CrnCommand;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.network.DeviceConnectPool;
import com.zy.core.network.ZyCrnConnectThread;
import com.zy.core.network.entity.ZyCrnStatusEntity;
import com.zy.core.thread.CrnThread;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.text.MessageFormat;
import java.util.Date;
/**
 * 堆垛机线程
 * Created by vincent on 2020/8/4
 */
@Data
@Slf4j
public class ZySiemensCrnThread implements Runnable, CrnThread {
    private DeviceConfig deviceConfig;
    private RedisUtil redisUtil;
    private ZyCrnConnectThread zyCrnConnectThread;
    private CrnProtocol crnProtocol;
    private boolean resetFlag = false;
    public ZySiemensCrnThread(DeviceConfig deviceConfig, RedisUtil redisUtil) {
        this.deviceConfig = deviceConfig;
        this.redisUtil = redisUtil;
    }
    @Override
    @SuppressWarnings("InfiniteLoopStatement")
    public void run() {
        this.connect();
        this.initCrn();
        while (true) {
            try {
                int step = 1;
                Task task = MessageQueue.poll(SlaveType.Crn, deviceConfig.getDeviceNo());
                if (task != null) {
                    step = task.getStep();
                }
                switch (step) {
                    // 读数据
                    case 1:
                        readStatus();
                        break;
                    default:
                        break;
                }
                Thread.sleep(200);
            } catch (Exception e) {
//                e.printStackTrace();
            }
        }
    }
    /**
     * 初始化堆垛机状态
     */
    private void initCrn() {
        if (null == crnProtocol) {
            crnProtocol = new CrnProtocol();
            crnProtocol.setCrnNo(deviceConfig.getDeviceNo());
        }
        crnProtocol.setMode(-1);
        crnProtocol.setTaskNo(0);
        crnProtocol.setStatus(-1);
        crnProtocol.setBay(0);
        crnProtocol.setLevel(0);
        crnProtocol.setForkPos(-1);
        crnProtocol.setLiftPos(-1);
        crnProtocol.setWalkPos(0);
        crnProtocol.setLoaded(0);
        crnProtocol.setAlarm(0);
        crnProtocol.setXSpeed(0);
        crnProtocol.setYSpeed(0);
        crnProtocol.setZSpeed(0);
        crnProtocol.setXDistance(0);
        crnProtocol.setYDistance(0);
        crnProtocol.setXDuration(0);
        crnProtocol.setYDuration(0);
    }
    @Override
    public boolean connect() {
        SiemensS7Net siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
        ThreadHandler thread = new ZyCrnConnectThread(siemensS7Net, deviceConfig);
        new Thread(thread).start();
        DeviceConnectPool.put(SlaveType.Crn, deviceConfig.getDeviceNo(), thread);
        return true;
    }
    /**
     * 读取状态
     */
    private void readStatus(){
        ZyCrnStatusEntity crnStatus = zyCrnConnectThread.getStatus();
        if (crnStatus == null) {
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】读取堆垛机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()));
            News.error("SiemensCrn"+" - 5"+" - 读取堆垛机plc状态信息失败 ===>> [id:{}] [ip:{}] [port:{}]", deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort());
            return;
        }
        crnProtocol.setMode(crnStatus.getMode());
        crnProtocol.setTaskNo(crnStatus.getTaskNo());
        crnProtocol.setStatus(crnStatus.getStatus());
        crnProtocol.setBay(crnStatus.getBay());
        crnProtocol.setLevel(crnStatus.getLevel());
        crnProtocol.setForkPos(crnStatus.getForkPos());
        crnProtocol.setLiftPos(crnStatus.getLiftPos());
        crnProtocol.setWalkPos(crnStatus.getWalkPos());
        crnProtocol.setLoaded(crnStatus.getLoaded());
        crnProtocol.setAlarm(crnStatus.getAlarm());
        crnProtocol.setTemp1(crnStatus.getTemp1());
        crnProtocol.setTemp2(crnStatus.getTemp2());
        crnProtocol.setTemp3(crnStatus.getTemp3());
        crnProtocol.setTemp4(crnStatus.getTemp4());
        crnProtocol.setXSpeed(crnStatus.getXSpeed());
        crnProtocol.setYSpeed(crnStatus.getYSpeed());
        crnProtocol.setZSpeed(crnStatus.getZSpeed());
        crnProtocol.setXDistance(crnStatus.getXDistance());
        crnProtocol.setYDistance(crnStatus.getYDistance());
        crnProtocol.setXDuration(crnStatus.getXDuration());
        crnProtocol.setYDuration(crnStatus.getYDuration());
        OutputQueue.CRN.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
//        // 复位信号
//        if (!Cools.isEmpty(crnProtocol.getStatusType()) && crnProtocol.getStatusType().equals(CrnStatusType.WAITING)) {
//            if (resetFlag) {
//                if(crnProtocol.getTaskNo()==9999){
//                    backHpFlag = false;
//                }
//                CrnCommand crnCommand = new CrnCommand();
//                crnCommand.setAckFinish((short)1);
//                if (write(crnCommand)) {
//                    resetFlag = false;
//                }
//            }
//        }
        if (crnProtocol.getAlarm() > 0) {
            crnProtocol.setLastCommandTime(-1L);
        }
        if (crnProtocol.getAlarm() == 0 && crnProtocol.getLastCommandTime() == -1) {
            crnProtocol.setLastCommandTime(System.currentTimeMillis());
        }
        if (System.currentTimeMillis() - crnProtocol.getDeviceDataLog() > 1000 * 1) {
            //采集时间超过1s,保存一次数据记录
            //保存数据记录
            DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class);
            DeviceDataLog deviceDataLog = new DeviceDataLog();
            deviceDataLog.setOriginData(JSON.toJSONString(crnStatus));
            deviceDataLog.setWcsData(JSON.toJSONString(crnProtocol));
            deviceDataLog.setType(String.valueOf(SlaveType.Crn));
            deviceDataLog.setDeviceNo(crnProtocol.getCrnNo());
            deviceDataLog.setCreateTime(new Date());
            deviceDataLogService.insert(deviceDataLog);
            //更新采集时间
            crnProtocol.setDeviceDataLog(System.currentTimeMillis());
        }
    }
    @Override
    public void close() {
        zyCrnConnectThread.close();
    }
    @Override
    public CrnProtocol getStatus() {
        return this.crnProtocol;
    }
    @Override
    public CrnCommand getPickAndPutCommand(String sourceLocNo, String targetLocNo, Integer taskNo, Integer crnNo) {
        CrnCommand crnCommand = new CrnCommand();
        crnCommand.setCrnNo(crnNo); // 堆垛机编号
        crnCommand.setTaskNo(taskNo.shortValue()); // 工作号
        crnCommand.setTaskMode(CrnTaskModeType.LOC_MOVE.id.shortValue()); // 任务模式:  库位移转
        crnCommand.setSourcePosX((short) Utils.getRow(sourceLocNo));     // 源库位排
        crnCommand.setSourcePosY((short) Utils.getBay(sourceLocNo));     // 源库位列
        crnCommand.setSourcePosZ((short) Utils.getLev(sourceLocNo));     // 源库位层
        crnCommand.setDestinationPosX((short) Utils.getRow(targetLocNo));     // 目标库位排
        crnCommand.setDestinationPosY((short) Utils.getBay(targetLocNo));     // 目标库位列
        crnCommand.setDestinationPosZ((short) Utils.getLev(targetLocNo));     // 目标库位层
        crnCommand.setCommand((short) 1);     // 任务确认
        return crnCommand;
    }
    @Override
    public CrnCommand getMoveCommand(String sourceLocNo, String targetLocNo, Integer taskNo, Integer crnNo) {
        CrnCommand crnCommand = new CrnCommand();
        crnCommand.setCrnNo(crnNo); // 堆垛机编号
        crnCommand.setTaskNo(taskNo.shortValue()); // 工作号
        crnCommand.setAckFinish((short) 0);  // 任务完成确认位
        crnCommand.setTaskMode(CrnTaskModeType.CRN_MOVE.id.shortValue()); // 任务模式:  堆垛机移动
        crnCommand.setSourcePosX((short) Utils.getRow(sourceLocNo));     // 源库位排
        crnCommand.setSourcePosY((short) Utils.getBay(sourceLocNo));     // 源库位列
        crnCommand.setSourcePosZ((short) Utils.getLev(sourceLocNo));     // 源库位层
        crnCommand.setDestinationPosX((short) 0);     // 目标库位排
        crnCommand.setDestinationPosY((short) 0);     // 目标库位列
        crnCommand.setDestinationPosZ((short) 0);     // 目标库位层
        crnCommand.setCommand((short) 1);     // 任务确认
        return crnCommand;
    }
    @Override
    public CrnCommand getResetCommand(Integer crnNo) {
        CrnCommand crnCommand = new CrnCommand();
        crnCommand.setCrnNo(crnNo); // 堆垛机编号
        crnCommand.setTaskNo((short) 0); // 工作号
        crnCommand.setAckFinish((short) 1);  // 任务完成确认位
        crnCommand.setTaskMode(CrnTaskModeType.NONE.id.shortValue()); // 任务模式
        crnCommand.setSourcePosX((short)0);     // 源库位排
        crnCommand.setSourcePosY((short)0);     // 源库位列
        crnCommand.setSourcePosZ((short)0);     // 源库位层
        crnCommand.setDestinationPosX((short)0);     // 目标库位排
        crnCommand.setDestinationPosY((short)0);     // 目标库位列
        crnCommand.setDestinationPosZ((short)0);     // 目标库位层
        crnCommand.setCommand((short) 1);     // 任务确认
        return crnCommand;
    }
    @Override
    public synchronized CommandResponse sendCommand(CrnCommand command) {
        this.crnProtocol.setLastCommandTime(System.currentTimeMillis());
        return zyCrnConnectThread.sendCommand(command);
    }
}
src/main/webapp/views/lift.html
File was deleted
src/main/webapp/views/lift_old.html
File was deleted
src/main/webapp/views/shuttle.html
File was deleted
src/main/webapp/views/shuttle2.html
File was deleted
src/main/webapp/views/shuttleNew.html
File was deleted
src/main/webapp/views/shuttle_zs.html
File was deleted
src/main/webapp/views/trafficControl.html
File was deleted