Selaa lähdekoodia

改版,去掉强制关闭Socket。添加回复报文和发送报文不对应,报文货不对版的情况。

tom 2 kuukautta sitten
vanhempi
commit
b81c84b977

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

@@ -99,7 +99,7 @@ public class TestIotController extends BaseController {
             case 27: {
                 // socketService.closeOne(new SimSocketVo("192.168.1.202", 33301));
 
-                socketService.openOne(new SimSocketParamVo(SocketService.IP_TEST, SocketService.PORT_TEST), true);
+                socketService.openOne(new SimSocketParamVo(SocketService.IP_TEST, SocketService.PORT_TEST));
                 // socketService.closeOne(new SimSocketVo("192.168.1.202", 11008));
             }
             case 100: {

+ 47 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/domain/SimMsg.java

@@ -1,8 +1,10 @@
 package com.ruoyi.sim.domain;
 
 import java.util.Date;
+import java.util.Objects;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.domain.AjaxResult;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.common.annotation.Excel;
@@ -249,12 +251,57 @@ public class SimMsg extends BaseEntity {
 
 // -------------------------------- tom add  --------------------------------
 
+    public boolean isResultOk() {
+        if (Objects.equals(this.result, Result.SUCCESS)) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isResultNotOk() {
+        return !isResultOk();
+    }
+
+    public AjaxResult getDefaultErrorAR() {
+        if (Objects.equals(this.result, Result.SUCCESS)) {
+            throw new IllegalArgumentException("参数错误!");
+        } else if (Objects.equals(this.result, Result.SOCKET_CONNECT_EXCEPTION)) {
+            return AjaxResult.error("模拟器通信连接失败!");
+        } else if (Objects.equals(this.result, Result.READ_TIMEOUT_EXCEPTION)) {
+            return AjaxResult.error("模拟器通信超时!");
+        } else if (Objects.equals(this.result, Result.RECEIVE_CHECK_FAIL)) {
+            return AjaxResult.error("回复报文格式错误!");
+        } else if (Objects.equals(this.result, Result.RECEIVE_NOT_MATCH)) {
+            return AjaxResult.error("回复报文不匹配!");
+        }
+        return null;
+    }
+
     public interface Result {
+        /**
+         * 默认空值。
+         */
         Integer DEFAULT_VALUE = 0;
+        /**
+         * 成功。
+         */
         Integer SUCCESS = 200;
+        /**
+         * Socket连接问题。
+         */
         Integer SOCKET_CONNECT_EXCEPTION = 501;
+        /**
+         * SocketTimeoutException。
+         */
         Integer READ_TIMEOUT_EXCEPTION = 502;
+        /**
+         * 接收报文格式不正确。
+         */
         Integer RECEIVE_CHECK_FAIL = 520;
+        /**
+         * 接收报文格式不匹配。
+         */
+        Integer RECEIVE_NOT_MATCH = 530;
     }
 
     public SimMsg() {

+ 9 - 7
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommCheckService.java

@@ -118,7 +118,7 @@ public class CommCheckService {
      *
      * @param seat      座次
      * @param important true:重要的场景 开始考试 重试次数不同,也会进行序列号检查。false:不重要场景 定时巡查。
-     * @return
+     * @return 在线的话,带一个Sim对象出来。离线Sim对象为空。
      */
     public AjaxResult checkOneSeatState(final Seat seat, final boolean important) {
         // check args.
@@ -133,11 +133,11 @@ public class CommCheckService {
         } else {
             retryTotalCount = CommConst.RETRY_COUNT_0;
         }
-        SimMsg smS01 = commBuildService.buildSendMsgWhichSim();
-        SimMsg smR01 = commSendService.send(smS01, seat, null, retryTotalCount, commStrategy.getSleepShort());
-        Integer result = smR01.getResult();
+        SimMsg smS = commBuildService.buildSendMsgWhichSim();
+        SimMsg smR = commSendService.send(smS, seat, null, retryTotalCount, commStrategy.getSleepShort());
+        Integer result = smR.getResult();
         if (Objects.equals(result, SimMsg.Result.SUCCESS)) {
-            final String simNum = CommParseUtils.subSimNum(smR01);
+            final String simNum = CommParseUtils.subSimNum(smR.getReceiveMsg());
             Sim sim = simService.uniqueBySimNum(simNum);
             if (sim == null) {
                 return AjaxResult.error("找不到模拟器[" + simNum + "]对应数据。");
@@ -156,7 +156,7 @@ public class CommCheckService {
             // 成功的话,Obj为Sim对象。
             return AjaxResult.success(msg, sim);
         } else if (Objects.equals(result, SimMsg.Result.RECEIVE_CHECK_FAIL)) {
-            return AjaxResult.error("失败,报文回复异常。");
+            return smR.getDefaultErrorAR();
         } else if (Objects.equals(result, SimMsg.Result.READ_TIMEOUT_EXCEPTION)) {
             // 更新SimId
             seatService.updateCurrentSimIdBySeatNum(seat.getSeatNum(), Sim.ID_0);
@@ -164,8 +164,10 @@ public class CommCheckService {
             String msg = MessageFormat.format(msgTemp, seat.getSeatNum());
             // 失败的话,Obj为空。
             return AjaxResult.success(msg, null);
+        } else if (Objects.equals(result, SimMsg.Result.RECEIVE_NOT_MATCH)) {
+            return smR.getDefaultErrorAR();
         }
-        return AjaxResult.error("失败");
+        return AjaxResult.error("检查座次模拟器失败!", null);
     }
 
     /**

+ 21 - 3
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommParseUtils.java

@@ -7,6 +7,10 @@ import org.apache.commons.lang3.StringUtils;
 public class CommParseUtils {
 
     /**
+     * AA 08 01 03 06 00 00 00 00 15 02 55
+     */
+
+    /**
      * 截取 内容报文。
      *
      * @param
@@ -19,10 +23,24 @@ public class CommParseUtils {
         return StringUtils.substring(sm.getReceiveMsg(), 10, 18);
     }
 
-    public static String subSimNum(SimMsg sm) {
-        if (StringUtils.isBlank(sm.getReceiveMsg())) {
+    public static String subSimNum(String msg) {
+        if (StringUtils.isBlank(msg)) {
+            throw new IllegalArgumentException("模拟器回复为空!");
+        }
+        return StringUtils.substring(msg, 2, 4);
+    }
+
+    public static String subCmd(String msg) {
+        if (StringUtils.isBlank(msg)) {
+            throw new IllegalArgumentException("模拟器回复为空!");
+        }
+        return StringUtils.substring(msg, 6, 8);
+    }
+
+    public static String subCmdId(String msg) {
+        if (StringUtils.isBlank(msg)) {
             throw new IllegalArgumentException("模拟器回复为空!");
         }
-        return StringUtils.substring(sm.getReceiveMsg(), 2, 4);
+        return StringUtils.substring(msg, 8, 10);
     }
 }

+ 32 - 7
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommReceiveService.java

@@ -159,16 +159,16 @@ public class CommReceiveService {
             // 判断必须存在
             String WHG_EXIST_MSG = checkValue.substring(4, 6);
             if (WHG_MSG_EXIST_YES.equals(WHG_EXIST_MSG)) {
-                return AjaxResult.success(f);
+                return AjaxResult.success("", f);
             } else {
-                return AjaxResult.error("故障部位[" + f.getBindHardwareMsg() + "][" + f.getReplaceName() + "]未正确安装;", f);
+                return AjaxResult.success("故障部位[" + f.getBindHardwareMsg() + "][" + f.getReplaceName() + "]未正确安装;", f);
             }
         }
         if (BLANK_CONTENT.equals(checkValue)) {
             l.info("故障部位[" + f.getBindHardwareMsg() + "][" + f.getReplaceName() + "]未正确安装;");
-            return AjaxResult.error("故障部位[" + f.getBindHardwareMsg() + "][" + f.getReplaceName() + "]未正确安装;", f);
+            return AjaxResult.success("故障部位[" + f.getBindHardwareMsg() + "][" + f.getReplaceName() + "]未正确安装;", f);
         } else {
-            return AjaxResult.success(f);
+            return AjaxResult.success("", f);
         }
     }
 
@@ -189,12 +189,12 @@ public class CommReceiveService {
     }
 
     /**
-     * 有返回报文的情况下,检查Receive的报文。
+     * 有返回报文的情况下,检查Receive的报文格式
      *
      * @param receiveMsg
      * @return
      */
-    public AjaxResult checkReceiveMsg(final String receiveMsg) {
+    public AjaxResult checkReceiveMsgFormat(final String receiveMsg) {
         l.info("####checkReceiveMsg#### = [{}]", receiveMsg);
         String msgErr = "ReceiveMsg ";
         // check:不能是empty
@@ -234,6 +234,31 @@ public class CommReceiveService {
 
             // todo: 比对校验值,不正确。
         }
-        return AjaxResult.success("接收报文检查正确!");
+        return AjaxResult.success("接收报文格式检查正确!");
+    }
+
+    public AjaxResult checkReceiveMsgMatch(final SimMsg sm) {
+        if (sm == null) {
+            return AjaxResult.error("空报文!");
+        }
+        final String s = sm.getSendMsg();
+        final String r = sm.getReceiveMsg();
+        if (StringUtils.isBlank(s) || StringUtils.isBlank(r)) {
+            return AjaxResult.error("空报文!");
+        }
+        if (StringUtils.equals(CommParseUtils.subSimNum(s), "00")) {
+
+        } else {
+            if (!StringUtils.equals(CommParseUtils.subSimNum(s), CommParseUtils.subSimNum(r))) {
+                return AjaxResult.error("subSimNum不对应!");
+            }
+        }
+        if (!StringUtils.equals(CommParseUtils.subCmd(s), CommParseUtils.subCmd(r))) {
+            return AjaxResult.error("subCmd不对应!");
+        }
+        if (!StringUtils.equals(CommParseUtils.subCmdId(s), CommParseUtils.subCmdId(r))) {
+            return AjaxResult.error("subCmdId不对应!");
+        }
+        return AjaxResult.success("接收报文匹配正确!");
     }
 }

+ 23 - 10
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommSendService.java

@@ -124,7 +124,9 @@ public class CommSendService {
 
     public AjaxResult debugReadAllFaultResistanceBySimNum(final Long seatId) {
         // check
-
+        if (seatId == null || seatId == 0L) {
+            return AjaxResult.error("尚未选择座次。");
+        }
         //
         // 打开socket
         {
@@ -692,10 +694,11 @@ public class CommSendService {
         q.setFaultType(Fault.Type.REAL_GZBW);
         q.setSimType(sim.getSimType());
         List<Fault> list = faultService.selectFaultList(q);
+        // 未正确安装可换件故障List
         List<Fault> listNG = new ArrayList<>();
         for (Fault f : list) {
             AjaxResult ar = readOneSimOneFaultCheck(seat, sim, f);
-            if (ar.isError()) {
+            if (!StringUtils.isBlank((String) ar.get(AjaxResult.MSG_TAG))) {
                 listNG.add(f);
                 l.info("故障部位[" + f.getBindHardwareMsg() + "][" + f.getReplaceName() + "]未正确安装;");
             } else {
@@ -713,7 +716,6 @@ public class CommSendService {
         return AjaxResult.error(sbNG.toString());
     }
 
-
     /**
      * 检查读取。
      *
@@ -723,9 +725,12 @@ public class CommSendService {
      */
     public AjaxResult readOneSimOneFaultCheck(Seat seat, Sim sim, Fault f) {
         l.info("readOneSimOneFaultCheck sim = {},f = {}", sim, f);
-        SimMsg sm1 = commBuildService.buildSendMsgReadFaultResistance(sim.getSimNum(), f.getBindHardwareMsg());
-        SimMsg sm2 = send(sm1, seat, sim, RETRY_COUNT_CHECK_ONE_FAULT, commStrategy.getSleepLong());
-        return simReceiveService.getOneFaultCheck(sm2, sim, f);
+        SimMsg smS = commBuildService.buildSendMsgReadFaultResistance(sim.getSimNum(), f.getBindHardwareMsg());
+        SimMsg smR = send(smS, seat, sim, RETRY_COUNT_CHECK_ONE_FAULT, commStrategy.getSleepLong());
+        if (smR.isResultNotOk()) {
+            return smR.getDefaultErrorAR();
+        }
+        return simReceiveService.getOneFaultCheck(smR, sim, f);
     }
 
     /**
@@ -865,7 +870,7 @@ public class CommSendService {
             // 不强制重开Socket。
             // 先进行Socket相关处理。
             SimSocketParamVo sspv = seat.toSimSocketParamVo();
-            socketService.openOne(sspv, socketService.isNotOk(sspv));
+            socketService.openOne(sspv);
             // Socket情况不正确,直接返回。
             if (socketService.isNotOk(sspv)) {
                 sm.setResult(SimMsg.Result.SOCKET_CONNECT_EXCEPTION);
@@ -901,16 +906,24 @@ public class CommSendService {
             sm.setReceiveTime(DateUtils.getNowDate());
             // log.
             {
-                AjaxResult ar = commReceiveService.checkReceiveMsg(sm.getReceiveMsg());
+                AjaxResult ar = commReceiveService.checkReceiveMsgFormat(sm.getReceiveMsg());
                 if (ar.isError()) {
                     // todo:
                     l.warn("####接收错误#### = {}", sm);
                     sm.setResult(SimMsg.Result.RECEIVE_CHECK_FAIL);
                     return sm;
-                } else {
-                    l.info("####接收成功#### = {}", sm);
                 }
             }
+            {
+                AjaxResult ar = commReceiveService.checkReceiveMsgMatch(sm);
+                if (ar.isError()) {
+                    // todo:
+                    l.warn("####接收错误#### = {}", sm);
+                    sm.setResult(SimMsg.Result.RECEIVE_NOT_MATCH);
+                    return sm;
+                }
+            }
+            l.info("####接收成功#### = {}", sm);
             if (sim != null) {
                 simService.updateLastReceivedTime(sim);
             }

+ 22 - 10
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamService.java

@@ -374,7 +374,7 @@ public class RealExamService {
         }
         // Check:如果有缓存Socket并且可用,使用缓存Socket,检查并建立Socket连接;否则返回对应错误。
         {
-            AjaxResult ar = socketService.openOne(seat.toSimSocketParamVo(), true);
+            AjaxResult ar = socketService.openOne(seat.toSimSocketParamVo());
             if (ar.isError()) {
                 return ar;
             }
@@ -382,6 +382,13 @@ public class RealExamService {
         // Check:发送通用询问指令,询问是连接的哪种型号的哪一台模拟器;否则返回对应错误。
         {
             AjaxResult ar = commCheckService.checkOneSeatState(seat, true);
+            l.debug("ar = {}", ar);
+            // 没有连接模拟器。
+            if (ar.get(AjaxResult.DATA_TAG) == null ||
+                    !StringUtils.equals(((Sim) ar.get(AjaxResult.DATA_TAG)).getSimState(), Sim.State.ONLINE)) {
+                return AjaxResult.error((String) ar.get(AjaxResult.MSG_TAG));
+            }
+            // 其他的异常情况。
             if (ar.isError()) {
                 return ar;
             }
@@ -393,17 +400,22 @@ public class RealExamService {
             // 设置上seatId和simId
             re = selectRealExamByExamId(examId);
             seat = seatService.uniqueByBindIp(studentBindIp);
-            if (seat.getCurrentSimId() == 0L) {
-                return AjaxResult.success("参数错误,座次上CurrentSimId = 0");
-            }
-            if (seat.getSeatId() == 0L) {
-                return AjaxResult.success("参数错误,座次上getSeatId = 0");
-            }
             l.debug("seat = {}", seat);
             re.setSeatId(seat.getSeatId());
             re.setSimId(seat.getCurrentSimId());
             updateRealExam(re);
         }
+        // Check: seat_id 和 current_sim_id
+        {
+            RealExam re0001 = selectRealExamByExamId(examId);
+            if (re0001 == null ||
+                    re0001.getSeatId() == null ||
+                    re0001.getSeatId() == 0L ||
+                    re0001.getSimId() == null ||
+                    re0001.getSimId() == 0) {
+                return AjaxResult.error("开始考试异常!<br/>请刷新页面重试!");
+            }
+        }
         // Step:查询模拟器在线状态,纯DB查询。
         {
             AjaxResult ar = commCheckService.checkOneSimOnlineState(seat.getCurrentSimId());
@@ -578,7 +590,7 @@ public class RealExamService {
         }
         // Check:如果有缓存Socket并且可用,使用缓存Socket,检查并建立Socket连接;否则返回对应错误。
         {
-            AjaxResult ar = socketService.openOne(seatStart.toSimSocketParamVo(), true);
+            AjaxResult ar = socketService.openOne(seatStart.toSimSocketParamVo());
             if (ar.isError()) {
                 return ar;
             }
@@ -624,9 +636,9 @@ public class RealExamService {
             // 修改真实考试结束时间。
             re.setEndTime(DateUtils.getNowDate());
             updateRealExam(re);
-            return AjaxResult.success("成功交卷!");
+            return AjaxResult.success("交卷成功!");
         } else {
-            return AjaxResult.error("失败交卷!");
+            return AjaxResult.error("交卷失败考试数据不完整。");
         }
     }
 

+ 8 - 9
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SocketService.java

@@ -110,10 +110,9 @@ public class SocketService {
 
     /**
      * @param sspv
-     * @param force 是否强制使用新连接的Socket
      * @return
      */
-    public AjaxResult openOne(final SimSocketParamVo sspv, final boolean force) {
+    public AjaxResult openOne(final SimSocketParamVo sspv) {
         // check.
         if (!config.isCommGlobal()) {
             l.warn("isCommGlobal == {} [模拟器通信被禁用!]", config.isCommGlobal());
@@ -121,9 +120,9 @@ public class SocketService {
         }
         //
         try {
-            if (isNotOk(sspv) || force) {
+            if (isNotOk(sspv)) {
                 final String key = sspv.toKey();
-                l.info("openSocket cachedSocket is not ok!try new socket ip = {}:{}!forceNew = {}", sspv.getIp(), sspv.getPort(), force);
+                l.info("openSocket cachedSocket is not ok!try new socket ip = {}:{}!", sspv.getIp(), sspv.getPort());
                 closeOne(sspv, false);
                 // 不指定本地端口实现。
                 Socket s = new Socket(sspv.getIp(), sspv.getPort());
@@ -137,7 +136,7 @@ public class SocketService {
                 // socket failed count reset.
                 failedReset0(sspv);
             } else {
-                l.info("openSocket cachedSocket cache ok!cached socket ip = {}:{}!forceNew = {}", sspv.getIp(), sspv.getPort(), force);
+                l.info("openSocket cachedSocket cache ok!cached socket ip = {}:{}!", sspv.getIp(), sspv.getPort());
             }
             Seat seat = seatService.uniqueByRs485IpAndPort(sspv.getIp(), sspv.getPort());
             seat.setSeatRs485SocketState(Seat.SocketState.ONLINE);
@@ -149,7 +148,7 @@ public class SocketService {
                 return AjaxResult.error("Socket[" + sspv.getIp() + ":" + sspv.getPort() + "],重试[" + failedGet(sspv) + "]次,创建失败!");
             } else {
                 failedPlus1(sspv);
-                AjaxResult ar = openOne(sspv, force);
+                AjaxResult ar = openOne(sspv);
                 if (ar.isSuccess()) {
                     return ar;
                 } else {
@@ -164,7 +163,7 @@ public class SocketService {
             l.warn("isCommGlobal == {} [模拟器通信被禁用!]", config.isCommGlobal());
             return AjaxResult.error("模拟器通信被禁用!");
         }
-        return openOne(sspv, false);
+        return openOne(sspv);
     }
 
     /**
@@ -179,7 +178,7 @@ public class SocketService {
         }
         List<Seat> allSeat = seatService.listAllEnable();
         for (Seat s : allSeat) {
-            AjaxResult ar = openOne(s.toSimSocketParamVo(), false);
+            AjaxResult ar = openOne(s.toSimSocketParamVo());
             l.debug("AjaxResult = {}", ar);
         }
         return AjaxResult.success("所有Socket,创建成功!");
@@ -240,7 +239,7 @@ public class SocketService {
      */
     public SocketWrapCacheVo get(final SimSocketParamVo sspv) {
         if (isNotOk(sspv)) {
-            AjaxResult ar = openOne(sspv, true);
+            AjaxResult ar = openOne(sspv);
             if (ar.isError()) {
                 // todo: isError
             }