当前位置:   article > 正文

java实现R485串口通信和数据解析_java rs485

java rs485

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

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

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

二、实现

1、pom.xml文件引入

  1. <dependency>
  2. <groupId>org.rxtx</groupId>
  3. <artifactId>rxtx</artifactId>
  4. <version>2.1.7</version>
  5. </dependency>

2、创建监听类 MyLister.clss

  1. package com.example.springboot.util;
  2. /**
  3. * Demo class
  4. *
  5. * @author XDRS
  6. * @date 2023/3/30 16:01
  7. */
  8. import gnu.io.SerialPortEvent;
  9. import gnu.io.SerialPortEventListener;
  10. import net.sf.json.JSONObject;
  11. import java.math.BigDecimal;
  12. import java.nio.ByteBuffer;
  13. import java.nio.charset.StandardCharsets;
  14. import java.util.Date;
  15. public class MyLister implements SerialPortEventListener {
  16. @Override
  17. public void serialEvent(SerialPortEvent arg0) {
  18. try {
  19. if (arg0.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
  20. SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
  21. byte[] bytes = serialPortUtil.readFromPort(PortInit.serialPort);
  22. String needData = printHexString(bytes);
  23. boolean b = needData.contains("01 03");
  24. String[] strings = needData.split(" ");
  25. int xxxx = Integer.parseInt(strings[0] + "", 16);
  26. if (xxxx == 1 && b) {
  27. System.out.println(new Date() + "【字节数组转16进制字符串】:-----" + needData);
  28. int xss = Integer.parseInt(strings[4] + "", 16);
  29. double value = BigDecimal.valueOf(xss).divide(BigDecimal.valueOf(10)).setScale(1, BigDecimal.ROUND_DOWN).doubleValue();
  30. System.out.println(new Date() + "水位:-----" + value + "℃");
  31. int yss = Integer.parseInt(strings[6] + "", 16);
  32. double value2 = BigDecimal.valueOf(yss).setScale(1, BigDecimal.ROUND_DOWN).doubleValue();
  33. System.out.println(new Date() + "水位:-----" + value2 + "mm");
  34. // 写入数据库,按照api方式发送指定服务上
  35. String url = "http://192.168.0.17:8888/api/geological/demo/insert";
  36. JSONObject object = new JSONObject();
  37. object.put("instrumentName", "水位计");
  38. object.put("value", needData);
  39. object.put("instrumentUid", 1);
  40. object.put("analyseValue", value2);
  41. object.put("type", "普通采集");
  42. String toString = object.toString();
  43. String post = CommonUtil.doHttpPost(url, toString);
  44. if (post.equals("0")) {
  45. System.out.println("传输数据失败");
  46. } else {
  47. System.out.println("传输数据成功");
  48. }
  49. }
  50. }
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. /**
  56. * 字节数组转16进制字符串
  57. *
  58. * @param b 字节数组
  59. * @return 16进制字符串
  60. */
  61. public static String printHexString(byte[] b) {
  62. StringBuilder sbf = new StringBuilder();
  63. for (byte value : b) {
  64. String hex = Integer.toHexString(value & 0xFF);
  65. if (hex.length() == 1) {
  66. hex = '0' + hex;
  67. }
  68. sbf.append(hex.toUpperCase()).append(" ");
  69. }
  70. return sbf.toString().trim();
  71. }
  72. /**
  73. * 十六进制字符串转byte[]
  74. *
  75. * @param hex 十六进制字符串
  76. * @return byte[]
  77. */
  78. public static byte[] hexStr2Byte(String hex) {
  79. if (hex == null) {
  80. return new byte[]{};
  81. }
  82. // 奇数位补0
  83. // if (hex.length() % StaticConstant.TWO != 0) {
  84. // hex = "0" + hex;
  85. // }
  86. int length = hex.length();
  87. ByteBuffer buffer = ByteBuffer.allocate(length / 2);
  88. for (int i = 0; i < length; i++) {
  89. String hexStr = hex.charAt(i) + "";
  90. i++;
  91. hexStr += hex.charAt(i);
  92. byte b = (byte) Integer.parseInt(hexStr, 16);
  93. buffer.put(b);
  94. }
  95. return buffer.array();
  96. }
  97. /**
  98. * 16进制转换成为string类型字符串
  99. *
  100. * @param s 待转换字符串
  101. */
  102. public static String hexStringToString(String s) {
  103. if (s == null || "".equals(s)) {
  104. return null;
  105. }
  106. s = s.replace(" ", "");
  107. byte[] baKeyword = new byte[s.length() / 2];
  108. for (int i = 0; i < baKeyword.length; i++) {
  109. try {
  110. baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
  111. } catch (Exception e) {
  112. e.printStackTrace();
  113. }
  114. }
  115. try {
  116. s = new String(baKeyword, StandardCharsets.UTF_8);
  117. } catch (Exception e1) {
  118. e1.printStackTrace();
  119. }
  120. return s;
  121. }
  122. }

2、创建 PortInit.class

  1. package com.example.springboot.util;
  2. import gnu.io.SerialPort;
  3. import org.springframework.boot.ApplicationArguments;
  4. import org.springframework.boot.ApplicationRunner;
  5. import org.springframework.stereotype.Component;
  6. import java.util.ArrayList;
  7. /**
  8. * Demo class
  9. *
  10. * @author XDRS
  11. * @date 2023/3/30 16:01
  12. */
  13. @Component
  14. public class PortInit implements ApplicationRunner{
  15. public static SerialPort serialPort = null;
  16. @Override
  17. public void run(ApplicationArguments args) {
  18. String portName = "COM1";
  19. //TestA();
  20. //查看所有串口
  21. SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
  22. ArrayList<String> port = serialPortUtil.findPort();
  23. System.out.println("发现全部串口:" + port);
  24. System.out.println("portName:" + portName);
  25. //打开该对应portName名字的串口
  26. PortInit.serialPort = serialPortUtil.openPort(portName, 9600, SerialPort.DATABITS_8, SerialPort.PARITY_NONE, SerialPort.PARITY_ODD);
  27. // 给对应的serialPort添加监听器
  28. serialPortUtil.addListener(PortInit.serialPort, new MyLister());
  29. }
  30. }

3、创建 SerialPortUtil.class

  1. package com.example.springboot.util;
  2. import gnu.io.*;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.OutputStream;
  8. import java.util.ArrayList;
  9. import java.util.Enumeration;
  10. import java.util.TooManyListenersException;
  11. /**
  12. * Demo class
  13. *
  14. * @author XDRS
  15. * @date 2023/3/30 16:00
  16. */
  17. public class SerialPortUtil {
  18. private static final Logger logger = LoggerFactory.getLogger(SerialPortUtil.class);
  19. private static SerialPortUtil serialPortUtil = null;
  20. static {
  21. // 在该类被ClassLoader加载时就初始化一个SerialTool对象
  22. if (serialPortUtil == null) {
  23. serialPortUtil = new SerialPortUtil();
  24. }
  25. }
  26. // 私有化SerialTool类的构造方法,不允许其他类生成SerialTool对象
  27. private SerialPortUtil() {
  28. }
  29. /**
  30. * 获取提供服务的SerialTool对象
  31. *
  32. * @return serialPortUtil
  33. */
  34. public static SerialPortUtil getSerialPortUtil() {
  35. if (serialPortUtil == null) {
  36. serialPortUtil = new SerialPortUtil();
  37. }
  38. return serialPortUtil;
  39. }
  40. /**
  41. * 查找所有可用端口
  42. *
  43. * @return 可用端口名称列表
  44. */
  45. public ArrayList<String> findPort() {
  46. //获得当前所有可用串口
  47. Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
  48. ArrayList<String> portNameList = new ArrayList<>();
  49. //将可用串口名添加到List并返回该List
  50. while (portList.hasMoreElements()) {
  51. String portName = portList.nextElement().getName();
  52. portNameList.add(portName);
  53. }
  54. return portNameList;
  55. }
  56. /**
  57. * 打开串口
  58. *
  59. * @param portName 端口名称
  60. * @param baudrate 波特率 19200
  61. * @param databits 数据位 8
  62. * @param parity 校验位(奇偶位) NONE :0
  63. * @param stopbits 停止位 1
  64. * @return 串口对象
  65. * // * @throws SerialPortParameterFailure 设置串口参数失败
  66. * // * @throws NotASerialPort 端口指向设备不是串口类型
  67. * // * @throws NoSuchPort 没有该端口对应的串口设备
  68. * // * @throws PortInUse 端口已被占用
  69. */
  70. public SerialPort openPort(String portName, int baudrate, int databits, int parity, int stopbits) {
  71. try {
  72. //通过端口名识别端口
  73. CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
  74. //打开端口,并给端口名字和一个timeout(打开操作的超时时间)
  75. CommPort commPort = portIdentifier.open(portName, 2000);
  76. //判断是不是串口
  77. if (commPort instanceof SerialPort) {
  78. SerialPort serialPort = (SerialPort) commPort;
  79. try {
  80. //设置一下串口的波特率等参数
  81. serialPort.setSerialPortParams(baudrate, databits, stopbits, parity);
  82. } catch (UnsupportedCommOperationException e) {
  83. }
  84. System.out.println("Open " + portName + " sucessfully !");
  85. return serialPort;
  86. } else {
  87. logger.error("不是串口");
  88. }
  89. } catch (NoSuchPortException e1) {
  90. logger.error("没有找到端口");
  91. e1.printStackTrace();
  92. } catch (PortInUseException e2) {
  93. logger.error("端口被占用");
  94. e2.printStackTrace();
  95. }
  96. return null;
  97. }
  98. /**
  99. * 关闭串口
  100. *
  101. * @param serialPort 待关闭的串口对象
  102. */
  103. public void closePort(SerialPort serialPort) {
  104. if (serialPort != null) {
  105. serialPort.close();
  106. }
  107. }
  108. /**
  109. * 往串口发送数据
  110. *
  111. * @param serialPort 串口对象
  112. * @param order 待发送数据
  113. * // * @throws SendDataToSerialPortFailure 向串口发送数据失败
  114. * // * @throws SerialPortOutputStreamCloseFailure 关闭串口对象的输出流出错
  115. */
  116. public void sendToPort(SerialPort serialPort, byte[] order) {
  117. OutputStream out = null;
  118. try {
  119. out = serialPort.getOutputStream();
  120. out.write(order);
  121. out.flush();
  122. } catch (IOException e) {
  123. e.printStackTrace();
  124. } finally {
  125. try {
  126. if (out != null) {
  127. out.close();
  128. }
  129. } catch (IOException e) {
  130. e.printStackTrace();
  131. }
  132. }
  133. }
  134. /**
  135. * 从串口读取数据
  136. *
  137. * @param serialPort 当前已建立连接的SerialPort对象
  138. * @return 读取到的数据
  139. * // * @throws ReadDataFromSerialPortFailure 从串口读取数据时出错
  140. * // * @throws SerialPortInputStreamCloseFailure 关闭串口对象输入流出错
  141. */
  142. public byte[] readFromPort(SerialPort serialPort) {
  143. InputStream in = null;
  144. byte[] bytes = null;
  145. try {
  146. in = serialPort.getInputStream();
  147. int bufflenth = in.available();
  148. while (bufflenth != 0) {
  149. bytes = new byte[bufflenth];
  150. in.read(bytes);
  151. bufflenth = in.available();
  152. }
  153. } catch (IOException e) {
  154. e.printStackTrace();
  155. } finally {
  156. try {
  157. if (in != null) {
  158. in.close();
  159. }
  160. } catch (IOException e) {
  161. e.printStackTrace();
  162. }
  163. }
  164. return bytes;
  165. }
  166. /**
  167. * 添加监听器
  168. *
  169. * @param port 串口对象
  170. * @param listener 串口监听器
  171. * // * @throws TooManyListeners 监听类对象过多
  172. */
  173. public void addListener(SerialPort port, SerialPortEventListener listener) {
  174. try {
  175. //给串口添加监听器
  176. port.addEventListener(listener);
  177. //设置当有数据到达时唤醒监听接收线程
  178. port.notifyOnDataAvailable(true);
  179. //设置当通信中断时唤醒中断线程
  180. port.notifyOnBreakInterrupt(true);
  181. } catch (TooManyListenersException e) {
  182. // throw new TooManyListeners();
  183. logger.error("太多监听器");
  184. e.printStackTrace();
  185. }
  186. }
  187. /**
  188. * 删除监听器
  189. *
  190. * @param port 串口对象
  191. * @param listener 串口监听器
  192. * // * @throws TooManyListeners 监听类对象过多
  193. */
  194. public void removeListener(SerialPort port, SerialPortEventListener listener) {
  195. //删除串口监听器
  196. port.removeEventListener();
  197. }
  198. /**
  199. * 设置串口的Listener
  200. *
  201. * @param serialPort
  202. * @param listener
  203. * @author mar
  204. * @date 2021/8/20 11:04
  205. */
  206. public static void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) {
  207. try {
  208. //给串口添加事件监听
  209. serialPort.addEventListener(listener);
  210. } catch (TooManyListenersException e) {
  211. e.printStackTrace();
  212. }
  213. //串口有数据监听
  214. serialPort.notifyOnDataAvailable(true);
  215. //中断事件监听
  216. serialPort.notifyOnBreakInterrupt(true);
  217. }
  218. }

4、创建 CommonUtil.class

  1. package com.example.springboot.util;
  2. import net.sf.json.JSONObject;
  3. import org.apache.commons.io.IOUtils;
  4. import java.io.BufferedReader;
  5. import java.io.DataInputStream;
  6. import java.io.DataOutputStream;
  7. import java.io.InputStream;
  8. import java.io.InputStreamReader;
  9. import java.io.OutputStream;
  10. import java.net.ConnectException;
  11. import java.net.HttpURLConnection;
  12. import java.net.URL;
  13. import java.net.URLConnection;
  14. import java.util.List;
  15. import java.util.Map;
  16. import javax.net.ssl.HttpsURLConnection;
  17. import javax.net.ssl.SSLContext;
  18. import javax.net.ssl.SSLSocketFactory;
  19. import javax.net.ssl.TrustManager;
  20. public class CommonUtil {
  21. /**
  22. * TODO 获取http访问后的json串
  23. * @param urlPath
  24. * @return
  25. */
  26. public static String getJSONContent(String urlPath) {
  27. String jsonString = "";
  28. // 访问路径
  29. try {
  30. // 创建HTTP连接
  31. URL url = new URL(urlPath);
  32. HttpURLConnection connection = (HttpURLConnection) url
  33. .openConnection();
  34. // 设置连接超时时间
  35. connection.setConnectTimeout(5000);
  36. connection.setRequestMethod("GET");
  37. connection.setDoInput(true);
  38. // 获取相应代码,判断是否响应结束
  39. int code = connection.getResponseCode();
  40. if (code == 200) {
  41. InputStream is = connection.getInputStream();
  42. DataInputStream indata = new DataInputStream(is);
  43. String ret = "";
  44. while (ret != null) {
  45. ret = indata.readLine();
  46. if (ret != null && !ret.trim().equals("")) {
  47. jsonString = jsonString
  48. + new String(ret.getBytes("ISO-8859-1"), "UTF-8");
  49. }
  50. }
  51. connection.disconnect();
  52. }
  53. } catch (Exception e) {
  54. e.printStackTrace();
  55. }
  56. return jsonString;
  57. }
  58. /**
  59. * 发送Http post请求
  60. *
  61. * @param xmlInfo
  62. * json转化成的字符串
  63. * @param URL
  64. * 请求url
  65. * @return 返回信息
  66. */
  67. public static String doHttpPost(String URL,String xmlInfo ) {
  68. System.out.println("发起的数据:" + xmlInfo);
  69. byte[] xmlData = xmlInfo.getBytes();
  70. InputStream instr = null;
  71. try {
  72. URL url = new URL(URL);
  73. URLConnection urlCon = url.openConnection();
  74. urlCon.setDoOutput(true);
  75. urlCon.setDoInput(true);
  76. urlCon.setUseCaches(false);
  77. urlCon.setRequestProperty("content-Type", "application/json");
  78. urlCon.setRequestProperty("charset", "utf-8");
  79. urlCon.setRequestProperty("Content-length",
  80. String.valueOf(xmlData.length));
  81. System.out.println(String.valueOf(xmlData.length));
  82. DataOutputStream printout = new DataOutputStream(
  83. urlCon.getOutputStream());
  84. printout.write(xmlData);
  85. printout.flush();
  86. printout.close();
  87. instr = urlCon.getInputStream();
  88. byte[] bis = IOUtils.toByteArray(instr);
  89. String ResponseString = new String(bis, "UTF-8");
  90. if ((ResponseString == null) || ("".equals(ResponseString.trim()))) {
  91. System.out.println("返回空");
  92. }
  93. System.out.println("返回数据为:" + ResponseString);
  94. return ResponseString;
  95. } catch (Exception e) {
  96. e.printStackTrace();
  97. return "0";
  98. } finally {
  99. try {
  100. instr.close();
  101. } catch (Exception ex) {
  102. ex.printStackTrace();
  103. return "0";
  104. }
  105. }
  106. }
  107. /**
  108. * 向指定URL发送GET方法的请求
  109. *
  110. * @param url
  111. * 发送请求的URL
  112. * @param param
  113. * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
  114. * @return URL 所代表远程资源的响应结果
  115. */
  116. public static String sendGet(String url, String param) {
  117. String result = "";
  118. BufferedReader in = null;
  119. try {
  120. String urlNameString = url + "?" + param;
  121. URL realUrl = new URL(urlNameString);
  122. // 打开和URL之间的连接
  123. URLConnection connection = realUrl.openConnection();
  124. // 设置通用的请求属性
  125. connection.setRequestProperty("accept", "*/*");
  126. connection.setRequestProperty("connection", "Keep-Alive");
  127. connection.setRequestProperty("Accept-Charset", "utf-8");
  128. connection.setRequestProperty("contentType", "utf-8");
  129. connection.setRequestProperty("user-agent",
  130. "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
  131. // 建立实际的连接
  132. connection.connect();
  133. // 获取所有响应头字段
  134. Map<String, List<String>> map = connection.getHeaderFields();
  135. // 遍历所有的响应头字段
  136. for (String key : map.keySet()) {
  137. System.out.println(key + "--->" + map.get(key));
  138. }
  139. // 定义 BufferedReader输入流来读取URL的响应
  140. in = new BufferedReader(new InputStreamReader(
  141. connection.getInputStream()));
  142. String line;
  143. while ((line = in.readLine()) != null) {
  144. result += line;
  145. }
  146. } catch (Exception e) {
  147. System.out.println("发送GET请求出现异常!" + e);
  148. e.printStackTrace();
  149. }
  150. // 使用finally块来关闭输入流
  151. finally {
  152. try {
  153. if (in != null) {
  154. in.close();
  155. }
  156. } catch (Exception e2) {
  157. e2.printStackTrace();
  158. }
  159. }
  160. return result;
  161. }
  162. public static JSONObject sendGet(String url) {
  163. JSONObject jsonObject = null;
  164. BufferedReader in = null;
  165. try {
  166. URL url2 = new URL(url);
  167. // 打开和URL之间的连接
  168. URLConnection connection = url2.openConnection();
  169. // 设置通用的请求属性
  170. connection.setRequestProperty("accept", "*/*");
  171. connection.setRequestProperty("connection", "Keep-Alive");
  172. connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
  173. connection.setConnectTimeout(5000);
  174. connection.setReadTimeout(5000);
  175. // 建立实际的连接
  176. connection.connect();
  177. // 定义 BufferedReader输入流来读取URL的响应
  178. in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  179. StringBuffer sb = new StringBuffer();
  180. String line;
  181. while ((line = in.readLine()) != null) {
  182. sb.append(line);
  183. }
  184. //jsonObject = new JSONObject(sb.toString());
  185. jsonObject = new JSONObject().fromObject(sb);
  186. return jsonObject;
  187. } catch (Exception e) {
  188. e.printStackTrace();
  189. }
  190. // 使用finally块来关闭输入流
  191. finally {
  192. try {
  193. if (in != null) {
  194. in.close();
  195. }
  196. } catch (Exception e2) {
  197. e2.printStackTrace();
  198. }
  199. }
  200. return null;
  201. }
  202. }

5、创建demo.class

  1. package com.example.springboot.controller;
  2. import com.example.springboot.util.PortInit;
  3. import com.example.springboot.util.SerialPortUtil;
  4. import gnu.io.SerialPort;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.scheduling.annotation.Scheduled;
  7. import org.springframework.web.bind.annotation.GetMapping;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import java.nio.ByteBuffer;
  10. /**
  11. * Demo class
  12. *
  13. * @author XDRS
  14. * @date 2023/3/30 15:50
  15. */
  16. @RestController
  17. public class Demo {
  18. @GetMapping
  19. public void test() {
  20. SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
  21. byte[] HEX = hexStr2Byte("000300040002841B");
  22. serialPortUtil.sendToPort(PortInit.serialPort, HEX);
  23. System.out.println(111111111);
  24. }
  25. /**
  26. * 定时任务,间隔5分钟采集一次数据
  27. */
  28. @Scheduled(cron = "0 0/5 * * * ?")
  29. public void send() {
  30. System.out.println("send ok");
  31. SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
  32. byte[] HEX = hexStr2Byte("000300040002841B");
  33. serialPortUtil.sendToPort(PortInit.serialPort, HEX);
  34. }
  35. /**
  36. * 十六进制字符串转byte[]
  37. *
  38. * @param hex 十六进制字符串
  39. * @return byte[]
  40. */
  41. public static byte[] hexStr2Byte(String hex) {
  42. if (hex == null) {
  43. return new byte[]{};
  44. }
  45. // 奇数位补0
  46. if (hex.length() % 2 != 0) {
  47. hex = "0" + hex;
  48. }
  49. int length = hex.length();
  50. ByteBuffer buffer = ByteBuffer.allocate(length / 2);
  51. for (int i = 0; i < length; i++) {
  52. String hexStr = hex.charAt(i) + "";
  53. i++;
  54. hexStr += hex.charAt(i);
  55. byte b = (byte) Integer.parseInt(hexStr, 16);
  56. buffer.put(b);
  57. }
  58. return buffer.array();
  59. }
  60. }

6、开启@EnableScheduling注解

 7、最后

  1. @SpringBootApplication
  2. @EnableScheduling
  3. public class SpringbootApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(SpringbootApplication.class, args);
  6. }
  7. @PreDestroy
  8. public void destory() {
  9. //关闭应用前 关闭端口
  10. SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
  11. serialPortUtil.removeListener(PortInit.serialPort, new MyLister());
  12. serialPortUtil.closePort(PortInit.serialPort);
  13. }
  14. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/326206
推荐阅读
相关标签
  

闽ICP备14008679号