当前位置:   article > 正文

java使用RXTX的详细总结_java rxtx

java rxtx

1 简介

  • 项目要求:读取串口信息,并输出展示相应的图像,本篇文章不深入谈前端的内容着重于后端遇到的问题。
  • 2021-01-08更新,发现一个重大的问题:如果有人能解决的话请在评论区回复:
    • 在连上串口后,当你突然把串口拔开,程序会报出很多异常,原因是SerialPortEventListener作为监听的接口无法被注销掉,如果使用serialPort进行注销,则主程序会崩溃(这种崩溃用Error或者Throwable接收不到)。看了底层源码,发现调用的是C++的API,所以可能没法解决。
    • 解决办法是:自己用C++写一个串口功能,然后在JAVA中用JNI调用吧。

2 开发阶段

2.1 RXTX包使用前的部署

  1. 下载该包
    也可以从百度云下载:https://pan.baidu.com/s/1Ruu90kNFi5QJcpwFcJB3LQ,提取码:4hpz

  2. 由于手动导入的时候我遇到了点问题,所以选择先将 RXTXcomm.jar 导入到本地仓库,然后在maven项目中引入
    手动导入的指令

mvn install:install-file -DgroupId=gnu.io -DartifactId=rxtx -Dversion=2.1.7 -Dpackaging=jar -Dfile=“G:\迅雷下载\rxtx-2.1-7-bins-r2\rxtx-2.1-7-bins-r2\RXTXcomm.jar”

然后再在maven项目中引入

<dependency>
    <groupId>gnu.io</groupId>
    <artifactId>rxtx</artifactId>
    <version>2.1.7</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 还需要复制dll
    复制 rxtxParallel.dll 和 rxtxSerial.dll 到 C:\Program Files\Java\jdk1.8.0_241\jre\bin 下,如果无法打包,可以将 jar 包复制到C:\Program Files\Java\jdk1.8.0_241\jre\lib 中

RXTX的使用过程:
在这里插入图片描述

2.2 获取所有可用的端口信息

  • CommPortIdentifier 类内部有三个主要的成员变量可以获取
  • 串口的名称类似于:“COM1”
  • 端口类型包括:I2C、并口、RS485、串口
// 获取当前所有可用的串口信息
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
// 遍历所有的串口信息
while(portList.hasMoreElements()){
	// 获取下一个端口信息
	CommPortIdentifier com = (CommPortIdentifier) portList.nextElement();
	// 端口当前的拥有者,如果没有返回null
	String currentOwner = com.getCurrentOwner();
	// 端口的名称
	String name = com.getName();
	// 端口的类型,需要解析
	int portType = com.getPortType();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.3 解析端口类型的工具

/**
 * @Description:获取通信端口类型名称
 * @author:Lu
 * @date:2015-8-29 上午11:35:32
 */
public static String getPortTypeName(int portType) {
	switch (portType) {
	case CommPortIdentifier.PORT_I2C:
		return "I2C";
	case CommPortIdentifier.PORT_PARALLEL: // 并口
		return "Parallel";
	case CommPortIdentifier.PORT_RAW:
		return "Raw";
	case CommPortIdentifier.PORT_RS485: // RS485端口
		return "RS485";
	case CommPortIdentifier.PORT_SERIAL: // 串口
		return "Serial";
	default:
		return "unknown type";
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

2.4 处理接收数据

  • 通过 CommPortIdentifier 类对象,打开端口,并获取到连接对象CommPort类的实例。该实例有个好用的子类 SerialPort类,可强转成该类
/**
 * 打开端口,注意操作顺序,输入流一定要先获取
 */
private void openPort() {
		try {
              /**
               * open方法(应用程序名【随意命名】,阻塞时等待的毫秒数)
               * open方法打开通讯端口,获得一个CommPort对象,它使程序独占端口。
               * 如果端口正被其他应用程序占用,将使用CommPortOwnershipListener事件机制
               * 传递一个PORT_OWNERSHIP_REQUESTED事件。
               * 每个端口都关联一个InputStream和一个OutputStream,如果端口是用
               * open方法打开的,那么任何的getInputStream都将返回相同的数据流对象,除非 有close被调用。
               */
				// open:(应用程序名【随意命名】,阻塞时等待的毫秒数)
				SerialPort serialPort = (SerialPort) commPortIdentifier.open("OpenPortServer", 2000);
				// 获取输入流
				inputStream = serialPort.getInputStream();
				// 设置串口监听,this对象即本类对象需要继承SerialPortEventListener接口。或者你在这里写一个匿名接口也行。接口内部函数的写法在下面
				serialPort.addEventListener(this);
				// 设置串口数据时间有效(可监听)
				serialPort.notifyOnDataAvailable(true);
				serialPort.notifyOnBreakInterrupt(true);
				// 设置串口通讯参数,可以参考SerialPort类的源码,里面有相关的常量
				// 波特率
          		// 数据位个数
				// 停止位
          		// 校验方式,0代表无奇偶校验,1代表偶校验,2代表偶校验
				serialPort.setSerialPortParams(9600, 8, 1, 0);
		} catch (PortInUseException e) {
				// 端口正在使用
				throw new RuntimeException(e);
		} catch (Exception e) {
				// 输入输出流错误
				throw new RuntimeException(e);
		}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 监听器
    • 监听器必须实现SerialPortEventListener接口,并通过serialPort.addEventListener(this);来注册监听器
    • 通过设置监听器来处理接收数据
    • 注意关闭操作的时候需要在 serialPort 中使用removeEventListener方法注销监听器,并且关闭输入流
  • 注意,上面获取到的InputStream的读取方法是阻塞方法,当没有数据的时候会阻塞等待数据的来临。
/**
 * 在这里进行连接状态判断
 *
 * @param event 连接状态
 */
@Override
public void serialEvent(SerialPortEvent event) {
    switch (event.getEventType()) {
        /**
         * 通讯中断
         */
        case SerialPortEvent.BI: {

        }
        break;
        /**
         * 溢位错误
         */
        case SerialPortEvent.OE: {

        }
        break;
        /**
         * 帧错误
         */
        case SerialPortEvent.FE: {

        }
        break;
        /**
         * 奇偶校验错误
         */
        case SerialPortEvent.PE: {

        }
        break;
        /**
         * 载波检测
         */
        case SerialPortEvent.CD: {

        }
        break;
        /**
         * 清除发送
         */
        case SerialPortEvent.CTS: {

        }
        break;
        /**
         * 数据设备准备好
         */
        case SerialPortEvent.DSR: {

        }
        break;
        /**
         * 响铃侦测
         */
        case SerialPortEvent.RI: {

        }
        break;
        /**
         * 输出缓冲区已清空
         */
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY: {
        }
        break;
        /**
         * 有数据到达
         */
        case SerialPortEvent.DATA_AVAILABLE: {
            // InputStream 通过serialPort在上面的代码中已经获取到了,在这里通过InputStream 读取字节流即可。字节流的操作和咱们一般用法一致
            // 在这里进行读取操作
            byte[] bytes = new byte[255];
            try {
                int len = inputStream.read(bytes);
                // 然后就是其他操作了

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        break;
        default: {
        }
        break;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

3 打包和运行

我的项目主要是在 Windows 系统下运行的。
1)idea 使用maven打包,发现没有主程序,这需要在pom.xml 加入下面这个插件

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>(你的启动类的全限定类名)com.wu.port.MySpringBootApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2)打包后,发现找不到RXTX的jar包,试了很久都是报这个错误。我的解决方法是:重新建立一个maven项目,把原来编的代码重新拷贝过来,然后再进行打包,发现就可以晕行了。
3)如果其他电脑要使用该项目,则必须要先安置好 .dll 文件,为此写一个批处理文件和 rxtxParallel.dll , rxtxSerial.dll , RXTXcomm.jar 放在一起

:: 本文件需要管理员权限运行
:: 获取当前路径
set cPath=%~dp0
cd /D cPath
:: 拷贝文件
copy rxtxParallel.dll %java_home%\jre\bin\  /y
copy rxtxSerial.dll %java_home%\jre\bin\  /y
copy RXTXcomm.jar %java_home%\jre\lib\ext\ /y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4)项目运行的批处理文件

:: 本文件不能以管理员身份运行,将本文件与jar包放置在一起
java -jar "%cd%\jar包名称"
  • 1
  • 2
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/289647
推荐阅读
相关标签
  

闽ICP备14008679号