android作为服务器的开发,安卓与pc的串口开发

公司要求,一个比较扯淡的架构

在安卓系统上完成一套mini的完整服务

包括规约解析的规约插件;包括调度,采集,存库等的采集系统;以及上层面向客户的各个应用

 

也就接触了android开发;

先说踩的坑把

在IDEA上做android开发;gradle的构建工具最好选下面版本,不然可能会报版本问题

classpath 'com.android.tools.build:gradle:7.0.0'

其他问题几乎没有,有应该也不是啥大问题把,没印象了

 

然后要在安卓上实现AB芯的通信,通过串口

应该是安卓模拟器天生的bug,发送数据超过8个字节就会挂掉,

环境构建的坑:

1.安卓模拟器没有root权限,需要命令行修改:

adb root
adb shell setenforce 0
adb shell

chmod 777 /dev/tty*

2.命令行启动模拟器,挂载串口 emulator @Nexus_9_API_30 -qemu -serial COM1

 

 

为了规避安卓模拟一发就挂,只能安卓往外发,在另一端写好接收后的代码,调试OK,搬回android项目,等上了真实终端调试

调试代码需要依赖rxtx

http://fizzed.com/oss/rxtx-for-java

还需要将dll文件放入:1将jar包放入jre/lib下的ext文件夹;2C:/System/System32

可能放一个地方也行,我两边都放了,项目能运行,也就没管

 

串口工具网上很多的我主要用了Configure Virtual Serial Port Driver开端口,serial_port_utility来开端口发数据

 

网上确实有解决安卓模拟器异常退出的方法,我倒腾了半天,没有成功,安装的程序又大又笨重,最后还是自己在PC写个接收程序,实现安卓端程序的分包问题等。

 

贴一下接收端的纯PC的java代码,代码主要也是从网上来得,但是源码的接收写的有问题,我这里优化了接收,以及我自己的分包策略

 

代码

 

package com.company;

import gnu.io.SerialPort;

import java.nio.charset.StandardCharsets;
import java.util.Locale;

import static com.company.SerialPortConstants.BEGIN_BYTES;
import static com.company.SerialPortConstants.END_BYTE;

public class client {

    static int i = 0;
    public static StringBuffer sb = new StringBuffer();

    public static void main(String[] args) throws SerialPortParameterFailure, NoSuchPort, InterruptedException {

       /* ArrayList<String> findPort = SerialTool.findPort();
        System.out.println("可用串口");
        for(String f:findPort) {
            System.out.println(f);
        }
        System.out.println();
        //设定发送字符串

        System.out.println(Arrays.toString(bs));//打印字符串
        System.out.println(findPort.get(0));//找到COM1串口*/
        byte[] bs = "AA".getBytes();
        SerialPort Port = SerialTool.openPort("COM2", 9600);//打开串口
        System.out.println(Port.getName());//获取串口名
        SerialTool.addListener(Port, new SerialTool.DataAvailableListener() {
            @SuppressWarnings("unused")
            @Override
            public void dataAvailable() {

                try {
                    if (Port == null) {
                        System.out.println("串口对象为空,监听失败!");
                    } else {
                        // 读取串口数据
                        new Thread(() -> {
                            while (true) {
                                byte[] data = null;
                                try {
                                    data = SerialTool.readFromPort(Port);
                                    /*System.out.println("打印"+data);*/
                                    if (data != null && data.length > 0) {

                                        sb.append(new String(data));
                                        spilt(sb);
                                        System.out.println();
                                        System.out.println();
                                        System.out.println("------------");
                                        System.out.println(new String(data));
                                        System.out.println(sb.toString());
                                        System.out.println("------------");
                                        System.out.println();
                                        System.out.println();
                                    }
                                } catch (NoSuchPort e) {
                                    e.printStackTrace();
                                } finally {
                                    try {
                                        Thread.sleep(1000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }

                            }
                        }).start();

                    }
                } catch (Exception e) {
                    System.out.println("错误");
                }
            }
        });
        String s = "##0897{\"businessObjList\":[{\"commObj\":{\"authId\":0,\"commAddr\":\"116000009488\",\"deviceId\":\"200000312\",\"eigenvalue\":3,\"extendObj\":{\"comInfo\":{\"baudRate\":\"2400\",\"byteSize\":\"0\",\"comPort\":31,\"parity\":\"0\",\"stopBits\":\"0\"},\"measurNo\":201,\"port\":0,\"pulseSerial\":-1,\"roadNo\":201,\"totalSerial\":0},\"protocolNumber\":401070011},\"dataObj\":{\"collBeginTime\":\"2023-02-07 15:15:00\",\"collCycle\":15,\"collEndTime\":\"2023-02-07 15:15:00\",\"dataItemList\":[{\"finshFlag\":0,\"itemId\":\"30303006\"}],\"timeType\":4},\"soureDeviceId\":\"200023123\",\"transCommand\":false}],\"cmdType\":2,\"commObj\":{\"authId\":0,\"commAddr\":\"201500010134\",\"deviceId\":\"200023123\",\"eigenvalue\":2,\"extendObj\":{\"comInfo\":{\"baudRate\":\"0\",\"byteSize\":\"0\",\"comPort\":111111,\"parity\":\"0\",\"stopBits\":\"0\"},\"measurNo\":0,\"port\":0,\"pulseSerial\":-1,\"roadNo\":0,\"totalSerial\":0},\"protocolNumber\":201130010},\"priority\":0,\"spathId\":111111,\"taskId\":280370423755964416,\"timeout\":0,\"udSign\":0}+\r\n";

        //send(s,Port);
        //SerialTool.sendToPort(Port, s.getBytes());
        /*byte[] readFromPort = SerialTool.readFromPort(Port);
        System.out.println(readFromPort);*/
        /*SerialTool.closePort(Port);*/
    }

    public static void spilt(StringBuffer sb) {
        int begin = sb.indexOf(new String(BEGIN_BYTES));
        int end = sb.indexOf(new String(END_BYTE));
        if (begin != -1 && begin > 0) {
            System.out.println("起始符不在0位置,去掉起始符之前的数据,当前数据:" + sb);
            sb.replace(0, begin, "");
        }
        if (begin != -1 && end != -1) {
            i++;
            String s = sb.substring(begin + 6, end - 1);
            sb.replace(begin, end + 2, "");
            System.out.println("拆分的第" + i + "条数据:" + s);
            // System.out.println("sb内容" + sb);

        }
    }

    private static void send(String s, SerialPort Port) throws NoSuchPort, InterruptedException {
        byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
        for (int i = 0; i < bytes.length; i = i + 7) {

            if (i + 7 < bytes.length) {
                byte[] bytes1 = new byte[7];
                for (int j = 0; j < 7; j++) {
                    bytes1[j] = bytes[i + j];
                }
                SerialTool.sendToPort(Port, bytes1);
                Thread.sleep(1000);
            } else {
                if (bytes.length % 7 != 0) {
                    byte[] bytes1 = new byte[bytes.length % 7];
                    for (int j = 0; j < bytes.length % 7; j++) {

                        bytes1[j] = bytes[i + j];
                    }
                    SerialTool.sendToPort(Port, bytes1);
                }

            }

        }
    }

    public static byte[] hex2Bytes(String hex) {
        if (hex == null || hex.length() == 0) {
            return null;
        }

        char[] hexChars = hex.toCharArray();
        byte[] bytes = new byte[hexChars.length / 2];   // 如果 hex 中的字符不是偶数个, 则忽略最后一个

        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt("" + hexChars[i * 2] + hexChars[i * 2 + 1], 16);
        }

        return bytes;
    }

    /**
     * byte[]转十六进制字符串
     *
     * @param array byte[]
     * @return 十六进制字符串
     */
    public static String byteArrayToHexString(byte[] array) {
        if (array == null) {
            return "";
        }
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < array.length; i++) {
            buffer.append(byteToHex(array[i]));
        }
        return buffer.toString();
    }

    /**
     * byte转十六进制字符
     *
     * @param b byte
     * @return 十六进制字符
     */
    public static String byteToHex(byte b) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        return hex.toUpperCase(Locale.getDefault());
    }

}

  

 

package com.company;

public class NoSuchPort extends Exception {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    @Override
    public String toString() {
        return "没有该端口对应的串口设备!";
    }
}

  

package com.company;

public interface SerialPortConstants {
    /**
     * 帧起始字符
     */
    byte[] BEGIN_BYTES = "##".getBytes();

    String BEGIN_STR = "##";

    /**
     * 帧结束字符
     */
    byte[] END_BYTE = new byte[]{0x0d, 0x0a};

    String UP_TOPIC_PRE = "iot/A-CHIP/700020010/up/";


}

  

package com.company;

public class SerialPortParameterFailure extends Exception {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    public SerialPortParameterFailure() {}

    @Override
    public String toString() {
        return "设置串口参数失败!打开串口操作未完成!";
    }
}

  

package com.company;

import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.TooManyListenersException;

public class SerialTool {

    /**
     * 查找所有可用端口
     *
     * @return 可用端口名称列表
     */
    public static final ArrayList<String> findPort() {

        //获得当前所有可用串口
        @SuppressWarnings("unchecked")
        Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
        ArrayList<String> portNameList = new ArrayList<String>();
        //将可用串口名添加到List并返回该List
        while (portList.hasMoreElements()) {
            String portName = portList.nextElement().getName();
            portNameList.add(portName);
        }

        return portNameList;

    }

    /**
     * 打开串口
     *
     * @param portName 端口名称
     * @param baudrate 波特率
     * @return 串口对象
     * @throws SerialPortParameterFailure 设置串口参数失败
     * @throws NotASerialPort             端口指向设备不是串口类型
     * @throws NoSuchPort                 没有该端口对应的串口设备
     * @throws PortInUse                  端口已被占用
     */
    public static final SerialPort openPort(String portName, int baudrate) throws SerialPortParameterFailure, NoSuchPort, NoSuchPort, NoSuchPort {

        try {

            //通过端口名识别端口
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);

            //打开端口,并给端口名字和一个timeout(打开操作的超时时间)
            CommPort commPort = portIdentifier.open(portName, 2000);

            //判断是不是串口
            if (commPort instanceof SerialPort) {

                SerialPort serialPort = (SerialPort) commPort;

                try {
                    //设置一下串口的波特率等参数
                    serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                    /*serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);*/
                } catch (UnsupportedCommOperationException e) {
                    throw new SerialPortParameterFailure();
                }

                System.out.println("Open " + portName + " successfully !");
                return serialPort;

            } else {
                //不是串口
                throw new NoSuchPort();
            }
        } catch (NoSuchPortException e1) {
            throw new NoSuchPort();
        } catch (PortInUseException e2) {
            throw new NoSuchPort();
        }
    }

    /**
     * 关闭串口
     *
     * @param serialport 待关闭的串口对象
     */
    public static void closePort(SerialPort serialPort) {
        if (serialPort != null) {
            serialPort.close();
            serialPort = null;

        }
    }

    /**
     * 往串口发送数据
     *
     * @param serialPort 串口对象
     * @param order      待发送数据
     * @throws SendDataToSerialPortFailure        向串口发送数据失败
     * @throws SerialPortOutputStreamCloseFailure 关闭串口对象的输出流出错
     */
    public static void sendToPort(SerialPort serialPort, byte[] order) throws NoSuchPort, NoSuchPort {

        OutputStream out = null;

        try {

            //order="ad".getBytes(StandardCharsets.UTF_8);
            out = serialPort.getOutputStream();
            out.write(order);
            out.flush();
            System.out.println("写入成功" + new String(order));

        } catch (IOException e) {
            throw new NoSuchPort();
        } finally {
            try {
                if (out != null) {
                    out.close();
                    out = null;
                }
            } catch (IOException e) {
                throw new NoSuchPort();
            }
        }

    }

    /**
     * 从串口读取数据
     *
     * @param serialPort 当前已建立连接的SerialPort对象
     * @return 读取到的数据
     * @throws ReadDataFromSerialPortFailure     从串口读取数据时出错
     * @throws SerialPortInputStreamCloseFailure 关闭串口对象输入流出错
     */
    public static byte[] readFromPort(SerialPort serialPort) throws NoSuchPort, NoSuchPort {

        InputStream in = null;
        List<byte[]> list = new ArrayList<>();
        int length = 0;

        try {

            in = serialPort.getInputStream();
            int bufflenth = in.available(); //获取buffer里的数据长度

            while (bufflenth != 0) {
                byte[] bytes = new byte[bufflenth]; //初始化byte数组为buffer中数据的长度
                in.read(bytes);
                bufflenth = in.available();
                list.add(bytes);
                length = length + bytes.length;
                System.out.println("读取成功");
            }
        } catch (IOException e) {
            throw new NoSuchPort();
        } finally {
            try {
                if (in != null) {
                    in.close();
                    in = null;
                }
            } catch (IOException e) {
                throw new NoSuchPort();
            }

        }
        if (length > 0) {
            byte[] bytesb = new byte[length];
            int index = 1;
            for (byte[] item : list) {
                index = copyToReq(bytesb, item, index);
            }


            System.out.println("读取数据" + new String(bytesb));
            return bytesb;
        }
        return null;

    }

    private static int copyToReq(byte[] req, byte[] msg, int index) {
        for (int i = 0; i < msg.length; i++) {
            req[i + index - 1] = msg[i];
        }
        return index + msg.length;
    }

    /**
     * 添加监听器
     *
     * @param port     串口对象
     * @param listener 串口监听器
     * @throws TooManyListeners 监听类对象过多
     */
    public static void addListener(SerialPort port, DataAvailableListener listener) throws NoSuchPort {

        try {

            //给串口添加监听器
            port.addEventListener(new SerialPortListener(listener));
            //设置当有数据到达时唤醒监听接收线程
            port.notifyOnDataAvailable(true);
            //设置当通信中断时唤醒中断线程
            port.notifyOnBreakInterrupt(true);

        } catch (TooManyListenersException e) {
            throw new NoSuchPort();
        }
    }

    /**
     * 串口监听
     */
    public static class SerialPortListener implements SerialPortEventListener {

        private DataAvailableListener mDataAvailableListener;

        public SerialPortListener(DataAvailableListener mDataAvailableListener) {
            this.mDataAvailableListener = mDataAvailableListener;
        }

        @Override
        public void serialEvent(SerialPortEvent serialPortEvent) {
            switch (serialPortEvent.getEventType()) {
                case SerialPortEvent.DATA_AVAILABLE: // 1.串口存在有效数据
                    if (mDataAvailableListener != null) {
                        mDataAvailableListener.dataAvailable();
                    }
                    break;

                case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2.输出缓冲区已清空
                    break;

                case SerialPortEvent.CTS: // 3.清除待发送数据
                    break;

                case SerialPortEvent.DSR: // 4.待发送数据准备好了
                    break;

                case SerialPortEvent.RI: // 5.振铃指示
                    break;

                case SerialPortEvent.CD: // 6.载波检测
                    break;

                case SerialPortEvent.OE: // 7.溢位(溢出)错误
                    break;

                case SerialPortEvent.PE: // 8.奇偶校验错误
                    break;

                case SerialPortEvent.FE: // 9.帧错误
                    break;

                case SerialPortEvent.BI: // 10.通讯中断
                    System.out.println("与串口设备通讯中断");
                    break;

                default:
                    break;
            }
        }
    }

    /**
     * 串口存在有效数据监听
     */
    public interface DataAvailableListener {
        /**
         * 串口存在有效数据
         */
        void dataAvailable();
    }


}

  

posted @ 2023-02-09 11:30  heroinss  阅读(362)  评论(0编辑  收藏  举报