1.创建监听
package com.datago.serve.common.serialport;
import com.datago.common.core.utils.StringUtils;
import com.datago.serve.common.config.SerialPortConfig;
import com.datago.serve.common.websocket.ScannerSocketServer;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import lombok.SneakyThrows;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import java.util.Map;
/**
* @ProjectName serial-port
* @Package com.datago.serialport.controller.boot
* @Name MyLister
* @Author HB
* @Date 2022/7/13 10:38
* @Version 1.0
*/
public class SerialPortLister implements SerialPortEventListener {
//1.返回数据
public static String lightData;
//2.返回数据
public static String servoData;
@Override
@SneakyThrows
public void serialEvent(SerialPortEvent arg0) {
if (arg0.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
Map comMap = SerialPortUtil.comMap;
if (comMap.size() > 0) {
SerialPort lightSerialPort = comMap.get(SerialPortConfig.light);
if (StringUtils.isNotNull(lightSerialPort)) {
byte[] bytes = serialPortUtil.readFromPorts(lightSerialPort);
String byteStr = new String(bytes, 0, bytes.length).trim();
if (!byteStr.equals("")) {
//赋返回值
lightData = byteStr;
}
}
SerialPort servoSerialPort = comMap.get(SerialPortConfig.servo);
if (StringUtils.isNotNull(servoSerialPort)) {
byte[] bytes = serialPortUtil.readFromPorts(servoSerialPort);
String byteStr = new String(bytes, 0, bytes.length).trim();
if (!byteStr.equals("")) {
//赋返回值 0正常运行1停止运行2有异常
if (!byteStr.equals(servoData)){
servoData = byteStr;
SerialPortConfig.redisService.setCacheObject("servoData",servoData);
//推送前端
JSONObject object = JSONObject.fromObject("{\"code\":10000,\"message\":\"\",\"data\":\"\"}");
object.put("turntableStatus",servoData);//0正常运行1停止运行2有异常
ScannerSocketServer.sendInfo(object.toString(), null);
}
}
}
}
}
}
}
2.串口工具类
package com.datago.serve.common.serialport;
import com.datago.common.core.utils.StringUtils;
import gnu.io.*;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
/**
* @ProjectName serial-port
* @Package com.datago.serialport.controller.boot
* @Name SerialPortUtil
* @Author HB
* @Date 2022/7/13 09:58
* @Version 1.0
*/
@Slf4j
public class SerialPortUtil {
private static SerialPortUtil serialPortUtil = null;
static {
//在该类被ClassLoader加载时就初始化一个serialTool对象
if (serialPortUtil == null) {
serialPortUtil = new SerialPortUtil();
}
}
//私有化SerialTool类的构造方法,不允许其他类生成SerialTool对象
private SerialPortUtil() {
}
/**
* 串口通信map,存储串口名称与串口信息
*/
public static Map comMap =new HashMap<>();
/**
* 获取提供服务的SerialTool对象
*/
public static SerialPortUtil getSerialPortUtil() {
if (serialPortUtil == null) {
serialPortUtil = new SerialPortUtil();
}
return serialPortUtil;
}
/**
* 打开串口
*/
public SerialPort openPort(String portName, int baudrate, int databits, int parity, int stopbatis) {
try {
//通过端口名识别端口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
//打开端口,并给端口名字一个timeout(打开操作的超时时间)
CommPort commPort = portIdentifier.open(portName, 2000);
//判断是不是串口
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
comMap.put(portName, serialPort);
//设置一下串口的波特率等参数
try {
serialPort.setSerialPortParams(baudrate, databits, parity, stopbatis);
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
}
log.info("Open-------------{}" + portName + "sucessfully");
return serialPort;
} else {
log.error("不是串口----------{}");
}
} catch (NoSuchPortException e) {
log.error("没有找到端口--------------{}");
e.printStackTrace();
} catch (PortInUseException e) {
log.error("端口被占用--------------{}");
e.printStackTrace();
}
return null;
}
/**
* 关闭串口
*/
public void closePort(SerialPort serialPort) {
if (serialPort != null) {
serialPort.close();
}
}
/**
* 往串口发送数据
*/
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();
}
}
}
/**从串口读取数据*/
public byte[] readFromPorts(SerialPort serialPort){
InputStream in=null;
byte[] bytes={};
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
try {
in=serialPort.getInputStream();
byte[] readBuffer = new byte[1];
int bufflenth=in.read(readBuffer);
while (bufflenth > 0){
bytes= byteMerger(bytes,readBuffer);
bufflenth=in.read(readBuffer);
}
}catch (IOException e){
e.printStackTrace();
}finally {
try {
in.close();
in = null;
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){
byte[] byte_3 = new byte[byte_1.length+byte_2.length];
System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
return byte_3;
}
/**添加监听器*/
public void addListener(SerialPort port,SerialPortEventListener listener){
try {
//给串口添加监听器
port.addEventListener(listener);
//设置当有数据到时唤醒监听接收线程
port.notifyOnDataAvailable(true);
//设置当通信中断时唤醒中断线程
port.notifyOnBreakInterrupt(true);
}catch (TooManyListenersException e){
log.error("太多监听器-------------{}");
e.printStackTrace();
}
}
/**删除监听器*/
public void removeListener(SerialPort port){
//删除串口监听器
port.removeEventListener();
}
//通过串口下发指令
public static void sendMessage(String com,String param){
//开启指定串口
SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
SerialPort serialPort = SerialPortUtil.comMap.get(com);
if (StringUtils.isNull(serialPort)) {
//打开该对应portname名字的串口
serialPort = serialPortUtil.openPort(com, 19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
//给对应的serialPort添加监听器
serialPortUtil.addListener(serialPort, new SerialPortLister());
}
//发送数据
try {
byte[] bytes = param.getBytes();
serialPortUtil.sendToPort(serialPort, bytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3.测试控制类
package com.datago.serve.controller;
import com.datago.serve.common.serialport.SerialPortLister;
import com.datago.serve.common.serialport.SerialPortUtil;
import gnu.io.SerialPort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 类描述:TODO
* 串口通讯
* @author HBO
* @date 2022-11-17 16:57
**/
@RestController
@RequestMapping("/serial")
public class SerialPortController {
@GetMapping(value = "/openSerial")
public void openSerial(@RequestParam(value = "portName") String portName,
@RequestParam(value = "port") Integer port) {
SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
//打开该对应portname名字的串口
SerialPort serialPort = serialPortUtil.openPort(portName, port, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
//给对应的serialPort添加监听器
serialPortUtil.addListener(serialPort, new SerialPortLister());
System.out.println("API开启串口通信");
}
@GetMapping(value = "/closeSerial")
private void closeSerial(@RequestParam(value = "portName") String portName) {
SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
SerialPort serialPort = SerialPortUtil.comMap.get(portName);
serialPortUtil.removeListener(serialPort);
serialPortUtil.closePort(serialPort);
SerialPortUtil.comMap.remove(portName);
System.out.println("API关闭串口通信");
}
@GetMapping(value = "/sendSerial")
private void sendSerial(@RequestParam(value = "portName") String portName,
@RequestParam(value = "code") String code) {
SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
SerialPort serialPort = SerialPortUtil.comMap.get(portName);
try {
byte[] bytes = code.getBytes();
serialPortUtil.sendToPort(serialPort, bytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
4.实际项目应用
//通过串口给伺服发送数据 参数:转台转速+旋转角度+侧相机焦距(伺服)
//查询所属项目获取参数
DgProject dgProject = dgProjectService.selectDgProjectByProjectId(projectId);
if (StringUtils.isNotNull(dgProject)) {
String s = dgProject.getTurntableSpeed() + dgProject.getTurntableAngle() + dgProject.getSideCameraFocal();
SerialPortUtil.sendMessage(SerialPortConfig.servo, s);
}
// 光源串口通讯 侧光源亮度(光源控制器)+底光源亮度(光源控制器)+通道A+B+C
if (StringUtils.isNotNull(dgProject)) {
String s = dgProject.getSideLightBrightness() + "-" + dgProject.getBottomLightBrightness()
+ "-" + SerialPortConfig.passagewayA + "-" + SerialPortConfig.passagewayB + "-" + SerialPortConfig.passagewayC;
SerialPortUtil.sendMessage(SerialPortConfig.light, s);
//获取返回数据
String lightData = SerialPortLister.lightData;
String s1 = setCameraParameterResult + "," + lightData;
}
}