自动化立体仓库 - WCS系统
#
Junjie
2025-01-14 ba77f258c619b296e51cadc0958bff23965dfc6d
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java
@@ -1,43 +1,36 @@
package com.zy.core.model.protocol;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.BasShuttleErr;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.BasShuttleErrService;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.core.News;
import com.zy.core.enums.ShuttleErrorCodeType;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.ShuttleStatusType;
import com.zy.core.model.command.ShuttleAssignCommand;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
/**
 * 四向穿梭车
 */
@Slf4j
@Data
public class ShuttleProtocol {
public class ShuttleProtocol implements Cloneable {
    //**********************必须存在属性**********************
    /**
     * 四向穿梭车号
     */
    private Short shuttleNo;
    private Integer shuttleNo;
    /**
     * 任务号
     */
    private Short taskNo = 0;
    /**
     * 任务指令
     */
    private ShuttleAssignCommand assignCommand;
    private Integer taskNo;
    /**
     * 当前小车状态(内部自我维护)
@@ -45,7 +38,7 @@
    private Integer protocolStatus;
    /**
     * 当前小车状态枚举
     * 当前小车作业状态枚举
     */
    private ShuttleProtocolStatusType protocolStatusType;
@@ -60,146 +53,151 @@
    private String locNo;
    /**
     * 小车忙状态位
     * 1: 忙
     * 0: 空闲
     * 小车设备状态0:忙碌 1:空闲
     */
    private Short busyStatus;
    private Integer deviceStatus;
    /**
     * 小车忙状态位枚举
     * 小车模式,0:手动 1:自动
     */
    private ShuttleStatusType busyStatusType;
    private Integer mode;
    /**
     * 当前二维码
     * 0为空
     */
    private Short currentCode;
    private String currentCode;
    /**
     * 电池电量百分比
     * 电池电量
     */
    private Short batteryPower;
    /**
     * 电池温度
     */
    private Integer batteryTemp;
    private String batteryPower;
    /**
     * 错误编号
     */
    private Short errorCode;
    private String errorCode;
    //**********************非必须属性,实际使用中可能存在空值**********************
    /**
     * 错误编号枚举
     * 电池温度
     */
    private ShuttleErrorCodeType errorCodeType;
    private String batteryTemp;
    /**
     * Plc输出状态IO
     * 是否顶升
     */
    private Short plcOutputStatusIO;
    private Boolean hasLift;
    /**
     * Plc输出状态IO-顶升位
     * 是否有托盘
     */
    private Boolean plcOutputLift;
    private Boolean hasPallet;
    /**
     * Plc输出状态IO-换向位
     * 行驶方向
     */
    private Boolean plcOutputTransfer;
    private String runDirection;
    /**
     * Plc输出状态IO-抱闸位
     * 是否为充电状态
     */
    private Boolean plcOutputBrake;
    private Boolean hasCharge;
    /**
     * Plc输出状态IO-充电位
     * 电池电压
     */
    private Boolean plcOutputCharge;
    private Integer batteryVoltage;
    /**
     * 错误信息码
     * 运行速度
     */
    private Short statusErrorCode;
    private Integer speed;
    /**
     * PLC输入状态,目前只有一个状态有效果,托盘雷达1有货,0无货
     */
    private Short plcInputStatus;
    //**********************系统自身所需属性**********************
    /**
     * 当前或者之前读到的二维码值
     */
    private Short currentOrBeforeCode;
    /**
     * 读到的二维码X方向偏移量
     */
    private Short codeOffsetX;
    /**
     * 读到的二维码Y方向偏移量
     */
    private Short codeOffsetY;
    /**
     * 当前的电压值
     */
    private Integer currentVoltage;
    /**
     * 当前的模拟量值
     */
    private Short currentAnalogValue;
    /**
     * 当前的升降伺服速度
     */
    private Short currentLiftServoSpeed;
    /**
     * 当前的行走伺服速度
     */
    private Short currentMoveServoSpeed;
    /**
     * 当前的升降伺服负载率
     */
    private Short currentLiftServoLoad;
    /**
     * 当前的行走伺服负载率
     */
    private Short currentMoveServoLoad;
    /**
     * 作业标记
     * 作业标记 false表示正在作业
     */
    private Boolean pakMk = true;
    public void setBusyStatus(Short status) {
        this.busyStatus = status;
        this.busyStatusType = ShuttleStatusType.get(status);
    }
    /**
     * 跑库状态
     */
    private Boolean moveLoc = false;
    public void setBusyStatus(ShuttleStatusType type) {
        this.busyStatus = type.id.shortValue();
        this.busyStatusType = type;
    }
    /**
     * 跑库类型,0:跑轨道,1:跑库位
     */
    private Integer moveType = 0;
    //获取电池电量
    public Short getBatteryPower$() {
        return (short) (this.batteryPower * 0.1);
    }
    /**
     * 跑库X起点
     */
    private Integer xStart = 0;
    //获取电池温度
    public Short getBatteryTemp$() {
        return (short) (this.batteryTemp * 0.1);
    /**
     * 跑库X终点
     */
    private Integer xTarget = 0;
    /**
     * 跑库X当前点位
     */
    private Integer xCurrent = 0;
    /**
     * 跑库Y起点
     */
    private Integer yStart = 0;
    /**
     * 跑库Y终点
     */
    private Integer yTarget = 0;
    /**
     * 跑库Y当前点位
     */
    private Integer yCurrent = 0;
    /**
     * 演示模式
     */
    private Boolean demo = false;
    /**
     * 日志采集时间
     */
    private Long deviceDataLog = System.currentTimeMillis();
    /**
     * 指令下发时间
     */
    private Long sendTime = 0L;
    /**
     * 最近一次在线时间
     */
    private Long lastOnlineTime = System.currentTimeMillis();
    /**
     * 扩展字段
     */
    private Object extend;
    /**
     * 系统消息
     */
    private String systemMsg;
    public String getProtocolStatus$() {
        if (this.protocolStatusType == null) {
            return "";
        }
        return this.protocolStatusType.desc;
    }
    /**
@@ -218,105 +216,33 @@
        this.protocolStatusType = status;
    }
    /**
     * 设置错误编号
     */
    public void setErrorCode(Short errorCode) {
        this.errorCode = errorCode;
        this.errorCodeType = ShuttleErrorCodeType.get(errorCode.intValue());
    }
    /**
     * 设置错误编号
     */
    public void setErrorCode(ShuttleErrorCodeType type) {
        this.errorCode = type.id.shortValue();
        this.errorCodeType = type;
    }
    // 是否处于空闲待命状态
    public Boolean isIdle() {
        boolean res = this.busyStatusType.equals(ShuttleStatusType.IDLE)
                && this.pakMk.equals(true)
                && this.errorCodeType.equals(ShuttleErrorCodeType.NORMAL)
                && this.taskNo == 0
                && this.protocolStatus.intValue() == ShuttleProtocolStatusType.IDLE.id
                ;
        if (!res) {
            return res;
        } else {
            // 电量
            try {
                Integer chargeLine = SpringUtils.getBean(BasShuttleService.class).selectById(this.shuttleNo).getChargeLine();
                if (chargeLine == null) {
                    return false;
                }
                return this.getBatteryPower$() >= chargeLine;
            } catch (Exception e) {
                News.error("fail", e);
                return false;
    public Integer getTaskNo() {
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        if (null != redisUtil) {
            Object o = redisUtil.get(RedisKeyType.SHUTTLE_FLAG.key + this.shuttleNo);
            if (!Cools.isEmpty(o)) {
                this.taskNo = Integer.parseInt(String.valueOf(o));
            }
        }
        return this.taskNo == null ? 0 : this.taskNo;
    }
    // 是否处于空闲待命状态,传入的taskNo和当前taskNo相同时允许放行
    public Boolean isIdle(Short taskNo) {
        boolean res = this.busyStatusType.equals(ShuttleStatusType.IDLE)
                && this.pakMk.equals(true)
                && this.errorCodeType.equals(ShuttleErrorCodeType.NORMAL)
                && (this.taskNo == 0 || this.taskNo.intValue() == taskNo.intValue())
                && this.protocolStatus.intValue() == ShuttleProtocolStatusType.IDLE.id
                ;
        if (!res) {
            return res;
        } else {
            // 电量
            try {
                Integer chargeLine = SpringUtils.getBean(BasShuttleService.class).selectById(this.shuttleNo).getChargeLine();
                return this.getBatteryPower$() > chargeLine;
            } catch (Exception e) {
                News.error("fail", e);
                return false;
            }
    public synchronized void setSyncTaskNo(Integer taskNo) {
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        if (null != redisUtil) {
            redisUtil.set(RedisKeyType.SHUTTLE_FLAG.key + this.shuttleNo, taskNo);
            this.taskNo = taskNo;
        }
    }
    // 是否满足充电状态
    public Boolean isRequireCharge() {
        if (this.busyStatusType == null || this.pakMk == null || this.errorCodeType == null || this.taskNo == null) {
            return false;
    @Override
    public ShuttleProtocol clone() {
        try {
            return (ShuttleProtocol) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        boolean res = this.busyStatusType.id.intValue() == ShuttleStatusType.IDLE.id.intValue()
                && this.pakMk
                && this.errorCodeType.id.intValue() == ShuttleErrorCodeType.NORMAL.id.intValue()
                && this.taskNo == 0
                && this.protocolStatusType.id == ShuttleProtocolStatusType.IDLE.id
                ;
        if (!res) {
            return res;
        } else {
            // 电量小于阈值或电压小于48V,需要进行充电
            try {
                BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
                if (shuttleService == null) {
                    return false;
                }
                BasShuttle basShuttle = shuttleService.selectById(this.shuttleNo);
                if (basShuttle == null) {
                    return false;
                }
                Integer chargeLine = basShuttle.getChargeLine();
                if (chargeLine == null) {
                    return false;
                }
                return this.getBatteryPower$() < chargeLine || this.currentVoltage < 48000;
            } catch (Exception e) {
                News.error("fail", e);
                return false;
            }
        }
        return null;
    }
    //通过当前二维码获取当前库位号
@@ -326,7 +252,7 @@
            return null;
        }
        //源库位(小车当前位置)
        LocMast currentLocMast = locMastService.queryByQrCode(this.currentCode.toString());
        LocMast currentLocMast = locMastService.queryByQrCode(this.currentCode);
        if (currentLocMast == null) {
            return null;
        }
@@ -335,31 +261,103 @@
    public String getStatusErrorCode$() {
        BasShuttleErrService basShuttleErrService = SpringUtils.getBean(BasShuttleErrService.class);
        BasShuttleErr basShuttleErr = basShuttleErrService.queryByCode(this.statusErrorCode.intValue());
        if (this.errorCode == null) {
            return "";
        }
        BasShuttleErr basShuttleErr = basShuttleErrService.queryByCode(Integer.valueOf(this.errorCode));
        if (basShuttleErr == null) {
            return null;
            return this.errorCode;
        }
        return basShuttleErr.getErrName();
    }
    public void setCurrentCode(Short currentCode) {
        this.currentCode = currentCode;
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        if (locMastService != null) {
            LocMast locMast = locMastService.queryByQrCode(currentCode.toString());
            if (locMast == null) {
                //查不到库位号,查询是否为站点
                BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
                if (basDevpService != null) {
                    BasDevp basDevp = basDevpService.queryByLocNo(currentCode.toString());
                    if (basDevp != null) {
                        this.locNo = basDevp.getLocNo();
                    }
                }
            }else{
                this.locNo = locMast.getLocNo();
            }
    public String getMode$() {
        if (this.mode == null) {
            return "";
        }
        if (this.mode == 0) {
            return "手动";
        } else if (this.mode == 1) {
            return "自动";
        }
        return "";
    }
    public String getDeviceStatus$() {
        if (this.deviceStatus == null) {
            return "";
        }
        if (this.deviceStatus == 0) {
            return "忙碌";
        } else if (this.deviceStatus == 1) {
            return "空闲";
        }
        return "";
    }
    public String getHasLift$() {
        if (this.hasLift == null) {
            return "";
        }
        return this.hasLift ? "Y" : "N";
    }
    public String getHasCharge$() {
        if (this.hasCharge == null) {
            return "";
        }
        return this.hasCharge ? "Y" : "N";
    }
    public String getHasPallet$() {
        if (this.hasPallet == null) {
            return "";
        }
        return this.hasPallet ? "Y" : "N";
    }
    public String getPakMk$() {
        if (this.pakMk == null) {
            return "";
        }
        return this.pakMk ? "Y" : "N";
    }
    public String getDemo$() {
        if (this.demo == null) {
            return "";
        }
        return this.demo ? "Y" : "N";
    }
    public HashMap<String, Object> getPoint() {
        HashMap<String, Object> map = new HashMap<>();
        if (this.currentCode == null) {
            return map;
        }
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        if (locMastService == null) {
            return map;
        }
        //源库位(小车当前位置)
        LocMast currentLocMast = locMastService.queryByQrCode(this.currentCode);
        if (currentLocMast == null) {
            return map;
        }
        map.put("x", currentLocMast.getRow1());
        map.put("y", currentLocMast.getBay1());
        map.put("z", currentLocMast.getLev1());
        return map;
    }
}