蓝牙实时收到一系列有规则数据。如下
55 AA 81 01 5C 00 0C 31 02 FF 01 00 0B 00 04 41 46 66 66
55 AA 81 01 = 数据头
5C = 效验位
00 0C = 数据长度
31 02 = 数据命令字
FF 01 00 0B = 某一项数据的ID
00 04 = 某一项数据的长度
41 46 66 66 = 某一项数据的值(IEEE-754格式的单精度4字节浮点数)
Android的蓝牙串口接收不知道怎么像Windows一样指定接收字节数。
所以现在的想法是,被动的全部接收,然后存在一个大的缓冲区里,开个线程处理读取缓冲区,处理。
但是对java的字节处理也不懂。所以求一个byte字节的先进先出解决算法。谢谢
|
39分 |
有个ByteArrayOutputStream可能可以用,不断把byte[]通过write写入缓冲区,最后调用toByteArray获取全部byte[]。
缺点是不能取出指定的字节数。
不过我觉得自己写一个也不麻烦,没有几行代码。
|
|
代码大概是下面这样的,我没有测试过:
public class BytesBuffer {
private byte[] buffer = new byte[4096];
private int head;
private int tail;
public void push(byte[] data, int start, int length) {
int free = buffer.length - tail;
if (free < data.length) {
int used = tail - head;
if (head + free >= data.length) {
System.arraycopy(buffer, head, buffer, 0, used);
} else {
int size = buffer.length * 2;
int want = used + data.length;
while (size < want) {
size += size;
}
byte[] block = new byte[size];
System.arraycopy(buffer, head, block, 0, used);
buffer = block;
}
tail = used;
head = 0;
}
System.arraycopy(data, start, buffer, tail, length);
tail += data.length;
}
public void push(byte[] data) {
push(data, 0, data.length);
}
public int pop(byte[] data, int start, int length) {
int used = tail - head;
if (used == 0)
return 0;
int size = used;
if (size > length) {
size = length;
}
System.arraycopy(buffer, head, data, start, size);
head += size;
if (head == tail) {
head = 0;
tail = 0;
}
return size;
}
public int pop(byte[] data) {
return pop(data, 0, data.length);
}
}
|
|
上面的代码有些错误,更正如下:
public class BytesBuffer {
private byte[] buffer = new byte[4096];
private int head;
private int tail;
public void push(byte[] data, int start, int length) {
int free = buffer.length - tail;
if (free < length) {
int used = tail - head;
if (head + free >= length) {
System.arraycopy(buffer, head, buffer, 0, used);
} else {
int size = buffer.length * 2;
int want = used + length;
while (size < want) {
size += size;
}
byte[] block = new byte[size];
System.arraycopy(buffer, head, block, 0, used);
buffer = block;
}
tail = used;
head = 0;
}
System.arraycopy(data, start, buffer, tail, length);
tail += data.length;
}
public void push(byte[] data) {
push(data, 0, data.length);
}
public int pop(byte[] data, int start, int length) {
int used = tail - head;
if (used == 0)
return 0;
int size = used;
if (size > length) {
size = length;
}
System.arraycopy(buffer, head, data, start, size);
head += size;
if (head == tail) {
head = 0;
tail = 0;
}
return size;
}
public int pop(byte[] data) {
return pop(data, 0, data.length);
}
}
|
|
用小号顶一下
|
|
上面的还是有些错误,现在应该没问题了
public class BytesBuffer {
private byte[] buffer = new byte[4096];
private int head;
private int tail;
public void push(byte[] data, int start, int length) {
int free = buffer.length - tail;
if (free < length) {
int used = tail - head;
if (head + free >= length) {
System.arraycopy(buffer, head, buffer, 0, used);
} else {
int size = buffer.length * 2;
int want = used + length;
while (size < want) {
size += size;
}
byte[] block = new byte[size];
System.arraycopy(buffer, head, block, 0, used);
buffer = block;
}
tail = used;
head = 0;
}
System.arraycopy(data, start, buffer, tail, length);
tail += length;
}
public void push(byte[] data) {
push(data, 0, data.length);
}
public int pop(byte[] data, int start, int length) {
int used = tail - head;
if (used == 0)
return 0;
int size = used;
if (size > length) {
size = length;
}
System.arraycopy(buffer, head, data, start, size);
head += size;
if (head == tail) {
head = 0;
tail = 0;
}
return size;
}
public int pop(byte[] data) {
return pop(data, 0, data.length);
}
}
|
|
|
|
非常感谢啊,马上试用一下
|
|
测试中发现一个问题,我用Read到byte数值中的值有负数,蓝牙传过来的是0-FF的值,而byte的MAX_VALUE只有0x7F
无法比较值。有什么好的办法呢?
//验证字节头 必须是 55 AA 81 01才为有效返回
mBytesBuffer.pop(bHead, 0, 1);
if(bHead[0] != 0x55)
continue;
mBytesBuffer.pop(bHead, 1, 1);
if(bHead[1] != 0xAA)
continue;
mBytesBuffer.pop(bHead, 2, 1);
if(bHead[1] != 0x81)
continue;
mBytesBuffer.pop(bHead, 3, 1);
if(bHead[1] != 0x01)
continue;
//获取其他数据
mBytesBuffer.pop(bCheck, 4, 1);
mBytesBuffer.pop(bLen, 5, 2);
mBytesBuffer.pop(bCmd, 7, 4);
mBytesBuffer.pop(bDsID, 11, 4);
mBytesBuffer.pop(bDsValueType, 15, 1);
mBytesBuffer.pop(bDsValueLen, 16, 2);
iValueDataLen = bDsValueLen[0]*0x100 + bDsValueLen[1];
bDsValueData = new byte[iValueDataLen];
mBytesBuffer.pop(bDsValueData, 18, iValueDataLen);
|
|
java的byte是有符号的(我觉得是很糟糕的设计),所以只好先转成int再比较:
if ((bHead[1] & 0xff) != 0x81)
continue;
|
|
上面的还是有些错误,现在应该没问题了
public class BytesBuffer {
private byte[] buffer = new byte[4096];
private int head;
private int tail;
public void push(byte[] data, int start, int length) {
int free = buffer.length - tail;
if (free < length) {
int used = tail - head;
if (head + free >= length) {
System.arraycopy(buffer, head, buffer, 0, used);
} else {
int size = buffer.length * 2;
int want = used + length;
while (size < want) {
size += size;
}
byte[] block = new byte[size];
System.arraycopy(buffer, head, block, 0, used);
buffer = block;
}
tail = used;
head = 0;
}
System.arraycopy(data, start, buffer, tail, length);
tail += length;
}
public void push(byte[] data) {
push(data, 0, data.length);
}
public int pop(byte[] data, int start, int length) {
int used = tail - head;
if (used == 0)
return 0;
int size = used;
if (size > length) {
size = length;
}
System.arraycopy(buffer, head, data, start, size);
head += size;
if (head == tail) {
head = 0;
tail = 0;
}
return size;
}
public int pop(byte[] data) {
return pop(data, 0, data.length);
}
}
测试中发现一个问题,我用Read到byte数值中的值有负数,蓝牙传过来的是0-FF的值,而byte的MAX_VALUE只有0x7F
无法比较值。有什么好的办法呢?
//验证字节头 必须是 55 AA 81 01才为有效返回
mBytesBuffer.pop(bHead, 0, 1);
if(bHead[0] != 0x55)
continue;
mBytesBuffer.pop(bHead, 1, 1);
if(bHead[1] != 0xAA)
continue;
mBytesBuffer.pop(bHead, 2, 1);
if(bHead[1] != 0x81)
continue;
mBytesBuffer.pop(bHead, 3, 1);
if(bHead[1] != 0x01)
continue;
//获取其他数据
mBytesBuffer.pop(bCheck, 4, 1);
mBytesBuffer.pop(bLen, 5, 2);
mBytesBuffer.pop(bCmd, 7, 4);
mBytesBuffer.pop(bDsID, 11, 4);
mBytesBuffer.pop(bDsValueType, 15, 1);
mBytesBuffer.pop(bDsValueLen, 16, 2);
iValueDataLen = bDsValueLen[0]*0x100 + bDsValueLen[1];
bDsValueData = new byte[iValueDataLen];
mBytesBuffer.pop(bDsValueData, 18, iValueDataLen);
java的byte是有符号的(我觉得是很糟糕的设计),所以只好先转成int再比较:
if ((bHead[1] & 0xff) != 0x81)
continue;
有效,谢了。我继续研究,这个先给分。
|