package com.ruoyi.sim.service.impl; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.sim.constant.CommConst; import com.ruoyi.sim.domain.Seat; import com.ruoyi.sim.domain.Sim; import com.ruoyi.sim.domain.SimMsg; 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; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.MessageFormat; import java.util.List; import java.util.Objects; import static com.ruoyi.sim.constant.CommConst.RETRY_COUNT_0; import static com.ruoyi.sim.constant.CommConst.RETRY_COUNT_QUERY_SN_IMPORTANT; @Service public class CommCheckService { private static final Logger l = LoggerFactory.getLogger(CommCheckService.class); @Autowired private SeatService seatService; @Autowired private SimService simService; @Autowired private CommBuildService commBuildService; @Autowired private CommSendService commSendService; @Autowired private SocketService socketService; @Autowired private CommStrategy commStrategy; /** * 等同于ping命令。 * * @param ipV4 * @return * @throws IOException */ public boolean pingIsReachable(String ipV4) { InetAddress ia = null; try { ia = InetAddress.getByName(ipV4); return ia.isReachable(CommConst.PING_TIME_OUT); } catch (UnknownHostException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } } /** * ping路由器得到状态 * * @param routerIp * @return */ public AjaxResult checkRouterState(final String routerIp) { if (routerIp == null || StringUtils.isBlank(routerIp)) { throw new IllegalArgumentException("routerIp isBlank"); } if (pingIsReachable(routerIp)) { return AjaxResult.success(); } else { simService.updateAllEnableState(Sim.State.OFFLINE); seatService.updateAllEnableState(Seat.SocketState.OFFLINE); return AjaxResult.error("路由器[" + routerIp + "]无法连接!"); } } /** * pingRS485得到状态 * * @param rs485Ip * @return */ public AjaxResult checkPingRs485State(final String rs485Ip) { if (rs485Ip == null || StringUtils.isBlank(rs485Ip)) { throw new IllegalArgumentException("rs485Ip isBlank"); } if (pingIsReachable(rs485Ip)) { return AjaxResult.success(); } else { // 更新SocketState seatService.updateSocketStateByRs485Ip(rs485Ip, Seat.SocketState.OFFLINE); return AjaxResult.error("RS485物联网网关[" + rs485Ip + "]无法连接!"); } } public AjaxResult checkPingStudentPcState(final String studentIp) { if (studentIp == null || StringUtils.isBlank(studentIp)) { throw new IllegalArgumentException("studentIp isBlank"); } if (pingIsReachable(studentIp)) { return AjaxResult.success(); } else { return AjaxResult.error("学员操作端[" + studentIp + "]无法连接!"); } } /** * 检查一个座次状况。 * 维护 seat表-socket_state字段; * 维护 seat表-sim_id字段; * 维护 sim表-Online、Offline状态; * * @param seat 座次 * @param important true:重要的场景 开始考试 重试次数不同,也会进行序列号检查。false:不重要场景 定时巡查。 * @return 在线的话,带一个Sim对象出来。离线Sim对象为空。 */ public AjaxResult checkOneSeatState(final Seat seat, final boolean important) { // check args. if (seat == null) { throw new IllegalArgumentException("seat is null"); } // socketService.tryOpenOne(seat.toSimSocketParamVo()); int retryTotalCount; if (important) { retryTotalCount = CommConst.RETRY_COUNT_WHICH_SIM_IMPORTANT; } else { retryTotalCount = CommConst.RETRY_COUNT_0; } 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(smR.getReceiveMsg()); Sim sim = simService.uniqueBySimNum(simNum); if (sim == null) { return AjaxResult.error("找不到模拟器[" + simNum + "]对应数据。"); } else { l.info("座号[{}]上发现模拟器[{}]", seat.getSeatNum(), sim.getSimNum()); } // 更新SimId seatService.updateCurrentSimIdBySeatNum(seat.getSeatNum(), sim.getSimId()); // 更新Sim状态 simService.updateSimStateBySimId(sim.getSimId(), Sim.State.ONLINE); // 查询出最新的Sim对象 sim = simService.uniqueBySimNum(simNum); // String msgTemp = "座号[{0}]-模拟器[{1}]型[{2}]在线"; String msg = MessageFormat.format(msgTemp, seat.getSeatNum(), Sim.TYPE_NAME_MAP.get(sim.getSimType()), sim.getSimNum()); // 成功的话,Obj为Sim对象。 return AjaxResult.success(msg, sim); } else if (Objects.equals(result, SimMsg.Result.RECEIVE_CHECK_FAIL)) { return smR.getDefaultErrorAR(); } else if (Objects.equals(result, SimMsg.Result.READ_TIMEOUT_EXCEPTION)) { // 更新SimId seatService.updateCurrentSimIdBySeatNum(seat.getSeatNum(), Sim.ID_0); String msgTemp = "座号[{0}]-没有连接任何接模拟器,检查线缆连接和线缆开关"; 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("检查座次模拟器失败!", null); } /** * 纯数据库查询,模拟器是否在线。 * 模拟器是否被禁用。 * * @param simId * @return */ public AjaxResult checkOneSimOnlineState(final Long simId) { if (simId == null || simId <= 0) { return AjaxResult.error("没有连接任何接模拟器,
检查线缆连接和线缆开关!"); } Sim sim = simService.selectSimBySimId(simId); if (sim != null) { switch (sim.getSimState()) { case Sim.State.ONLINE: { return AjaxResult.success("模拟器[" + sim.getSimNum() + "]在线!"); } case Sim.State.OFFLINE: { return AjaxResult.success("模拟器[" + sim.getSimNum() + "]离线!"); } case Sim.State.DISABLE: { return AjaxResult.error("模拟器[" + sim.getSimNum() + "]禁用!"); } } } return AjaxResult.error("模拟器[" + Objects.requireNonNull(sim).getSimNum() + "]XXXX!"); } /** * 默认Seat中已经有CurrentSimId数据 * 检查回应报文模拟器类型是否正确。 * * @param seat 座次 * @param important * @param targetSimType 期望模拟器目标类型 * @return */ public AjaxResult checkOneSimType(final Seat seat, final boolean important, final String targetSimType) { // check args. if (seat == null) { throw new IllegalArgumentException("seat is null"); } if (seat.getCurrentSimId() == null || Sim.ID_0.equals(seat.getCurrentSimId())) { throw new IllegalArgumentException("sim id is 0"); } if (!simService.existBySimId(seat.getCurrentSimId())) { return AjaxResult.error("模拟器ID[" + seat.getCurrentSimId() + "]不存在!"); } // final String msgErrorTemp = "连接模拟器类型或序列号不正确!
应该连接模拟器型号:
"; final String msgOk = "连接模拟器类型或序列号正确!"; int retryTotalCount; if (important) { retryTotalCount = RETRY_COUNT_QUERY_SN_IMPORTANT; } else { retryTotalCount = RETRY_COUNT_0; } Sim sim = simService.selectSimBySimId(seat.getCurrentSimId()); SimMsg smS = commBuildService.buildSendMsgReadSimType(sim.getSimNum()); SimMsg smR = commSendService.send(smS, seat, sim, retryTotalCount, commStrategy.getSleepShort()); if (StringUtils.isNotBlank(smR.getReceiveMsg())) { final String content = CommParseUtils.subContentData(smR); switch (targetSimType) { case Sim.TYPE_0001 -> { if (content.startsWith(CommConst.TYPE_0001_SN_PREFIX) && content.endsWith(sim.getSimNum())) { return AjaxResult.success(msgOk); } else { return AjaxResult.error(msgErrorTemp + Sim.TYPE_NAME_MAP.get(targetSimType)); } } case Sim.TYPE_0002 -> { if (content.startsWith(CommConst.TYPE_0002_SN_PREFIX) && content.endsWith(sim.getSimNum())) { return AjaxResult.success(msgOk); } else { return AjaxResult.error(msgErrorTemp + Sim.TYPE_NAME_MAP.get(targetSimType)); } } case Sim.TYPE_0003 -> { if (content.startsWith(CommConst.TYPE_0003_SN_PREFIX) && content.endsWith(sim.getSimNum())) { return AjaxResult.success(msgOk); } else { return AjaxResult.error(msgErrorTemp + Sim.TYPE_NAME_MAP.get(targetSimType)); } } default -> throw new IllegalStateException("Unexpected value: " + targetSimType); } } return AjaxResult.error("失败,检查一个模拟器[" + sim.getSimNum() + "]型号或序列号执行错误!
请检查模拟器线缆连接情况和连接模拟器型号!"); } /** * 默认Seat中已经有CurrentSimId数据 * * @param seat * @param important * @return */ @Transactional public AjaxResult checkOneSimOnlineState(final Seat seat, final boolean important) { // check args. if (seat == null) { throw new IllegalArgumentException("seat is null"); } if (seat.getCurrentSimId() == null || Sim.ID_0.equals(seat.getCurrentSimId())) { return AjaxResult.error("模拟器ID不存在!"); } if (!simService.existBySimId(seat.getCurrentSimId())) { return AjaxResult.error("模拟器ID[" + seat.getCurrentSimId() + "]不存在!"); } // int retryTotalCount; if (important) { retryTotalCount = RETRY_COUNT_QUERY_SN_IMPORTANT; } else { retryTotalCount = RETRY_COUNT_0; } Sim sim = simService.selectSimBySimId(seat.getCurrentSimId()); SimMsg smS02 = commBuildService.buildSendMsgReadSimType(sim.getSimNum()); SimMsg smR02 = commSendService.send(smS02, seat, sim, retryTotalCount, commStrategy.getSleepShort()); if (StringUtils.isNotBlank(smR02.getReceiveMsg())) { // 只要返回正确报文,即认为在线。 simService.updateSimStateBySimId(sim.getSimId(), Sim.State.ONLINE); socketService.failedReset0(seat.toSimSocketParamVo()); return AjaxResult.success("成功,检查一个模拟器[" + sim.getSimNum() + "]OK!"); } return AjaxResult.error("失败,检查一个模拟器[" + sim.getSimNum() + "]在线状态执行错误!"); } /** * [定时执行]查找所有没有被手动禁用的座次 和 座次上的模拟器。 */ public AjaxResult checkAllSeatAndSimState() { List list = seatService.listAllEnable(); list.forEach(seat -> { checkOneSeatState(seat, false); // checkOneSimState(seat, false); }); return AjaxResult.success("检查完毕,成功!"); } }