接上篇的协议开发练习。
课设需要用手机和开发板通信,接收开发板发来的传感器数据进行处理输出,并可以控制开发板的执行器。
在写蓝牙的安卓程序期间遇到了很多问题,在此记录以下。
1.数据传输我们采取16进制字节流进行传输,那么就有了字符串和16进制数据转换的问题
public static String bytesToHexString(byte[] bytes) { //字节流转为16进制串
String result = "";
int i;
for ( i = 0; i < bytes.length; i++) {
String hexString = Integer.toHexString(bytes[i] & 0xFF);
if (hexString.length() == 1) {
hexString = '0' + hexString;
}
result += hexString.toUpperCase();
}
return result;
}
private byte[] hexStringToBytes(String message) { //16进制串转为字节流
int len = message.length() / 2;
char[] chars = message.toCharArray();
String[] hexStr = new String[len];
byte[] bytes = new byte[len];
for (int i = 0, j = 0; j < len; i += 2, j++) {
hexStr[j] = "" + chars[i] + chars[i + 1];
bytes[j] = (byte) Integer.parseInt(hexStr[j], 16);
}
return bytes;
}
2.接收数据时出现错误,大于20字节时,20字节后面的数据丢失,网上搜索发现如下的说法,但我确实没有找到相关说明,暂且这么记吧。
http://zhidao.baidu.com/link?url=k0LLv63E_716T-tkFrn6n805GA-fh4nTPPIl3RyiUBLVyd8l-iWMf6PV-DNe56YjrLqMDUK93uZE68PDJxmHXKvWBT1-gXrQbSyePJccAne
协议规定,payload 最大 27。在协议第六章中的 2.4,刨去 L2CAP 的头,4 个字节,剩下的就 23 个字节 MTU。就是你看到的。ATT 层会用掉上 1 个字节的 op code, 2 个字节的 attribute handle,就剩下 20了。这剩下的 20 字节就是我们常说的发送的 20 字节的数据。
接下来就是将分片的数据组装成一个完整的数据包
public final int MES_HEAD_LEN = 3; //包头长度
public final int MES_TAIL_LEN = 2; //包尾长度
public static boolean devideFlag = false;
public static int DEVIDE_NUM; //分片数
public byte[] returnByte = new byte[200];
public int[] devideLength = new int[10];
public byte[][] newbyte = new byte[10][];
//接收数据,判断有无分片,并进行包的拼接
public void devideContent(byte[] bytes)
{
int i = 0;
// newbyte[DEVIDE_NUM] = bytes;
if(bytes[0] == -69) {
if(bytes[1] == Protocal.SLAVE_STA_READY || bytes[1] == Protocal.SLAVE_EXU_SUCCE) { //从机就绪
if(bytes[2] == Protocal.DIVIDE_DISABLE) { //数据无分片
devideFlag = true;
newbyte[DEVIDE_NUM] = bytes;
devideLength[DEVIDE_NUM] = bytes.length;
}
else { //数据有分片
newbyte[DEVIDE_NUM] = bytes;
devideLength[DEVIDE_NUM] = bytes.length;
DEVIDE_NUM++;
}
}
}
if(devideFlag) {
Log.d(TAG, "分片数 "+DEVIDE_NUM);
int len;
System.arraycopy(newbyte[0],0,returnByte,0,devideLength[0]-2);
len = devideLength[0]-2;
for (i = 1; i < DEVIDE_NUM+1; i++) {
System.arraycopy(newbyte[i],3,returnByte,len, devideLength[i]-5);
len += devideLength[i]-5;
}
System.arraycopy(newbyte[DEVIDE_NUM],devideLength[DEVIDE_NUM]-2,returnByte,len,2);
DEVIDE_NUM = 0;
}
}
3.数据解析
//数据解析
/*
by eagle zhao
将16进制串转换为16进制数组data,16进制串中1个字节代表8位如0x11,在16进制串中存储为'1' '1',故需将两个字符转换为1个16进制数字。
*/
public void dataAnalysis(String hex) {
char[] message = hex.toString().toCharArray();
int[] data = new int[message.length];
int[][] datadevide = new int[10][];
int j,i,k=0;
for(i = 0,j=0; i < message.length; i++,j++) {
if(message[i] >= '0' && message[i] <= '9') {
data[j] = message[i] - '0';
}else if(message[i] >= 'A' && message[i] <= 'Z') {
data[j] = message[i] - 'A' + 10;
}
data[j] = data[j] << 4;
i++;
if(message[i] >= '0' && message[i] <= '9') {
data[j] += message[i] - '0';
}else if(message[i] >= 'A' && message[i] <= 'Z') {
data[j] += message[i] - 'A' + 10;
}
}
if(data[1] == 0x11) {
listAdapter.add("执行成功");
messageListView.smoothScrollToPosition(listAdapter.getCount() - 1);
}
else if(data[1] == 0x01){ //从机发来数据
outPutCal(data); //输出数据
}
}