|
@@ -13,9 +13,12 @@ import java.io.FileOutputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.io.Serializable;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
import java.util.Timer;
|
|
|
import java.util.TimerTask;
|
|
|
+import java.util.UUID;
|
|
|
|
|
|
import cn.minbb.serialport.app.DataType;
|
|
|
import cn.minbb.serialport.listener.OnDataProgressListener;
|
|
@@ -24,6 +27,7 @@ import cn.minbb.serialport.listener.OnSerialPortDataListener;
|
|
|
import cn.minbb.serialport.thread.SerialPortReadThread;
|
|
|
import cn.minbb.serialport.utils.ByteUtil;
|
|
|
import cn.minbb.serialport.utils.LogUtil;
|
|
|
+import cn.minbb.serialport.utils.PackageUtil;
|
|
|
|
|
|
/**
|
|
|
* 串口管理器 - 单例模式 防止 反射 克隆 序列化 破坏
|
|
@@ -39,7 +43,6 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
private OnDataProgressListener onDataProgressListener;
|
|
|
|
|
|
private HandlerThread mSendingHandlerThread;
|
|
|
- private Handler mSendingHandler;
|
|
|
private SerialPortReadThread mSerialPortReadThread;
|
|
|
|
|
|
private SerialPortStatus serialPortStatus = SerialPortStatus.CLOSE;
|
|
@@ -48,6 +51,12 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
private static int LENGTH = 64;
|
|
|
// 超时时间
|
|
|
private static int TIMEOUT = 5000;
|
|
|
+ // 会话 ID
|
|
|
+ private String sessionId = null;
|
|
|
+ // 流水 ID
|
|
|
+ private String serialId = null;
|
|
|
+ // 字节缓冲区列表
|
|
|
+ private List<byte[]> bytesBufferList = new ArrayList<>();
|
|
|
|
|
|
// 默认是第一次创建
|
|
|
private static volatile boolean isCreate = false;
|
|
@@ -76,10 +85,61 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取当前串口状态
|
|
|
+ * 同步设置串口状态
|
|
|
*/
|
|
|
- public SerialPortStatus getSerialPortStatus() {
|
|
|
- return serialPortStatus;
|
|
|
+ private synchronized void setSerialPortStatus(SerialPortStatus serialPortStatus) {
|
|
|
+ this.serialPortStatus = serialPortStatus;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步获取当前串口状态
|
|
|
+ */
|
|
|
+ public synchronized SerialPortStatus getSerialPortStatus() {
|
|
|
+ return this.serialPortStatus;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步获取会话 ID
|
|
|
+ */
|
|
|
+ public synchronized String getSessionId() {
|
|
|
+ return sessionId;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步设置流水号
|
|
|
+ */
|
|
|
+ public synchronized void setSerialId(String serialId) {
|
|
|
+ this.serialId = serialId;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步获取流水号
|
|
|
+ */
|
|
|
+ public synchronized String getSerialId() {
|
|
|
+ return serialId;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步获取字节缓冲区列表
|
|
|
+ */
|
|
|
+ public synchronized List<byte[]> getBytesBufferList() {
|
|
|
+ return bytesBufferList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收到串口数据调用,同步锁
|
|
|
+ *
|
|
|
+ * @param bytes 收到的 Byte 数组
|
|
|
+ */
|
|
|
+ private synchronized void dataBytesReceived(byte[] bytes) {
|
|
|
+ bytesBufferList.add(bytes);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清空字符缓冲区列表
|
|
|
+ */
|
|
|
+ private synchronized void dataBytesReceivedOver() {
|
|
|
+ bytesBufferList.clear();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -97,13 +157,20 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
* 串口设备
|
|
|
* 波特率
|
|
|
*
|
|
|
- * @return 打开是否成功
|
|
|
+ * @return 打开是否成功返回会话 ID,失败返回 null
|
|
|
*/
|
|
|
- public boolean openDefaultSerialPort() {
|
|
|
+ public String openDefaultSerialPort() {
|
|
|
return openCustomSerialPort(new File("/dev/ttyS1"), 115200);
|
|
|
}
|
|
|
|
|
|
- public boolean openCustomSerialPort(File device, int baudRate) {
|
|
|
+ /**
|
|
|
+ * 打开指定波特率的串口
|
|
|
+ *
|
|
|
+ * @param device 路径
|
|
|
+ * @param baudRate 波特率
|
|
|
+ * @return 打开是否成功返回会话 ID,失败返回 null
|
|
|
+ */
|
|
|
+ public String openCustomSerialPort(File device, int baudRate) {
|
|
|
Log.i(TAG, "openSerialPort: " + String.format("打开串口 %s 波特率 %s", device.getPath(), baudRate));
|
|
|
// 校验串口权限
|
|
|
if (!device.canRead() || !device.canWrite()) {
|
|
@@ -113,7 +180,7 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
if (null != mOnOpenSerialPortListener) {
|
|
|
mOnOpenSerialPortListener.onFail(device, OnOpenSerialPortListener.Status.NO_READ_WRITE_PERMISSION);
|
|
|
}
|
|
|
- return false;
|
|
|
+ return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -129,15 +196,15 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
startSendThread();
|
|
|
// 开启接收消息的线程
|
|
|
startReadThread();
|
|
|
- serialPortStatus = SerialPortStatus.OPEN;
|
|
|
- return true;
|
|
|
+ setSerialPortStatus(SerialPortStatus.OPEN);
|
|
|
+ return UUID.randomUUID().toString();
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
if (null != mOnOpenSerialPortListener) {
|
|
|
mOnOpenSerialPortListener.onFail(device, OnOpenSerialPortListener.Status.OPEN_FAIL);
|
|
|
}
|
|
|
}
|
|
|
- return false;
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -173,7 +240,8 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
|
|
|
mOnOpenSerialPortListener = null;
|
|
|
mOnSerialPortDataListener = null;
|
|
|
- serialPortStatus = SerialPortStatus.CLOSE;
|
|
|
+ sessionId = null;
|
|
|
+ setSerialPortStatus(SerialPortStatus.CLOSE);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -205,54 +273,12 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
// 开启发送消息的线程
|
|
|
mSendingHandlerThread = new HandlerThread("mSendingHandlerThread");
|
|
|
mSendingHandlerThread.start();
|
|
|
- // Handler
|
|
|
-// mSendingHandler = new Handler(mSendingHandlerThread.getLooper()) {
|
|
|
-// @Override
|
|
|
-// public void handleMessage(Message msg) {
|
|
|
-// try {
|
|
|
-//// byte[] sendBytes = new byte[64];
|
|
|
-// Data data = (Data) msg.obj;
|
|
|
-// switch (data.getDataType()) {
|
|
|
-// case BYTES:
|
|
|
-// SendDataBytesImpl sendDataBytesImpl = new SendDataBytesImpl();
|
|
|
-// SendDataContext<byte[]> contextBytes = new SendDataContext<>(mFileInputStream, mFileOutputStream, onDataProgressListener, sendDataBytesImpl);
|
|
|
-// contextBytes.doSend((byte[]) data.getData());
|
|
|
-// break;
|
|
|
-// case STRING:
|
|
|
-// SendDataStringImpl sendDataStringImpl = new SendDataStringImpl();
|
|
|
-// SendDataContext<String> contextString = new SendDataContext<>(mFileInputStream, mFileOutputStream, onDataProgressListener, sendDataStringImpl);
|
|
|
-// contextString.doSend((String) data.getData());
|
|
|
-// break;
|
|
|
-// case FILE:
|
|
|
-// SendDataFileImpl sendDataFileImpl = new SendDataFileImpl();
|
|
|
-// SendDataContext<File> contextFile = new SendDataContext<>(mFileInputStream, mFileOutputStream, onDataProgressListener, sendDataFileImpl);
|
|
|
-// contextFile.doSend((File) data.getData());
|
|
|
-// break;
|
|
|
-// }
|
|
|
-//// if (null != mFileOutputStream && null != sendBytes && 0 < sendBytes.length) {
|
|
|
-//// try {
|
|
|
-//// mFileOutputStream.write(sendBytes);
|
|
|
-//// if (null != mOnSerialPortDataListener) {
|
|
|
-//// mOnSerialPortDataListener.onDataSent(sendBytes);
|
|
|
-//// }
|
|
|
-//// } catch (IOException e) {
|
|
|
-//// e.printStackTrace();
|
|
|
-//// }
|
|
|
-//// }
|
|
|
-// } catch (IOException e) {
|
|
|
-// throw new RuntimeException(e);
|
|
|
-// } catch (Exception e) {
|
|
|
-// throw new RuntimeException(e);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// };
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 停止发送消息线程
|
|
|
*/
|
|
|
private void stopSendThread() {
|
|
|
- mSendingHandler = null;
|
|
|
if (null != mSendingHandlerThread) {
|
|
|
mSendingHandlerThread.interrupt();
|
|
|
mSendingHandlerThread.quit();
|
|
@@ -263,21 +289,21 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
/**
|
|
|
* 开启接收消息的线程
|
|
|
*/
|
|
|
- private static byte[] dataBytes = new byte[0];
|
|
|
-
|
|
|
private void startReadThread() {
|
|
|
mSerialPortReadThread = new SerialPortReadThread(mFileInputStream) {
|
|
|
@Override
|
|
|
public void onDataReceived(final byte[] bytes) {
|
|
|
+ // 设置接收流水号
|
|
|
+ if (null == getSerialId()) setSerialId(String.valueOf(System.currentTimeMillis()));
|
|
|
// 收到 EOF(-1) 或者超时则认为数据包接收完毕
|
|
|
// 串口空闲状态下收到数据,启动超时计时器,并修改串口状态为数据输入状态
|
|
|
- if (SerialPortStatus.OPEN == serialPortStatus) {
|
|
|
- serialPortStatus = SerialPortStatus.DATA_IN;
|
|
|
+ if (SerialPortStatus.OPEN == getSerialPortStatus()) {
|
|
|
+ setSerialPortStatus(SerialPortStatus.DATA_IN);
|
|
|
new Timer().schedule(new TimerTask() {
|
|
|
@Override
|
|
|
public void run() {
|
|
|
// 超时执行
|
|
|
- if (SerialPortStatus.DATA_IN == serialPortStatus) {
|
|
|
+ if (SerialPortStatus.DATA_IN == getSerialPortStatus()) {
|
|
|
// 解包收到的数据
|
|
|
LogUtil.setAppendFile("接收超时");
|
|
|
dataNotify();
|
|
@@ -370,6 +396,7 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
*/
|
|
|
private void sendData(byte[] payload, DataType dataType) throws IOException {
|
|
|
if (null != mFd && null != mFileInputStream && null != mFileOutputStream) {
|
|
|
+ setSerialPortStatus(SerialPortStatus.DATA_OUT);
|
|
|
switch (dataType) {
|
|
|
case BYTES:
|
|
|
LogUtil.setAppendFile("发送字符数组:" + Arrays.toString(payload));
|
|
@@ -405,6 +432,7 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
+ setSerialPortStatus(SerialPortStatus.OPEN);
|
|
|
} else {
|
|
|
LogUtil.setAppendFile("数据流为空");
|
|
|
throw new RuntimeException("数据流为空");
|
|
@@ -415,25 +443,19 @@ public class SerialPortManager extends SerialPort implements Serializable, Clone
|
|
|
* 数据回调方法,当串口接收数据超时或者收到数据结束符时候调用,用于通知应用程序收到的数据
|
|
|
*/
|
|
|
private void dataNotify() {
|
|
|
- // 串口状态设置为空闲
|
|
|
- serialPortStatus = SerialPortStatus.OPEN;
|
|
|
if (null != mOnSerialPortDataListener) {
|
|
|
- mOnSerialPortDataListener.onDataReceived(dataBytes, new String(dataBytes));
|
|
|
- LogUtil.setAppendFile("Notify:" + new String(dataBytes) + Arrays.toString(dataBytes));
|
|
|
- dataBytes = new byte[0];
|
|
|
+ // TODO: 2020-04-16 解包
|
|
|
+ String data = PackageUtil.analyze(getBytesBufferList(), getSerialId());
|
|
|
+ mOnSerialPortDataListener.onDataReceived(null, data);
|
|
|
} else {
|
|
|
LogUtil.setAppendFile("串口数据监听器未定义");
|
|
|
throw new RuntimeException("串口数据监听器未定义");
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 收到串口数据调用,同步锁
|
|
|
- *
|
|
|
- * @param bytes 收到的 Byte 数组
|
|
|
- */
|
|
|
- private synchronized void dataBytesReceived(byte[] bytes) {
|
|
|
- dataBytes = ByteUtil.addBytes(dataBytes, bytes);
|
|
|
+ dataBytesReceivedOver();
|
|
|
+ // 重置流水号
|
|
|
+ setSerialId(null);
|
|
|
+ // 串口状态设置为空闲
|
|
|
+ setSerialPortStatus(SerialPortStatus.OPEN);
|
|
|
}
|
|
|
|
|
|
@Override
|