在对接之前,首先安装基础环境
一、安装基础环境,软件包地址
链接:https://pan.baidu.com/s/11VPQij60af8nFxwUErsnGA?pwd=5jm8
提取码:5jm8
二、实现
1、pom.xml文件引入
<dependency>
<groupId>org.rxtx</groupId>
<artifactId>rxtx</artifactId>
<version>2.1.7</version>
</dependency>
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 {
@Override
public 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
*/
@Component
public class PortInit implements ApplicationRunner{
public static SerialPort serialPort = null;
@Override
public void run(ApplicationArguments args) {
String portName = "COM1";
//TestA();
//查看所有串口
SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
ArrayList<String> 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<String> findPort() {
//获得当前所有可用串口
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<>();
//将可用串口名添加到List并返回该List
while (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<String>> 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
*/
@RestController
public class Demo {
@GetMapping
public 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[]{};
}
// 奇数位补0
if (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
@EnableScheduling
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
@PreDestroy
public void destory() {
//关闭应用前 关闭端口
SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
serialPortUtil.removeListener(PortInit.serialPort, new MyLister());
serialPortUtil.closePort(PortInit.serialPort);
}
}
以上完结,希望大家多多提出宝贵意见,一起完善,感谢~!!