Ver Fonte

保存old socket。

tom há 2 meses atrás
pai
commit
b920d62c46

+ 11 - 11
ruoyi-admin/src/main/resources/application.yml

@@ -76,23 +76,23 @@ spring:
     # server-阿里云47服务器内网
     # host: 127.0.0.1
     # host: 192.168.1.40
-    host: 192.168.1.61
+    # host: 192.168.1.61
     # server-阿里云47服务器外网
-    # host: 47.104.188.84
+    host: 47.104.188.84
     # 端口,默认为6379
-    port: 6379
-    # port: 65007
+    # port: 6379
+    port: 65007
     # 数据库索引
     # server-阿里云47服务器内网
-    # database: 2
+    database: 2
     # server-其他
-    database: 0
+    # database: 0
     # database: 2
     # 密码
     # server-阿里云47
-    # password: Z*eQ8xXK7ryYynFv
+    password: Z*eQ8xXK7ryYynFv
     # server-现场实验室
-    password: x2fs#W3rZ9dZXiMb
+    # password: x2fs#W3rZ9dZXiMb
     # server-李硕红米本机
     # password: redis123456
     # 连接超时时间
@@ -153,12 +153,12 @@ xss:
 sim-module-config:
   # 123.112.16.165
   # routerIp: 221.218.212.74
-  routerIp: 192.168.1.1
+  routerIp: 221.218.210.247
   # 123.112.16.165
   # rs485Ip: 221.218.212.74
-  rs485Ip: 192.168.1.202
+  rs485Ip: 221.218.210.247
   #
-  rs485Port: 11008
+  rs485Port: 8899
   #
   commGlobal: true
   #

+ 7 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/constant/CommConst.java

@@ -108,4 +108,11 @@ public interface CommConst {
 
     Integer PORT_MIN = 1;
     Integer PORT_MAX = 65535;
+
+    public interface COMM_TYPE {
+        Integer SET = 1;
+        Integer CLEAR = 2;
+        Integer READ = 3;
+        Integer WHO = 4;
+    }
 }

+ 8 - 13
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/RealExamController.java

@@ -3,6 +3,7 @@ package com.ruoyi.sim.controller;
 import java.util.List;
 
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.sim.domain.RealExamCollection;
 import com.ruoyi.sim.domain.vo.RealExamVo;
 import com.ruoyi.sim.service.impl.RealExamService;
 import io.swagger.annotations.Api;
@@ -10,13 +11,7 @@ import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
@@ -76,23 +71,23 @@ public class RealExamController extends BaseController {
 
     @GetMapping("/student/exam/start/{examId}")
     @ApiOperation("[学生][正式使用]开始考试")
-    public AjaxResult studentStartRealExam(@PathVariable("examId") Long examId) {
+    public AjaxResult studentStartRealExam(@PathVariable("examId") Long examId, @RequestParam final String ip) {
         l.info("[学生][正式使用]开始考试");
-        return realExamService.studentStartRealExam(examId);
+        return realExamService.studentStartRealExam(examId, ip, RealExamCollection.Type.EXAM);
     }
 
     @GetMapping("/student/exercise/start/{examId}")
     @ApiOperation("[学生][正式使用]开始练习")
-    public AjaxResult studentStartRealExercise(@PathVariable("examId") Long examId) {
+    public AjaxResult studentStartRealExercise(@PathVariable("examId") Long examId, @RequestParam final String ip) {
         l.info("[学生][正式使用]开始练习");
-        return realExamService.studentStartRealExam(examId);
+        return realExamService.studentStartRealExam(examId, ip, RealExamCollection.Type.EXERCISE);
     }
 
     @GetMapping("/student/self-exercise/start/{examId}")
     @ApiOperation("[学生][正式使用]开始自主练习")
-    public AjaxResult studentStartRealSelfExercise(@PathVariable("examId") Long examId) {
+    public AjaxResult studentStartRealSelfExercise(@PathVariable("examId") Long examId, @RequestParam final String ip) {
         l.info("[学生][正式使用]开始自主练习");
-        return realExamService.studentStartRealExam(examId);
+        return realExamService.studentStartRealExam(examId, ip, RealExamCollection.Type.SELF_EXERCISE);
     }
 
     @GetMapping("/student/exam/answering/{examId}")

+ 13 - 9
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/TestIotController.java

@@ -4,10 +4,8 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.sim.domain.Fault;
 import com.ruoyi.sim.domain.RealExam;
-import com.ruoyi.sim.service.impl.CommSendService;
-import com.ruoyi.sim.service.impl.FaultService;
-import com.ruoyi.sim.service.impl.MajorService;
-import com.ruoyi.sim.service.impl.RealExamService;
+import com.ruoyi.sim.domain.vo.SimSocketVo;
+import com.ruoyi.sim.service.impl.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -31,8 +29,10 @@ public class TestIotController extends BaseController {
     private RealExamService realExamService;
     @Autowired
     private FaultService faultService;
+    @Autowired
+    private SocketService socketService;
 
-    @ApiOperation("testIot通信")
+    @ApiOperation("debug666")
     @GetMapping(value = "/{codeId}")
     public AjaxResult testIndex(@PathVariable("codeId") Integer codeId) {
 
@@ -94,7 +94,7 @@ public class TestIotController extends BaseController {
             }
             break;
             case 22: {
-                realExamService.studentStartRealExam(examId);
+                realExamService.studentStartRealExam(examId, null, null);
                 //
             }
             break;
@@ -112,10 +112,14 @@ public class TestIotController extends BaseController {
                 realExamService.studentLoopPostRealExam(examId);
                 //
             }
-            case 66: {
-
+            case 26: {
+                AjaxResult aj = socketService.openAll();
+                return aj;
+            }
+            case 27: {
+                socketService.closeOne(new SimSocketVo("192.168.1.202", 11001));
+                socketService.closeOne(new SimSocketVo("192.168.1.202", 11008));
             }
-            break;
         }
         return AjaxResult.success();
     }

+ 36 - 12
ruoyi-sim/src/main/java/com/ruoyi/sim/domain/Seat.java

@@ -27,33 +27,39 @@ public class Seat extends BaseEntity {
     private Long seatNum;
 
     /**
-     * 学员端座次上[电脑]绑定的[IP地址]
+     * [电脑]绑定的[IP地址]
      */
-    // @Excel(name = "学员端座次上[电脑]绑定的[IP地址]")
+    @Excel(name = "[电脑]绑定的[IP地址]")
     private String seatBindIp;
 
     /**
-     * 学员端座次上[RS485]绑定的[IP地址]
+     * [RS485]绑定的[IP地址]
      */
-    // @Excel(name = "学员端座次上[RS485]绑定的[IP地址]")
+    @Excel(name = "[RS485]绑定的[IP地址]")
     private String seatRs485Ip;
 
     /**
-     * 学员端座次上[RS485]绑定的[端口]
+     * [RS485]绑定的[端口]
      */
-    // @Excel(name = "学员端座次上[RS485]绑定的[端口]")
-    private Long seatRs485Port;
+    @Excel(name = "[RS485]绑定的[端口]")
+    private Integer seatRs485Port;
+
+    /**
+     * Socket状态:[0]:初始化,[1]:打开,[2]:关闭,[5]:禁用
+     */
+    @Excel(name = "Socket状态:[0]:初始化,[1]:打开,[2]:关闭,[5]:禁用")
+    private String seatRs485SocketState;
 
     /**
      * 当前座上学员/用户ID
      */
-    // @Excel(name = "当前座上学员/用户ID")
+    @Excel(name = "当前座上学员/用户ID")
     private Long currentUserId;
 
     /**
-     * 学员端座次上模拟器的ID:[0]没有连接任何模拟器
+     * 模拟器的ID:[0]没有连接任何模拟器,[xx]:具体某台模拟器
      */
-    // @Excel(name = "学员端座次上模拟器的ID:[0]没有连接任何模拟器")
+    @Excel(name = "模拟器的ID:[0]没有连接任何模拟器,[xx]:具体某台模拟器")
     private Long currentSimId;
 
     public void setSeatId(Long seatId) {
@@ -88,14 +94,22 @@ public class Seat extends BaseEntity {
         return seatRs485Ip;
     }
 
-    public void setSeatRs485Port(Long seatRs485Port) {
+    public void setSeatRs485Port(Integer seatRs485Port) {
         this.seatRs485Port = seatRs485Port;
     }
 
-    public Long getSeatRs485Port() {
+    public Integer getSeatRs485Port() {
         return seatRs485Port;
     }
 
+    public void setSeatRs485SocketState(String seatRs485SocketState) {
+        this.seatRs485SocketState = seatRs485SocketState;
+    }
+
+    public String getSeatRs485SocketState() {
+        return seatRs485SocketState;
+    }
+
     public void setCurrentUserId(Long currentUserId) {
         this.currentUserId = currentUserId;
     }
@@ -120,6 +134,7 @@ public class Seat extends BaseEntity {
                 .append("seatBindIp", getSeatBindIp())
                 .append("seatRs485Ip", getSeatRs485Ip())
                 .append("seatRs485Port", getSeatRs485Port())
+                .append("seatRs485SocketState", getSeatRs485SocketState())
                 .append("currentUserId", getCurrentUserId())
                 .append("currentSimId", getCurrentSimId())
                 .append("createBy", getCreateBy())
@@ -129,4 +144,13 @@ public class Seat extends BaseEntity {
                 .append("remark", getRemark())
                 .toString();
     }
+
+    // -------------------------------- tom add  --------------------------------
+
+    public interface SocketState {
+        String ENABLE_INIT = "0";
+        String ONLINE = "1";
+        String OFFLINE = "2";
+        String DISABLE = "5";
+    }
 }

+ 10 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/domain/vo/SimSocketVo.java

@@ -1,5 +1,7 @@
 package com.ruoyi.sim.domain.vo;
 
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
 public class SimSocketVo {
 
     /**
@@ -34,4 +36,12 @@ public class SimSocketVo {
     public void setPort(Integer port) {
         this.port = port;
     }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this)
+                .append("ip", ip)
+                .append("port", port)
+                .toString();
+    }
 }

+ 8 - 8
ruoyi-sim/src/main/java/com/ruoyi/sim/domain/vo/SocketWrapValue.java

@@ -18,13 +18,13 @@ public class SocketWrapValue {
 
     private Socket socket;
 
-    private Long connectedTimeMillis;
+    private Long okTimeMillis;
 
-    public SocketWrapValue(String ip, Integer port, Socket socket, Long connectedTimeMillis) {
+    public SocketWrapValue(String ip, Integer port, Socket socket, Long okTimeMillis) {
         this.ip = ip;
         this.port = port;
         this.socket = socket;
-        this.connectedTimeMillis = connectedTimeMillis;
+        this.okTimeMillis = okTimeMillis;
     }
 
     public String getIp() {
@@ -43,12 +43,12 @@ public class SocketWrapValue {
         this.socket = socket;
     }
 
-    public Long getConnectedTimeMillis() {
-        return connectedTimeMillis;
+    public Long getOkTimeMillis() {
+        return okTimeMillis;
     }
 
-    public void setConnectedTimeMillis(Long connectedTimeMillis) {
-        this.connectedTimeMillis = connectedTimeMillis;
+    public void setOkTimeMillis(Long okTimeMillis) {
+        this.okTimeMillis = okTimeMillis;
     }
 
     @Override
@@ -56,7 +56,7 @@ public class SocketWrapValue {
         return new ToStringBuilder(this)
                 .append("ip", ip)
                 .append("socket", socket)
-                .append("connectedTimeMillis", connectedTimeMillis)
+                .append("okTimeMillis", okTimeMillis)
                 .toString();
     }
 }

+ 0 - 1
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommBuildService.java

@@ -70,7 +70,6 @@ public class CommBuildService {
     }
 
     /**
-     *
      * @param simNum
      * @param orn
      * @param cmd

+ 3 - 2
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommSendService.java

@@ -834,8 +834,9 @@ public class CommSendService {
                 }
             }
             previousSendSleep = sleep;
-            InputStream is = socketOldService.getCachedSocket().getInputStream();
-            OutputStream os = socketOldService.getCachedSocket().getOutputStream();
+            Socket socket = socketOldService.getCachedSocket();
+            InputStream is = socket.getInputStream();
+            OutputStream os = socket.getOutputStream();
             os.write(hexStrToByteArrs(sm.getSendMsg()));
             sm.setSendTime(DateUtils.getNowDate());
             if (s != null) {

+ 3 - 1
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/FailedCountService.java

@@ -35,7 +35,9 @@ public class FailedCountService {
     }
 
     public void reset0(final String key) {
-        failedMap.get(key).set(COUNT_0);
+        if (failedMap.containsKey(key)) {
+            failedMap.get(key).set(COUNT_0);
+        }
     }
 
     public void resetAll() {

+ 3 - 1
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamCollectionService.java

@@ -321,11 +321,13 @@ public class RealExamCollectionService extends Ele6RYBaseService {
             closeAllExamExcludeId(ref.getExamCollectionId());
         }
         // Step 4:尝试打开所有Socket,提前准备,允许有打开失败的
-
+        // SocketOldService
         AjaxResult ar1 = socketOldService.openSocket();
         if (ar1.isError()) {
             return ar1;
         }
+        //
+
         // 更新相关数据
 
 

+ 12 - 7
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamService.java

@@ -290,7 +290,7 @@ public class RealExamService {
      * @return RealExam
      */
     @Transactional
-    public AjaxResult studentStartRealExam(final Long examId) {
+    public AjaxResult studentStartRealExam(final Long examId, final String ip, final String type) {
         l.info("studentStartRealExam = {}", examId);
         // todo: 暂时没有解决方案 检查 考试的sim和seat,是否正确对应。
         {
@@ -299,43 +299,48 @@ public class RealExamService {
             // l.info("fake re = {}", re);
         }
         // check id data.
+        // Step 1:检查examId有效性。
         {
             AjaxResult arE1 = checkExamId(examId);
             if (arE1.isError()) {
                 return arE1;
             }
         }
+        // Step 2:ping通 路由器、学员端电脑、RS485;否则返回对应错误。
+        // Step 3:如果有缓存Socket并且可用,使用缓存Socket,检查并建立Socket连接;否则返回对应错误。
+        // Step 4:发送通用询问指令,询问是连接的哪种型号的哪一台模拟器;否则返回对应错误。
         RealExam re = selectRealExamByExamId(examId);
         Sim s = simService.selectSimBySimId(re.getSimId());
-        // Step 1 主动查询一次模拟器状态。获取模拟器在线/离线状态。
+        // Step 5:主动查询一次模拟器状态。更新模拟器在线/离线状态;否则返回对应错误
         {
             AjaxResult arE3 = commSendService.checkOneSimStateActive(s);
             if (arE3.isError()) {
                 return arE3;
             }
         }
+        // Step 6:修改exam表对应examId的一条数据,填充并锁定seat_id和sim_id值。
         s = simService.selectSimBySimId(re.getSimId());
-        // Step 2 读取对应一台模拟器 所有故障部位值。检查模拟器所有的 真实的 故障部位 是否异常 或者 空值。特殊的故障部位要单独判断。
+        // Step 7:可换件检查,读取对应一台模拟器 所有故障部位值。检查模拟器所有的 真实的 故障部位 是否异常 或者 空值。特殊的故障部位要单独判断。
         if (SimDebugConfig.CHECK_REPLACE_EMPTY) {
             AjaxResult arE2 = commSendService.readOneSimAllFaultCheck(s);
             if (arE2.isError()) {
                 return arE2;
             }
         }
-        // Step 3 清除对应一台模拟器 所有 真实的 故障部位故障。
+        // Step 8:清除对应一台模拟器 所有 真实的 故障部位故障。
         {
             commSendService.clearOneSimAllFaultByExam(re);
         }
-        // Step 4 下发对应一台模拟器 出题选中的 故障位置故障。
+        // Step 9:下发对应一台模拟器 出题选中的 故障位置故障。
         {
             commSendService.writeOneSimAllSelectFaultByExam(re);
         }
-        // Step 5 读取对应一台模拟器 所有的 真实的 故障部位 电阻值代表值 作为出题值。
+        // Step 10:读取对应一台模拟器 所有的 真实的 故障部位 电阻值代表值 作为出题值。
         // 修改关联状态
         {
             commSendService.readOneSimAllFaultFirstTimeByExam(re);
         }
-        // Step 6 修改当前Exam状态。
+        // Step 11:修改当前exam_id状态。
         if (realExamFaultService.isType2ExamPrepareStartOk(re.getExamId())) {
             updateOneState(re.getExamId(), RealExam.State.SIM_PREPARE_OK);
             updateOneState(re.getExamId(), RealExam.State.ANSWERING);

+ 11 - 2
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SeatService.java

@@ -1,8 +1,11 @@
 package com.ruoyi.sim.service.impl;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 import com.ruoyi.common.utils.DateUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.sim.mapper.SeatMapper;
@@ -97,7 +100,13 @@ public class SeatService {
         return true;
     }
 
-    public List<Seat> all() {
-        return seatMapper.selectSeatList(new Seat());
+    public List<Seat> listAllEnable() {
+        List<Seat> list = new ArrayList<>();
+        seatMapper.selectSeatList(new Seat())
+                .stream()
+                .filter(Objects::nonNull)
+                .filter(s -> !StringUtils.equals(Seat.SocketState.DISABLE, s.getSeatRs485SocketState()))
+                .forEach(list::add);
+        return list;
     }
 }

+ 4 - 1
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SimService.java

@@ -152,8 +152,11 @@ public class SimService {
         listAll()
                 .stream()
                 .filter(Objects::nonNull)
-                .filter(s -> !Sim.State.DISABLE.equals(s.getSimState()))
+                .filter(s -> !StringUtils.equals(Sim.State.DISABLE, s.getSimState()))
                 .forEach(list::add);
+        for (Sim sim : list) {
+            l.info("listAllEnable : {}", sim);
+        }
         return list;
     }
 

+ 71 - 33
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SocketService.java

@@ -3,6 +3,7 @@ package com.ruoyi.sim.service.impl;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.sim.config.SimConfig;
 import com.ruoyi.sim.constant.CommConst;
+import com.ruoyi.sim.domain.Seat;
 import com.ruoyi.sim.domain.vo.SimSocketVo;
 import com.ruoyi.sim.domain.vo.SocketWrapValue;
 import org.apache.commons.lang3.StringUtils;
@@ -14,6 +15,7 @@ import org.springframework.stereotype.Service;
 import java.io.IOException;
 import java.net.Socket;
 import java.util.HashMap;
+import java.util.List;
 
 import static com.ruoyi.sim.constant.CommConst.SOCKET_TIME_OUT;
 
@@ -26,11 +28,13 @@ public class SocketService {
 
     private static final Logger l = LoggerFactory.getLogger(SocketService.class);
 
-    private static final int INIT_SIZE = 16;
+    private static final int INIT_SIZE = 32;
     /**
      * 6 hours
+     * 1000L * 60 * 60 * 6
+     * 1000L * 60 * 5
      */
-    private static final long LIMIT = 1000L * 60 * 60 * 6;
+    private static final long TIMEOUT_LIMIT = 1000L * 60 * 60 * 6;
 
     /**
      * key: ip:port
@@ -42,6 +46,8 @@ public class SocketService {
     private SimConfig config;
     @Autowired
     private FailedCountService failedCountService;
+    @Autowired
+    private SeatService seatService;
 
     /**
      * @param ip   ip v4.
@@ -49,15 +55,34 @@ public class SocketService {
      * @return true:socket ok!
      */
     public boolean isOk(final String ip, final Integer port) {
-        if (cachedMap.containsKey(ip)) {
-            Socket s = cachedMap.get(buildKey(ip, port)).getSocket();
+        final String key = buildKey(ip, port);
+        if (cachedMap.containsKey(key)) {
+            Socket s = cachedMap.get(key).getSocket();
             if (s != null) {
-                return (s.isConnected() && s.isBound() && !s.isClosed());
+                return (s.isConnected() && s.isBound() && !s.isClosed() && !isTimeout(ip, port));
             }
         }
         return false;
     }
 
+    public boolean isNotOk(final String ip, final Integer port) {
+        return !isOk(ip, port);
+    }
+
+    public boolean isTimeout(final String ip, final Integer port) {
+        final String key = buildKey(ip, port);
+        if (cachedMap.containsKey(key)) {
+            Long cached = cachedMap.get(key).getOkTimeMillis();
+            if (cached == null || cached == 0L) {
+                return true;
+            }
+            if (System.currentTimeMillis() - cached > TIMEOUT_LIMIT) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * @param ip   ip v4.
      * @param port
@@ -88,8 +113,8 @@ public class SocketService {
             final String ip = ssv.getIp();
             final Integer port = ssv.getPort();
             final String key = buildKey(ip, port);
-            if (!isOk(ip, port)) {
-                l.info("openSocket cachedSocket is not ok!new socket ip = {}!", ip);
+            if (isNotOk(ip, port)) {
+                l.info("openSocket cachedSocket is not ok!new socket ip = {}:{}!", ip, port);
                 closeOne(ssv);
                 Socket s = new Socket(ip, port);
                 s.setSoTimeout(SOCKET_TIME_OUT);
@@ -97,8 +122,11 @@ public class SocketService {
                 cachedMap.put(key, value);
                 // failed count reset.
                 failedCountService.reset0(key);
+            } else {
+                l.info("openSocket cachedSocket cache ok!cached socket ip = {}:{}!", ip, port);
             }
         } catch (IOException e) {
+            l.error(ssv.toString());
             throw new RuntimeException(e);
         } finally {
 
@@ -106,64 +134,74 @@ public class SocketService {
         return AjaxResult.success("openOneSocket Success!");
     }
 
-
-
     /**
      * todo:部分返回Aj结果。
      *
-     * @param ssvs
      * @return
      */
-    public AjaxResult openAll(final SimSocketVo[] ssvs) {
+    public AjaxResult openAll() {
         if (!config.isCommGlobal()) {
             l.warn("isCommGlobal == {} [模拟器通信被禁用!]", config.isCommGlobal());
             return AjaxResult.error("模拟器通信被禁用!");
         }
-        for (SimSocketVo ssv : ssvs) {
-            openOne(ssv);
+        List<Seat> allSeat = seatService.listAllEnable();
+        for (Seat s : allSeat) {
+            openOne(new SimSocketVo(s.getSeatRs485Ip(), s.getSeatRs485Port()));
         }
         return AjaxResult.success("openAllSocket Success!");
     }
 
     public AjaxResult closeOne(final SimSocketVo ssv) {
-        String msgOk = "关闭Socket成功!";
         if (!config.isCommGlobal()) {
             l.warn("isCommGlobal == {} [模拟器通信被禁用!]", config.isCommGlobal());
             return AjaxResult.error("模拟器通信被禁用!");
         }
+        String msgOk = "关闭Socket成功!";
         final String key = buildKey(ssv.getIp(), ssv.getPort());
-        if (!cachedMap.containsKey(key)) {
-            cachedMap.remove(key);
-            return AjaxResult.success(msgOk);
-        } else {
-            try {
+        try {
+            if (cachedMap.containsKey(key)) {
                 Socket s = cachedMap.get(key).getSocket();
                 s.getInputStream().close();
                 s.getOutputStream().close();
                 s.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                cachedMap.remove(key);
-                // failed count reset.
-                failedCountService.reset0(key);
-                return AjaxResult.success(msgOk);
             }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            cachedMap.remove(key);
+            // failed count reset.
+            failedCountService.reset0(key);
+            return AjaxResult.success(msgOk);
         }
     }
 
-    public AjaxResult closeAll(final SimSocketVo[] ssvs) {
-        String msgOk = "关闭所有Socket成功!";
-        for (SimSocketVo ssv : ssvs) {
-            AjaxResult ar = closeOne(ssv);
-            if (ar != null && !ar.isSuccess()) {
-                return ar;
-            }
+    public AjaxResult closeAll() {
+        if (!config.isCommGlobal()) {
+            l.warn("isCommGlobal == {} [模拟器通信被禁用!]", config.isCommGlobal());
+            return AjaxResult.error("模拟器通信被禁用!");
+        }
+        final String msgOk = "关闭所有Socket成功!";
+        List<Seat> allSeat = seatService.listAllEnable();
+        for (Seat s : allSeat) {
+            closeOne(new SimSocketVo(s.getSeatRs485Ip(), s.getSeatRs485Port()));
         }
         return AjaxResult.success(msgOk);
     }
 
     /**
+     * @param ip
+     * @param port
+     * @return
+     */
+    public Socket get(final String ip, final Integer port) {
+        final String key = buildKey(ip, port);
+        if (isNotOk(ip, port)) {
+            openOne(new SimSocketVo(ip, port));
+        }
+        return cachedMap.get(key).getSocket();
+    }
+
+    /**
      * 初始化。
      */
     public void resetAll() {

+ 11 - 1
ruoyi-sim/src/main/resources/mapper/sim/SeatMapper.xml

@@ -10,6 +10,7 @@
         <result property="seatBindIp" column="seat_bind_ip"/>
         <result property="seatRs485Ip" column="seat_rs485_ip"/>
         <result property="seatRs485Port" column="seat_rs485_port"/>
+        <result property="seatRs485SocketState" column="seat_rs485_socket_state"/>
         <result property="currentUserId" column="current_user_id"/>
         <result property="currentSimId" column="current_sim_id"/>
         <result property="createBy" column="create_by"/>
@@ -25,6 +26,7 @@
                seat_bind_ip,
                seat_rs485_ip,
                seat_rs485_port,
+               seat_rs485_socket_state,
                current_user_id,
                current_sim_id,
                create_by,
@@ -42,6 +44,9 @@
             <if test="seatBindIp != null  and seatBindIp != ''">and seat_bind_ip = #{seatBindIp}</if>
             <if test="seatRs485Ip != null  and seatRs485Ip != ''">and seat_rs485_ip = #{seatRs485Ip}</if>
             <if test="seatRs485Port != null ">and seat_rs485_port = #{seatRs485Port}</if>
+            <if test="seatRs485SocketState != null  and seatRs485SocketState != ''">and seat_rs485_socket_state =
+                #{seatRs485SocketState}
+            </if>
             <if test="currentUserId != null ">and current_user_id = #{currentUserId}</if>
             <if test="currentSimId != null ">and current_sim_id = #{currentSimId}</if>
         </where>
@@ -53,7 +58,7 @@
     </select>
 
     <insert id="insertSeat" parameterType="Seat" useGeneratedKeys="true" keyProperty="seatId">
-        <selectKey keyProperty="seatId" order="AFTER" resultType="java.lang.Long">
+        <selectKey keyProperty="seat_id" order="AFTER" resultType="java.lang.Long">
             select LAST_INSERT_ID()
         </selectKey>
         insert into mx_seat
@@ -62,6 +67,7 @@
             <if test="seatBindIp != null and seatBindIp != ''">seat_bind_ip,</if>
             <if test="seatRs485Ip != null and seatRs485Ip != ''">seat_rs485_ip,</if>
             <if test="seatRs485Port != null">seat_rs485_port,</if>
+            <if test="seatRs485SocketState != null and seatRs485SocketState != ''">seat_rs485_socket_state,</if>
             <if test="currentUserId != null">current_user_id,</if>
             <if test="currentSimId != null">current_sim_id,</if>
             <if test="createBy != null">create_by,</if>
@@ -75,6 +81,7 @@
             <if test="seatBindIp != null and seatBindIp != ''">#{seatBindIp},</if>
             <if test="seatRs485Ip != null and seatRs485Ip != ''">#{seatRs485Ip},</if>
             <if test="seatRs485Port != null">#{seatRs485Port},</if>
+            <if test="seatRs485SocketState != null and seatRs485SocketState != ''">#{seatRs485SocketState},</if>
             <if test="currentUserId != null">#{currentUserId},</if>
             <if test="currentSimId != null">#{currentSimId},</if>
             <if test="createBy != null">#{createBy},</if>
@@ -92,6 +99,9 @@
             <if test="seatBindIp != null and seatBindIp != ''">seat_bind_ip = #{seatBindIp},</if>
             <if test="seatRs485Ip != null and seatRs485Ip != ''">seat_rs485_ip = #{seatRs485Ip},</if>
             <if test="seatRs485Port != null">seat_rs485_port = #{seatRs485Port},</if>
+            <if test="seatRs485SocketState != null and seatRs485SocketState != ''">seat_rs485_socket_state =
+                #{seatRs485SocketState},
+            </if>
             <if test="currentUserId != null">current_user_id = #{currentUserId},</if>
             <if test="currentSimId != null">current_sim_id = #{currentSimId},</if>
             <if test="createBy != null">create_by = #{createBy},</if>