Java与多串口通讯(二)

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;

                        }
                    }

你可能感兴趣的:(串口通讯,后台,开源分享项目,java,开发语言,运维)