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.R;
|
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.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.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
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<String, Thread> fakeThreadMap = new ConcurrentHashMap();
|
private ConcurrentHashMap<String, Socket> fakeServerMap = new ConcurrentHashMap();
|
private ConcurrentHashMap<String, JSONObject> fakeStatusMap = new ConcurrentHashMap();
|
private ConcurrentHashMap<String, JSONObject> 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<String, Object> 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<DeviceConfig> deviceConfigs = fakeDeviceUtils.getFakeDeviceConfig();
|
for (DeviceConfig device : deviceConfigs) {
|
excuteFakeCommand(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo());
|
}
|
}catch (Exception e){
|
e.printStackTrace();
|
}
|
}
|
});
|
fakeCommandThread.start();
|
}
|
|
private synchronized void initFakeDeviceServer(FakeDeviceUtils fakeDeviceUtils) {
|
if(!enableFake){
|
return;
|
}
|
|
List<DeviceConfig> 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<DeviceConfig> 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) {
|
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);
|
|
//delay
|
Thread.sleep(2000);
|
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);
|
|
//delay
|
Thread.sleep(2000);
|
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);
|
|
//delay
|
Thread.sleep(2000);
|
fakeStatus.put("hasCharge", true);
|
|
Integer batteryPower = Integer.parseInt(fakeStatus.getString("batteryPower"));
|
while (true) {
|
Thread.sleep(10000);
|
batteryPower = batteryPower + 1;
|
fakeStatus.put("batteryPower", batteryPower);
|
fakeStatusMap.put(key, fakeStatus);
|
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);
|
|
//delay
|
Thread.sleep(2000);
|
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);
|
|
//delay
|
Thread.sleep(2000);
|
|
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")) {
|
fakeStatus.put("deviceStatus", 0);//设备忙碌
|
fakeStatusMap.put(key, fakeStatus);
|
Thread.sleep(2000);
|
|
JSONObject body = command.getJSONObject("commandBody");
|
String pathList = body.getString("path");
|
List<JSONObject> list = JSON.parseArray(pathList, JSONObject.class);
|
for (JSONObject path : list) {
|
while (true) {
|
JSONObject realFakeStatus = fakeStatusMap.get(key);
|
Integer errorCode = realFakeStatus.getInteger("errorCode");
|
if (errorCode > 0) {
|
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);
|
Thread.sleep(2000);
|
}
|
|
fakeStatus.put("deviceStatus", 1);//设备空闲
|
fakeStatusMap.put(key, fakeStatus);
|
}
|
}catch (Exception e){
|
e.printStackTrace();
|
}
|
}).start();
|
}
|
|
private void handleClient(DeviceConfig device) throws IOException {
|
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));
|
// 读取服务器的响应
|
StringBuffer sb = new StringBuffer();
|
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) {
|
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")) {
|
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<Integer>() {{
|
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<String, Thread> getFakeThreadMap() {
|
return this.fakeThreadMap;
|
}
|
|
@Override
|
public ConcurrentHashMap<String, JSONObject> getFakeStatusMap() {
|
return this.fakeStatusMap;
|
}
|
|
@Override
|
public ConcurrentHashMap<String, JSONObject> 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;
|
}
|
}
|