网站建设 微信营销,推广公司名字 有创意,js统计网站访问人数,深圳装修公司咨询记录一下使用SpringBootjSerialComm实现Java串口通信#xff0c;使用Java语言开发串口#xff0c;对串口进行读写操作,在win和linux系统都是可以的#xff0c;有一点好处是不需要导入额外的文件。
案例demo源码#xff1a;SpringBootjSerialComm实现Java串口通信 读取串口…记录一下使用SpringBootjSerialComm实现Java串口通信使用Java语言开发串口对串口进行读写操作,在win和linux系统都是可以的有一点好处是不需要导入额外的文件。
案例demo源码SpringBootjSerialComm实现Java串口通信 读取串口数据以及发送数据
之前使用RXTXcomm实现Java串口通信这种方式对linux(centos)的支持效果不好还有些问题 但在win下面使用还不错原文地址SpringBootRXTXcomm实现Java串口通信 读取串口数据以及发送数据
不需要额外导入文件 比如dll 只需要导入对应的包 dependencygroupIdcom.fazecast/groupIdartifactIdjSerialComm/artifactIdversion2.9.2/version/dependencypom.xml
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.0.5.RELEASE/versionrelativePath/ !-- lookup parent from repository --/parentmodelVersion4.0.0/modelVersiongroupIdboot.example.jSerialComm/groupIdartifactIdboot-example-jSerialComm-2.0.5/artifactIdversion0.0.1-SNAPSHOT/versionnameboot-example-jSerialComm-2.0.5/nameurlhttp://maven.apache.org/urlpropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingproject.reporting.outputEncodingUTF-8/project.reporting.outputEncodingjava.version1.8/java.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.fazecast/groupIdartifactIdjSerialComm/artifactIdversion2.9.2/version/dependencydependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion2.9.2/version/dependencydependencygroupIdcom.github.xiaoymin/groupIdartifactIdswagger-bootstrap-ui/artifactIdversion1.9.2/version/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationmainClassboot.example.SerialPortApplication/mainClassincludeSystemScopetrue/includeSystemScope!--外部进行打包--/configurationexecutionsexecutiongoalsgoalrepackage/goal/goals/execution/executions/plugin/plugins/build/projectSerialPortApplication启动类
package boot.example;import boot.example.serialport.SerialPortManager;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.annotation.PreDestroy;
import java.io.IOException;/*** 蚂蚁舞*/
SpringBootApplication
EnableScheduling
EnableAsync
public class SerialPortApplication implements CommandLineRunner {public static void main(String[] args) throws IOException {SpringApplication.run(SerialPortApplication.class, args);}Overridepublic void run(String... args) throws Exception {try{// winSerialPortManager.connectSerialPort(COM1);// linux centos//SerialPortManager.connectSerialPort(ttyS1);} catch (Exception e){System.out.println(e.toString());}}PreDestroypublic void destroy() {SerialPortManager.closeSerialPort();}}
SwaggerConfig
package boot.example;import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;/*** 蚂蚁舞*/
Configuration
EnableSwagger2
public class SwaggerConfig {Beanpublic Docket createRestApi(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).paths(Predicates.not(PathSelectors.regex(/error.*))).paths(PathSelectors.regex(/.*)).build().apiInfo(apiInfo());}private ApiInfo apiInfo(){return new ApiInfoBuilder().title(SpringBootjSerialComm实现Java串口通信 读取串口数据以及发送数据).description(测试接口).version(0.01).build();}}
SerialPortController
package boot.example.controller;import boot.example.serialport.ConvertHexStrAndStrUtils;
import boot.example.serialport.SerialPortManager;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;/*** 蚂蚁舞*/
Controller
RequestMapping(/serialPort)
public class SerialPortController {GetMapping(/list)ResponseBodypublic ListString listPorts() {ListString portList SerialPortManager.getSerialPortList();if(!portList.isEmpty()){return portList;}return null;}PostMapping(/send/{hexData})ResponseBodypublic String sendPorts(PathVariable(hexData) String hexData) {if (SerialPortManager.SERIAL_PORT_STATE){SerialPortManager.sendSerialPortData(ConvertHexStrAndStrUtils.hexStrToBytes(hexData));return success;}return fail;}}
ConvertHexStrAndStrUtils
package boot.example.serialport;import java.nio.charset.StandardCharsets;/*** 蚂蚁舞*/
public class ConvertHexStrAndStrUtils {private static final char[] HEXES {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f};public static String bytesToHexStr(byte[] bytes) {if (bytes null || bytes.length 0) {return null;}StringBuilder hex new StringBuilder(bytes.length * 2);for (byte b : bytes) {hex.append(HEXES[(b 4) 0x0F]);hex.append(HEXES[b 0x0F]);}return hex.toString().toUpperCase();}public static byte[] hexStrToBytes(String hex) {if (hex null || hex.length() 0) {return null;}char[] hexChars hex.toCharArray();byte[] bytes new byte[hexChars.length / 2]; // 如果 hex 中的字符不是偶数个, 则忽略最后一个for (int i 0; i bytes.length; i) {bytes[i] (byte) Integer.parseInt( hexChars[i * 2] hexChars[i * 2 1], 16);}return bytes;}public static String strToHexStr(String str) {StringBuilder sb new StringBuilder();byte[] bs str.getBytes();int bit;for (int i 0; i bs.length; i) {bit (bs[i] 0x0f0) 4;sb.append(HEXES[bit]);bit bs[i] 0x0f;sb.append(HEXES[bit]);}return sb.toString().trim();}public static String hexStrToStr(String hexStr) {//能被16整除,肯定可以被2整除byte[] array new byte[hexStr.length() / 2];try {for (int i 0; i array.length; i) {array[i] (byte) (0xff Integer.parseInt(hexStr.substring(i * 2, i * 2 2), 16));}hexStr new String(array, StandardCharsets.UTF_8);} catch (Exception e) {e.printStackTrace();return ;}return hexStr;}}
SerialPortManager
package boot.example.serialport;import com.fazecast.jSerialComm.SerialPort;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;/*** 蚂蚁舞*/
public class SerialPortManager {public static final int SERIAL_BAUD_RATE 115200;public static volatile boolean SERIAL_PORT_STATE false;public static volatile SerialPort SERIAL_PORT_OBJECT null;//查找所有可用端口public static ListString getSerialPortList() {// 获得当前所有可用串口SerialPort[] serialPorts SerialPort.getCommPorts();ListString portNameList new ArrayListString();// 将可用串口名添加到List并返回该Listfor(SerialPort serialPort:serialPorts) {System.out.println(serialPort.getSystemPortName());portNameList.add(serialPort.getSystemPortName());}//去重portNameList portNameList.stream().distinct().collect(Collectors.toList());return portNameList;}// 连接串口public static void connectSerialPort(String portName){try {SerialPort serialPort SerialPortManager.openSerialPort(portName, SERIAL_BAUD_RATE);TimeUnit.MILLISECONDS.sleep(2000);//给当前串口对象设置监听器serialPort.addDataListener(new SerialPortListener(new SerialPortCallback()));if(serialPort.isOpen()) {SERIAL_PORT_OBJECT serialPort;SERIAL_PORT_STATE true;System.out.println(portName-- start success);}} catch (InterruptedException ex) {ex.printStackTrace();}}// 打开串口public static SerialPort openSerialPort(String portName, Integer baudRate) {SerialPort serialPort SerialPort.getCommPort(portName);if (baudRate ! null) {serialPort.setBaudRate(baudRate);}if (!serialPort.isOpen()) { //开启串口serialPort.openPort(1000);}else{return serialPort;}serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);serialPort.setComPortParameters(baudRate, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);return serialPort;}// 关闭串口public static void closeSerialPort() {if (SERIAL_PORT_OBJECT ! null SERIAL_PORT_OBJECT.isOpen()){SERIAL_PORT_OBJECT.closePort();SERIAL_PORT_STATE false;SERIAL_PORT_OBJECT null;}}// 发送字节数组public static void sendSerialPortData(byte[] content) {if (SERIAL_PORT_OBJECT ! null SERIAL_PORT_OBJECT.isOpen()){SERIAL_PORT_OBJECT.writeBytes(content, content.length);}}// 读取字节数组public static byte[] readSerialPortData() {if (SERIAL_PORT_OBJECT ! null SERIAL_PORT_OBJECT.isOpen()){byte[] reslutData null;try {if (!SERIAL_PORT_OBJECT.isOpen()){return null;};int i0;while (SERIAL_PORT_OBJECT.bytesAvailable() 0 i 5) Thread.sleep(20);byte[] readBuffer new byte[SERIAL_PORT_OBJECT.bytesAvailable()];int numRead SERIAL_PORT_OBJECT.readBytes(readBuffer, readBuffer.length);if (numRead 0) {reslutData readBuffer;}} catch (InterruptedException e) {e.printStackTrace();}return reslutData;}return null;}}
SerialPortListener
package boot.example.serialport;import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;/*** 蚂蚁舞*/
public class SerialPortListener implements SerialPortDataListener {private final SerialPortCallback serialPortCallback;public SerialPortListener(SerialPortCallback serialPortCallback) {this.serialPortCallback serialPortCallback;}Overridepublic int getListeningEvents() { //必须是return这个才会开启串口工具的监听return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;}Overridepublic void serialEvent(SerialPortEvent serialPortEvent) {if (serialPortCallback ! null) {serialPortCallback.dataAvailable();}}
}
SerialPortCallback
package boot.example.serialport;import java.text.SimpleDateFormat;
import java.util.Date;/*** 蚂蚁舞*/
public class SerialPortCallback {public void dataAvailable() {try {//当前监听器监听到的串口返回数据 backbyte[] back SerialPortManager.readSerialPortData();System.out.println(back-(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date()))--ConvertHexStrAndStrUtils.bytesToHexStr(back));String s ConvertHexStrAndStrUtils.bytesToHexStr(back);System.out.println(rev--data:s);//throw new Exception();} catch (Exception e) {System.out.println(e.toString());}}
}
项目结构
demo使用的波特率是115200 其他参数就默认的就好一般只有波特率改动
启动项目和启动com工具项目和com之间使用的是com1和com2虚拟串口 虚拟串口有工具的比如Configure Virtual Serial Port Driver 可以看到com1和com2都已经在使用 应用程序用的com1端口 com工具用的com2端口这样的虚拟串口工具可以模拟调试使用的 应用程序通过com1向com2发送数据 com工具通过com2向com1的应用程序发送数据全双工双向的如此可以测试了。
访问地址 http://localhost:24810/doc.html 查看当前的串口 win系统下的两个虚拟串口 通过虚拟串口发送数据到com工具 通过com工具查看收到的数据已经发送数据给应用程序 控制台收到数据 记录着将来用得着。