Communication rebuild.

This commit is contained in:
dxl
2020-04-13 18:33:18 +08:00
parent fb8104858c
commit d1472b8694
18 changed files with 273 additions and 456 deletions
@@ -16,7 +16,7 @@ public interface IChameleonExecutor {
byte[] requestChameleon(int timeout, int length);
int requestChameleon(String at, int timeout) throws IOException;
void requestChameleon(String at) throws IOException;
Communication getCom();
@@ -55,14 +55,14 @@ public class ChameleonExecutor implements IChameleonExecutor {
try {
synchronized (lock) {
//请求并且判断结果!
if (requestChameleon(at, timeout) == -1) return null;
requestChameleon(at);
//初始化必须的变量
ByteArrayOutputStream bos = new ByteArrayOutputStream(512);
long currentTime = System.currentTimeMillis();
//Log.d(LOG_TAG, "得到锁成功,当前线程ID: " + Thread.currentThread().getId());
do {
//开始接收,每次接收一个字节!
byte tmpByte = read(1);
byte tmpByte = read();
if (tmpByte != -1) {
//接收完毕,有有效的字节!!!
bos.write(tmpByte);
@@ -75,7 +75,7 @@ public class ChameleonExecutor implements IChameleonExecutor {
//Log.d(LOG_TAG, "有换行,下一步判断是否需要继续接收!");
if (!xmodemMode) {
//延迟判断新行,200ms延迟最大限度提升成功率!!!
tmpByte = read(50);
tmpByte = read();
if (tmpByte != -1) {
//Log.d(LOG_TAG, "需要");
bos.write(tmpByte);
@@ -117,7 +117,7 @@ public class ChameleonExecutor implements IChameleonExecutor {
//Log.d(LOG_TAG, "得到锁成功,当前线程ID: " + Thread.currentThread().getId());
do {
//开始接收,每次接收一个字节!
byte tmpByte = read(1);
byte tmpByte = read();
if (tmpByte != -1) {
ret[pos] = tmpByte;
if (++pos == length) break;
@@ -127,18 +127,16 @@ public class ChameleonExecutor implements IChameleonExecutor {
}
/**
* @param at 指令,ascii编码集,需要在后缀附带\r换行!
* @param timeout 超时,多久之后接收不到完整的数据帧自动返回?
* @param at 指令,ascii编码集,需要在后缀附带\r换行!
* @return 发送成功的字节数,如果发送失败则返回 -1
*/
@Override
public int requestChameleon(String at, int timeout) throws IOException {
if (at == null) return -1;
public void requestChameleon(String at) throws IOException {
//Log.d(LOG_TAG, "尝试得到锁,当前线程ID: " + Thread.currentThread().getId());
//发送命令必须回应,否则系命令错误!
at = checkAT(at);
byte[] sendBuf = HexUtil.getAsciiBytes(at);
return mCom.write(sendBuf, 0, sendBuf.length, timeout);
mCom.getOutput().write(sendBuf);
}
/**
@@ -152,17 +150,11 @@ public class ChameleonExecutor implements IChameleonExecutor {
/**
* 读取一个字节,简化读取!
*
* @param timeout 超时值
* @return 读取结果,-1为失败!
*/
private byte read(int timeout) {
byte[] b = new byte[1];
private byte read() {
try {
int len = mCom.read(b, 0, 1, timeout);
if (len != -1) {
return b[0];
}
return -1;
return (byte) mCom.getInput().read();
} catch (IOException e) {
e.printStackTrace();
}
@@ -193,7 +185,7 @@ public class ChameleonExecutor implements IChameleonExecutor {
//Log.d(LOG_TAG, "得到锁成功,当前线程ID: " + Thread.currentThread().getId());
do {
//开始接收,每次接收一个字节!
byte tmpByte = read(1);
byte tmpByte = read();
if (tmpByte != -1) {
++count;
}
@@ -46,8 +46,8 @@ public class ExecutorImpl implements IChameleonExecutor {
}
@Override
public int requestChameleon(String at, int timeout) throws IOException {
return mExecutor.requestChameleon(at, timeout);
public void requestChameleon(String at) throws IOException {
mExecutor.requestChameleon(at);
}
@Override
@@ -1,46 +1,21 @@
package cn.dxl.com;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
/*
* author DXL
* 通信接口,实现了必要的元素传递以及通信实现规定
*/
public interface Communication extends Serializable, Closeable {
public interface Communication extends Serializable {
/**
* @param sendMsg data buffer, transfer data from here.
* @param offset the data from buffer valid offset.
* @param length the data length from buffer,buffer may be 1024bytes, but valid data length is 512bytes.
* @param timeout if write need timeout, use me.
* @return the length of write finished.
* @throws IOException throw a IOException if have some problem.
* Get OutputStream implement!
*/
int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException;
OutputStream getOutput();
/**
* @param recvMsg data buffer, read data to here.
* @param offset read data to buffer from offset started.
* @param length the length of data need read.
* @param timeout if read need timeout at data length no enough, use me.
* @return the length of read finished.
* @throws IOException throw a IOException if have some problem.
*/
int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException;
/**
* flush outputstream.
*
* @throws IOException throw a IOException if have some problem.
*/
void flush() throws IOException;
/**
* close io stream
*
* @throws IOException throw a IOException if have some problem.
*/
void close() throws IOException;
/*
* Get InputStream implement!
* */
InputStream getInput();
}
@@ -0,0 +1,57 @@
package cn.rrg.bulkio;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
public class BulkInputStream extends InputStream {
private int timeout;
private UsbDeviceConnection connection;
private UsbEndpoint endpoint;
public BulkInputStream(UsbDeviceConnection connection, UsbEndpoint endpoint) {
this.connection = connection;
this.endpoint = endpoint;
}
@Override
public int read() throws IOException {
byte[] bs = new byte[1];
int len = connection.bulkTransfer(endpoint, bs, 1, timeout);
if (len > 0) {
return bs[0];
}
if (len < 0) {
return -1;
}
return 0;
}
@Override
public int read(@NonNull byte[] b) throws IOException {
return connection.bulkTransfer(endpoint, b, b.length, timeout);
}
@Override
public int read(@NonNull byte[] b, int off, int len) throws IOException {
return connection.bulkTransfer(endpoint, b, off, len, timeout);
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Override
public void close() throws IOException {
connection.close();
}
}
@@ -0,0 +1,48 @@
package cn.rrg.bulkio;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import androidx.annotation.NonNull;
import java.io.IOException;
import java.io.OutputStream;
public class BulkOutputStream extends OutputStream {
private int timeout;
private UsbDeviceConnection connection;
private UsbEndpoint endpoint;
public BulkOutputStream(UsbDeviceConnection connection, UsbEndpoint endpoint) {
this.connection = connection;
this.endpoint = endpoint;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
@Override
public void write(int b) throws IOException {
connection.bulkTransfer(endpoint, new byte[]{(byte) b}, 0, 1, timeout);
}
@Override
public void write(@NonNull byte[] b, int off, int len) throws IOException {
connection.bulkTransfer(endpoint, b, off, len, timeout);
}
@Override
public void write(@NonNull byte[] b) throws IOException {
connection.bulkTransfer(endpoint, b, 0, b.length, timeout);
}
@Override
public void close() throws IOException {
connection.close();
}
}
@@ -26,8 +26,6 @@ import cn.dxl.utils.ContextContentProvider;
public abstract class AbsBluetoothSpp implements DriverInterface<BluetoothDevice, BluetoothAdapter> {
private Context context = ContextContentProvider.mContext;
//LOG的标签 LOG TAG
private static final String LOG_TAG = "AbsBluetoothSpp";
//允许失败的次数上限,事不过三...
private static final int FAILD_MAX = 3;
//优化,超过多少次就判断失败,不自动连接!
@@ -37,7 +35,7 @@ public abstract class AbsBluetoothSpp implements DriverInterface<BluetoothDevice
//蓝牙设备套接字
private static BluetoothSocket btSocket = null;
//蓝牙设备适配器
protected BluetoothAdapter btAdapter = null;
private BluetoothAdapter btAdapter;
//蓝牙SPP的IO接口
protected InputStream inputStream = null;
protected OutputStream outputStream = null;
@@ -46,54 +44,8 @@ public abstract class AbsBluetoothSpp implements DriverInterface<BluetoothDevice
// SPP UUID
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
/**
* 实现了SPP的发送
*
* @param sendMsg 发送缓冲区,内有将要被发送的字节数据!
* @param offset 偏移值
* @param length 长度
* @param timeout 超时值
* @return 返回接收的实际长度
* @throws IOException 在出现IO异常时抛出!
*/
@Override
public abstract int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException;
/**
* 实现了SPP的接收
*
* @param recvMsg 接收缓冲区!
* @param offset 偏移值
* @param length 长度
* @param timeout 超时值
* @return 返回接收的实际长度
* @throws IOException 在出现IO异常时抛出!
*/
@Override
public abstract int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException;
/**
* 刷新输出缓冲区,这个应当是不会再变动的!
*/
@Override
public void flush() throws IOException {
if (outputStream != null)
outputStream.flush();
}
/**
* 关闭设备,此实现也应当是不变的,因此不需要设为抽象!
*/
@Override
public void close() throws IOException {
if (outputStream != null && inputStream != null) {
outputStream.close();
inputStream.close();
}
if (btSocket != null && btSocket.isConnected()) {
btSocket.close();
btSocket = null;
}
public AbsBluetoothSpp() {
btAdapter = BluetoothAdapter.getDefaultAdapter();
}
@Override
@@ -209,6 +161,17 @@ public abstract class AbsBluetoothSpp implements DriverInterface<BluetoothDevice
}
}
private void close() throws IOException {
if (outputStream != null && inputStream != null) {
outputStream.close();
inputStream.close();
}
if (btSocket != null && btSocket.isConnected()) {
btSocket.close();
btSocket = null;
}
}
@Override
public void unregister() {
if (registerState) {
@@ -23,9 +23,6 @@ public interface DriverInterface<D, A> extends Communication {
//断开与设备的链接(在某些设备上不一定是立刻生效的)
void disconect();
//获得驱动的ID!
int getUniqueId();
//解注册广播之类的
void unregister();
}
@@ -1,17 +1,17 @@
package cn.rrg.com;
import android.bluetooth.BluetoothAdapter;
import android.annotation.SuppressLint;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by DXL on 2017/8/21.
*/
public class SppHasBlock extends AbsBluetoothSpp {
private static final Object LOCK = new Object();
private static final int UNIQUE_ID = 0x02;
@SuppressLint("StaticFieldLeak")
private static SppHasBlock sppCacheTransfer = null;
private static final int TIMEOUT = 5000;
//单例模式因此需要将此构造方法私有化
private SppHasBlock() { /*can't using this constructor*/ }
@@ -19,8 +19,6 @@ public class SppHasBlock extends AbsBluetoothSpp {
public static SppHasBlock get() {
synchronized (LOCK) {
if (sppCacheTransfer == null) {
//得到蓝牙适配器
btAdapter = BluetoothAdapter.getDefaultAdapter();
//在同步块里建立实例
sppCacheTransfer = new SppHasBlock();
}
@@ -29,38 +27,12 @@ public class SppHasBlock extends AbsBluetoothSpp {
}
@Override
public int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException {
setThreadPriority();
if (outputStream == null) return -1;
outputStream.write(sendMsg, offset, length - offset);
outputStream.flush();
return length;
public OutputStream getOutput() {
return outputStream;
}
@Override
public int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException {
setThreadPriority();
if (inputStream == null) return -1;
long start = System.currentTimeMillis();
while (inputStream.available() < (length - offset)) {
if ((System.currentTimeMillis() - start) > TIMEOUT) {
// 已经超时!
return -1;
}
}
for (int i = offset; i < length; i++) {
recvMsg[i] = (byte) inputStream.read();
}
//Log.d("****", "接收: " + HexUtil.toHexString(recvMsg, offset, length));
return length;
}
@Override
public int getUniqueId() {
return UNIQUE_ID;
}
private void setThreadPriority() {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
public InputStream getInput() {
return inputStream;
}
}
@@ -1,15 +1,16 @@
package cn.rrg.com;
import android.bluetooth.BluetoothAdapter;
import android.annotation.SuppressLint;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by DXL on 2017/8/21.
*/
public class SppNonBlock extends AbsBluetoothSpp {
private static final Object LOCK = new Object();
private static final int UNIQUE_ID = 0x01;
@SuppressLint("StaticFieldLeak")
private static SppNonBlock bluetoothSpp = null;
//单例模式因此需要将此构造方法私有化
@@ -18,8 +19,6 @@ public class SppNonBlock extends AbsBluetoothSpp {
public static SppNonBlock get() {
synchronized (LOCK) {
if (bluetoothSpp == null) {
//得到蓝牙适配器
btAdapter = BluetoothAdapter.getDefaultAdapter();
//在同步块里建立实例
bluetoothSpp = new SppNonBlock();
}
@@ -28,44 +27,12 @@ public class SppNonBlock extends AbsBluetoothSpp {
}
@Override
public int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException {
int res = 0;
for (int i = offset; i < length; i++) {
/*outputStream.write(sendMsg[i]);
outputStream.flush();*/
res += 1;
}
//减去偏移值才是真正的长度!
//return res;
// TODO 优化速度,全部往内核写缓存再通知CPU发送,避免CPU切换影响速度
outputStream.write(sendMsg, offset, length - offset);
outputStream.flush();
return res;
}
/**
* 实现了SPP的接收
*
* @param recvMsg 接收缓冲区!
* @param offset 偏移值
* @param length 长度
* @param timeout 超时值
* @return 返回接收的实际长度
* @throws IOException 在出现IO异常时抛出!
*/
@Override
public int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException {
long start = System.currentTimeMillis();
while (inputStream.available() <= length - offset) {
if (inputStream.available() >= length - offset) break;
if (inputStream.available() == 0)
if (System.currentTimeMillis() - start > timeout) return 0;
}
return inputStream.read(recvMsg, offset, length - offset);
public OutputStream getOutput() {
return outputStream;
}
@Override
public int getUniqueId() {
return UNIQUE_ID;
public InputStream getInput() {
return inputStream;
}
}
@@ -28,9 +28,4 @@ public class UniversalBulkTransfer extends UsbBulkTransferRaw {
public String getDeviceNameOnFound() {
return "PN53X";
}
@Override
public int getUniqueId() {
return 0x06;
}
}
@@ -3,8 +3,6 @@ package cn.rrg.com;
public class UsbAcr122Raw extends UsbBulkTransferRaw {
//日志特征
private static final String LOG_TAG = UsbAcr122Raw.class.getSimpleName();
// ID!
private static final int UNIQUE_ID = 0x03;
// single instance!
private static UsbAcr122Raw mUsbRaw;
//设备VP码
@@ -66,6 +64,16 @@ public class UsbAcr122Raw extends UsbBulkTransferRaw {
return DRIVER_ACR122U;
}
@Override
public String getDevice() {
return DRIVER_ACR122U;
}
@Override
public void disconect() {
//TODO don't need
}
private static boolean isAcr122(int producetId, int ventorId) {
boolean ret = false;
int var3 = ventorId << 16 | producetId;
@@ -82,19 +90,4 @@ public class UsbAcr122Raw extends UsbBulkTransferRaw {
}
return ret;
}
@Override
public String getDevice() {
return DRIVER_ACR122U;
}
@Override
public void disconect() {
//TODO don't need
}
@Override
public int getUniqueId() {
return UNIQUE_ID;
}
}
@@ -13,12 +13,15 @@ import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import cn.dxl.utils.ContextContentProvider;
import cn.rrg.bulkio.BulkInputStream;
import cn.rrg.bulkio.BulkOutputStream;
public abstract class UsbBulkTransferRaw implements DriverInterface<String, UsbManager> {
@@ -243,39 +246,12 @@ public abstract class UsbBulkTransferRaw implements DriverInterface<String, UsbM
}
@Override
public int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException {
//Log.d(LOG_TAG, "write: " + HexUtil.toHexString(sendMsg, offset, length));
//Log.d(LOG_TAG, "write: " + length);
//if (len < 0) throw new IOException("write timeout");
//Log.d(LOG_TAG, "write timeout value: " + timeout);
//Log.d(LOG_TAG, "write length result: " + len);
return mCon.bulkTransfer(mEpOut, sendMsg, offset, length, timeout);
public OutputStream getOutput() {
return new BulkOutputStream(mCon, mEpOut);
}
@Override
public int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException {
//Log.d(LOG_TAG, "read: " + HexUtil.toHexString(recvMsg, offset, length));
//Log.d(LOG_TAG, "read: 要接收的字节数 " + length);
/*do {
len = mCon.bulkTransfer(mEpIn, recvMsg, offset, length, 50);
Log.d(LOG_TAG, "read: 接收到的的字节数 " + len);
if (len == -1) return;
} while (len != length);
*/
//Log.d(LOG_TAG, "read timeout value: " + timeout);
//Log.d(LOG_TAG, "read length result: " + len);
return mCon.bulkTransfer(mEpIn, recvMsg, offset, length, timeout);
//Log.d(LOG_TAG, "read: " + len);
//if (len < 0) throw new IOException("recv timeout");
}
@Override
public void flush() throws IOException {
//TODO don't need
}
@Override
public void close() throws IOException {
mCon.close();
public InputStream getInput() {
return new BulkInputStream(mCon, mEpIn);
}
}
@@ -12,13 +12,12 @@ import android.hardware.usb.UsbManager;
import android.util.Log;
import com.felhr.usbserial.UsbSerialDevice;
import com.felhr.usbserial.UsbSerialInterface;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import cn.dxl.utils.ContextContentProvider;
@@ -31,8 +30,6 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
private static Context mContext = ContextContentProvider.mContext;
//日志标签
private static final String LOG_TAG = UsbSerialControl.class.getSimpleName();
// ID
private final int UNIQUE_ID = 0x04;
//广播名称
public static final String ACTION_BROADCAST = "com.rrg.devices.usb_attach_uart";
//权限请求广播!
@@ -49,8 +46,6 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
private BroadcastReceiver usbReceiver;
//注册状态
private boolean isRegister = false;
//轮询队列
private final Queue<Byte> recvBufQueue = new LinkedList<>();
//广播过滤!
private IntentFilter filter = new IntentFilter();
@@ -70,7 +65,7 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
//在申请权限的时候如果成功那么应当进行设备的初始化
if (action.equals(ACTION_PERMISSION)) {
//get permission success
if (initUsbSerial(context)) {
if (init1()) {
//初始化成功则回调串口设备加入方法
mCallback.onAttach(NAME_DRIVER_USB_UART);
} else {
@@ -85,7 +80,7 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
action.equals(ACTION_BROADCAST)) {
Log.d(LOG_TAG, "收到UsbSerial设备寻找的广播!");
if (mCallback != null) {
if (initUsbSerial(context)) {
if (init1()) {
//初始化成功则回调串口设备加入方法
mCallback.onAttach(NAME_DRIVER_USB_UART);
} else {
@@ -124,10 +119,60 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
}
}
//串口备初始化函数
private boolean initUsbSerial(Context context) {
@Override
public void register(DevCallback<String> callback) {
mCallback = callback;
register1();
}
@Override
public boolean connect(String t) {
return connect1();
}
@Override
public UsbManager getAdapter() {
return (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
}
@Override
public String getDevice() {
return mPort != null ? mPort.getClass().getSimpleName() : NAME_DRIVER_USB_UART;
}
private void close() throws IOException {
if (mPort == null) {
//Log.e(LOG_TAG, "port is null");
return;
}
mPort.close();
mPort = null;
}
@Override
public void disconect() {
//TODO 暂时不做处理
}
@Override
public void unregister() {
//广播解注册
unregister1();
}
@Override
public OutputStream getOutput() {
return mPort.getOutputStream();
}
@Override
public InputStream getInput() {
return mPort.getInputStream();
}
private boolean init1() {
//得到Usb管理器
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
if (usbManager == null) return false;
//尝试取出所有可用的列表
if (usbManager.getDeviceList() == null || usbManager.getDeviceList().size() <= 0) {
@@ -146,126 +191,19 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
//如果对于这个设备没有权限!
if (!usbManager.hasPermission(usbDevice)) {
//发送广播申请权限
PendingIntent intent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_PERMISSION), 0);
PendingIntent intent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PERMISSION), 0);
//Log.d(LOG_TAG, "尝试获得USB权限!");
usbManager.requestPermission(usbDevice, intent);
//当没有权限的时候应当直接返回
return false;
}
//一切正常返回true!
return connect1("dxl");
}
@Override
public int write(byte[] sendMsg, int offset, int length, int timeout) throws IOException {
//TODO 注释防止外泄
if (mPort == null) {
//Log.e(LOG_TAG, "port is null");
return -1;
}
//构建一个可用字节的缓冲区
byte[] tmpBuf = new byte[length - offset];
//将可用字节灌装到定义的缓冲区
System.arraycopy(sendMsg, offset, tmpBuf, 0, tmpBuf.length);
//在同步块中进行提交操作!
mPort.write(tmpBuf);
/*
//Log.d(LOG_TAG, "发送的字节: " + HexUtil.toHexString(tmpBuf, 0, length - offset));*/
/*
* TODO CDC驱动类下PM3的消息发送和接收!
* */
//Log.d(LOG_TAG, "write: " + new String(sendMsg));
return length - offset;
}
@Override
public int read(byte[] recvMsg, int offset, int length, int timeout) throws IOException {
if (mPort == null) {
//Log.e(LOG_TAG, "port is null");
return -1;
}
if (timeout == 0) {
//超时为0可能不稳定
//Log.d(LOG_TAG, "超时值为0,可能不稳定,自动优化!");
timeout = 1000;
}
boolean isRerequest = false;
//超时操作
long startTime = System.currentTimeMillis();
//堵塞函数,直到接收到完整的数据包或者超时
//此处判断的是轮询队列中的元素个数
int oldSize = recvBufQueue.size();
//是否大于等于要接收到的数据长度,如果符合
//则说明队列中的数据接收已经到了差不多完整的地步
//Log.d(LOG_TAG, "超时值: " + timeout);
while (!(oldSize >= (length - offset))) {
int newSize = recvBufQueue.size();
if (newSize > oldSize) {
//有新的数据,延迟一下!
//Log.d(LOG_TAG, "有数据进入,延迟500ms!!");
//延长时间!
timeout += 500;
//更新队列计数值!
oldSize = newSize;
}
if (System.currentTimeMillis() - startTime > timeout) {
//Log.d(LOG_TAG, "超时,二次维稳启动,超时值自动增加500ms进行重新请求...");
if (!isRerequest) {
timeout += 500;
isRerequest = true;
} else {
//Log.d(LOG_TAG, "超时...");
return -1;
}
/*Log.d(LOG_TAG, "超时...");
return -1;*/
}
//Log.d(LOG_TAG, "等待超时...");
}
//Log.d(LOG_TAG, "数据缓冲区内长度正常,开始拷贝...");
int len = 0;
//线程锁,实现队列操作保护
synchronized (recvBufQueue) {
//从轮询缓冲队列中取出对应长度的数据
for (int i = offset; i < length; ++i) {
//判断轮询缓冲区的元素是否可用
if (recvBufQueue.peek() != null) {
Byte b = recvBufQueue.poll();
if (b != null) {
recvMsg[i] = b;
++len;
}
}
}
}
//TODO 返回的是当前读取到的缓冲区的数据的长度(实际长度)!
return len;
}
@Override
public void flush() throws IOException {
//don't support flush
}
@Override
public void close() throws IOException {
if (mPort == null) {
//Log.e(LOG_TAG, "port is null");
return;
}
mPort.close();
mPort = null;
}
@Override
public void register(DevCallback<String> callback) {
mCallback = callback;
register1();
return connect1();
}
private void register1() {
if (!isRegister) {
unRegister();
unregister1();
try {
mContext.registerReceiver(usbReceiver, filter);
isRegister = true;
@@ -274,7 +212,7 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
}
}
private void unRegister() {
private void unregister1() {
if (isRegister) {
try {
mContext.unregisterReceiver(usbReceiver);
@@ -284,7 +222,7 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
}
}
private boolean connect1(String addr) {
private boolean connect1() {
if (mPort != null) {
return true;
}
@@ -310,7 +248,7 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
//得到串口端口对象
mPort = UsbSerialDevice.createUsbSerialDevice(usbDevice, connection);
//尝试打开串口
if (mPort.open()) {
if (mPort.syncOpen()) {
//设置波特率
mPort.setBaudRate(115200);
//设置数据位
@@ -321,53 +259,9 @@ public class UsbSerialControl implements DriverInterface<String, UsbManager> {
mPort.setParity(UsbSerialDevice.PARITY_NONE);
//数据流控制
mPort.setFlowControl(UsbSerialDevice.FLOW_CONTROL_OFF);
//新数据回调
mPort.read(new UsbSerialInterface.UsbReadCallback() {
@Override
public void onReceivedData(byte[] bytes) {
//进行加锁,提高数据吞吐稳定性
for (byte b : bytes) {
synchronized (recvBufQueue) {
recvBufQueue.add(b);
}
}
// Log.d(LOG_TAG, "接收到的数据: " + HexUtil.toHexString(bytes));
}
});
Log.d(LOG_TAG, "Usb链接成功,通信创建成功!!");
return true;
}
return false;
}
@Override
public boolean connect(String t) {
return connect1(t);
}
@Override
public UsbManager getAdapter() {
return (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
}
@Override
public String getDevice() {
return mPort != null ? mPort.getClass().getSimpleName() : NAME_DRIVER_USB_UART;
}
@Override
public void disconect() {
//TODO 暂时不做处理
}
@Override
public int getUniqueId() {
return UNIQUE_ID;
}
@Override
public void unregister() {
//广播解注册
unRegister();
}
}
-1
View File
@@ -30,5 +30,4 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(path: ':communication')
}
@@ -6,9 +6,6 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import cn.dxl.com.Communication;
/**
* @author DXL
* 抽象XModem,定义协议的基本特性,通用动作!
@@ -32,10 +29,12 @@ public abstract class AbstractXModem {
protected int mErrorMax = 10;
// 通信接口,用于读取串口数据
private Communication mCom;
private InputStream inputStream;
private OutputStream outputStream;
public AbstractXModem(Communication com) {
this.mCom = com;
public AbstractXModem(InputStream input, OutputStream output) {
inputStream = input;
outputStream = output;
}
/**
@@ -56,7 +55,7 @@ public abstract class AbstractXModem {
* @throws IOException 异常
*/
protected void flush() throws IOException {
mCom.flush();
outputStream.flush();
}
/**
@@ -65,22 +64,18 @@ public abstract class AbstractXModem {
* @return 数据
* @throws IOException 异常
*/
protected byte read(int timeout) throws IOException {
byte[] b = new byte[1];
mCom.read(b, 0, 1, timeout);
return b[0];
protected byte read() throws IOException {
return (byte) inputStream.read();
}
/**
* 发送数据
*
* @param data 数据
* @return 发送成功的字节长度!
* @throws IOException 异常
*/
protected int write(byte data, int timeout) throws IOException {
byte[] b = {data};
return mCom.write(b, 0, 1, timeout);
protected void write(byte data) throws IOException {
outputStream.write(data);
}
/**
@@ -91,7 +86,7 @@ public abstract class AbstractXModem {
* @return 发送成功的字节
* @throws IOException 异常
*/
protected int write(byte[] dataByte, byte[] checkSum, int timeout) throws IOException {
protected void write(byte[] dataByte, byte[] checkSum) throws IOException {
//分配缓冲区!
ByteBuffer bb = ByteBuffer
.allocate(dataByte.length + checkSum.length)
@@ -99,15 +94,13 @@ public abstract class AbstractXModem {
.put(dataByte) //提交数据!
.put(checkSum); //提交校验!
byte[] array = bb.array();
return mCom.write(array, 0, array.length, timeout);
outputStream.write(array);
}
/**
* 取消传输。使停止!
*
* @param timeout 超时值!
*/
public void cancel(int timeout) throws IOException {
write(mCAN, timeout);
public void cancel() throws IOException {
write(mCAN);
}
}
@@ -11,8 +11,8 @@ public class XModem1024 extends AbstractXModem {
//起始头!
private byte STX = 0x02;
public XModem1024(Communication com) {
super(com);
public XModem1024(InputStream input, OutputStream output) {
super(input, output);
}
@Override
@@ -4,8 +4,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import cn.dxl.com.Communication;
public class XModem128 extends AbstractXModem {
/**
@@ -21,11 +19,9 @@ public class XModem128 extends AbstractXModem {
// 开始
private byte SOH = 0x01;
// 超时
private final int TIMEOUT = 1000;
public XModem128(Communication com) {
super(com);
public XModem128(InputStream input, OutputStream output) {
super(input, output);
}
@Override
@@ -52,14 +48,14 @@ public class XModem128 extends AbstractXModem {
errorCount = 0;
while (errorCount < mErrorMax) {
// 控制字符 + 包序号 + 包序号的反码 + 数据 + 校验和
write(SOH, TIMEOUT); //1、发送控制字符!
write(blockNumber, TIMEOUT); //2、发送包序号!
write((byte) (255 - blockNumber), TIMEOUT); //3、发送包序号的反码!
write(SOH); //1、发送控制字符!
write(blockNumber); //2、发送包序号!
write((byte) (255 - blockNumber)); //3、发送包序号的反码!
checkSum = calcChecksum(sector, mBlockSize); //4、计算数据的校验和
write(sector, new byte[]{checkSum}, TIMEOUT); //5、进行数据+校验和的封包发送!
write(sector, new byte[]{checkSum}); //5、进行数据+校验和的封包发送!
flush(); //6、刷新缓冲区,发送数据!
// 获取应答数据
byte data = read(TIMEOUT);
byte data = read();
//Log.d(LOG_TAG, "应答数据为: " + HexUtil.toHexString(data));
// 如果收到应答数据则跳出循环,发送下一包数据
// 未收到应答,错误包数+1,继续重发
@@ -83,8 +79,8 @@ public class XModem128 extends AbstractXModem {
// 所有数据发送完成后,发送结束标识
boolean isAck = false;
while (!isAck) {
write(mEOT, TIMEOUT);
isAck = read(TIMEOUT) == mACK;
write(mEOT);
isAck = read() == mACK;
}
return true;
}
@@ -102,14 +98,14 @@ public class XModem128 extends AbstractXModem {
// 初始化数据缓冲区
byte[] sector = new byte[mBlockSize];
// 握手,发起传输!
write(mNAK, TIMEOUT);
write(mNAK);
while (true) {
if (errorCount > mErrorMax) {
//Log.d(LOG_TAG, "错误重试次数已达上限!");
return false;
}
// 获取应答数据
data = read(TIMEOUT);
data = read();
if (data != mEOT) {
try {
// 判断接收到的是否是开始标识
@@ -119,7 +115,7 @@ public class XModem128 extends AbstractXModem {
continue;
}
// 获取包序号
data = read(TIMEOUT);
data = read();
//Log.d(LOG_TAG, "包序号: " + data);
// 判断包序号是否正确
if (data != blocknumber) {
@@ -128,7 +124,7 @@ public class XModem128 extends AbstractXModem {
continue;
}
// 获取包序号的反码
byte _blocknumber = read(TIMEOUT);
byte _blocknumber = read();
//Log.d(LOG_TAG, "包序号的反码: " + _blocknumber);
// 判断包序号的反码是否正确
if (data + _blocknumber != (byte) 255) {
@@ -138,11 +134,11 @@ public class XModem128 extends AbstractXModem {
}
// 获取数据
for (int i = 0; i < mBlockSize; i++) {
sector[i] = read(TIMEOUT);
sector[i] = read();
}
//Log.d(LOG_TAG, "获取到的数据: " + HexUtil.toHexString(sector));
// 获取校验和
checkSum = read(TIMEOUT);
checkSum = read();
//Log.d(LOG_TAG, "接收到的校验和: " + checkSum);
// 判断校验和是否正确
int crc = calcChecksum(sector, mBlockSize);
@@ -154,7 +150,7 @@ public class XModem128 extends AbstractXModem {
}
//Log.d(LOG_TAG, "接收一帧完成!");
// 发送应答
write(mACK, TIMEOUT);
write(mACK);
// 包序号自增
blocknumber++;
// 将数据写入本地
@@ -167,7 +163,7 @@ public class XModem128 extends AbstractXModem {
// 如果出错发送重传标识
if (errorCount != 0) {
//Log.d(LOG_TAG, "错误,将发送重传标志!");
write(mNAK, TIMEOUT);
write(mNAK);
}
}
} else {
@@ -175,7 +171,7 @@ public class XModem128 extends AbstractXModem {
}
}
// 发送应答
write(mACK, TIMEOUT);
write(mACK);
return true;
}
@@ -186,7 +182,7 @@ public class XModem128 extends AbstractXModem {
* @param byteCount
* @return byte checksum value
*/
public byte calcChecksum(byte[] buffer, int byteCount) {
private byte calcChecksum(byte[] buffer, int byteCount) {
byte checksum = 0;
int bufPos = 0;
while (byteCount-- != 0) {