【JAVA】通过串口获取BLE蓝牙消息

最近在做一个小程序和硬件连接有关的项目,硬件是一块没有联网的开发板,首先要通过BLE蓝牙发送消息,将wifi账号和密码通过蓝牙发送到板子上,结果这个硬件厂商比较奇葩的是,他们板子的蓝牙消息走的是串口,直接去监听ubuntu系统的蓝牙还监听不到蓝牙消息,这就很奇葩了,问过厂家后才知道他们蓝牙走的是串口,那直接去监听蓝牙肯定监听不到了,没办法,改代码吧,从串口获取蓝牙消息。

比较常用的有两种方法,第一种是使用jSerialComm串口监听方式,第二种是rxtx串口监听方式,第二种官网下载jar包的时候出现404,目前我也还没有找到合适的jar包,有兴趣的可以了解一下,所以这里就只上第一种方法了。

好了,话不多说,上代码

一、maven引入

        
            com.fazecast
            jSerialComm
            2.6.0
        

二、代码


import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;



@Component
@Slf4j
public class jSerialCommUtil {



        // 当前串口对象引用
        static SerialPort serialPort;

        // 堵塞队列:用来存放串口发送到服务端的数据
        public BlockingQueue msgQueue = new LinkedBlockingQueue();

        // 线程控制标识
        public static boolean flag = true;





        /**
         * 打开电脑上指定的串口
         *
         * @param portName 端口名称,如 COM1,为 null 时,默认使用电脑中能用的端口中的第一个
         * @param b        波特率(baudrate),如 9600
         * @param d        数据位(datebits),如  8
         * @param s        停止位(stopbits),如  1
         * @param p        校验位 (parity),如 0
         * @return 打开的串口对象,打开失败时,返回 null
         */
        public final SerialPort openSerialPort(String portName, int b, int d, int s, int p) {

            SerialPort[] commPorts = SerialPort.getCommPorts();
            for (SerialPort itemPort : commPorts) {
                System.out.println("板子的串口名称---------"+itemPort.getSystemPortName());
                if (portName.equals(itemPort.getSystemPortName())) {
                    //判断串口是否打开,如果没打开,就打开串口。
                    if (itemPort.isOpen()) {
                        System.out.println("串口 " + portName + "已打开...");
                        return null;
                    }
                    //设置超时
                    itemPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);
                    // 第一个参数为波特率,默认9600;
                    // 第二个参数为每一位的大小,默认8,可以输入5到8之间的值;
                    // 第三个参数为停止位大小,只接受内置常量,可以选择(ONE_STOP_BIT, ONE_POINT_FIVE_STOP_BITS, TWO_STOP_BITS);
                    // 第四位为校验位,同样只接受内置常量,可以选择 NO_PARITY, EVEN_PARITY, ODD_PARITY, MARK_PARITY,SPACE_PARITY。
                    itemPort.setComPortParameters(b, d, s, p);
                    //设置串口的控制流,可以设置为disabled,或者CTS, RTS/CTS, DSR, DTR/DSR, Xon, Xoff, Xon/Xoff等
                    //serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
                    boolean isOpen = itemPort.openPort();
                    if (isOpen) {
                     
                        serialPort = itemPort;

                        System.out.println("打开串口 " + portName + " 成功...");
                        try {
                            Thread.sleep(1000);//打开串口后要休眠一段时间才能接收到输入流
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        itemPort.addDataListener(new SerialPortDataListener() {
                            @Override
                            public int getListeningEvents() {
                                return SerialPort.LISTENING_EVENT_DATA_RECEIVED;
                            }

                            @Override
                            public void serialEvent(SerialPortEvent serialPortEvent) {
                                byte[] newData = serialPortEvent.getReceivedData();
                                String weight = new String(newData);
                                if (StringUtils.isNotBlank(weight)) {
                                    msgQueue.add(weight);
                                }

                              System.out.println(String.format("串口%s接收到数据大小:%s,串口数据内容:%s"
                                        , serialPortEvent.getSerialPort().getSystemPortName(), newData.length, new String(newData)));

                        //TODO 这里已经从串口获取到蓝牙消息了,处理你自己的业务逻辑

                            }
                        });

                        return serialPort;
                    } else {

                        System.out.println("打开串口 " + portName + " 失败...");
                    }
                }
            }
            if (serialPort == null) {

                System.out.println("打开串口 " + portName + " 失败...,请检查串口名称是否正确,或是否被占用");
            }
            return null;
        }

}

OK,到此就搞定了,已经可以从串口获取到蓝牙消息。

最后别忘了关闭串口,当然是否关闭串口也要根据自己的业务逻辑来


        /**
         * 关闭串口
         *
         * @param serialPort 要关闭的串口对象
         */
        public Boolean closeSerialPort(SerialPort serialPort) {
            if (serialPort != null) {
                //关闭串口。该函数同样会返回一个boolean值,表明串口是否成功关闭
                return serialPort.closePort();
            }
            return false;
        }

这个方法有个好处就是,不用写个死循环去一直监听,也不用使用webscoket一直去访问,也算是大大减轻了服务器压力。但是得看硬件厂家是不是也和这家一样奇葩,走的是串口

方法到这里就结束了,然后把这个打成jar包,部署到开发板上,通过BLE调试助手app,就可以试着发送蓝牙消息了。

注意:板子中的波特率这个不一定都是9600,这个要咨询一下开发板的硬件厂家,串口名称也需要问一下厂家。数据位,停止位,校验位一般情况下都是固定的,8、1、0写死就行。

你可能感兴趣的:(java)