在对接之前,首先安装基础环境

一、安装基础环境,软件包地址

链接:https://pan.baidu.com/s/11VPQij60af8nFxwUErsnGA?pwd=5jm8
提取码:5jm8

二、实现

1、pom.xml文件引入

org.rxtxrxtx2.1.7

2、创建监听类 MyLister.clss

package com.example.springboot.util;/** * Demo class * * @author XDRS * @date 2023/3/30 16:01 */import gnu.io.SerialPortEvent;import gnu.io.SerialPortEventListener;import net.sf.json.JSONObject;import java.math.BigDecimal;import java.nio.ByteBuffer;import java.nio.charset.StandardCharsets;import java.util.Date;public class MyLister implements SerialPortEventListener {@Overridepublic void serialEvent(SerialPortEvent arg0) {try {if (arg0.getEventType() == SerialPortEvent.DATA_AVAILABLE) {SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();byte[] bytes = serialPortUtil.readFromPort(PortInit.serialPort);String needData = printHexString(bytes);boolean b = needData.contains("01 03");String[] strings = needData.split(" ");int xxxx = Integer.parseInt(strings[0] + "", 16);if (xxxx == 1 && b) {System.out.println(new Date() + "【字节数组转16进制字符串】:-----" + needData);int xss = Integer.parseInt(strings[4] + "", 16);double value = BigDecimal.valueOf(xss).divide(BigDecimal.valueOf(10)).setScale(1, BigDecimal.ROUND_DOWN).doubleValue();System.out.println(new Date() + "水位:-----" + value + "℃");int yss = Integer.parseInt(strings[6] + "", 16);double value2 = BigDecimal.valueOf(yss).setScale(1, BigDecimal.ROUND_DOWN).doubleValue();System.out.println(new Date() + "水位:-----" + value2 + "mm");// 写入数据库,按照api方式发送指定服务上String url = "http://192.168.0.17:8888/api/geological/demo/insert";JSONObject object = new JSONObject();object.put("instrumentName", "水位计");object.put("value", needData);object.put("instrumentUid", 1);object.put("analyseValue", value2);object.put("type", "普通采集");String toString = object.toString();String post = CommonUtil.doHttpPost(url, toString);if (post.equals("0")) {System.out.println("传输数据失败");} else {System.out.println("传输数据成功");}}}} catch (Exception e) {e.printStackTrace();}}/** * 字节数组转16进制字符串 * * @param b 字节数组 * @return 16进制字符串 */public static String printHexString(byte[] b) {StringBuilder sbf = new StringBuilder();for (byte value : b) {String hex = Integer.toHexString(value & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sbf.append(hex.toUpperCase()).append(" ");}return sbf.toString().trim();}/** * 十六进制字符串转byte[] * * @param hex 十六进制字符串 * @return byte[] */public static byte[] hexStr2Byte(String hex) {if (hex == null) {return new byte[]{};}// 奇数位补0//if (hex.length() % StaticConstant.TWO != 0) {//hex = "0" + hex;//}int length = hex.length();ByteBuffer buffer = ByteBuffer.allocate(length / 2);for (int i = 0; i < length; i++) {String hexStr = hex.charAt(i) + "";i++;hexStr += hex.charAt(i);byte b = (byte) Integer.parseInt(hexStr, 16);buffer.put(b);}return buffer.array();}/** * 16进制转换成为string类型字符串 * * @param s 待转换字符串 */public static String hexStringToString(String s) {if (s == null || "".equals(s)) {return null;}s = s.replace(" ", "");byte[] baKeyword = new byte[s.length() / 2];for (int i = 0; i < baKeyword.length; i++) {try {baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));} catch (Exception e) {e.printStackTrace();}}try {s = new String(baKeyword, StandardCharsets.UTF_8);} catch (Exception e1) {e1.printStackTrace();}return s;}}

2、创建 PortInit.class

package com.example.springboot.util;import gnu.io.SerialPort;import org.springframework.boot.ApplicationArguments;import org.springframework.boot.ApplicationRunner;import org.springframework.stereotype.Component;import java.util.ArrayList;/** * Demo class * * @author XDRS * @date 2023/3/30 16:01 */@Componentpublic class PortInit implements ApplicationRunner{public static SerialPort serialPort = null;@Overridepublic void run(ApplicationArguments args) {String portName = "COM1";//TestA();//查看所有串口SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();ArrayList port = serialPortUtil.findPort();System.out.println("发现全部串口:" + port);System.out.println("portName:" + portName);//打开该对应portName名字的串口PortInit.serialPort = serialPortUtil.openPort(portName, 9600, SerialPort.DATABITS_8, SerialPort.PARITY_NONE, SerialPort.PARITY_ODD);// 给对应的serialPort添加监听器serialPortUtil.addListener(PortInit.serialPort, new MyLister());}}

3、创建 SerialPortUtil.class

package com.example.springboot.util;import gnu.io.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.Enumeration;import java.util.TooManyListenersException;/** * Demo class * * @author XDRS * @date 2023/3/30 16:00 */public class SerialPortUtil {private static final Logger logger = LoggerFactory.getLogger(SerialPortUtil.class);private static SerialPortUtil serialPortUtil = null;static {// 在该类被ClassLoader加载时就初始化一个SerialTool对象if (serialPortUtil == null) {serialPortUtil = new SerialPortUtil();}}// 私有化SerialTool类的构造方法,不允许其他类生成SerialTool对象private SerialPortUtil() {}/** * 获取提供服务的SerialTool对象 * * @return serialPortUtil */public static SerialPortUtil getSerialPortUtil() {if (serialPortUtil == null) {serialPortUtil = new SerialPortUtil();}return serialPortUtil;}/** * 查找所有可用端口 * * @return 可用端口名称列表 */public ArrayList findPort() {//获得当前所有可用串口Enumeration portList = CommPortIdentifier.getPortIdentifiers();ArrayList portNameList = new ArrayList();//将可用串口名添加到List并返回该Listwhile (portList.hasMoreElements()) {String portName = portList.nextElement().getName();portNameList.add(portName);}return portNameList;}/** * 打开串口 * * @param portName 端口名称 * @param baudrate 波特率19200 * @param databits 数据位8 * @param parity 校验位(奇偶位)NONE :0 * @param stopbits 停止位 1 * @return 串口对象 * // * @throws SerialPortParameterFailure 设置串口参数失败 * // * @throws NotASerialPort 端口指向设备不是串口类型 * // * @throws NoSuchPort 没有该端口对应的串口设备 * // * @throws PortInUse端口已被占用 */public SerialPort openPort(String portName, int baudrate, int databits, int parity, int stopbits) {try {//通过端口名识别端口CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);//打开端口,并给端口名字和一个timeout(打开操作的超时时间)CommPort commPort = portIdentifier.open(portName, 2000);//判断是不是串口if (commPort instanceof SerialPort) {SerialPort serialPort = (SerialPort) commPort;try {//设置一下串口的波特率等参数serialPort.setSerialPortParams(baudrate, databits, stopbits, parity);} catch (UnsupportedCommOperationException e) {}System.out.println("Open " + portName + " sucessfully !");return serialPort;} else {logger.error("不是串口");}} catch (NoSuchPortException e1) {logger.error("没有找到端口");e1.printStackTrace();} catch (PortInUseException e2) {logger.error("端口被占用");e2.printStackTrace();}return null;}/** * 关闭串口 * * @param serialPort 待关闭的串口对象 */public void closePort(SerialPort serialPort) {if (serialPort != null) {serialPort.close();}}/** * 往串口发送数据 * * @param serialPort 串口对象 * @param order待发送数据 * // * @throws SendDataToSerialPortFailure向串口发送数据失败 * // * @throws SerialPortOutputStreamCloseFailure 关闭串口对象的输出流出错 */public void sendToPort(SerialPort serialPort, byte[] order) {OutputStream out = null;try {out = serialPort.getOutputStream();out.write(order);out.flush();} catch (IOException e) {e.printStackTrace();} finally {try {if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();}}}/** * 从串口读取数据 * * @param serialPort 当前已建立连接的SerialPort对象 * @return 读取到的数据 * // * @throws ReadDataFromSerialPortFailure 从串口读取数据时出错 * // * @throws SerialPortInputStreamCloseFailure 关闭串口对象输入流出错 */public byte[] readFromPort(SerialPort serialPort) {InputStream in = null;byte[] bytes = null;try {in = serialPort.getInputStream();int bufflenth = in.available();while (bufflenth != 0) {bytes = new byte[bufflenth];in.read(bytes);bufflenth = in.available();}} catch (IOException e) {e.printStackTrace();} finally {try {if (in != null) {in.close();}} catch (IOException e) {e.printStackTrace();}}return bytes;}/** * 添加监听器 * * @param port 串口对象 * @param listener 串口监听器 * // * @throws TooManyListeners 监听类对象过多 */public void addListener(SerialPort port, SerialPortEventListener listener) {try {//给串口添加监听器port.addEventListener(listener);//设置当有数据到达时唤醒监听接收线程port.notifyOnDataAvailable(true);//设置当通信中断时唤醒中断线程port.notifyOnBreakInterrupt(true);} catch (TooManyListenersException e) {//throw new TooManyListeners();logger.error("太多监听器");e.printStackTrace();}}/** * 删除监听器 * * @param port 串口对象 * @param listener 串口监听器 * // * @throws TooManyListeners 监听类对象过多 */public void removeListener(SerialPort port, SerialPortEventListener listener) {//删除串口监听器port.removeEventListener();}/** * 设置串口的Listener * * @param serialPort * @param listener * @author mar * @date 2021/8/20 11:04 */public static void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) {try {//给串口添加事件监听serialPort.addEventListener(listener);} catch (TooManyListenersException e) {e.printStackTrace();}//串口有数据监听serialPort.notifyOnDataAvailable(true);//中断事件监听serialPort.notifyOnBreakInterrupt(true);}}

4、创建 CommonUtil.class

package com.example.springboot.util;import net.sf.json.JSONObject;import org.apache.commons.io.IOUtils;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.ConnectException;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLConnection;import java.util.List;import java.util.Map;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManager;public class CommonUtil {/** * TODO 获取http访问后的json串 * @param urlPath * @return */public static String getJSONContent(String urlPath) {String jsonString = "";// 访问路径try {// 创建HTTP连接URL url = new URL(urlPath);HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 设置连接超时时间connection.setConnectTimeout(5000);connection.setRequestMethod("GET");connection.setDoInput(true);// 获取相应代码,判断是否响应结束int code = connection.getResponseCode();if (code == 200) {InputStream is = connection.getInputStream();DataInputStream indata = new DataInputStream(is);String ret = "";while (ret != null) {ret = indata.readLine();if (ret != null && !ret.trim().equals("")) {jsonString = jsonString+ new String(ret.getBytes("ISO-8859-1"), "UTF-8");}}connection.disconnect();}} catch (Exception e) {e.printStackTrace();}return jsonString;}/** * 发送Http post请求 * * @param xmlInfo *json转化成的字符串 * @param URL *请求url * @return 返回信息 */public static String doHttpPost(String URL,String xmlInfo ) {System.out.println("发起的数据:" + xmlInfo);byte[] xmlData = xmlInfo.getBytes();InputStream instr = null;try {URL url = new URL(URL);URLConnection urlCon = url.openConnection();urlCon.setDoOutput(true);urlCon.setDoInput(true);urlCon.setUseCaches(false);urlCon.setRequestProperty("content-Type", "application/json");urlCon.setRequestProperty("charset", "utf-8");urlCon.setRequestProperty("Content-length",String.valueOf(xmlData.length));System.out.println(String.valueOf(xmlData.length));DataOutputStream printout = new DataOutputStream(urlCon.getOutputStream());printout.write(xmlData);printout.flush();printout.close();instr = urlCon.getInputStream();byte[] bis = IOUtils.toByteArray(instr);String ResponseString = new String(bis, "UTF-8");if ((ResponseString == null) || ("".equals(ResponseString.trim()))) {System.out.println("返回空");}System.out.println("返回数据为:" + ResponseString);return ResponseString;} catch (Exception e) {e.printStackTrace();return "0";} finally {try {instr.close();} catch (Exception ex) {ex.printStackTrace();return "0";}}}/** * 向指定URL发送GET方法的请求 * * @param url *发送请求的URL * @param param *请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */public static String sendGet(String url, String param) {String result = "";BufferedReader in = null;try {String urlNameString = url + "?" + param;URL realUrl = new URL(urlNameString);// 打开和URL之间的连接URLConnection connection = realUrl.openConnection();// 设置通用的请求属性connection.setRequestProperty("accept", "*/*");connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("Accept-Charset", "utf-8");connection.setRequestProperty("contentType", "utf-8");connection.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 建立实际的连接connection.connect();// 获取所有响应头字段Map<String, List> map = connection.getHeaderFields();// 遍历所有的响应头字段for (String key : map.keySet()) {System.out.println(key + "--->" + map.get(key));}// 定义 BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String line;while ((line = in.readLine()) != null) {result += line;}} catch (Exception e) {System.out.println("发送GET请求出现异常!" + e);e.printStackTrace();}// 使用finally块来关闭输入流finally {try {if (in != null) {in.close();}} catch (Exception e2) {e2.printStackTrace();}}return result;}public static JSONObject sendGet(String url) {JSONObject jsonObject = null;BufferedReader in = null;try {URL url2 = new URL(url);// 打开和URL之间的连接URLConnection connection = url2.openConnection();// 设置通用的请求属性connection.setRequestProperty("accept", "*/*");connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");connection.setConnectTimeout(5000);connection.setReadTimeout(5000);// 建立实际的连接connection.connect();// 定义 BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(connection.getInputStream()));StringBuffer sb = new StringBuffer();String line;while ((line = in.readLine()) != null) {sb.append(line);}//jsonObject = new JSONObject(sb.toString());jsonObject = new JSONObject().fromObject(sb);return jsonObject;} catch (Exception e) {e.printStackTrace();}// 使用finally块来关闭输入流finally {try {if (in != null) {in.close();}} catch (Exception e2) {e2.printStackTrace();}}return null;}}

5、创建demo.class

package com.example.springboot.controller;import com.example.springboot.util.PortInit;import com.example.springboot.util.SerialPortUtil;import gnu.io.SerialPort;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.nio.ByteBuffer;/** * Demo class * * @author XDRS * @date 2023/3/30 15:50 */@RestControllerpublic class Demo {@GetMappingpublic void test() {SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();byte[] HEX = hexStr2Byte("000300040002841B");serialPortUtil.sendToPort(PortInit.serialPort, HEX);System.out.println(111111111);}/** * 定时任务,间隔5分钟采集一次数据 */@Scheduled(cron = "0 0/5 * * * ?")public void send() {System.out.println("send ok");SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();byte[] HEX = hexStr2Byte("000300040002841B");serialPortUtil.sendToPort(PortInit.serialPort, HEX);}/** * 十六进制字符串转byte[] * * @param hex 十六进制字符串 * @return byte[] */public static byte[] hexStr2Byte(String hex) {if (hex == null) {return new byte[]{};}// 奇数位补0if (hex.length() % 2 != 0) {hex = "0" + hex;}int length = hex.length();ByteBuffer buffer = ByteBuffer.allocate(length / 2);for (int i = 0; i < length; i++) {String hexStr = hex.charAt(i) + "";i++;hexStr += hex.charAt(i);byte b = (byte) Integer.parseInt(hexStr, 16);buffer.put(b);}return buffer.array();}}

6、开启@EnableScheduling注解

7、最后

@SpringBootApplication@EnableSchedulingpublic class SpringbootApplication {public static void main(String[] args) {SpringApplication.run(SpringbootApplication.class, args);}@PreDestroypublic void destory() {//关闭应用前 关闭端口SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();serialPortUtil.removeListener(PortInit.serialPort, new MyLister());serialPortUtil.closePort(PortInit.serialPort);}}

以上完结,希望大家多多提出宝贵意见,一起完善,感谢~!!