package com.zy.core.thread.fake; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zy.common.Cools; import com.zy.common.SpringUtils; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; import com.zy.core.model.param.UpdateFakeThreadStatusParam; import com.zy.core.properties.DeviceConfig; import com.zy.core.thread.FakeThread; import com.zy.core.thread.impl.NyShuttleThread; import com.zy.core.utils.FakeDeviceUtils; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @Slf4j @SuppressWarnings("all") public class FakeNyShuttleThread implements FakeThread { private RedisUtil redisUtil; private JSONObject fakeStatusDemo = JSONObject.parseObject("{\"mode\":1,\"extend\":{\"countQuantity\":400,\"suspendState\":0,\"minCellVoltage\":3279,\"chargeCycleTimes\":0,\"maxCellVoltage\":3281,\"surplusQuantity\":204,\"voltage\":5248},\"hasLift\":false,\"hasPallet\":false,\"batteryVoltage\":5248,\"runDirection\":\"2\",\"currentCode\":\"{\\\"x\\\":19,\\\"y\\\":11,\\\"z\\\":2}\",\"errorCode\":\"0\",\"hasCharge\":false,\"batteryPower\":\"51\",\"speed\":0,\"deviceStatus\":1}"); private ServerSocket serverSocket; private Integer gatewayPort; private boolean enableFake; private boolean enableFakeDeviceThread; private ConcurrentHashMap fakeThreadMap = new ConcurrentHashMap(); private ConcurrentHashMap fakeServerMap = new ConcurrentHashMap(); private ConcurrentHashMap fakeStatusMap = new ConcurrentHashMap(); private ConcurrentHashMap fakeCommandMap = new ConcurrentHashMap(); private boolean fake = false; public FakeNyShuttleThread(RedisUtil redisUtil, Integer gatewayPort, boolean enableFake, boolean enableFakeDeviceThread) { this.redisUtil = redisUtil; this.gatewayPort = gatewayPort; this.enableFake = enableFake; this.enableFakeDeviceThread = enableFakeDeviceThread; } @Override public void run() { News.info("Fake Server is Started"); FakeDeviceUtils fakeDeviceUtils = null; while (true) { try { fakeDeviceUtils = SpringUtils.getBean(FakeDeviceUtils.class); }catch (Exception e){} if(fakeDeviceUtils == null){ continue; } break; } acceptorThread(); fakeCommandThread(); initDeviceThread(fakeDeviceUtils); initFakeDeviceServer(fakeDeviceUtils); } private void acceptorThread() { if(!enableFake){ return; } Thread acceptorThread = new Thread(() -> { log.info("{}:acceptorThread is start"); try { while (true) { try { if (serverSocket == null) { serverSocket = new ServerSocket(gatewayPort); } }catch (Exception e){ e.printStackTrace(); } if(serverSocket == null){ continue; } Socket fakeSocket = serverSocket.accept(); InputStream inputStream = fakeSocket.getInputStream(); if(inputStream == null){ continue; } // 获取输入流 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); // 读取服务器的响应 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; } } // log.info("acceptorThread is end:{}", sb.toString()); JSONObject result = null; try { result = JSON.parseObject(sb.toString()); }catch (Exception e) { log.error("error body:{}", sb.toString()); e.printStackTrace(); } if(result == null){ continue; } Object msgType = result.get("msgType"); if (msgType != null) { if ("fakeDeviceFirstConnect".equals(msgType)) { DeviceConfig device = JSON.parseObject(JSON.toJSONString(result.get("deviceConfig")), DeviceConfig.class); log.info("{}:device is start,devices:{}", device.getDeviceNo(),JSON.toJSONString(fakeServerMap)); String fakeStatus = JSON.toJSONString(fakeStatusDemo); if (!Cools.isEmpty(device.getFakeInitStatus())) { fakeStatus = device.getFakeInitStatus(); } fakeServerMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeSocket); fakeStatusMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), JSON.parseObject(fakeStatus)); HashMap map = new HashMap<>(); map.put("deviceNo", device.getDeviceNo()); map.put("status", "success"); // 获取输出流 OutputStreamWriter writer = new OutputStreamWriter(fakeSocket.getOutputStream()); writer.write(JSON.toJSONString(map) + "\r\n"); writer.flush(); } } Thread.sleep(1000); } }catch (Exception e){ e.printStackTrace(); } }); acceptorThread.start(); } private void fakeCommandThread() { if(!enableFake){ return; } Thread fakeCommandThread = new Thread(() -> { while (true) { try { FakeDeviceUtils fakeDeviceUtils = null; try { fakeDeviceUtils = SpringUtils.getBean(FakeDeviceUtils.class); }catch (Exception e){} if(fakeDeviceUtils == null){ continue; } List deviceConfigs = fakeDeviceUtils.getFakeDeviceConfig(); for (DeviceConfig device : deviceConfigs) { if (!device.getDeviceType().equals(String.valueOf(SlaveType.Shuttle))) { continue; } excuteFakeCommand(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), device); } }catch (Exception e){ e.printStackTrace(); } } }); fakeCommandThread.start(); } private synchronized void initFakeDeviceServer(FakeDeviceUtils fakeDeviceUtils) { if(!enableFake){ return; } List deviceConfigs = fakeDeviceUtils.getFakeDeviceConfig(); for (DeviceConfig device : deviceConfigs) { if (!device.getDeviceType().equals(String.valueOf(SlaveType.Shuttle))) { continue; } if (!device.getThreadImpl().equals("NyShuttleThread")) { continue; } if (fakeThreadMap.containsKey(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo())) { continue; } log.info("{}:device is run,devices:{}", device.getDeviceNo(),JSON.toJSONString(fakeServerMap)); Thread fakeThread = new Thread(() -> { log.info("{}:device is start handle client", device.getDeviceNo()); try { while (true) { if(fakeServerMap.containsKey(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo())){ handleClient(device); } } }catch (Exception e){ e.printStackTrace(); } }); fakeThread.start(); fakeThreadMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeThread); } } private void initDeviceThread(FakeDeviceUtils fakeDeviceUtils) { if (!enableFakeDeviceThread) { return; } List deviceConfigs = fakeDeviceUtils.getFakeDeviceConfig(); for (DeviceConfig device : deviceConfigs) { if (!device.getDeviceType().equals(String.valueOf(SlaveType.Shuttle))) { continue; } if (!device.getThreadImpl().equals("NyShuttleThread")) { continue; } NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getDeviceNo()); if (shuttleThread == null) { // init NyShuttleThread thread = new NyShuttleThread(device, redisUtil);; new Thread(thread).start(); SlaveConnection.put(SlaveType.Shuttle, device.getDeviceNo(), thread); } try { Thread.sleep(1000); }catch (Exception e){} } } private void excuteFakeCommand(String key, DeviceConfig deviceConfig) { if (!fakeCommandMap.containsKey(key)) { return; } JSONObject command = fakeCommandMap.get(key); fakeCommandMap.remove(key); new Thread(() -> { try { log.info("Fake Shuttle Command Running: {}", JSON.toJSONString(command)); JSONObject fakeStatus = fakeStatusMap.get(key); String commandType = command.getString("commandType"); if (commandType == null) { return; } if (commandType.equals("liftUp")) { fakeStatus.put("deviceStatus", 0);//设备忙碌 fakeStatusMap.put(key, fakeStatus); long startTime = System.currentTimeMillis(); while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 2) { continue; } break; } fakeStatus.put("hasLift", true); fakeStatus.put("deviceStatus", 1);//设备空闲 fakeStatusMap.put(key, fakeStatus); } else if (commandType.equals("liftDown")) { fakeStatus.put("deviceStatus", 0);//设备忙碌 fakeStatusMap.put(key, fakeStatus); long startTime = System.currentTimeMillis(); while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 2) { continue; } break; } fakeStatus.put("hasLift", false); fakeStatus.put("deviceStatus", 1);//设备空闲 fakeStatusMap.put(key, fakeStatus); } else if (commandType.equals("charge")) { fakeStatus.put("deviceStatus", 0);//设备忙碌 fakeStatusMap.put(key, fakeStatus); long startTime = System.currentTimeMillis(); while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 2) { continue; } break; } fakeStatus.put("hasCharge", true); Integer batteryPower = Integer.parseInt(fakeStatus.getString("batteryPower")); while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 10) { continue; } batteryPower = batteryPower + 1; fakeStatus.put("batteryPower", batteryPower); fakeStatusMap.put(key, fakeStatus); startTime = System.currentTimeMillis(); if (batteryPower >= 100) { break; } } fakeStatus.put("deviceStatus", 1);//设备空闲 fakeStatusMap.put(key, fakeStatus); } else if (commandType.equals("stopCharge")) { fakeStatus.put("deviceStatus", 0);//设备忙碌 fakeStatusMap.put(key, fakeStatus); long startTime = System.currentTimeMillis(); while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 2) { continue; } break; } fakeStatus.put("hasCharge", false); fakeStatus.put("deviceStatus", 1);//设备空闲 fakeStatusMap.put(key, fakeStatus); } else if (commandType.equals("updateFloor")) { fakeStatus.put("deviceStatus", 0);//设备忙碌 fakeStatusMap.put(key, fakeStatus); long startTime = System.currentTimeMillis(); while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 2) { continue; } break; } JSONObject body = command.getJSONObject("commandBody"); String currentCode = fakeStatus.getString("currentCode"); JSONObject point = JSON.parseObject(currentCode); point.put("z", body.getInteger("z")); fakeStatus.put("currentCode", JSON.toJSONString(point)); fakeStatus.put("deviceStatus", 1);//设备空闲 fakeStatusMap.put(key, fakeStatus); } else if (commandType.equals("move") || commandType.equals("intoLift") || commandType.equals("outLift")) { String baseCommandKey = RedisKeyType.FAKE_SHUTTLE_MOVE_EXECUTE_COMMAND_LIST.key + deviceConfig.getDeviceNo() + "_"; while (true) { Set keys = redisUtil.searchKeys(baseCommandKey); if (keys.isEmpty()) { break; } } String finalKey = baseCommandKey + System.currentTimeMillis(); redisUtil.set(finalKey, true, 60 * 2); JSONObject body = command.getJSONObject("commandBody"); String requestType = body.getString("requestType"); String pathList = body.getString("path"); List executePathList = JSON.parseArray(pathList, JSONObject.class); fakeStatus.put("deviceStatus", 0);//设备忙碌 fakeStatusMap.put(key, fakeStatus); long startTime = System.currentTimeMillis(); while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 2) { continue; } break; } for (JSONObject path : executePathList) { while (true) { JSONObject realFakeStatus = fakeStatusMap.get(key); Integer errorCode = realFakeStatus.getInteger("errorCode"); if (errorCode > 0) { continue; } break; } while (true) { if((System.currentTimeMillis() - startTime) < 1000 * 1) { continue; } break; } String currentCode = fakeStatus.getString("currentCode"); JSONObject point = JSON.parseObject(currentCode); point.put("x", path.getInteger("xp")); point.put("y", path.getInteger("yp")); point.put("z", path.getInteger("z")); fakeStatus.put("currentCode", JSON.toJSONString(point)); fakeStatus.put("deviceStatus", 0);//设备忙碌 fakeStatusMap.put(key, fakeStatus); startTime = System.currentTimeMillis(); } fakeStatus.put("deviceStatus", 1);//设备空闲 fakeStatusMap.put(key, fakeStatus); redisUtil.del(finalKey); } } catch (Exception e) { e.printStackTrace(); } }).start(); } private void handleClient(DeviceConfig device) throws IOException { StringBuffer sb = new StringBuffer(); try { Socket socket = fakeServerMap.get(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo()); if (socket == null) { return; } InputStream inputStream = socket.getInputStream(); if(inputStream == null){ removeFake(device); return; } // 获取输入流 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); // 读取服务器的响应 char[] chars = new char[2048];//缓冲区 while (true) { reader.read(chars); String trim = new String(chars); int lastIndexOf = trim.lastIndexOf("\r\n"); if (lastIndexOf != -1) { trim = trim.substring(0, lastIndexOf); sb.append(trim); break; } } JSONObject result = JSON.parseObject(sb.toString()); // log.info("收到Client Data: {}", JSON.toJSONString(result)); processCommand(result, device); } catch (Exception e) { log.error("handleClient deviceNo:{},recevie:{}", device.getDeviceNo(), sb); e.printStackTrace(); } } private void removeFake(DeviceConfig device) { fakeServerMap.remove(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo()); fakeStatusMap.remove(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo()); fakeCommandMap.remove(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo()); } public void processCommand(JSONObject result, DeviceConfig device) throws IOException { String response = null; JSONObject fakeStatus = fakeStatusMap.get(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo()); JSONObject request = result.getJSONObject("request"); JSONObject header = request.getJSONObject("header"); JSONObject body = request.getJSONObject("body"); Integer requestId = header.getInteger("requestId"); String requestType = body.getString("requestType"); Integer taskId = body.getInteger("taskId"); JSONObject fakeCommand = new JSONObject(); fakeCommand.put("deviceNo", device.getDeviceNo()); fakeCommand.put("deviceType", device.getDeviceType()); fakeCommand.put("commandType", requestType); fakeCommand.put("commandBody", body); if (requestType.equals("liftUp")) { fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand); response = genereateFakeCommandResponse(requestId, taskId, requestType); } else if (requestType.equals("liftDown")) { fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand); response = genereateFakeCommandResponse(requestId, taskId, requestType); } else if (requestType.equals("charge")) { fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand); response = genereateFakeCommandResponse(requestId, taskId, requestType); } else if (requestType.equals("stopCharge")) { fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand); response = genereateFakeCommandResponse(requestId, taskId, requestType); } else if (requestType.equals("updateFloor")) { fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand); response = genereateFakeCommandResponse(requestId, taskId, requestType); } else if (requestType.equals("move") || requestType.equals("intoLift") || requestType.equals("outLift")) { fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand); response = genereateFakeCommandResponse(requestId, taskId, requestType); } else if (requestType.equals("readState")) { response = genereateFakeStatusResponse(requestId, fakeStatus, device.getDeviceNo()); } fakeStatusMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeStatus); if (response != null) { Socket fakeSocket = fakeServerMap.get(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo()); OutputStreamWriter writer = new OutputStreamWriter(fakeSocket.getOutputStream()); writer.write(response + "\r\n"); writer.flush(); } } public String genereateFakeStatusResponse(Integer taskId, JSONObject fakeStatus, Integer deviceNo) { JSONObject result = new JSONObject(); JSONObject response = new JSONObject(); result.put("msgType", "responseMsg"); result.put("robotId", deviceNo); result.put("response", response); JSONObject header = new JSONObject(); JSONObject body = new JSONObject(); response.put("header", header); response.put("body", body); header.put("responseId", taskId); header.put("version", "GV-APP-F427-N24036-1112"); body.put("responseType", "state"); body.put("workingMode", fakeStatus.getInteger("mode")); body.put("free", fakeStatus.getInteger("deviceStatus")); body.put("point", fakeStatus.getString("currentCode")); body.put("powerPercent", fakeStatus.getString("batteryPower")); body.put("voltage", fakeStatus.getInteger("batteryVoltage")); body.put("errCode", new ArrayList() {{ add(fakeStatus.getInteger("errorCode")); add(0); }}); body.put("liftPosition", fakeStatus.getBoolean("hasLift") == true ? 2 : 1); body.put("loadState", fakeStatus.getBoolean("hasPallet") == true ? 1 : 0); body.put("runDir", fakeStatus.getString("runDirection")); body.put("chargState", fakeStatus.getBoolean("hasCharge") == true ? 1 : 0); body.put("speed", fakeStatus.getInteger("speed")); JSONObject extend = fakeStatus.getJSONObject("extend"); body.put("suspendState", extend.getInteger("suspendState")); body.put("maxCellVoltage", extend.getInteger("maxCellVoltage")); body.put("minCellVoltage", extend.getInteger("minCellVoltage")); body.put("voltage", extend.getInteger("voltage")); body.put("chargeCycleTimes", extend.getInteger("chargeCycleTimes")); body.put("surplusQuantity", extend.getInteger("surplusQuantity")); body.put("countQuantity", extend.getInteger("countQuantity")); return JSON.toJSONString(result); } public String genereateFakeCommandResponse(Integer responseId, Integer taskId, String commandType) { JSONObject result = new JSONObject(); JSONObject response = new JSONObject(); result.put("msgType", "responseMsg"); result.put("robotId", 5001); result.put("response", response); JSONObject header = new JSONObject(); JSONObject body = new JSONObject(); response.put("header", header); response.put("body", body); header.put("responseId", responseId); header.put("version", "GV-APP-F427-N24036-1112"); body.put("responseType", commandType); body.put("result", "success"); body.put("taskId", taskId); return JSON.toJSONString(result); } @Override public boolean connect() { return true; } @Override public void close() { } @Override public ConcurrentHashMap getFakeThreadMap() { return this.fakeThreadMap; } @Override public ConcurrentHashMap getFakeStatusMap() { return this.fakeStatusMap; } @Override public ConcurrentHashMap getFakeCommandMap() { return this.fakeCommandMap; } @Override public boolean updateFakeStatus(UpdateFakeThreadStatusParam param) { String key = param.getDeviceType() + param.getDeviceNo(); JSONObject result = fakeStatusMap.get(key); if (result == null) { return false; } JSONObject newData = JSON.parseObject(param.getData()); this.fakeStatusMap.put(key, newData); return true; } }