tom 2 тижнів тому
батько
коміт
690dd479d9
21 змінених файлів з 442 додано та 69 видалено
  1. 9 0
      pom.xml
  2. 11 2
      ruoyi-admin/src/main/resources/application-druid.yml
  3. 7 3
      ruoyi-admin/src/main/resources/application.yml
  4. 8 0
      ruoyi-sim/pom.xml
  5. 10 3
      ruoyi-sim/src/main/java/com/ruoyi/sim/controller/FaultController.java
  6. 10 13
      ruoyi-sim/src/main/java/com/ruoyi/sim/controller/HardwareCommDebugController.java
  7. 7 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/controller/RealExamCollectionController.java
  8. 6 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/controller/RealExamController.java
  9. 11 3
      ruoyi-sim/src/main/java/com/ruoyi/sim/controller/SimController.java
  10. 3 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/controller/TestIotController.java
  11. 47 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/domain/vo/FaultShowVo.java
  12. 22 2
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommBuildService.java
  13. 1 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommConst.java
  14. 84 30
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommSendService.java
  15. 53 9
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/FaultService.java
  16. 1 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamCollectionService.java
  17. 67 3
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamService.java
  18. 16 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SeatService.java
  19. 34 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SimService.java
  20. 34 0
      ruoyi-sim/src/main/java/com/ruoyi/sim/util/CRC16Modbus.java
  21. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

+ 9 - 0
pom.xml

@@ -228,6 +228,15 @@
                 <enabled>true</enabled>
             </releases>
         </repository>
+
+        <repository>
+            <id>mangoautomation</id>
+            <name>mangoautomation</name>
+            <url>https://maven.mangoautomation.net/repository/ias-release</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
     </repositories>
 
     <pluginRepositories>

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

@@ -6,13 +6,22 @@ spring:
         druid:
             # 主库数据源
             master:
+                # url: jdbc:mysql://127.0.0.1:3306/pla-chem-sim-dev-1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 # url: jdbc:mysql://47.104.188.84:65006/pla-chem-sim-dev-1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 # username: sim
                 # password: 6JwWnz6PEXRGYLr3
 
-                url: jdbc:mysql://192.168.1.40:3306/pla-chem-sim-dev-1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                # url: jdbc:mysql://192.168.1.40:3306/pla-chem-sim-dev-1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                # username: root
+                # password: 8M6ahN7BXsXXDccR
+
+                url: jdbc:mysql://192.168.1.61:4886/pla-chem-sim-dev-1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
-                password: 8M6ahN7BXsXXDccR
+                password: 7ZNo#9Arn3DFBN8N
+
+                # url: jdbc:mysql://127.0.0.1:3306/pla-chem-sim-dev-1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                # username: root
+                # password: my123456
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭

+ 7 - 3
ruoyi-admin/src/main/resources/application.yml

@@ -8,6 +8,7 @@ ruoyi:
   copyrightYear: 2024
   # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
   profile: C:/ruoyi/uploadPath
+  # profile: /home/ruoyi/uploadPath
   # 获取ip地址开关
   addressEnabled: false
   # 验证码类型 math 数字计算 char 字符验证
@@ -17,6 +18,7 @@ ruoyi:
 server:
   # 服务器的HTTP端口,默认为8080
   port: 8080
+  # port: 8093
   servlet:
     # 应用的访问路径
     context-path: /
@@ -68,17 +70,19 @@ spring:
   # redis 配置
   redis:
     # 地址
+    # host: 127.0.0.1
+    # host: 192.168.1.40
+    host: 192.168.1.61
     # host: 47.104.188.84
-    host: 192.168.1.40
     # 端口,默认为6379
-    # port: 65007
     port: 6379
+    # port: 65007
     # 数据库索引
     # database: 2
     database: 0
     # 密码
     # password: Z*eQ8xXK7ryYynFv
-    password: 6w2C%6BzjRG3dY%3
+    password: x2fs#W3rZ9dZXiMb
     # 连接超时时间
     timeout: 10s
     lettuce:

+ 8 - 0
ruoyi-sim/pom.xml

@@ -51,6 +51,14 @@
             <artifactId>jmockdata</artifactId>
             <version>4.3.0</version>
         </dependency>
+
+        <!-- https://mvnrepository.com/artifact/com.infiniteautomation/modbus4j -->
+        <!-- modbus4j -->
+        <dependency>
+            <groupId>com.infiniteautomation</groupId>
+            <artifactId>modbus4j</artifactId>
+            <version>3.0.3</version>
+        </dependency>
     </dependencies>
 
     <properties>

+ 10 - 3
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/FaultController.java

@@ -106,11 +106,17 @@ public class FaultController extends BaseController {
     }
 
     @GetMapping("/listTypeGZBW/{simType}")
-    @ApiOperation("list某模拟器型号,所有[故障部位]基础数据。")
+    @ApiOperation("list某模拟器型号,所有的 包括真实的,虚假的,[故障部位]基础数据。")
     public AjaxResult listType3and30(@PathVariable(value = "simType") String simType) {
         return faultService.listType3and30(simType);
     }
 
+    @GetMapping("/listTypeRealGZBW/{simType}")
+    @ApiOperation("list某模拟器型号,所有的真实的[故障部位]基础数据。")
+    public AjaxResult listType3(@PathVariable(value = "simType") String simType) {
+        return faultService.listType3(simType);
+    }
+
     @GetMapping("/listTypeGZXX/{simType}")
     @ApiOperation("list某模拟器型号,所有[故障现象]基础数据。")
     public AjaxResult listType1(@PathVariable(value = "simType") String simType) {
@@ -129,8 +135,9 @@ public class FaultController extends BaseController {
         return faultService.listEnableByType(simType, Fault.Type.PCFF);
     }
 
-    @GetMapping("/listTypeXFJL/{simType}")
-    @ApiOperation("list某模拟器型号,所有[修复结论]基础数据。")
+    // @GetMapping("/listTypeXFJL/{simType}")
+    // @ApiOperation("list某模拟器型号,所有[修复结论]基础数据。")
+    // !!不要修复结论
     public AjaxResult listType5(@PathVariable(value = "simType") String simType) {
         return faultService.listEnableByType(simType, Fault.Type.XFJL);
     }

+ 10 - 13
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/HardwareCommDebugController.java

@@ -37,15 +37,14 @@ public class HardwareCommDebugController extends BaseController {
     @GetMapping(value = "/debugReadOneFaultResistance/{simNum}/{bindHardwareMsg}")
     @ApiOperation("debug读取一个故障位置数据")
     public AjaxResult debugReadOneFaultResistance(@PathVariable("simNum") final String simNum,
-                                                  @PathVariable("bindHardwareMsg") String bindHardwareMsg) {
+                                                  @PathVariable("bindHardwareMsg") final String bindHardwareMsg) {
         return success(commSendService.debugReadOneFaultResistance(simNum, bindHardwareMsg));
     }
 
-    @GetMapping(value = "/debugReadAllFaultResistance/{simNum}/{simType}")
+    @GetMapping(value = "/debugReadAllFaultResistance/{simNum}")
     @ApiOperation("debug读取全部故障位置数据")
-    public AjaxResult debugReadAllFaultResistance(@PathVariable("simNum") final String simNum,
-                                                  @PathVariable("simType") String simType) {
-        return success(commSendService.debugReadAllFaultResistance(simNum, simType));
+    public AjaxResult debugReadAllFaultResistance(@PathVariable("simNum") final String simNum) {
+        return success(commSendService.debugReadAllFaultResistance(simNum));
     }
 
     @GetMapping(value = "/debugClearOneFault/{simNum}/{bindHardwareMsg}")
@@ -55,11 +54,10 @@ public class HardwareCommDebugController extends BaseController {
         return success(commSendService.debugClearOneFault(simNum, bindHardwareMsg));
     }
 
-    @GetMapping(value = "/debugClearAllFault/{simNum}/{simType}")
+    @GetMapping(value = "/debugClearAllFault/{simNum}")
     @ApiOperation("debug清除所有故障")
-    public AjaxResult debugClearAllFault(@PathVariable("simNum") final String simNum,
-                                         @PathVariable("simType") final String simType) {
-        return success(commSendService.debugClearAllFault(simNum, simType));
+    public AjaxResult debugClearAllFault(@PathVariable("simNum") final String simNum) {
+        return success(commSendService.debugClearAllFault(simNum));
     }
 
     @GetMapping(value = "/debugWriteOneFault/{simNum}/{bindHardwareMsg}")
@@ -69,10 +67,9 @@ public class HardwareCommDebugController extends BaseController {
         return success(commSendService.debugWriteOneFault(simNum, bindHardwareMsg));
     }
 
-    @GetMapping(value = "/debugWriteAllFault/{simNum}/{simType}")
+    @GetMapping(value = "/debugWriteAllFault/{simNum}")
     @ApiOperation("debug下发所有故障")
-    public AjaxResult debugWriteAllFault(@PathVariable("simNum") final String simNum,
-                                         @PathVariable("simType") final String simType) {
-        return success(commSendService.debugWriteAllFault(simNum, simType));
+    public AjaxResult debugWriteAllFault(@PathVariable("simNum") final String simNum) {
+        return success(commSendService.debugWriteAllFault(simNum));
     }
 }

+ 7 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/RealExamCollectionController.java

@@ -2,9 +2,12 @@ package com.ruoyi.sim.controller;
 
 import cn.ele6.catalyzer.ruoyi.vue.enhance.TableDataInfo;
 import com.ruoyi.sim.domain.vo.RealExamCollectionVo;
+import com.ruoyi.sim.service.impl.CommSendService;
 import com.ruoyi.sim.service.impl.RealExamCollectionService;
 import io.swagger.annotations.Api;
 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;
@@ -29,6 +32,8 @@ import com.ruoyi.sim.domain.RealExamCollection;
 @Api("考试集合Controller")
 public class RealExamCollectionController extends BaseController {
 
+    private static final Logger l = LoggerFactory.getLogger(RealExamCollectionController.class);
+
     @Autowired
     private RealExamCollectionService service;
 
@@ -95,6 +100,7 @@ public class RealExamCollectionController extends BaseController {
     @PutMapping(value = "/teacher/exam/open/{examCollectionId}")
     @ApiOperation("[教师][演示使用]打开考试集合")
     public AjaxResult openExam(@PathVariable("examCollectionId") Long examCollectionId) {
+        l.info("[教师][演示使用]打开考试集合");
         return service.open(examCollectionId);
     }
 
@@ -107,6 +113,7 @@ public class RealExamCollectionController extends BaseController {
     @PutMapping(value = "/teacher/exam/close/{examCollectionId}")
     @ApiOperation("[教师][演示使用]关闭考试集合")
     public AjaxResult closeExam(@PathVariable("examCollectionId") Long examCollectionId) {
+        l.info("[教师][演示使用]关闭考试集合");
         return service.close(examCollectionId);
     }
 

+ 6 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/RealExamController.java

@@ -7,6 +7,8 @@ import com.ruoyi.sim.domain.vo.RealExamVo;
 import com.ruoyi.sim.service.impl.RealExamService;
 import io.swagger.annotations.Api;
 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;
@@ -32,6 +34,8 @@ import com.ruoyi.common.core.page.TableDataInfo;
 @RequestMapping("/sim/real-exam")
 @Api("考试Controller")
 public class RealExamController extends BaseController {
+
+    private static final Logger l = LoggerFactory.getLogger(RealExamController.class);
     @Autowired
     private RealExamService realExamService;
 
@@ -73,6 +77,7 @@ public class RealExamController extends BaseController {
     @GetMapping("/student/exam/start/{examId}")
     @ApiOperation("[学生][演示使用]开始考试")
     public AjaxResult studentStartRealExam(@PathVariable("examId") Long examId) {
+        l.info("[学生][演示使用]开始考试");
         return realExamService.studentStartRealExam(examId);
     }
 
@@ -85,6 +90,7 @@ public class RealExamController extends BaseController {
     @GetMapping("/student/exam/submit/{examId}")
     @ApiOperation("[学生][演示使用]交卷")
     public AjaxResult studentSubmitRealExam(@PathVariable("examId") Long examId) {
+        l.info("[学生][演示使用]交卷");
         return realExamService.studentSubmitRealExam(examId);
     }
 

+ 11 - 3
ruoyi-sim/src/main/java/com/ruoyi/sim/controller/SimController.java

@@ -30,8 +30,8 @@ public class SimController extends BaseController {
     private SimService simService;
 
     // @PreAuthorize("@ss.hasPermi('sim:sim:list')")
-    @GetMapping("/list")
-    @ApiOperation("[分页]查询模拟器列表")
+    // @GetMapping("/list")
+    // @ApiOperation("[分页]查询模拟器列表")
     public TableDataInfo list(Sim sim) {
         startPage();
         List<Sim> list = simService.selectSimList(sim);
@@ -54,7 +54,7 @@ public class SimController extends BaseController {
      * 获取模拟器详细信息
      */
     // @PreAuthorize("@ss.hasPermi('sim:sim:query')")
-    @GetMapping(value = "/{simId}")
+    // @GetMapping(value = "/{simId}")
     public AjaxResult getInfo(@PathVariable("simId") Long simId) {
         return success(simService.selectSimBySimId(simId));
     }
@@ -88,4 +88,12 @@ public class SimController extends BaseController {
     public AjaxResult remove(@PathVariable Long[] simIds) {
         return toAjax(simService.deleteSimBySimIds(simIds));
     }
+
+    // -------------------------------- tom add  --------------------------------
+
+    @GetMapping("/listAllEnable")
+    @ApiOperation("获取所有没有被禁用的模拟器列表")
+    public AjaxResult listAllEnable() {
+        return simService.listAllEnableAj();
+    }
 }

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

@@ -112,6 +112,9 @@ public class TestIotController extends BaseController {
                 realExamService.studentLoopPostRealExam(examId);
                 //
             }
+            case 66: {
+
+            }
             break;
         }
         return AjaxResult.success();

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

@@ -0,0 +1,47 @@
+package com.ruoyi.sim.domain.vo;
+
+public class FaultShowVo {
+
+    /**
+     * 故障ID
+     */
+    private String faultId;
+
+    private String name;
+
+    private String bindHardwareMsg;
+
+    private Long orderNum;
+
+    public String getFaultId() {
+        return faultId;
+    }
+
+    public void setFaultId(String faultId) {
+        this.faultId = faultId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getBindHardwareMsg() {
+        return bindHardwareMsg;
+    }
+
+    public void setBindHardwareMsg(String bindHardwareMsg) {
+        this.bindHardwareMsg = bindHardwareMsg;
+    }
+
+    public Long getOrderNum() {
+        return orderNum;
+    }
+
+    public void setOrderNum(Long orderNum) {
+        this.orderNum = orderNum;
+    }
+}

+ 22 - 2
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommBuildService.java

@@ -1,7 +1,10 @@
 package com.ruoyi.sim.service.impl;
 
 import com.ruoyi.sim.domain.SimMsg;
+import com.ruoyi.sim.util.CRC16Modbus;
 import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -10,6 +13,13 @@ import static com.ruoyi.sim.service.impl.CommConst.*;
 @Service
 public class CommBuildService {
 
+    private static final Logger l = LoggerFactory.getLogger(CommBuildService.class);
+    /**
+     * CRC-16(Modbus)
+     *
+     * https://www.23bei.com/tool/59.html
+     */
+    public static boolean CRC_16_MODBUS = true;
 
     @Autowired
     private SnowflakeIdService idService;
@@ -82,9 +92,19 @@ public class CommBuildService {
         m.append(cmd);
         m.append(cmdId);
         m.append(data);
+        if (CRC_16_MODBUS) {
+            String crcContent = m.toString();
+            byte[] sendByteContent = CommSendService.hexStrToByteArrs(crcContent);
+            l.info("sendByteContent = {}", CommSendService.bytesToHexV2(sendByteContent));
+            byte[] sendByteCrc = CRC16Modbus.calculateCRC(sendByteContent);
+            l.info("sendByteCrc = {}", CommSendService.bytesToHexV2(sendByteCrc));
+            String crc = CommSendService.bytesToHexV2(sendByteCrc);
+            l.debug("crc: {}", crc.toUpperCase());
+            m.append(crc.toUpperCase());
+        }
         m.append(SUFFIX);
         final String mFinal = m.toString();
-        if (mFinal.length() != LENGTH_20) {
+        if (mFinal.length() != LENGTH_24) {
             throw new IllegalArgumentException("buildSendMsg length error");
         }
         smS.setSendMsg(mFinal);
@@ -101,7 +121,7 @@ public class CommBuildService {
         if (StringUtils.isEmpty(receiveMsg)) {
             return false;
         }
-        if (receiveMsg.length() != LENGTH_20) {
+        if (receiveMsg.length() != LENGTH_24) {
             return false;
         }
         final String orn = StringUtils.substring(receiveMsg, 4, 6);

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

@@ -44,6 +44,7 @@ public interface CommConst {
      * 报文长度
      */
     int LENGTH_20 = 20;
+    int LENGTH_24 = 24;
 
     /**
      * 请求间隔睡眠时间-long

+ 84 - 30
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/CommSendService.java

@@ -4,6 +4,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.sim.config.SimConfig;
 import com.ruoyi.sim.domain.*;
+import com.ruoyi.sim.util.CRC16Modbus;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.slf4j.Logger;
@@ -258,6 +259,7 @@ public class CommSendService {
      * @param re
      */
     public void clearOneSimAllFaultByExam(RealExam re) {
+        l.info("清除exam = {}", re);
         // check
 
         // 更新Exam状态。
@@ -266,11 +268,14 @@ public class CommSendService {
         }
         //
         List<RealExamFault> list = realExamFaultService.listAllType2InitStateByExamId(re.getExamId());
+        if (list != null) {
+            l.info("清除exam list = {}", list.size());
+        }
         list.forEach(ref -> {
             Fault f = faultService.selectFaultByFaultId(ref.getFaultId());
             if (faultService.isDisable(f.getFaultId())) {
-                l.warn("故障 {} -Disable", f.getName());
-                return;
+                l.warn("故障 {} -被禁用", f.getName());
+                throw new IllegalArgumentException("故障被禁用");
             }
             Sim s = simService.selectSimBySimId(re.getSimId());
             // check
@@ -328,11 +333,11 @@ public class CommSendService {
      * debug清除所有故障
      *
      * @param simNum
-     * @param simType
      * @return
      */
-    public List<SimMsg> debugClearAllFault(final String simNum, String simType) {
+    public List<SimMsg> debugClearAllFault(final String simNum) {
         List<SimMsg> list = new ArrayList<>();
+        String simType = simService.uniqueBySimNum(simNum).getSimType();
         for (String b : getGZBWBySimType(simType)) {
             list.add(debugClearOneFault(simNum, b));
         }
@@ -384,12 +389,12 @@ public class CommSendService {
      * debug下发所有故障
      *
      * @param simNum
-     * @param simType
      * @return
      * @throws IOException
      */
-    public List<SimMsg> debugWriteAllFault(final String simNum, String simType) {
+    public List<SimMsg> debugWriteAllFault(final String simNum) {
         List<SimMsg> list = new ArrayList<>();
+        String simType = simService.uniqueBySimNum(simNum).getSimType();
         for (String b : getGZBWBySimType(simType)) {
             list.add(debugWriteOneFault(simNum, b));
         }
@@ -481,12 +486,12 @@ public class CommSendService {
      * debug读取全部故障位置数据
      *
      * @param simNum
-     * @param simType
      * @return
      * @throws IOException
      */
-    public List<SimMsg> debugReadAllFaultResistance(final String simNum, final String simType) {
+    public List<SimMsg> debugReadAllFaultResistance(final String simNum) {
         List<SimMsg> list = new ArrayList<>();
+        String simType = simService.uniqueBySimNum(simNum).getSimType();
         for (String b : getGZBWBySimType(simType)) {
             list.add(debugReadOneFaultResistance(simNum, b));
         }
@@ -579,23 +584,38 @@ public class CommSendService {
                 simService.updateSimStateBySimId(s.getSimId(), Sim.State.SIM_OFFLINE);
                 failCountClearOne(s.getSimId());
             }
-            // 进行重试
             // 先考虑一台模拟器演示。
+            // 进行重试 start
             if (sm.getRetryCount() == RETRY_COUNT_0) {
-                l.warn("####RetryTotalCount不重试#### = {}", sm);
+                l.warn("####RetryTotalCount不重试RETRY_COUNT_0#### = {}", sm);
                 return sm;
             }
             if (sm.getRetryCount() < retryTotalCount) {
                 sm.retryCountPlus1();
                 send(sm, s, retryTotalCount, sleep);
-            } else {
                 l.warn("####RetryTotalCount重试#### = {}", sm);
+            } else {
+                l.warn("####RetryTotalCount达到重试上限#### = {}", sm);
             }
+            // 进行重试 end
         }
         return sm;
     }
 
     /**
+     * todo:
+     *
+     * @param sm
+     * @param s
+     * @param retryTotalCount
+     * @param sleep
+     * @return
+     */
+    public SimMsg sendRetry(final SimMsg sm, final Sim s, final int retryTotalCount, final long sleep) {
+        return null;
+    }
+
+    /**
      * cachedSocket is ok
      *
      * @return
@@ -665,24 +685,6 @@ public class CommSendService {
         return AjaxResult.success();
     }
 
-    public byte[] hexStrToByteArrs(String hexString) {
-//        if (StringUtils.isEmpty(hexString)) {
-//            return null;
-//        }
-        hexString = hexString.replaceAll(" ", "");
-        int len = hexString.length();
-        int index = 0;
-
-        byte[] bytes = new byte[len / 2];
-
-        while (index < len) {
-            String sub = hexString.substring(index, index + 2);
-            bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
-            index += 2;
-        }
-        return bytes;
-    }
-
     /**
      * 等同于ping命令。
      *
@@ -694,7 +696,7 @@ public class CommSendService {
         InetAddress ia = null;
         try {
             ia = InetAddress.getByName(ipV4);
-            return ia.isReachable(2000);
+            return ia.isReachable(2048);
         } catch (UnknownHostException e) {
             e.printStackTrace();
             return false;
@@ -727,4 +729,56 @@ public class CommSendService {
     private void failCountClearAll() {
         map.clear();
     }
+
+    /**
+     * https://mvnrepository.com/artifact/com.infiniteautomation/modbus4j/3.0.3
+     */
+    public void test02() {
+        byte[] data = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02}; // 示例数据
+        // int crc = ModbusUtils.calculateCRC(data);
+        // System.out.println("CRC-16/MODBUS 校验值: " + Integer.toHexString(crc));
+    }
+
+
+    public static byte[] hexStrToByteArrs(String hexString) {
+//        if (StringUtils.isEmpty(hexString)) {
+//            return null;
+//        }
+        hexString = hexString.replaceAll(" ", "");
+        int len = hexString.length();
+        int index = 0;
+
+        byte[] bytes = new byte[len / 2];
+
+        while (index < len) {
+            String sub = hexString.substring(index, index + 2);
+            bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
+            index += 2;
+        }
+        return bytes;
+    }
+
+    public String logBytesToString(byte[] bytes) {
+        if (bytes == null || bytes.length == 0) {
+            return "";
+        }
+        StringBuffer sbHex = new StringBuffer();
+        byte[] buffer = new byte[bytes.length];
+        for (int i = 0; i < bytes.length; i++) {
+            sbHex.append(String.format("%02X", buffer[i]));
+        }
+        return sbHex.toString();
+    }
+
+    public static String bytesToHexV2(byte[] bytes) {
+        StringBuilder hexString = new StringBuilder();
+        for (byte b : bytes) {
+            String hex = Integer.toHexString(0xFF & b); // 将字节转换为十六进制字符串
+            if (hex.length() == 1) {
+                hexString.append('0'); // 如果是单个字符,补零
+            }
+            hexString.append(hex);
+        }
+        return hexString.toString();
+    }
 }

+ 53 - 9
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/FaultService.java

@@ -6,6 +6,7 @@ import java.util.stream.Collectors;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.sim.domain.TaskFault;
+import com.ruoyi.sim.domain.vo.FaultShowVo;
 import com.ruoyi.sim.domain.vo.FaultTreeVo;
 import org.apache.commons.lang3.RandomUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -177,7 +178,7 @@ public class FaultService {
     }
 
     /**
-     * list某模拟器型号,所有[故障部位]基础数据。
+     * list某模拟器型号,所有的 包括真实的,虚假的,[故障部位]基础数据。
      *
      * @param simType
      * @return
@@ -191,20 +192,57 @@ public class FaultService {
             return AjaxResult.error("simType value error!");
         }
         // do query.
-        List<Fault> list = new ArrayList<>();
+        List<Fault> list1 = new ArrayList<>();
         Fault q3 = new Fault();
         q3.setSimType(simType);
         q3.setFaultState(Fault.State.ENABLE);
         q3.setFaultType(Fault.Type.REAL_GZBW);
-        list.addAll(selectFaultList(q3));
+        list1.addAll(selectFaultList(q3));
         Fault q30 = new Fault();
         q30.setSimType(simType);
         q30.setSimType(simType);
         q30.setFaultState(Fault.State.ENABLE);
         q30.setFaultType(Fault.Type.FAKE_GZBW);
-        list.addAll(selectFaultList(q30));
-        Collections.sort(list);
-        return AjaxResult.success(list);
+        list1.addAll(selectFaultList(q30));
+        Collections.sort(list1);
+        List<FaultShowVo> list2 = new ArrayList<>();
+        for (Fault f : list1) {
+            FaultShowVo vo = new FaultShowVo();
+            BeanUtils.copyProperties(f, vo);
+            list2.add(vo);
+        }
+        return AjaxResult.success(list2);
+    }
+
+    /**
+     * list某模拟器型号,所有的 包括真实的[故障部位]基础数据。
+     *
+     * @param simType
+     * @return
+     */
+    public AjaxResult listType3(final String simType) {
+        // check
+        if (StringUtils.isEmpty(simType)) {
+            return AjaxResult.error("simType empty!");
+        }
+        if (!simService.checkSimTypeOk(simType)) {
+            return AjaxResult.error("simType value error!");
+        }
+        // do query.
+        List<Fault> list1 = new ArrayList<>();
+        Fault q3 = new Fault();
+        q3.setSimType(simType);
+        q3.setFaultState(Fault.State.ENABLE);
+        q3.setFaultType(Fault.Type.REAL_GZBW);
+        list1.addAll(selectFaultList(q3));
+        Collections.sort(list1);
+        List<FaultShowVo> list2 = new ArrayList<>();
+        for (Fault f : list1) {
+            FaultShowVo vo = new FaultShowVo();
+            BeanUtils.copyProperties(f, vo);
+            list2.add(vo);
+        }
+        return AjaxResult.success(list2);
     }
 
     /**
@@ -222,13 +260,19 @@ public class FaultService {
             return AjaxResult.error("simType value error!");
         }
         // do query.
-        List<Fault> list = new ArrayList<>();
+        List<Fault> list1 = new ArrayList<>();
         Fault q = new Fault();
         q.setSimType(simType);
         q.setFaultState(Fault.State.ENABLE);
         q.setFaultType(faultType);
-        list.addAll(selectFaultList(q));
-        return AjaxResult.success(list);
+        list1.addAll(selectFaultList(q));
+        List<FaultShowVo> list2 = new ArrayList<>();
+        for (Fault f : list1) {
+            FaultShowVo vo = new FaultShowVo();
+            BeanUtils.copyProperties(f, vo);
+            list2.add(vo);
+        }
+        return AjaxResult.success(list2);
     }
 
 

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

@@ -343,6 +343,7 @@ public class RealExamCollectionService extends Ele6RYBaseService {
             updateRealExamCollection(f);
         }
         // 关闭socket
+
         return commSendService.closeSocket();
     }
 

+ 67 - 3
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/RealExamService.java

@@ -114,6 +114,19 @@ public class RealExamService {
     @Autowired
     private SimConfig simConfig;
 
+    public boolean exist(Long examId) {
+        if (examId == null) {
+            return false;
+        }
+        if (examId == 0) {
+            return false;
+        }
+        RealExam re = selectRealExamByExamId(examId);
+        if (re == null) {
+            return false;
+        }
+        return true;
+    }
 
     public List<RealExamVo> list(RealExam q) {
         List<RealExamVo> list = new ArrayList<>();
@@ -267,11 +280,32 @@ public class RealExamService {
     @Transactional
     public AjaxResult studentStartRealExam(Long examId) {
         l.info("studentStartRealExam = {}", examId);
+        // todo: 暂时没有解决方案 检查 考试的sim和seat,是否正确对应。
+        // check
+        // 检查 examId 是否正确存在
+        {
+            if (!exist(examId)) {
+                return AjaxResult.error("对应考试Id不存在!");
+            }
+        }
         RealExam re = selectRealExamByExamId(examId);
-        if (re == null) {
-            return AjaxResult.error("examId不存在!");
+        // 检查 seat_id 是否正确存在
+        {
+            if (!seatService.exist(re.getSeatId())) {
+                return  AjaxResult.error("对应座Id不存在!");
+            }
+        }
+        // 检查 sim_id 是否正确存在
+        {
+            if (!simService.exist(re.getSimId())) {
+                return AjaxResult.error("对应模拟器Id不存在!");
+            }
+        }
+        {
+            // todo:delete
+            // re.setSimId(getFakeSimId(re));
+            // l.info("fake re = {}", re);
         }
-
         // Step 1 读取对应一台模拟器 所有故障部位值。检查模拟器所有的 真实的 故障部位 是否异常 或者 空值。
 
         // Step 2 清除对应一台模拟器 所有故障部位故障。
@@ -296,6 +330,32 @@ public class RealExamService {
     }
 
     /**
+     * 根据考试集合获得sim_id
+     *
+     * @param exam
+     * @return
+     */
+    @Deprecated
+    public long getFakeSimId(RealExam exam) {
+        {
+            RealExamCollection coll = realExamCollectionService.selectRealExamCollectionByExamCollectionId(exam.getExamCollectionId());
+            String simType = coll.getSimType();
+            switch (simType) {
+                case Sim.TYPE_0001 -> {
+                    return 11L;
+                }
+                case Sim.TYPE_0002 -> {
+                    return 12L;
+                }
+                case Sim.TYPE_0003 -> {
+                    return 31L;
+                }
+            }
+        }
+        return 0L;
+    }
+
+    /**
      * [轮询][学生]正在考试界面。
      *
      * @param realExamId
@@ -323,6 +383,10 @@ public class RealExamService {
     @Transactional
     public AjaxResult studentSubmitRealExam(Long examId) {
         RealExam re = selectRealExamByExamId(examId);
+        {
+            // todo:delete
+            // re.setSimId(getFakeSimId(re));
+        }
         // 最后检查一下模拟器状态。
         Sim s = simService.selectSimBySimId(re.getSimId());
         if (s == null || !Sim.State.ONLINE.equals(s.getSimState())) {

+ 16 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SeatService.java

@@ -80,4 +80,20 @@ public class SeatService {
     public int deleteSeatBySeatId(Long seatId) {
         return seatMapper.deleteSeatBySeatId(seatId);
     }
+
+    // -------------------------------- tom add  --------------------------------
+
+    public boolean exist(Long seatId) {
+        if (seatId == null) {
+            return false;
+        }
+        if (seatId == 0) {
+            return false;
+        }
+        Seat s = selectSeatBySeatId(seatId);
+        if (s == null) {
+            return false;
+        }
+        return true;
+    }
 }

+ 34 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/service/impl/SimService.java

@@ -4,6 +4,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.DateUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -88,10 +89,43 @@ public class SimService {
 
     // -------------------------------- tom add  --------------------------------
 
+    public boolean exist(Long simId) {
+        if (simId == null) {
+            return false;
+        }
+        if (simId == 0) {
+            return false;
+        }
+        Sim sim = selectSimBySimId(simId);
+        if (sim == null) {
+            return false;
+        }
+        return true;
+    }
+
+    public Sim uniqueBySimNum(String simNum) {
+        Sim q = new Sim();
+        q.setSimNum(simNum);
+        List<Sim> simList = simMapper.selectSimList(q);
+        if (!simList.isEmpty()) {
+            return simList.get(0);
+        }
+        return null;
+    }
+
     public List<Sim> listAll() {
         return selectSimList(new Sim());
     }
 
+    /**
+     * 获取所有没有被禁用的模拟器列表
+     *
+     * @return
+     */
+    public AjaxResult listAllEnableAj() {
+        return AjaxResult.success(listAllEnable());
+    }
+
     public List<Sim> listAllEnable() {
         List<Sim> list = new ArrayList<>();
         listAll()

+ 34 - 0
ruoyi-sim/src/main/java/com/ruoyi/sim/util/CRC16Modbus.java

@@ -0,0 +1,34 @@
+package com.ruoyi.sim.util;
+
+public class CRC16Modbus {
+
+    private static final int POLYNOMIAL = 0xA001; // CRC-16/MODBUS 多项式
+    private static final int INITIAL_VALUE = 0xFFFF; // 初始值
+
+    public static byte[] calculateCRC(byte[] data) {
+        int crc = INITIAL_VALUE;
+        for (byte b : data) {
+            crc ^= (b & 0xFF); // 将数据字节与寄存器低 8 位异或
+            for (int i = 0; i < 8; i++) {
+                if ((crc & 0x0001) != 0) { // 检查最低位
+                    crc >>= 1;
+                    crc ^= POLYNOMIAL;
+                } else {
+                    crc >>= 1;
+                }
+            }
+        }
+        // 返回 CRC 值,低位在前,高位在后
+        return new byte[]{(byte) (crc & 0xFF), (byte) (crc >> 8)};
+    }
+
+    /**
+     * main test.
+     * @param args
+     */
+    public static void main(String[] args) {
+        byte[] data = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01}; // 示例数据
+        byte[] crc = calculateCRC(data);
+        System.out.println("CRC-16/MODBUS: " + String.format("%02X %02X", crc[0], crc[1]));
+    }
+}

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

@@ -75,7 +75,7 @@ public class SysUserServiceImpl implements ISysUserService
     @DataScope(deptAlias = "d", userAlias = "u")
     public List<SysUser> selectUserList(SysUser user)
     {
-        log.info("user = {}", user);
+        // log.info("user = {}", user);
         return userMapper.selectUserList(user);
     }