Java通过rs485串口与硬件设备交互:
**需求背景:**java代码访问雷达水位计,发送请求代码,接收返回代码,解析数据转换为double格式后发送给位于其它服务器的Java程序。
串口不同于socket通信,没有url与端口。串口即为计算机上的硬件连接端口,如USB端口、显示器端口等。监听串口的操作,就是使用代码或虚拟串口软件,定时监听指定串口动态,观察其是否有数据交互。
需要先要下载RXTX的jar包,win64位下载地址:http://pan.baidu.com/s/1o6zLmTc);将解压后的rxtxParallel.dll和rxtxSerial.dll两个文件放在%JAVA_HOME%/jre/bin目录下,这样该包才能被正常的加载和调用。
添加依赖:idea-Project Structure-Libraries-"+"添加rxtxjar包路径:通常在java jre\lib\ext下:例 D:\configFile\jdk1.8\jre\lib\ext
业务部分:
package com.example.waterlevel.service;
import com.alibaba.fastjson.JSONObject;
import com.example.waterlevel.service.impl.WaterLevelServiceImpl;
import gnu.io.PortInUseException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.awt.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
@Slf4j
public class TaskService {
@Autowired
WaterLevelDataService waterLevelDataService;
private RestTemplate restTemplate;
@Autowired
private void initRestTemplate(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
@Autowired
WaterLevelServiceImpl waterLevelService;
@Value("${hydrology.server_url}")
private String URL;
// 请求报文byte[]数组,每个设备应该都有对应的交互报文,在其配套文档里
private static byte[] BYTES = new byte[]{
0x01, 0x03, 0x00, 0x00, 0x00, 0x02, (byte) 0xC4, 0x0B};
private final double BASELINE = 67.20;
public double getWaterLevel4Radar() {
log.info("getWaterLevel4Radar begin.");
DecimalFormat df = new DecimalFormat("######0.00");
try {
// 开启端口:输入设备所连接的串口名(这里是COM3)打开串口链接,并开启监听
int com;
if (WaterLevelDataService.connect != 1) {
// 这里加了一个标识,循环读取串口数据时,如果串口是打开状态则无需再次打开
com = waterLevelDataService.listenPort("COM3");
if (com != 1) {
log.error("串口开启失败,请检查串口情况");
return 0.0;
}
}
// 向水位计发送请求报文
for (int i = 0; i < 10; i++) {
String msg = waterLevelDataService.setFlowSpeedOrder(BYTES); // 将常量请求报文byte[]数组发送至串口
Thread.sleep(1000);
log.info("请求发送情况: " + msg);
}
int size = WaterLevelDataService.doubleList.size();
log.info("雷达水位集合数据条目: " + size);
// 计算水位值
for (int i = 0; i < 100; i++) {
if (size >= 10) {
// 收集到10条以上数据则计算平均水位值
double asDouble = WaterLevelDataService.doubleList.stream().mapToDouble(flt -> flt).average().getAsDouble();
double realLevel = BASELINE - asDouble / 100;
double formatRealLevel = Double.parseDouble(df.format(realLevel)