美文网首页
短信猫串口通信(RXTXcomm.jar)

短信猫串口通信(RXTXcomm.jar)

作者: Memory_2e2e | 来源:发表于2019-11-19 10:36 被阅读0次
      项目部署在内网,无法调用第三方短信接口,故采用短信猫设备插卡作为短信收发中心,通过与服务器串口通信。

环境

  • jdk1.8
  • windows7 64位
  • RXTXcomm.jar(放到 JAVA_HOME\jre\lib\ext)
  • rxtxSerial.dll 64位 (放到JAVA_HOME\bin)
  • springboot 2.1.4.RELEASE

核心处理类

package com.yudu.sms.handler;

import com.yudu.sms.config.SmsConfig;
import com.yudu.sms.pojo.SmsIn;
import com.yudu.sms.pojo.SmsOut;
import com.yudu.sms.repository.SmsInRepository;
import gnu.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

@Component
public class SmsHandler implements SerialPortEventListener {
   private static final Logger logger = LoggerFactory.getLogger(SmsHandler.class);
   @Autowired
   private SmsInRepository smsInRepository;

   private ConcurrentLinkedQueue<SmsOut> smsQueue = new ConcurrentLinkedQueue<SmsOut>();
   private ConcurrentLinkedQueue<SmsIn> smsInQueue = new ConcurrentLinkedQueue<SmsIn>();

   private InputStream inputStream;
   private OutputStream outputStream;
   private SerialPort serialPort;

   private byte[] rcvHead = new byte[5]; // 包头 "+CMS:";
   private byte[] rcvTail = new byte[4]; // 包尾 "\r\n\0\0"
   private byte[] rcvSucess = new byte[15]; // "SMS_SEND_SUCESS"
   private byte[] rcvFail = new byte[13]; // "SMS_SEND_FAIL"

   private zlyInt iHead = new zlyInt(); // 查找包头
   private zlyInt iTail = new zlyInt(); // 查找包尾
   private zlyInt iSucess = new zlyInt(); // 查找是否发送成功
   private zlyInt iFail = new zlyInt(); // 查找是否发送失败

   private int bHeadFinded; // 接收使用
   private byte[] bufSms = new byte[500]; // 接收缓冲区
   private int ibufSms; // 接收缓冲区中,当前收到的字符数
   private SmsHandler() { }

   public void init() {
      initBag();
      String port = "COM3";
      registPort(port);
      //开两个线程独立完成短信接收和发送
      new Thread(new SendSmsTask()).start();
      new Thread(new ReceiveSmsTask()).start();
   }

   private void initBag() {
      // 接收短信的协议头
      // "+CMS:";2B 43 4D 53 3A
      rcvHead[0] = 0x2B;
      rcvHead[1] = 0x43;
      rcvHead[2] = 0x4D;
      rcvHead[3] = 0x53;
      rcvHead[4] = 0x3A;
      // 接收短信的包尾
      // "\r\n\0\0" 0D 0A 00 00
      rcvTail[0] = 0x0D;
      rcvTail[1] = 0x0A;
      rcvTail[2] = 0x00;
      rcvTail[3] = 0x00;
      // 发生成功的应答信息
      // "SMS_SEND_SUCESS" 53 4D 53 5F 53 45 4E 44 5F 53 55 43 45 53 53
      rcvSucess[0] = 0x53;
      rcvSucess[1] = 0x4D;
      rcvSucess[2] = 0x53;
      rcvSucess[3] = 0x5F;
      rcvSucess[4] = 0x53;
      rcvSucess[5] = 0x45;
      rcvSucess[6] = 0x4E;
      rcvSucess[7] = 0x44;
      rcvSucess[8] = 0x5F;
      rcvSucess[9] = 0x53;
      rcvSucess[10] = 0x55;
      rcvSucess[11] = 0x43;
      rcvSucess[12] = 0x45;
      rcvSucess[13] = 0x53;
      rcvSucess[14] = 0x53;
      // 发送失败的应答信息
      // "SMS_SEND_FAIL" 53 4D 53 5F 53 45 4E 44 5F 46 41 49 4C
      // byte[] rcvFail = new byte[13];
      rcvFail[0] = 0x53;
      rcvFail[1] = 0x4D;
      rcvFail[2] = 0x53;
      rcvFail[3] = 0x5F;
      rcvFail[4] = 0x53;
      rcvFail[5] = 0x45;
      rcvFail[6] = 0x4E;
      rcvFail[7] = 0x44;
      rcvFail[8] = 0x5F;
      rcvFail[9] = 0x46;
      rcvFail[10] = 0x41;
      rcvFail[11] = 0x49;
      rcvFail[12] = 0x4C;
   }

   private void registPort(String port) {
      Enumeration<?> portList = CommPortIdentifier.getPortIdentifiers();// 获取所有的端口
      while (portList.hasMoreElements()) {
         CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
         if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
            if (portId.getName().toUpperCase().equals(port.toUpperCase())) {
               try {
                  serialPort = (SerialPort) portId.open("sunder", 2000);
                  logger.info("打开端口:"+port);
               } catch (PortInUseException e) {
                  logger.error("端口已经被占用...");
                  throw new RuntimeException("端口已经被占用...");
               }

               try {
                  inputStream = serialPort.getInputStream();
                  outputStream = serialPort.getOutputStream();
               } catch (IOException e) {
                  logger.error("获取端口的输入输出流出错...");
                  throw new RuntimeException("获取端口的输入输出流出错...");
               }

               // 设置监听
               try {
                  serialPort.addEventListener((SerialPortEventListener) this);
               } catch (TooManyListenersException e) {
                  throw new RuntimeException(e);
               }

               // 开启数据达到通知
               serialPort.notifyOnDataAvailable(true);

               try {
                  serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);
               } catch (UnsupportedCommOperationException e) {
                  logger.error("打开端口失败");
                  throw new RuntimeException("打开端口失败");
               }
            }
         }
      }
   }

   public void sendSms(String smscontent, String rNum, String sPerson, String sPersonId, int type) throws Exception {
      SmsOut smsOut = new SmsOut();
      smsOut.setContext(smscontent);
      smsOut.setDate(new Date());
      smsOut.setIsVisible(true);
      smsOut.setType(type);
      smsOut.setIsSuccess(1);
      smsOut.setrNum(rNum);
      smsOut.setrPerson(sPerson);
      smsOut.setrPersonId(sPersonId);
      smsQueue.add(smsOut); // 加入队列即可

  }
   class ReceiveSmsTask implements Runnable{
       @Override
       public void run() {
           while (true) {
               SmsIn smsIn = smsInQueue.poll();
               while (smsIn != null) {
                   logger.info("接收:号码:"+smsIn.getsNum()+"-内容:"+smsIn.getContext());
                   smsInRepository.insert(smsIn);
                   try {
                       Thread.sleep(1000 * 5);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   smsIn = smsInQueue.poll();
               }
               try {
                   Thread.sleep(1000 * 60 * 2);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
       }
   }
   class SendSmsTask implements Runnable {
      @Override
      public void run() {
          while (true) {
            SmsOut smsOut = smsQueue.poll();
            while (smsOut != null) {
               String sms = smsOut.getrNum() + ":0:" + smsOut.getContext();
               try {
                  outputStream.write(sms.getBytes("GBK"), 0, sms.getBytes("GBK").length);
                  outputStream.flush();
                  logger.info("短信发送成功:" + sms);
               } catch (Exception e) {
                  e.printStackTrace();
                  if (logger.isErrorEnabled()) {
                     logger.error("短信发送失败:" + sms);
                  }
               }
               try {
                  Thread.sleep(1000 * 5);
               } catch (InterruptedException e) {
                  e.printStackTrace();
               }
               smsOut = smsQueue.poll();
            }
            try {
               Thread.sleep(1000 * 60 * 2);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }
   }

   @Override
   public void serialEvent(SerialPortEvent event)  {
      switch (event.getEventType()) {
      case SerialPortEvent.BI:
      case SerialPortEvent.OE:
      case SerialPortEvent.FE:
      case SerialPortEvent.PE:
      case SerialPortEvent.CD:
      case SerialPortEvent.CTS:
      case SerialPortEvent.DSR:
      case SerialPortEvent.RI:
      case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
         break;
      case SerialPortEvent.DATA_AVAILABLE: // 接收到数据
         byte[] readBuffer = new byte[200];
         int numBytes = 0;
         int j;
         String s;
         try {
            while (inputStream.available() > 0) {
               numBytes = inputStream.read(readBuffer);
               for (j = 0; j < numBytes; j++) {
                  if (1 == SearchStrInStream2(rcvSucess, readBuffer[j], iSucess)) {
                      logger.info("发送成功");
                  }
                  if (1 == SearchStrInStream2(rcvFail, readBuffer[j], iFail)) {
                      logger.info("发送失败");
                  }
                  if (bHeadFinded == 1) {// 接收
                     bufSms[ibufSms] = readBuffer[j];
                     ibufSms++;
                     if (1 == SearchStrInStream2(rcvTail, readBuffer[j], iTail)) {
                        bHeadFinded = 0;
                        s = new String(bufSms, 0, ibufSms, "gbk");
                        bufSms = new byte[500];
                        SmsIn smsIn = new SmsIn();
                        smsIn.setId(UUID.randomUUID().toString().replace("-",""));
                        smsIn.setContext(s.substring(26));
                        smsIn.setsNum(s.substring(2, 13));
                        smsIn.setDate(new Date());
                        smsIn.setIsVisible(false);
                        smsIn.setIsRead(false);
                        smsIn.setsPerson("无");
                        smsIn.setsPersonId("null");
                        smsInQueue.add(smsIn); // 加入队列即可
                     }
                  }

                  if (1 == SearchStrInStream2(rcvHead, readBuffer[j], iHead)) {
                     bHeadFinded = 1;
                     ibufSms = 0;
                  }
               }
            }
         } catch (IOException e) {
            System.out.println(e);
         }
         break;
      }
   }

   // 查询字符流的函数
   public int SearchStrInStream2(byte[] strToCmp, byte c, zlyInt i) {
      if (i.i > strToCmp.length) {
         i.i = 0;
         return 0;
      }
      if (i.i != 0) {
         if (c != strToCmp[i.i]) {
            i.i = 0;
         } else {
         }
      }
      if (c == strToCmp[i.i]) {
         (i.i)++;
      }
      if ((int) (i.i) == strToCmp.length) {
         i.i = 0;
         return 1;
      }
      return 0;
   }

   public class zlyInt // 查询字符流的函数需要获取输出参数的办法
   {
      int i = 0;
   }

}

实战项目,参考github案例

相关文章

  • 短信猫串口通信(RXTXcomm.jar)

    环境 jdk1.8 windows7 64位 RXTXcomm.jar(放到 JAVA_HOME\jre\lib\...

  • 如何使用金笛短信猫收发短信,USB单口为例

    因短信猫通讯原理为串口通讯,USB接口的短信猫需安装USB口转串口的驱动,方可正常使用。 工具/原料 USB口金笛...

  • Android平台的串口通信技术

    概念 串口通信 概念;串口通信(Serial Communications)按位(bit)发送和接收字节。串口可以...

  • 干货小知识:一文教你Java程序与串口通信的实现及通信!

    串口通信的原理 串口通信指串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使...

  • Python串口通信

    前言 从需求说起 串口通信控制二维码阅读器 串口通信控制门闸机 pyserial python 串口通信第三方包 ...

  • 9月21日

    今天讲的全新内容 串口通信 什么是串口和并口 主要讲解是串口通信寄存器的配置 并且初步实现了通信功能 下午复习上午...

  • 2018-01-08课后总结

    今天学习了串口通信。串口通信分为串行通信和并行通信,综合串行和并行的优缺点,在工业分布中串行通信的应用更为广泛。了...

  • Java RXTX

    RXTX是一个通讯库RXTXcomm.jar是针对类的疯转.dll是针对平台接口的实现 RXTX包含有串口,I2C...

  • java实现上位机与下位机串口通信

    串口通信是在工程应用中很常见。在上位机与下位机通讯过程中常通过有线的串口进行通信,在低速传输模式下串口通信得到广泛...

  • STM32学习:USART串口通信

    一、STM32F1的USART介绍 (一)串口通信简介 串口通信(Serial Communication),是指...

网友评论

      本文标题:短信猫串口通信(RXTXcomm.jar)

      本文链接:https://www.haomeiwen.com/subject/mwqwictx.html