#
Junjie
3 天以前 ce511a3d55e5f349b1647172e562c1659bbc8172
src/main/java/com/zy/core/thread/fake/FakeNyShuttleThread.java
@@ -2,14 +2,16 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zy.common.Cools;
import com.zy.common.SpringUtils;
import com.zy.common.exception.CoolException;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.ThreadHandler;
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;
@@ -17,112 +19,450 @@
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.*;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@SuppressWarnings("all")
public class FakeNyShuttleThread implements ThreadHandler {
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\\\":12,\\\"y\\\":37,\\\"z\\\":3}\",\"errorCode\":\"0\",\"hasCharge\":false,\"batteryPower\":\"51\",\"speed\":0,\"deviceStatus\":1}");
    private HashMap<String, Socket> fakeServerMap = new HashMap();
    private HashMap<String, JSONObject> fakeStatusMap = new HashMap();
    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) {
    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 {
                initFakeDeviceServer();
            }catch (Exception e){
                e.printStackTrace();
                fakeDeviceUtils = SpringUtils.getBean(FakeDeviceUtils.class);
            }catch (Exception e){}
            if(fakeDeviceUtils == null){
                continue;
            }
            break;
        }
        acceptorThread();
        fakeCommandThread();
        initDeviceThread(fakeDeviceUtils);
        initFakeDeviceServer(fakeDeviceUtils);
    }
    private void initFakeDeviceServer() {
        FakeDeviceUtils fakeDeviceUtils = null;
        try {
            fakeDeviceUtils = SpringUtils.getBean(FakeDeviceUtils.class);
        }catch (Exception e){}
        if(fakeDeviceUtils == null){
    private void acceptorThread() {
        if(!enableFake){
            return;
        }
        String fakeDeviceConfig = fakeDeviceUtils.getFakeDeviceConfig();
        if(null != fakeDeviceConfig){
            List<DeviceConfig> deviceConfigs = JSON.parseArray(fakeDeviceConfig, DeviceConfig.class);
            for (DeviceConfig device : deviceConfigs) {
                if (!device.getDeviceType().equals(String.valueOf(SlaveType.Shuttle))) {
                    continue;
                }
                if (!device.getThreadImpl().equals("NyShuttleThread")) {
                    continue;
                }
                if (fakeServerMap.containsKey(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo())) {
                    continue;
                }
                Thread fakeThread = new Thread(() -> {
        Thread acceptorThread = new Thread(() -> {
            log.info("{}:acceptorThread is start");
            try {
                while (true) {
                    try {
                        ServerSocket serverSocket = new ServerSocket(device.getPort());
                        Socket fakeSocket = serverSocket.accept();
                        fakeServerMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeSocket);
                        fakeStatusMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), JSON.parseObject(JSON.toJSONString(fakeStatusDemo)));
                        while (true) {
                            if(fakeSocket == null) {
                                fakeServerMap.remove(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo());
                                break;
                            }
                            handleClient(fakeSocket, device);
                        if (serverSocket == null) {
                            serverSocket = new ServerSocket(gatewayPort);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                });
                fakeThread.start();
                // init
                ThreadHandler thread = new NyShuttleThread(device, redisUtil);;
                new Thread(thread).start();
                SlaveConnection.put(SlaveType.Shuttle, device.getDeviceNo(), thread);
                    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) {
                        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<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 handleClient(Socket socket, DeviceConfig device) throws IOException {
    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, 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<String> 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<JSONObject> 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(socket.getInputStream()));
            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) {
                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));
//            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 {
@@ -136,42 +476,32 @@
        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")) {
            fakeStatus.put("hasLift", true);
            fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand);
            response = genereateFakeCommandResponse(requestId, taskId, requestType);
        } else if (requestType.equals("liftDown")) {
            fakeStatus.put("hasLift", false);
            fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand);
            response = genereateFakeCommandResponse(requestId, taskId, requestType);
        } else if (requestType.equals("charge")) {
            fakeStatus.put("hasCharge", true);
            fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand);
            response = genereateFakeCommandResponse(requestId, taskId, requestType);
        } else if (requestType.equals("stopCharge")) {
            fakeStatus.put("hasCharge", false);
            fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand);
            response = genereateFakeCommandResponse(requestId, taskId, requestType);
        } else if (requestType.equals("updateFloor")) {
            String currentCode = fakeStatus.getString("currentCode");
            JSONObject point = JSON.parseObject(currentCode);
            point.put("z", body.getInteger("z"));
            fakeStatus.put("currentCode", JSON.toJSONString(point));
            fakeCommandMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeCommand);
            response = genereateFakeCommandResponse(requestId, taskId, requestType);
        } else if (requestType.equals("move")) {
            String pathList = body.getString("path");
            List<JSONObject> list = JSON.parseArray(pathList, JSONObject.class);
            for (JSONObject path : list) {
                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));
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } 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);
            response = genereateFakeStatusResponse(requestId, fakeStatus, device.getDeviceNo());
        }
        fakeStatusMap.put(String.valueOf(SlaveType.Shuttle) + device.getDeviceNo(), fakeStatus);
@@ -183,11 +513,11 @@
        }
    }
    public String genereateFakeStatusResponse(Integer taskId, JSONObject fakeStatus) {
    public String genereateFakeStatusResponse(Integer taskId, JSONObject fakeStatus, Integer deviceNo) {
        JSONObject result = new JSONObject();
        JSONObject response = new JSONObject();
        result.put("msgType", "responseMsg");
        result.put("robotId", 5001);
        result.put("robotId", deviceNo);
        result.put("response", response);
        JSONObject header = new JSONObject();
@@ -204,7 +534,10 @@
        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("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"));
@@ -253,4 +586,31 @@
    }
    @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;
    }
}