-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
445 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
android-wsbridge/app/src/main/java/com/dji/wsbridge/lib/BridgeToUSBRunner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package com.dji.wsbridge.lib; | ||
|
||
import android.util.Log; | ||
import com.dji.wsbridge.lib.connection.USBConnectionManager; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
public class BridgeToUSBRunner extends Thread { | ||
|
||
private static final String TAG = StreamRunner.class.getSimpleName(); | ||
public long byteCount = 0; | ||
// 从web-socket 读 | ||
private InputStream mInputStream; | ||
// 往usb中写 | ||
private OutputStream mOutputStream; | ||
private AtomicBoolean mStop = new AtomicBoolean(false); | ||
private DJIPluginRingBufferParser parser; | ||
|
||
public BridgeToUSBRunner(InputStream in, OutputStream out, String name) { | ||
super(name); | ||
mInputStream = in; | ||
mOutputStream = out; | ||
parser = new DJIPluginRingBufferParser(100 * 1024, mOutputStream); | ||
} | ||
|
||
@Override | ||
public void run() { | ||
int ret; | ||
USBConnectionManager.UsbModel usbModel = USBConnectionManager.getInstance().getUSBModel(); | ||
// As explained in: | ||
// https://developer.android.com/guide/topics/connectivity/usb/accessory.html | ||
// "The Android accessory protocol supports packet buffers up to 16384 bytes, | ||
// so you can choose to always declare your buffer to be of this size for simplicity." | ||
byte[] buffer = new byte[16384]; | ||
|
||
while (!mStop.get()) { | ||
try { | ||
if (mOutputStream != null && mInputStream != null) { | ||
ret = mInputStream.read(buffer); | ||
if (ret < 0) { | ||
// Do nothing since it is empty | ||
Log.d(TAG, getName() + ": ret is less than 0"); | ||
break; | ||
} else { | ||
Log.d(TAG, getName() + ": Runner is running"); | ||
if (usbModel != USBConnectionManager.UsbModel.LOGIC_LINK) { | ||
byteCount += ret; | ||
mOutputStream.write(buffer, 0, ret); | ||
} else { | ||
// parser.parse(buffer, 0, ret); | ||
|
||
|
||
int v1RealDataLength = ret + 8; | ||
byte[] box_head = new byte[v1RealDataLength]; | ||
int it = 0; | ||
|
||
box_head[it] = LOGIC_LINK_HEADER_0X55;it++; | ||
box_head[it] = LOGIC_LINK_HEADER_0XCC;it++; | ||
|
||
box_head[it] = (byte) (CHANNEL_CMD & 0xff);it++; | ||
box_head[it] = (byte) ((CHANNEL_CMD & 0xff00) >> 8);it++; | ||
|
||
box_head[it] = (byte) (ret & 0xff);it++; | ||
box_head[it] = (byte) ((ret & 0xff00) >> 8);it++; | ||
box_head[it] = (byte) ((ret & 0xff0000) >> 16);it++; | ||
box_head[it] = (byte) ((ret & 0xff000000) >> 24);it++; | ||
|
||
System.arraycopy(buffer, 0, box_head, 8, ret); | ||
byteCount += ret; | ||
try { | ||
mOutputStream.write(box_head, 0, v1RealDataLength); | ||
// mOutputStream.flush(); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
} | ||
mOutputStream.flush(); | ||
} | ||
} | ||
} catch (Exception e) { | ||
//Crashlytics.logException(e); | ||
//e.printStackTrace(); | ||
//Log.e(TAG, e.getMessage()); | ||
} | ||
} | ||
Log.d(TAG, getName() + ": Runner is stopped"); | ||
} | ||
|
||
public void cleanup() { | ||
mStop.set(true); | ||
} | ||
|
||
public static final int CHANNEL_CMD = 22345; | ||
|
||
static final byte LOGIC_LINK_HEADER_0X55 = Utils.getByte(0x55); | ||
|
||
static final byte LOGIC_LINK_HEADER_0XCC = Utils.getByte(0xCC); | ||
} |
195 changes: 195 additions & 0 deletions
195
android-wsbridge/app/src/main/java/com/dji/wsbridge/lib/DJIPluginRingBufferParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
package com.dji.wsbridge.lib; | ||
|
||
import android.util.Log; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
|
||
public class DJIPluginRingBufferParser { | ||
private String TAG = getClass().getSimpleName(); | ||
|
||
/** 命令通道 */ | ||
public static final int CHANNEL_CMD = 22345; | ||
|
||
static final byte LOGIC_LINK_HEADER_0X55 = Utils.getByte(0x55); | ||
|
||
static final byte LOGIC_LINK_HEADER_0XCC = Utils.getByte(0xCC); | ||
|
||
/** | ||
* mavice air 2新增的逻辑链路的帧头长度 | ||
*/ | ||
private static final int LOGIC_LINK_HEAD_LENGTH = 8; | ||
|
||
private final float factor = 1f / 8f; // 扩容因子 | ||
|
||
private boolean isGettedHeader = false; | ||
private final boolean isDebug = true; | ||
|
||
protected byte[] buffer; | ||
private int byteOffset = 0; | ||
|
||
private String name = "default"; | ||
|
||
private OutputStream mOutputStream; | ||
|
||
public DJIPluginRingBufferParser(int bufferSize, OutputStream out) { | ||
this.buffer = new byte[bufferSize]; | ||
mOutputStream = out; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getName() { | ||
return this.name; | ||
} | ||
|
||
public void parse(byte[] buffer, int offset, int count) { | ||
if (count > this.buffer.length - byteOffset) { | ||
tryToExpandCapacity(count); | ||
} | ||
System.arraycopy(buffer, offset, this.buffer, byteOffset, count); | ||
byteOffset += count; | ||
findPack(); | ||
} | ||
|
||
/** | ||
* @Description : 当容量不足时,尝试扩容 | ||
* @param length 需要扩容的容量值 | ||
*/ | ||
private void tryToExpandCapacity(final int length) { | ||
final int newCapacity = newCapacity(this.buffer.length, length); | ||
if (isDebug) { | ||
Log.d(TAG, "Try to expand capacity:" + (newCapacity - this.buffer.length)); | ||
} | ||
final byte[] newArray = new byte[newCapacity]; | ||
System.arraycopy(this.buffer, 0, newArray, 0, this.buffer.length); | ||
this.buffer = newArray; | ||
} | ||
|
||
/** | ||
* @Description : 计算新的容量值 | ||
* @param originLength 当前的容量值 | ||
* @param length 需要增加的容量值 | ||
* @return | ||
*/ | ||
private int newCapacity(final int originLength, final int length) { | ||
int size = 0; | ||
do { | ||
size += (int) (factor * originLength); | ||
} while (size <= length); | ||
return (size + originLength); | ||
} | ||
|
||
private void resetBuffer() { | ||
if (isDebug) { | ||
Log.d(TAG, "_" + name + "byteOffset=" + byteOffset + " expendSize=" + expendSize); | ||
} | ||
if (expendSize > 0) { | ||
byteOffset -= expendSize; | ||
if (byteOffset > 0) { | ||
System.arraycopy(buffer, expendSize, buffer, 0, byteOffset); | ||
} else { | ||
if (isDebug && byteOffset < 0) { | ||
Log.d(TAG, "_" + name + "byteOffset < 0"); | ||
} | ||
byteOffset = 0; | ||
} | ||
expendSize = 0; | ||
} | ||
} | ||
|
||
private int myHeaderIndex = 0; | ||
private int expendSize = 0; | ||
|
||
private void findPack() { | ||
|
||
while (true) { | ||
resetBuffer(); | ||
|
||
if (!isGettedHeader) { | ||
for (int i = 0; i < byteOffset; i++) { | ||
|
||
if (buffer[i]==LOGIC_LINK_HEADER_0X55) { | ||
|
||
myHeaderIndex = i; | ||
if (myHeaderIndex >= byteOffset) {//不足以找到完整包头 跳出循环继续接收 | ||
expendSize = myHeaderIndex; | ||
break; | ||
} | ||
|
||
isGettedHeader = true; | ||
|
||
if (isGettedHeader) { | ||
expendSize = myHeaderIndex+1; | ||
break; | ||
} | ||
} | ||
expendSize++; | ||
}//for | ||
} | ||
|
||
//没有包头 清空当前数据 | ||
if (!isGettedHeader) { | ||
if (isDebug) { | ||
Log.d(TAG, "_" + name + "parseRcvBuffer 当前buffer没有包头"); | ||
} | ||
break; | ||
} | ||
|
||
if (byteOffset < expendSize + 2) { | ||
break; | ||
} | ||
|
||
int v1Length = Utils.getInt(buffer, expendSize, 2) & 0x03FF; | ||
int v1Version = Utils.getInt(buffer, expendSize, 2) >> 10; | ||
if (isDebug) { | ||
byte[] data11 = new byte[2]; | ||
System.arraycopy(buffer, expendSize, data11, 0, 2); | ||
Log.d(TAG, "_" + name + "parseRcvBuffer V1 data length:"+v1Length + " v1 version:" + v1Version + " "+ Utils.bytesToHex(data11)); | ||
} | ||
|
||
if (v1Length < 0) { | ||
isGettedHeader = false; | ||
continue; | ||
} | ||
|
||
if (byteOffset < myHeaderIndex + v1Length) { | ||
break; | ||
} | ||
|
||
int v1RealDataLength = v1Length + LOGIC_LINK_HEAD_LENGTH; | ||
|
||
PackBufferObject bufferObject = PackBufferObject.getPackBufferObject(v1RealDataLength); | ||
byte[] box_head = bufferObject.getBuffer(); | ||
int it = 0; | ||
|
||
//逻辑链路固定的header 0x55, 0xcc | ||
box_head[it] = LOGIC_LINK_HEADER_0X55;it++; | ||
box_head[it] = LOGIC_LINK_HEADER_0XCC;it++; | ||
|
||
//通道号 | ||
box_head[it] = (byte) (CHANNEL_CMD & 0xff);it++; | ||
box_head[it] = (byte) ((CHANNEL_CMD & 0xff00) >> 8);it++; | ||
|
||
//v1数据长度 | ||
box_head[it] = (byte) (v1Length & 0xff);it++; | ||
box_head[it] = (byte) ((v1Length & 0xff00) >> 8);it++; | ||
box_head[it] = (byte) ((v1Length & 0xff0000) >> 16);it++; | ||
box_head[it] = (byte) ((v1Length & 0xff000000) >> 24);it++; | ||
|
||
System.arraycopy(buffer, myHeaderIndex, box_head, it, v1Length); | ||
try { | ||
mOutputStream.write(box_head, 0, v1RealDataLength); | ||
mOutputStream.flush(); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
expendSize += v1Length; | ||
isGettedHeader = false; | ||
} | ||
|
||
resetBuffer(); | ||
} | ||
|
||
} |
40 changes: 40 additions & 0 deletions
40
android-wsbridge/app/src/main/java/com/dji/wsbridge/lib/PackBufferObject.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.dji.wsbridge.lib; | ||
|
||
import java.util.ArrayList; | ||
|
||
public class PackBufferObject { | ||
|
||
private byte[] buffer; | ||
private volatile boolean isUsing = true; | ||
private boolean isRepeat; | ||
|
||
private PackBufferObject(int length) { | ||
int minLength = 100; | ||
int mLength = length< minLength ? minLength : length; | ||
buffer = new byte[mLength];//最长上行长度 | ||
} | ||
|
||
public byte[] getBuffer() { | ||
return buffer; | ||
} | ||
|
||
public void willRepeat(boolean isRepeat) { | ||
this.isRepeat = isRepeat; | ||
} | ||
public void noUsed() { | ||
if (!isRepeat)isUsing = false; | ||
} | ||
|
||
private static ArrayList<PackBufferObject> list = new ArrayList<>(); | ||
static synchronized PackBufferObject getPackBufferObject(int length) { | ||
for (PackBufferObject object : list) { | ||
if (!object.isUsing && object.getBuffer().length>=length) { | ||
object.isUsing = true; | ||
return object; | ||
} | ||
} | ||
PackBufferObject object = new PackBufferObject(length); | ||
list.add(object); | ||
return object; | ||
} | ||
} |
Oops, something went wrong.