#
Junjie
2024-04-17 e977a034ff8568e523cea97ca45b0c4473a69685
#
4个文件已修改
2个文件已添加
840 ■■■■■ 已修改文件
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/NavigatePositionConvert.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/model/command/NyShuttleHttpCommand.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/model/protocol/ShuttleProtocol.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/thread/impl/NyShuttleThread.java 717 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/thread/impl/SurayShuttleThread.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/NavigatePositionConvert.java
@@ -15,14 +15,15 @@
        String locNo = Utils.getLocNo(x, y, z);
        //库位号转小车二维码
        LocService locMastService = SpringUtils.getBean(LocService.class);
        Loc locMast = locMastService.getOne(new LambdaQueryWrapper<Loc>()
        LocService locService = SpringUtils.getBean(LocService.class);
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getLocNo, locNo)
                .eq(Loc::getHostId, hostId));
        if (locMast == null) {
                .eq(Loc::getHostId, hostId)
                .eq(Loc::getStatus, 1));
        if (loc == null) {
            return null;
        }
        return locMast.getCode();
        return loc.getCode();
    }
    //坐标编号转xy轴
@@ -45,6 +46,19 @@
        return node;
    }
    //小车条形码转路径算法节点
    public static NavigateNode codeToNode(String code, Long hostId) {
        LocService locService = SpringUtils.getBean(LocService.class);
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getCode, code)
                .eq(Loc::getHostId, hostId)
                .eq(Loc::getStatus, 1));
        NavigateNode node = new NavigateNode(loc.getRow(), loc.getBay());
        node.setZ(loc.getLev());
        return node;
    }
    //路径算法节点转WCS系统库位号
    public static String nodeToLocNo(NavigateNode node) {
        return xyzToLocNo(node.getX(), node.getY(), node.getZ());
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/model/command/NyShuttleHttpCommand.java
New file
@@ -0,0 +1,56 @@
package com.zy.asrs.wcs.rcs.model.command;
import com.zy.asrs.wcs.core.model.NavigateNode;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class NyShuttleHttpCommand {
    //消息类型
    private String msgType;
    //车辆编号
    private Integer robotId;
    //请求消息
    private NyRequest request;
    //工作号
    private Integer taskNo;
    @Data
    public static class NyRequest {
        //消息头
        private NyHeader header;
        //消息体
        private Map<String, Object> body;
        //HTTP请求头
        @Data
        public static class NyHeader {
            //请求编号,唯一编号
            private Integer requestId;
            //版本号
            private String version;
        }
    }
    /**
     * 命令是否完成,默认false未完成
     */
    private Boolean complete = false;
    /**
     * 行走命令所占用的节点list
     */
    private List<NavigateNode> nodes;
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/model/protocol/ShuttleProtocol.java
@@ -58,6 +58,11 @@
    private Integer deviceStatus;
    /**
     * 小车模式,0:手动 1:自动
     */
    private Integer mode;
    /**
     * 当前二维码
     * 0为空
     */
@@ -159,6 +164,16 @@
    private Long deviceDataLog = System.currentTimeMillis();
    /**
     * 指令下发时间
     */
    private Long sendTime = 0L;
    /**
     * 最近一次在线时间
     */
    private Long lastOnlineTime = System.currentTimeMillis();
    /**
     * 设备信息
     */
    private Device device;
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/thread/impl/NyShuttleThread.java
New file
@@ -0,0 +1,717 @@
package com.zy.asrs.wcs.rcs.thread.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zy.asrs.framework.common.DateUtils;
import com.zy.asrs.framework.common.SpringUtils;
import com.zy.asrs.framework.exception.CoolException;
import com.zy.asrs.wcs.common.ExecuteSupport;
import com.zy.asrs.wcs.core.entity.BasShuttle;
import com.zy.asrs.wcs.core.entity.Loc;
import com.zy.asrs.wcs.core.model.NavigateNode;
import com.zy.asrs.wcs.core.model.command.ShuttleCommand;
import com.zy.asrs.wcs.core.model.command.ShuttleRedisCommand;
import com.zy.asrs.wcs.core.model.enums.MotionCtgType;
import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType;
import com.zy.asrs.wcs.core.service.BasShuttleService;
import com.zy.asrs.wcs.core.service.LocService;
import com.zy.asrs.wcs.core.utils.NavigatePositionConvert;
import com.zy.asrs.wcs.core.utils.RedisUtil;
import com.zy.asrs.wcs.rcs.News;
import com.zy.asrs.wcs.rcs.cache.OutputQueue;
import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant;
import com.zy.asrs.wcs.rcs.entity.Device;
import com.zy.asrs.wcs.rcs.entity.DeviceDataLog;
import com.zy.asrs.wcs.rcs.model.command.NyShuttleHttpCommand;
import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType;
import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol;
import com.zy.asrs.wcs.rcs.service.DeviceDataLogService;
import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
import com.zy.asrs.wcs.system.entity.Dict;
import com.zy.asrs.wcs.system.service.DictService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.*;
@Slf4j
@SuppressWarnings("all")
public class NyShuttleThread implements ShuttleThread {
    private Device device;
    private RedisUtil redisUtil;
    private ShuttleProtocol shuttleProtocol;
    private Socket socket;
    public NyShuttleThread(Device device, RedisUtil redisUtil) {
        this.device = device;
        this.redisUtil = redisUtil;
    }
    @Override
    public void run() {
        News.info("{}号四向车线程启动", device.getDeviceNo());
        this.connect();
        while (true) {
            try {
                read();
                Thread.sleep(500);
            } catch (Exception e) {
                log.error("ShuttleThread Fail", e);
            }
        }
    }
    private void read() {
        try {
            if (this.socket == null || this.socket.isClosed()) {
                //链接断开重新链接
                this.connect();
            }
            readStatus();
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】读取四向穿梭车状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.getPort()));
        }
    }
    private void readStatus() {
        try {
            //----------读取四向穿梭车状态-----------
            NyShuttleHttpCommand readStatusCommand = getReadStatusCommand(Integer.parseInt(device.getDeviceNo()));
            JSONObject data = requestCommand(readStatusCommand);
            if (data == null) {
                shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE);
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.getPort()));
            }else {
                if (null == shuttleProtocol) {
                    shuttleProtocol = new ShuttleProtocol();
                    shuttleProtocol.setShuttleNo(Integer.valueOf(device.getDeviceNo()));
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                    shuttleProtocol.setDevice(device);
                    InnerSuhttleExtend extend = new InnerSuhttleExtend();
                    shuttleProtocol.setExtend(extend);
                }
                //----------读取四向穿梭车状态-----------
                //小车设备状态
                shuttleProtocol.setDeviceStatus(data.getInteger("free"));
                //小车模式
                shuttleProtocol.setDeviceStatus(data.getInteger("workingMode"));
                //当前二维码
                shuttleProtocol.setCurrentCode(data.getString("coord"));
                //电池电量
                shuttleProtocol.setBatteryPower(data.getString("powerPercent"));
                //电池电压
                shuttleProtocol.setBatteryVoltage(data.getInteger("voltage"));
                //故障
                shuttleProtocol.setErrorCode(data.getString("errState"));
                //是否顶升
                shuttleProtocol.setHasLift(data.getInteger("liftPosition") == 1 ? true : false);
                //是否有托盘
                shuttleProtocol.setHasPallet(data.getInteger("loadState") == 1 ? true : false);
                //行驶方向
                shuttleProtocol.setRunDirection(data.getString("runDir") == null ? "none" : data.getString("direction"));
                //是否为充电状态
                shuttleProtocol.setHasCharge(data.getInteger("chargState") == 1 ? true : false);
                //*********读取扩展字段**********
                InnerSuhttleExtend extend = (InnerSuhttleExtend) shuttleProtocol.getExtend();
                //管制状态
                extend.setSuspendState(data.getInteger("suspendState"));
                //当前速度
                extend.setSpeed(data.getInteger("speed"));
                //剩余电量
                extend.setSurplusQuantity(data.getInteger("surplusQuantity"));
                //总电量
                extend.setCountQuantity(data.getInteger("countQuantity"));
                shuttleProtocol.setExtend(extend);//扩展字段
                //最近一次在线时间
                shuttleProtocol.setLastOnlineTime(System.currentTimeMillis());
                ///读取四向穿梭车状态-end
                //小车处于运行中,将标记置为false
                if (shuttleProtocol.getDeviceStatus() == 1) {
                    shuttleProtocol.setPakMk(false);
                }
                if (shuttleProtocol.getProtocolStatusType() == null && shuttleProtocol.getDeviceStatus().intValue() == 0) {
                    //小车空闲状态、小车任务状态为未知,认定曾离线过,需要复位成空闲
                    shuttleProtocol.setProtocolStatusType(ShuttleProtocolStatusType.IDLE);
                }
                if (System.currentTimeMillis() - shuttleProtocol.getDeviceDataLog() > 1000 * 5) {
                    //采集时间超过5s,保存一次数据记录
                    //保存数据记录
                    DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class);
                    DeviceDataLog deviceDataLog = new DeviceDataLog();
                    deviceDataLog.setOriginData(JSON.toJSONString(data));
                    deviceDataLog.setWcsData(JSON.toJSONString(shuttleProtocol));
                    deviceDataLog.setType(String.valueOf(SlaveType.Shuttle));
                    deviceDataLog.setDeviceNo(String.valueOf(shuttleProtocol.getShuttleNo()));
                    deviceDataLog.setCreateTime(new Date());
                    deviceDataLog.setHostId(device.getHostId());
                    deviceDataLogService.save(deviceDataLog);
                    //更新采集时间
                    shuttleProtocol.setDeviceDataLog(System.currentTimeMillis());
                }
                //将四向穿梭车状态保存至数据库
                BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
                BasShuttle basShuttle = shuttleService.getOne(new LambdaQueryWrapper<BasShuttle>()
                        .eq(BasShuttle::getShuttleNo, device.getDeviceNo())
                        .eq(BasShuttle::getHostId, device.getHostId()));
                if (basShuttle == null) {
                    basShuttle = new BasShuttle();
                    //四向穿梭车号
                    basShuttle.setShuttleNo(Integer.valueOf(device.getDeviceNo()));
                    basShuttle.setStatus(1);
                    basShuttle.setDeleted(0);
                    basShuttle.setHostId(device.getHostId());
                    shuttleService.save(basShuttle);
                }
                //任务号
                basShuttle.setTaskNo(shuttleProtocol.getTaskNo().intValue());
                //修改时间
                basShuttle.setUpdateTime(new Date());
                //设备状态
                basShuttle.setProtocol(JSON.toJSONString(shuttleProtocol));
                if (shuttleService.updateById(basShuttle)) {
                    OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), device.getDeviceNo()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.getPort()));
            try {
                this.socket.close();
                this.socket = null;
                Thread.sleep(1000);
                this.connect();
            } catch (IOException | InterruptedException exception) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public ShuttleProtocol getStatus() {
        if (this.shuttleProtocol == null) {
            return null;
        }
        return this.shuttleProtocol.clone();
    }
    @Override
    public Device getDevice() {
        return this.device;
    }
    @Override
    public boolean movePath(List<NavigateNode> nodes, Integer taskNo) {
        return true;
    }
    @Override
    public boolean move(ShuttleCommand command) {
        try {
            //发出请求
            NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class);
            JSONObject result = requestCommand(httpCommand);
            if (result == null) {
                return false;//请求失败
            }
            this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    @Override
    public boolean lift(ShuttleCommand command) {
        try {
            //发出请求
            NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class);
            JSONObject result = requestCommand(httpCommand);
            if (result == null) {
                return false;//请求失败
            }
            this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    @Override
    public boolean charge(ShuttleCommand command) {
        try {
            //发出请求
            NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class);
            JSONObject result = requestCommand(httpCommand);
            if (result == null) {
                return false;//请求失败
            }
            this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    @Override
    public boolean reset(ShuttleCommand command) {
        return false;
    }
    @Override
    public boolean isIdle() {
        return this.isIdle(null);
    }
    @Override
    public boolean isIdle(ExecuteSupport support) {
        if (null != support) {
            if (!support.judgement()) {
                return false;
            }
        }
        if (this.shuttleProtocol.getDeviceStatus() == null
                || this.shuttleProtocol.getPakMk() == null
                || this.shuttleProtocol.getErrorCode() == null
                || this.shuttleProtocol.getProtocolStatus() == null
                || this.shuttleProtocol.getMode() == null
                || this.shuttleProtocol.getExtend() == null
        ) {
            return false;
        }
        InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend();
        boolean res = this.shuttleProtocol.getDeviceStatus() == 0
                && this.shuttleProtocol.getMode() == 1
                && this.shuttleProtocol.getPakMk()
                && this.shuttleProtocol.getErrorCode().equals("0")
                && (this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.IDLE.id || this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.WAITING.id)
                && extend.getSuspendState() == 0
                ;
        return res;
    }
    @Override
    public boolean isDeviceIdle() {
        if (this.shuttleProtocol.getDeviceStatus() == null
                || this.shuttleProtocol.getPakMk() == null
                || this.shuttleProtocol.getErrorCode() == null
                || this.shuttleProtocol.getMode() == null
                || this.shuttleProtocol.getExtend() == null
        ) {
            return false;
        }
        InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend();
        boolean res = this.shuttleProtocol.getDeviceStatus() == 0
                && this.shuttleProtocol.getMode() == 1
                && this.shuttleProtocol.getPakMk()
                && this.shuttleProtocol.getErrorCode().equals("0")
                && extend.getSuspendState() == 0
                ;
        return res;
    }
    @Override
    public boolean isRequireCharge() {
        if (this.shuttleProtocol.getDeviceStatus() == null
                || this.shuttleProtocol.getPakMk() == null
                || this.shuttleProtocol.getErrorCode() == null
                || this.shuttleProtocol.getProtocolStatus() == null
                || this.shuttleProtocol.getMode() == null
                || this.shuttleProtocol.getExtend() == null
        ) {
            return false;
        }
        InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend();
        boolean res = this.shuttleProtocol.getDeviceStatus() == 0
                && this.shuttleProtocol.getMode() == 1
                && this.shuttleProtocol.getPakMk()
                && this.shuttleProtocol.getErrorCode().equals("0")
                && this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.IDLE.id
                && extend.getSuspendState() == 0
                ;
        if (!res) {
            return res;
        } else {
            // 电量小于阈值需要进行充电
            try {
                BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
                if (shuttleService == null) {
                    return false;
                }
                BasShuttle basShuttle = shuttleService.getById(this.device.getDeviceNo());
                if (basShuttle == null) {
                    return false;
                }
                Integer chargeLine = basShuttle.getChargeLine();
                if (chargeLine == null) {
                    return false;
                }
                return Integer.valueOf(this.shuttleProtocol.getBatteryPower()) < chargeLine;
            } catch (Exception e) {
                return false;
            }
        }
    }
    @Override
    public boolean isCharging() {
        if (this.shuttleProtocol.getDeviceStatus() == null || this.shuttleProtocol.getHasCharge() == null) {
            return false;
        }
        if (this.shuttleProtocol.getDeviceStatus() == 1 && this.shuttleProtocol.getHasCharge()) {
            //运行中 && 充电中
            return true;
        }
        return false;
    }
    @Override
    public boolean isChargingCompleted() {
        Integer maxPower = 100;
        DictService dictService = SpringUtils.getBean(DictService.class);
        if (dictService != null) {
            Dict chargeMaxValue = dictService.getOne(new LambdaQueryWrapper<Dict>()
                    .eq(Dict::getFlag, "chargeMaxValue")
                    .eq(Dict::getStatus, 1));
            if (chargeMaxValue != null) {
                maxPower = Integer.parseInt(chargeMaxValue.getValue());
            }
        }
        if (this.shuttleProtocol.getHasCharge() == null) {
            return false;
        }
        if (this.shuttleProtocol.getBatteryPower() == null) {
            return false;
        }
        if (!this.shuttleProtocol.getHasCharge()) {
            return false;
        }
        if (Integer.valueOf(this.shuttleProtocol.getBatteryPower()) >= maxPower) {
            return true;
        }
        return false;
    }
    @Override
    public List<NavigateNode> getMoveAdvancePath() {
        ObjectMapper objectMapper = SpringUtils.getBean(ObjectMapper.class);
        ArrayList<NavigateNode> path = new ArrayList<>();
        if (shuttleProtocol.getTaskNo() != 0) {
            //存在任务,获取指令
            Object object = redisUtil.get(DeviceRedisConstant.SHUTTLE_WORK_FLAG + shuttleProtocol.getTaskNo());
            if (object != null) {
                ShuttleRedisCommand redisCommand = null;
                try {
                    redisCommand = objectMapper.readValue(String.valueOf(object), ShuttleRedisCommand.class);
                } catch (JsonProcessingException e) {
                    return path;
                }
                List<NavigateNode> nodes = redisCommand.getAssignCommand().getNodes();//穿梭车预计路径
                if (nodes == null) {
                    return path;
                }
                if (!nodes.isEmpty()) {
                    path.addAll(nodes);
                }
            }
        }
        return path;
    }
    @Override
    public int generateDeviceTaskNo(int taskNo, MotionCtgType motionCtgType) {
        return taskNo;
    }
    @Override
    public synchronized boolean setProtocolStatus(ShuttleProtocolStatusType status) {
        this.shuttleProtocol.setProtocolStatus(status);
        return true;
    }
    @Override
    public synchronized boolean setSyncTaskNo(Integer taskNo) {
        this.shuttleProtocol.setSyncTaskNo(taskNo);
        return true;
    }
    @Override
    public synchronized boolean setPakMk(boolean pakMk) {
        this.shuttleProtocol.setPakMk(pakMk);
        return true;
    }
    @Override
    public ShuttleCommand getMoveCommand(Integer taskNo, String startCodeNum, String distCodeNum, Integer allDistance, Integer runDirection, Integer runSpeed) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(Integer.parseInt(device.getDeviceNo()), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", "move");//移动命令
        body.put("taskId", getTaskId());//TaskID需要随机
        body.put("start", navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(startCodeNum, device.getHostId())));//起点
        body.put("target", navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(distCodeNum, device.getHostId())));//终点
        request.setBody(body);
        httpStandard.setRequest(request);
        LocService locService = SpringUtils.getBean(LocService.class);
        Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>()
                .eq(Loc::getCode, distCodeNum)
                .eq(Loc::getHostId, this.device.getHostId()));
        if (loc == null) {
            throw new CoolException("库位信息不存在");
        }
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(Integer.parseInt(this.device.getDeviceNo()));
        command.setBody(JSON.toJSONString(httpStandard));
        command.setMode(ShuttleCommandModeType.MOVE.id);
        command.setTargetLocNo(loc.getLocNo());
        return command;
    }
    @Override
    public ShuttleCommand getLiftCommand(Integer taskNo, Boolean lift) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(Integer.parseInt(device.getDeviceNo()), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", lift ? "liftUp" : "liftDown");//顶升或下降命令
        body.put("taskId", getTaskId());//TaskID需要随机
        request.setBody(body);
        httpStandard.setRequest(request);
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(Integer.parseInt(this.device.getDeviceNo()));
        command.setBody(JSON.toJSONString(body));
        command.setMode(lift ? ShuttleCommandModeType.PALLET_LIFT.id : ShuttleCommandModeType.PALLET_DOWN.id);
        return command;
    }
    @Override
    public ShuttleCommand getChargeCommand(Integer taskNo, Boolean charge) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(Integer.parseInt(device.getDeviceNo()), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", charge ? "charge" : "stopCharge");//充电或停止充电
        body.put("taskId", getTaskId());//TaskID需要随机
        request.setBody(body);
        httpStandard.setRequest(request);
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(Integer.parseInt(this.device.getDeviceNo()));
        command.setBody(JSON.toJSONString(httpStandard));
        command.setMode(charge ? ShuttleCommandModeType.CHARGE_OPEN.id : ShuttleCommandModeType.CHARGE_CLOSE.id);
        return command;
    }
    @Override
    public boolean connect() {
        try {
            Socket socket = new Socket(device.getIp(),device.getPort());
            socket.setSoTimeout(60000);
            socket.setKeepAlive(true);
            this.socket = socket;
            if (null == shuttleProtocol) {
                shuttleProtocol = new ShuttleProtocol();
                shuttleProtocol.setShuttleNo(Integer.parseInt(device.getDeviceNo()));
            }
            shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
            log.info(MessageFormat.format("【{0}】四向穿梭车Socket链接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.getPort()));
        } catch (IOException e) {
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket链接失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.getPort()));
        }
        return true;
    }
    @Override
    public void close() {
    }
    //获取HTTP请求标准结构体
    private NyShuttleHttpCommand getHttpStandard(Integer shuttleNo, Integer taskNo) {
        NyShuttleHttpCommand httpStandard = new NyShuttleHttpCommand();
        httpStandard.setMsgType("requestMsg");//请求消息
        httpStandard.setRobotId(shuttleNo);//车辆编号
        httpStandard.setTaskNo(taskNo);//工作号
        //设置请求消息
        NyShuttleHttpCommand.NyRequest request = new NyShuttleHttpCommand.NyRequest();
        NyShuttleHttpCommand.NyRequest.NyHeader header = new NyShuttleHttpCommand.NyRequest.NyHeader();
        header.setVersion("1.0");//版本号
        header.setRequestId(getRequestId());//消息编号
        //设置请求头
        request.setHeader(header);
        httpStandard.setRequest(request);
        return httpStandard;
    }
    //获取请求编号
    private Integer getRequestId() {
        Random random = new Random();
        return random.nextInt(9999999);
    }
    //获取TaskId
    private static Integer getTaskId() {
        Random random = new Random();
        return random.nextInt(999999);
    }
    //获取读FAS状态信息命令
    private NyShuttleHttpCommand getReadStatusCommand(Integer shuttleNo) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(shuttleNo, 9999);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", "readState");//读FAS状态信息
        request.setBody(body);
        httpStandard.setRequest(request);
        return httpStandard;
    }
    //发出请求
    private JSONObject requestCommand(NyShuttleHttpCommand httpCommand) throws IOException {
        if (this.socket == null) {
            return null;
        }
        //压缩数据包
        JSONObject data = JSON.parseObject(JSON.toJSONString(httpCommand));
        data.remove("nodes");
        // 获取输入流和输出流
        BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
        OutputStreamWriter writer = new OutputStreamWriter(this.socket.getOutputStream());
        writer.write(JSON.toJSONString(data) + "\r\n");
        writer.flush();
//            System.out.println("Sent message to server: " + JSON.toJSONString(httpCommand));
        // 读取服务器的响应
        StringBuffer sb = new StringBuffer();
        String response = null;
        char[] chars = new char[2048];//缓冲区
        do {
            reader.read(chars);
            String trim = new String(chars).trim();
            sb.append(trim);
            if (sb.lastIndexOf("\r\n") != -1) {
                break;
            }
        } while (response != null);
//            System.out.println("Received response from server: " + sb);
        JSONObject result = JSON.parseObject(sb.toString());//得到响应结果集
        if (!result.get("msgType").equals("responseMsg")) {//不是响应内容
            return null;
        }
        JSONObject resultResponse = JSON.parseObject(result.get("response").toString());
        JSONObject resultHeader = JSON.parseObject(resultResponse.get("header").toString());
        int responseId = Integer.parseInt(resultHeader.get("responseId").toString());
        if (responseId != httpCommand.getRequest().getHeader().getRequestId()) {
            return null;//响应ID与请求ID不一致,不在调试模式下
        }
        return filterBodyData(result);//返回Body结果集
    }
    private static JSONObject filterBodyData(JSONObject data) {
        Object response = data.get("response");
        if (response == null) {
            return null;
        }
        JSONObject result = JSON.parseObject(response.toString());
        Object body = result.get("body");
        if (body == null) {
            return null;
        }
        JSONObject jsonBody = JSON.parseObject(body.toString());
        return jsonBody;
    }
    //地图节点转换牛眼节点
    private static Map<String, Object> navigateNodeToNyPointNode(NavigateNode node) {
        int[] NyPosition = WCSXyzToNyXyz(node.getX(), node.getY(), node.getZ());//WCS系统坐标转牛眼坐标
        HashMap<String, Object> point = new HashMap<>();
        point.put("x", NyPosition[0]);
        point.put("y", NyPosition[1]);
        point.put("z", NyPosition[2]);
        return point;
    }
    //WCS系统坐标转牛眼坐标
    private static int[] WCSXyzToNyXyz(int x, int y, int z) {
        //WCS系统Y轴 => 牛眼X轴转换公式
        int x1 = Math.abs(y - 61) + 11;
        //WCS系统X轴 => 牛眼Y轴转换公式
        int y1 = x + 10;
        return new int[]{x1, y1, z};
    }
    @Data
    private class InnerSuhttleExtend {
        /**
         * 管制状态不在管制下/被管制中
         * 0/1
         */
        private Integer suspendState;
        /**
         * 当前速度,单位mm/s
         */
        private Integer speed;
        /**
         * 剩余电量/10(A)
         */
        private Integer surplusQuantity;
        /**
         * 总电量/10(A)
         */
        private Integer countQuantity;
    }
}
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/rcs/thread/impl/SurayShuttleThread.java
@@ -31,6 +31,8 @@
import com.zy.asrs.wcs.rcs.thread.ShuttleThread;
import com.zy.asrs.wcs.core.utils.RedisUtil;
import com.zy.asrs.wcs.rcs.entity.Device;
import com.zy.asrs.wcs.system.entity.Dict;
import com.zy.asrs.wcs.system.service.DictService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -111,6 +113,11 @@
                    //离线
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE);
                }
                if(deviceStatus != 4 || deviceStatus != 6 || deviceStatus != 7 || deviceStatus != 8 || deviceStatus != 255 || deviceStatus != -1) {
                    shuttleProtocol.setMode(1);//自动状态
                }
                shuttleProtocol.setDeviceStatus(deviceStatus);
                //当前二维码
                shuttleProtocol.setCurrentCode(data.getString("groundCode") == null ? "0" : data.getString("groundCode"));
@@ -134,6 +141,8 @@
                extend.setStatusDescription(data.getString("statusDescription"));//状态描述
                shuttleProtocol.setExtend(extend);//扩展字段
                //最近一次在线时间
                shuttleProtocol.setLastOnlineTime(System.currentTimeMillis());
                ///读取四向穿梭车状态-end
                //小车处于忙碌状态,将标记置为true
@@ -321,6 +330,7 @@
            JSONObject jsonObject = JSON.parseObject(response);
            Integer code = jsonObject.getInteger("code");
            if (code.equals(200)) {
                this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
                return true;
            }
        } catch (Exception e) {
@@ -351,6 +361,7 @@
            JSONObject jsonObject = JSON.parseObject(response);
            Integer code = jsonObject.getInteger("code");
            if (code.equals(200)) {
                this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
                return true;
            }
        } catch (Exception e) {
@@ -381,6 +392,7 @@
            JSONObject jsonObject = JSON.parseObject(response);
            Integer code = jsonObject.getInteger("code");
            if (code.equals(200)) {
                this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
                return true;
            }
        } catch (Exception e) {
@@ -472,7 +484,6 @@
                }
                return Integer.valueOf(this.shuttleProtocol.getBatteryPower()) < chargeLine;
            } catch (Exception e) {
                News.error("fail", e);
                return false;
            }
        }
@@ -493,11 +504,22 @@
    @Override
    public boolean isChargingCompleted() {
        Integer maxPower = 100;
        DictService dictService = SpringUtils.getBean(DictService.class);
        if (dictService != null) {
            Dict chargeMaxValue = dictService.getOne(new LambdaQueryWrapper<Dict>()
                    .eq(Dict::getFlag, "chargeMaxValue")
                    .eq(Dict::getStatus, 1));
            if (chargeMaxValue != null) {
                maxPower = Integer.parseInt(chargeMaxValue.getValue());
            }
        }
        if (this.shuttleProtocol.getBatteryPower() == null) {
            return false;
        }
        if (Integer.valueOf(this.shuttleProtocol.getBatteryPower()) >= 100) {
        if (Integer.valueOf(this.shuttleProtocol.getBatteryPower()) >= maxPower) {
            return true;
        }
        return false;
zy-asrs-wcs/src/main/resources/application.yml
@@ -18,7 +18,7 @@
#    url: jdbc:mysql://47.97.1.152:3306/asrs?useUnicode=trKue&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
#    username: root
#    password: zy@123
    url: jdbc:mysql://localhost:3306/asrs?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    url: jdbc:mysql://192.168.4.15:3306/asrs?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: xltys1995
#    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver