123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- package com.ruoyi.sim.service.impl;
- import com.ruoyi.sim.config.SimConfig;
- import com.ruoyi.sim.domain.*;
- import org.apache.commons.lang3.StringUtils;
- import org.slf4j.LoggerFactory;
- import org.slf4j.Logger;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.Socket;
- import java.net.SocketTimeoutException;
- import java.util.List;
- import java.util.Objects;
- import static com.ruoyi.sim.service.impl.CommSendService.Const.*;
- /**
- * 硬件通信
- * send service.
- */
- @Service
- public class CommSendService {
- interface Const {
- String ROUTER_IP = "127.0.0.1";
- String IP = "123.112.16.165";
- int PORT = 8899;
- /**
- * 报文长度
- */
- int MSG_LENGTH = 20;
- String PREFIX = "AA";
- String SUFFIX = "55";
- /**
- * orientation
- */
- String ORN_SEND = "01";
- /**
- * orientation
- */
- String ORN_RECEIVE = "02";
- String CMD_DATA_PLACE_HOLDER = "00000000";
- /**
- * 故障下发
- */
- String CMD_SET_FAULT = "01";
- /**
- * 故障清清除
- */
- String CMD_CLEAR_FAULT = "02";
- /**
- * 设备类型读取
- */
- String CMD_READ_TYPE = "03";
- /**
- * 状态读取 RESISTANCE电阻值
- */
- String CMD_READ_FAULT_RESISTANCE = "03";
- String CMD_ID_GET_SN = "B1";
- int LENGTH_2 = 2;
- int LENGTH_8 = 8;
- int LENGTH_20 = 20;
- }
- private static final Logger l = LoggerFactory.getLogger(CommSendService.class);
- /**
- * 缓存的Socket连接。
- */
- private Socket cachedSocket = null;
- @Autowired
- private CommReceiveService simReceiveService;
- @Autowired
- private SimService simService;
- @Autowired
- private FaultService faultService;
- @Autowired
- private RealExamService realExamService;
- @Autowired
- private RealExamFaultService realExamFaultService;
- @Autowired
- private SimConfig sConfig;
- /**
- * 初始化方法,项目启动后自动运行。
- */
- public void init() {
- //
- try {
- if (!isReachable(ROUTER_IP)) {
- // todo:ping 不通。
- }
- if (!isReachable(IP)) {
- // todo:ping 不通。
- }
- openSocket();
- //
- checkAllSimState();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * 定时任务。
- */
- public void scheduledLoopRead() {
- readAll();
- }
- public void readAll() {
- List<RealExam> listRE = realExamService.listAllStatus(RealExam.STATE_ANSWERING);
- listRE.forEach(e -> {
- if (e == null) {
- return;
- }
- List<RealExamFault> listREF = realExamFaultService.listAllType2YesLoopReadState(e.getExamId());
- listREF.forEach(ref -> {
- Sim s = simService.selectSimBySimId(e.getSimId());
- Fault f = faultService.selectFaultByFaultId(ref.getFaultId());
- if (f != null &&
- f.getFaultType().equals(Fault.TYPE_3) &&
- f.getFaultState().equals(Fault.STATE_ENABLE)
- )
- readOneFaultResistance(s, ref, f);
- });
- });
- }
- /**
- * Async version.
- */
- @Async("tp-comm")
- public void readAllAsync() {
- readAll();
- }
- public void readOneExamAtLast(RealExam re) {
- List<RealExamFault> listREF = realExamFaultService.listAllType2YesLoopReadState(re.getExamId());
- listREF.forEach(ref -> {
- Sim s = simService.selectSimBySimId(re.getSimId());
- Fault f = faultService.selectFaultByFaultId(ref.getFaultId());
- readOneFaultResistance(s, ref, f);
- });
- realExamService.updateOneState(re, RealExam.STATE_SUBMITTED);
- }
- /**
- * 定时任务。
- */
- public void scheduledCheckAllSimState() {
- checkAllSimState();
- }
- /**
- * 查找所有没有被手动禁用,并order by sim_num的模拟器列表。检查所有模拟器状态。
- */
- public void checkAllSimState() {
- List<Sim> list = simService.listAllEnable();
- list.forEach(s -> {
- checkOneSimState(s);
- });
- }
- @Async()
- public void checkAllSimStateAsync() {
- }
- public void checkOneSimState(Sim s) {
- l.info(s.toString());
- // check todo:
- if (Objects.isNull(s)) {
- return;
- }
- //
- try {
- SimMsg sm = new SimMsg();
- String sendMsg = buildSendMsgReadSimType(s.getSimNum());
- sm.setSendMsg(sendMsg);
- String receiveMsg = send(sendMsg, s);
- sm.setReceiveMsg(receiveMsg);
- simReceiveService.checkOneSimState(sm, s);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * 清除一个考试的,对应的某型号一台模拟器的,所有设备故障。
- *
- * @param re
- */
- public void clearListFaultByRealExam(RealExam re) {
- // check
- if (Objects.isNull(re)) {
- }
- //
- List<RealExamFault> list = realExamFaultService.listAllType2InitStateByExamId(re.getExamId());
- list.forEach(ref -> {
- Fault f = faultService.selectFaultByFaultId(ref.getFaultId());
- if (faultService.isDisable(f.getFaultId())) {
- l.warn("故障{}-Disable", ref.getFaultId());
- return;
- }
- l.info("f.toString() = " + f.toString());
- Sim s = simService.selectSimBySimId(re.getSimId());
- l.info("s.toString() = " + s.toString());
- // check
- if (Objects.isNull(f)) {
- }
- clearOneFault(s, ref, f);
- });
- }
- /**
- * Async version.
- *
- * @param re
- */
- @Async("tp-comm")
- public void clearListFaultByRealExamAsync(RealExam re) {
- clearListFaultByRealExam(re);
- }
- public void clearAll() {
- // todo:
- simService.listAllEnable().forEach(s -> {
- String simType = s.getSimType();
- List<Fault> listF = faultService.listAllType3EnableBySimType(simType);
- listF.forEach(f -> {
- clearOneFault(s, null, f);
- });
- });
- }
- /**
- * @param s
- * @param reF 可以为空,表示不关联考试的。
- * @param f
- */
- public void clearOneFault(Sim s, RealExamFault reF, Fault f) {
- // check todo:
- //
- try {
- // step1
- SimMsg sm1 = new SimMsg();
- String sendMsg1 = buildSendMsgClearFault(s.getSimNum(), f.getBindHardwareMsg());
- sm1.setSendMsg(sendMsg1);
- String receiveMsg1 = send(sendMsg1, s);
- sm1.setReceiveMsg(receiveMsg1);
- simReceiveService.clearOneFault(sm1, s, reF, f);
- // step2
- if (reF != null && realExamFaultService.isState(reF.getRefId(), RealExamFault.REF_STATE_CLEARED)) {
- writeOneFault(s, reF, f);
- }
- } catch (SocketTimeoutException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- public void writeOneFault(Sim s, RealExamFault ref, Fault f) {
- try {
- // 下发故障
- SimMsg sm1 = new SimMsg();
- String sendMsg1 = buildSendMsgWriteFault(s.getSimNum(), f.getBindHardwareMsg());
- sm1.setSendMsg(sendMsg1);
- String receiveMsg1 = send(sendMsg1, s);
- sm1.setReceiveMsg(receiveMsg1);
- // todo:
- // 读取一次当前电阻代表值作为出题值。
- SimMsg sm2 = new SimMsg();
- String sendMsg2 = buildSendMsgReadFaultResistance(s.getSimNum(), f.getBindHardwareMsg());
- sm2.setSendMsg(sendMsg2);
- String receiveMsg2 = send(sendMsg2, s);
- sm2.setReceiveMsg(receiveMsg2);
- simReceiveService.setFaultQuestionValue(sm2, s, ref, f);
- // 修改关联状态。
- {
- RealExamFault f1 = realExamFaultService.selectRealExamFaultByRefId(ref.getRefId());
- f1.setRefState(RealExamFault.REF_STATE_LOOP_READ);
- realExamFaultService.updateRealExamFault(f1);
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- public void readOneFaultResistance(Sim s, RealExamFault reF, Fault f) {
- try {
- SimMsg sm = new SimMsg();
- String sendMsg = buildSendMsgReadFaultResistance(s.getSimNum(), "03");
- sm.setSendMsg(sendMsg);
- String receiveMsg = send(sendMsg, s);
- sm.setReceiveMsg(receiveMsg);
- simReceiveService.setFaultAnswerValue(sm, s, reF, f);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- public void test() {
- try {
- {
- String sendMsg = buildSendMsgReadFaultResistance("01", "04");
- send(sendMsg, null);
- }
- {
- String sendMsg = buildSendMsgReadFaultResistance("01", "05");
- send(sendMsg, null);
- }
- {
- String sendMsg = buildSendMsgReadFaultResistance("01", "06");
- send(sendMsg, null);
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * 设备类型读取
- *
- * @param simNum sim.sim_num
- */
- public String buildSendMsgReadSimType(final String simNum) {
- return buildSendMsg(simNum, CMD_READ_TYPE, CMD_ID_GET_SN);
- }
- /**
- * 故障下发
- *
- * @param simNum sim.sim_num
- * @param bindHardwareMsg fault.bind_hardware_msg
- */
- public String buildSendMsgWriteFault(final String simNum, final String bindHardwareMsg) {
- return buildSendMsg(simNum, CMD_SET_FAULT, bindHardwareMsg);
- }
- /**
- * 状态读取
- *
- * @param simNum sim.sim_num
- * @param bindHardwareMsg fault.bind_hardware_msg
- */
- public String buildSendMsgReadFaultResistance(final String simNum, final String bindHardwareMsg) {
- return buildSendMsg(simNum, CMD_READ_FAULT_RESISTANCE, bindHardwareMsg);
- }
- /**
- * 故障清清除
- *
- * @param simNum sim.sim_num
- * @param bindHardwareMsg fault.bind_hardware_msg
- */
- public String buildSendMsgClearFault(final String simNum, final String bindHardwareMsg) {
- return buildSendMsg(simNum, CMD_CLEAR_FAULT, bindHardwareMsg);
- }
- public String buildSendMsg(final String simNum, final String cmd, final String cmdId) {
- return buildSendMsg(simNum, cmd, cmdId, CMD_DATA_PLACE_HOLDER);
- }
- public String buildSendMsg(final String simNum, final String cmd, final String cmdId, final String data) {
- if (StringUtils.isEmpty(simNum) || StringUtils.isEmpty(cmd) || StringUtils.isEmpty(cmdId) || StringUtils.isEmpty(data)) {
- throw new IllegalArgumentException("buildSendMsg isEmpty");
- }
- if (simNum.length() != LENGTH_2) {
- throw new IllegalArgumentException("buildSendMsg length error");
- }
- if (cmd.length() != LENGTH_2) {
- throw new IllegalArgumentException("buildSendMsg length error");
- }
- if (cmdId.length() != LENGTH_2) {
- throw new IllegalArgumentException("buildSendMsg length error");
- }
- if (data.length() != LENGTH_8) {
- throw new IllegalArgumentException("buildSendMsg length error");
- }
- StringBuffer m = new StringBuffer();
- m.append(PREFIX);
- m.append(simNum);
- m.append(ORN_SEND);
- m.append(cmd);
- m.append(cmdId);
- m.append(data);
- m.append(SUFFIX);
- final String mFinal = m.toString();
- if (mFinal.length() != LENGTH_20) {
- throw new IllegalArgumentException("buildSendMsg length error");
- }
- return mFinal;
- }
- /**
- * send hex message
- *
- * @param sendMsg
- * @param s 可以为空,更新最后发送/接收时间 用。
- * @return
- */
- public synchronized String send(final String sendMsg, final Sim s) throws IOException {
- l.info("sendMsg = " + sendMsg);
- String receiveMsg = null;
- if (cachedSocket == null) {
- openSocket();
- }
- InputStream is = cachedSocket.getInputStream();
- OutputStream os = cachedSocket.getOutputStream();
- os.write(hexStrToByteArrs(sendMsg));
- if (s != null) {
- simService.updateLastSentTime(s);
- }
- byte[] buffer = new byte[1024];
- int length = is.read(buffer);
- StringBuffer sbHex = new StringBuffer();
- for (int i = 0; i < length; i++) {
- sbHex.append(String.format("%02X", buffer[i]));
- }
- receiveMsg = sbHex.toString();
- l.info("receiveMsg = {}", receiveMsg);
- if (!checkReceiveMsg(receiveMsg)) {
- // todo:
- l.warn("checkReceiveMsg fail receiveMsg = {}", receiveMsg);
- return "";
- }
- if (s != null) {
- simService.updateLastReceivedTime(s);
- }
- return receiveMsg;
- }
- public void openSocket() throws IOException {
- if (cachedSocket == null) {
- cachedSocket = new Socket(IP, PORT);
- // setSoTimeout
- // cachedSocket.setSoTimeout(1000);
- }
- }
- /**
- * todo:异常精细处理
- *
- * @throws IOException
- */
- public void closeSocket() throws IOException {
- if (cachedSocket != null) {
- cachedSocket.close();
- }
- cachedSocket = null;
- }
- 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
- *
- * @param ipV4
- * @return
- * @throws IOException
- */
- public boolean isReachable(String ipV4) throws IOException {
- InetAddress ia = InetAddress.getByName(ipV4);
- return ia.isReachable(sConfig.getGatewayReachableTimeout());
- }
- /**
- * check receiveMsg
- *
- * @param receiveMsg
- * @return
- */
- public boolean checkReceiveMsg(String receiveMsg) {
- if (StringUtils.isEmpty(receiveMsg)) {
- return false;
- }
- if (receiveMsg.length() != CommSendService.Const.LENGTH_20) {
- return false;
- }
- final String orn = StringUtils.substring(receiveMsg, 4, 6);
- if (!CommSendService.Const.ORN_RECEIVE.equals(orn)) {
- return false;
- }
- if (!StringUtils.startsWith(receiveMsg, CommSendService.Const.PREFIX)) {
- return false;
- }
- if (!StringUtils.endsWith(receiveMsg, CommSendService.Const.SUFFIX)) {
- return false;
- }
- return true;
- }
- }
|