#
Junjie
3 天以前 285a51e8bc0f9128ea238d3edfe6c654a30e1acb
src/main/java/com/zy/core/thread/impl/NyShuttleThread.java
@@ -22,10 +22,12 @@
import com.zy.common.utils.NavigatePositionConvert;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.Utils.DeviceMsgUtils;
import com.zy.core.action.ShuttleAction;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.*;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.DeviceMsgModel;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.command.NyShuttleHttpCommand;
import com.zy.core.model.command.ShuttleCommand;
@@ -38,11 +40,7 @@
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.*;
@@ -53,10 +51,10 @@
    private ShuttleSlave slave;
    private RedisUtil redisUtil;
    private ShuttleProtocol shuttleProtocol;
    private Socket socket;
    private static final boolean DEBUG = false;//调试模式
    private List<JSONObject> socketReadResults = new ArrayList<>();
    private List<JSONObject> socketResults = new ArrayList<>();
    //原始设备数据
@@ -70,26 +68,15 @@
    @Override
    public void run() {
        News.info("{}号四向车线程启动", slave.getId());
        this.connect();
        //监听消息并存储
        Thread innerThread = new Thread(() -> {
            while (true) {
                try {
                    listenSocketMessage();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        innerThread.start();
        //设备读取
        Thread readThread = new Thread(() -> {
            while (true) {
                try {
                    listenMessageFromRedis();
                    listenInit();//监听初始化事件
                    read();
                    Thread.sleep(50);
                    Thread.sleep(100);
                } catch (Exception e) {
                    log.error("ShuttleThread Fail", e);
                }
@@ -101,7 +88,13 @@
        Thread executeThread = new Thread(() -> {
            while (true) {
                try {
                    ShuttleAction shuttleAction = SpringUtils.getBean(ShuttleAction.class);
                    ShuttleAction shuttleAction = null;
                    try {
                        shuttleAction = SpringUtils.getBean(ShuttleAction.class);
                    }catch (Exception e){
                        continue;
                    }
                    if (shuttleAction == null) {
                        continue;
                    }
@@ -135,7 +128,6 @@
        Thread otherThread = new Thread(() -> {
            while (true) {
                try {
                    listenInit();//监听初始化事件
                    saveLog();//保存数据
                } catch (Exception e) {
                    e.printStackTrace();
@@ -173,28 +165,30 @@
        }
    }
    private void listenSocketMessage() {
    private void listenMessageFromRedis() {
        try {
            if (this.socket == null) {
            DeviceMsgUtils deviceMsgUtils = SpringUtils.getBean(DeviceMsgUtils.class);
            if (deviceMsgUtils == null) {
                return;
            }
            DeviceMsgModel deviceMsg = deviceMsgUtils.getDeviceMsg(SlaveType.Shuttle, slave.getId());
            if(deviceMsg == null){
                return;
            }
            JSONObject result = JSON.parseObject(deviceMsg.getDeviceMsg().toString());//得到响应结果集
            // 获取输入流
            BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            // 读取服务器的响应
            StringBuffer sb = new StringBuffer();
            char[] chars = new char[2048];//缓冲区
            while (true) {
                reader.read(chars);
                String trim = new String(chars);
                sb.append(trim);
                if (trim.lastIndexOf("\r\n") != -1) {
                    break;
            String msgType = result.getString("msgType");
            if ("responseMsg".equals(msgType)) {
                JSONObject response = result.getJSONObject("response");
                JSONObject body = response.getJSONObject("body");
                if (body.containsKey("workingMode")) {
                    //read
                    socketReadResults.add(body);
                    return;
                }
            }
            JSONObject result = JSON.parseObject(sb.toString());//得到响应结果集
            if (!socketResults.isEmpty() && socketResults.size() >= 5) {
            if (!socketResults.isEmpty() && socketResults.size() >= 20) {
                socketResults.remove(0);//清理头节点
            }
            socketResults.add(result);//添加数据
@@ -220,7 +214,6 @@
                JSONObject resultResponse = JSON.parseObject(socketResult.get("response").toString());
                JSONObject resultBody = JSON.parseObject(resultResponse.get("body").toString());
                String responseType = resultBody.get("responseType").toString();
                String responseTaskId = resultBody.get("taskId").toString();
                if (DEBUG) {
                    result = socketResult;
                    break;
@@ -230,8 +223,11 @@
                    continue;//响应类型与请求类型不一致,不在调试模式下
                }
                if (!responseTaskId.equals(taskId)) {
                    continue;//响应ID与请求ID不一致,不在调试模式下
                if (taskId != null) {
                    String responseTaskId = resultBody.get("taskId").toString();
                    if (!responseTaskId.equals(taskId)) {
                        continue;//响应ID与请求ID不一致,不在调试模式下
                    }
                }
                result = socketResult;
@@ -250,10 +246,6 @@
    private void read() {
        try {
            if (this.socket == null || this.socket.isClosed()) {
                //链接断开重新链接
                this.connect();
            }
            readStatus();
        } catch (Exception e) {
            e.printStackTrace();
@@ -273,12 +265,37 @@
            }
            //----------读取四向穿梭车状态-----------
            DeviceMsgUtils deviceMsgUtils = null;
            try {
                deviceMsgUtils = SpringUtils.getBean(DeviceMsgUtils.class);
            }catch (Exception e){
            }
            if(deviceMsgUtils == null){
                return;
            }
            NyShuttleHttpCommand readStatusCommand = getReadStatusCommand(slave.getId());
            JSONObject data = requestCommand(readStatusCommand);
            //指令超过五条,不再下发任务状态请求
            TreeSet<String> deviceCommandMsgListKey = deviceMsgUtils.getDeviceCommandMsgListKey(SlaveType.Shuttle, slave.getId());
            if (deviceCommandMsgListKey.size() < 5) {
                requestCommandAsync(readStatusCommand);//请求状态
            }
            if (this.socketReadResults.isEmpty()) {
                if (System.currentTimeMillis() - shuttleProtocol.getLastOnlineTime() > 1000 * 60) {
                    //最后一次上线时间超过60s,认定离线
                    this.shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE);
                }
                return;
            }
            JSONObject data = this.socketReadResults.get(0);
            this.socketReadResults.remove(0);
            if (data == null) {
                if (System.currentTimeMillis() - shuttleProtocol.getLastOnlineTime() > 1000 * 60) {
                    //最后一次上线时间超过60s,认定离线
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE);
                    this.shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE);
                }
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            }else {
@@ -335,9 +352,13 @@
                    shuttleProtocol.setPakMk(true);
                }
                if (shuttleProtocol.getProtocolStatusType() == null && shuttleProtocol.getDeviceStatus().intValue() == 0) {
                if (shuttleProtocol.getProtocolStatusType() == null && shuttleProtocol.getDeviceStatus().intValue() == 1) {
                    //小车空闲状态、小车任务状态为未知,认定曾离线过,需要复位成空闲
                    shuttleProtocol.setProtocolStatusType(ShuttleProtocolStatusType.IDLE);
                    this.shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                }
                if (shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.OFFLINE) && shuttleProtocol.getDeviceStatus().intValue() == 1) {
                    this.shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                }
                this.originDeviceData = data;
@@ -347,14 +368,6 @@
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            try {
                this.socket.close();
                this.socket = null;
                Thread.sleep(1000);
                this.connect();
            } catch (IOException | InterruptedException exception) {
                e.printStackTrace();
            }
        }
    }
@@ -381,6 +394,9 @@
                String requestType = resultBody.getString("requestType");
                Integer requestId = resultHeader.getInteger("requestId");
                if (requestType.equals("init")) {
                    removeIdx = i;//此数据已经处理,从结果集中剔除
                    socketResults.remove(removeIdx);
                    Integer code = resultBody.getInteger("code");
                    //小车复位请求
                    ShuttleCommand initCommand = getInitCommand(requestId, code);
@@ -388,19 +404,13 @@
                    NyShuttleHttpCommand httpCommand = JSON.parseObject(initCommand.getBody(), NyShuttleHttpCommand.class);
                    JSONObject requestResult = requestCommand(httpCommand);
                    removeIdx = i;//此数据已经处理,从结果集中剔除
                    log.info(MessageFormat.format("【{0}】四向车复位上报 ===>> [code:{1}] [ip:{2}] [port:{3}]", slave.getId(), code, slave.getIp(), slave.getPort()));
                    OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向车复位上报 ===>> [code:{1}] [ip:{2}] [port:{3}]", slave.getId(), code, slave.getIp(), slave.getPort()));
                    break;
                }
            }
            if (removeIdx != -1) {
                socketResults.remove(removeIdx);
            }
        } catch (Exception e) {
//            e.printStackTrace();
            e.printStackTrace();
        }
    }
@@ -464,18 +474,14 @@
            for (NyShuttleHttpCommand requestCommand : commandList) {
                while (true) {
                    int i = 0;
                    i++;
                    JSONObject result = requestCommand(requestCommand);
                    if (result == null) {
//                        return response;//请求失败
                        News.info("Socket命令下发失败,任务数据={},次数={}", JSON.toJSON(requestCommand), i);
                        continue;//请求失败尝试重新请求
                    }
                    this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
                    response.setMessage(JSON.toJSONString(result));
                    response.setResult(true);
                    News.info("Socket命令下发成功,任务数据={},次数={},响应数据={}", JSON.toJSON(requestCommand), i, JSON.toJSONString(result));
                    break;
                }
            }
@@ -698,6 +704,19 @@
            }
        }
        //***************判断是否满充校准***************
        Config shuttleMaxPowerVerifyConfig = configService.selectOne(new EntityWrapper<Config>()
                .eq("code", "shuttleMaxPowerVerify")
                .eq("status", 1));
        if (shuttleMaxPowerVerifyConfig != null) {
            if (shuttleMaxPowerVerifyConfig.getValue().equals("true")) {
                if (this.shuttleProtocol.getBatteryVoltage() < 5630) {
                    return false;//电压不够继续充电
                }
            }
        }
        //***************判断是否满充校准***************
        if (this.shuttleProtocol.getHasCharge() == null) {
            return false;
        }
@@ -713,6 +732,32 @@
        if (Integer.valueOf(this.shuttleProtocol.getBatteryPower()) >= maxPower) {
            return true;
        }
        return false;
    }
    @Override
    public boolean isFault() {
        if (this.shuttleProtocol.getErrorCode() == null
                || this.shuttleProtocol.getMode() == null
                || this.shuttleProtocol.getExtend() == null
        ) {
            return false;
        }
        if (this.shuttleProtocol.getMode() == 0) {
            return true;
        }
        if (!this.shuttleProtocol.getErrorCode().equals("0")) {
            return true;
        }
        InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend();
        if (extend.getSuspendState() == 1) {
            return true;
        }
        return false;
    }
@@ -1004,17 +1049,6 @@
    @Override
    public boolean connect() {
        try {
            Socket socket = new Socket(slave.getIp(), slave.getPort());
            socket.setSoTimeout(10000);
            socket.setKeepAlive(true);
            this.socket = socket;
            log.info(MessageFormat.format("【{0}】四向穿梭车Socket链接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
        } catch (IOException e) {
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket链接失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            return false;
        }
        return true;
    }
@@ -1067,47 +1101,78 @@
        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");
        // 获取输出流
        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));
        String requestType = null;
        String taskId = null;
        try {
            requestType = httpCommand.getRequest().getBody().get("requestType").toString();
            taskId = httpCommand.getRequest().getBody().get("taskId").toString();
        } catch (Exception e) {
            return null;
        }
        // 获取服务器响应
        // 尝试100次
        JSONObject result = null;
        for (int i = 0; i < 100; i++) {
            result = getRequestBody(requestType, taskId);
            if (result == null) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else {
                break;
            DeviceMsgUtils deviceMsgUtils = SpringUtils.getBean(DeviceMsgUtils.class);
            if (deviceMsgUtils == null) {
                return null;
            }
            //压缩数据包
            JSONObject data = JSON.parseObject(JSON.toJSONString(httpCommand));
            data.remove("nodes");
            String key = deviceMsgUtils.sendDeviceCommand(SlaveType.Shuttle, slave.getId(), data);
            String requestType = null;
            String taskId = null;
            try {
                requestType = httpCommand.getRequest().getBody().get("requestType").toString();
                taskId = httpCommand.getRequest().getBody().get("taskId").toString();
            } catch (Exception e) {
//            return null;
                //taskId可能取空,不报错,正常情况
            }
            // 获取服务器响应
            // 尝试30次
            JSONObject result = null;
            for (int i = 0; i < 30; i++) {
                result = getRequestBody(requestType, taskId);
                if (result == null) {
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }
            return result;//返回Body结果集
        }catch (Exception e) {
            e.printStackTrace();
        }
        return result;//返回Body结果集
        return null;
    }
    //发出请求-移步
    private void requestCommandAsync(NyShuttleHttpCommand httpCommand) throws IOException {
        try {
            DeviceMsgUtils deviceMsgUtils = SpringUtils.getBean(DeviceMsgUtils.class);
            if (deviceMsgUtils == null) {
                return;
            }
            //压缩数据包
            JSONObject data = JSON.parseObject(JSON.toJSONString(httpCommand));
            data.remove("nodes");
            String key = deviceMsgUtils.sendDeviceCommand(SlaveType.Shuttle, slave.getId(), data);
            String requestType = null;
            String taskId = null;
            try {
                requestType = httpCommand.getRequest().getBody().get("requestType").toString();
                taskId = httpCommand.getRequest().getBody().get("taskId").toString();
            } catch (Exception e) {
//            return null;
                //taskId可能取空,不报错,正常情况
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    private JSONObject filterBodyData(JSONObject data) {