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代码,代码主要也是从网上来得,但是源码的接收写的有问题,我这里优化了接收,以及我自己的分包策略

 

代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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());
    }
 
}

  

 

1
2
3
4
5
6
7
8
9
10
11
12
package com.company;
 
public class NoSuchPort extends Exception {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    @Override
    public String toString() {
        return "没有该端口对应的串口设备!";
    }
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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/";
 
 
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.company;
 
public class SerialPortParameterFailure extends Exception {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
 
    public SerialPortParameterFailure() {}
 
    @Override
    public String toString() {
        return "设置串口参数失败!打开串口操作未完成!";
    }
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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 @   heroinss  阅读(371)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示