一,发射器情况:有1个Service,Service下有2个Characteristic,其中1个Characteristic命名为writeCharacteristic(FFF1)具有read,write 2个属性,另外1个Characteristic命名为notifyCharacteristic(FFF2)具有notify属性
以上信息可以在获得Characteristic后用日志查看,代码如下:writeCharacteristic的Properties返回10,说明具有 PROPERTY_READ(和PROPERTY_WRITE (8)
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
uuidCharac = gattCharacteristic.getUuid().toString();
if (writeCharacUUID.equals(uuidCharac) ){
mWiriteCharacteristic=gattCharacteristic;
System.out.println("s-2 myCharacter + uuid=" + uuidCharac);
System.out.println("s-3 myCharacter + toString=" + gattCharacteristic.toString());
System.out.println("s-3 myCharacter + Permissions=" + gattCharacteristic.getPermissions());
System.out.println("s-3 myCharacter + Properties=" + gattCharacteristic.getProperties());
System.out.println("s-3 myCharacter + WriteType=" + gattCharacteristic.getWriteType());
System.out.println("s-3 myCharacter + Value=" + gattCharacteristic.getValue());
charas.add(gattCharacteristic);
}
else if(notifyCharaUUID.equals(uuidCharac)) {
mNotifyCharacteristic=gattCharacteristic;
System.out.println("s-2 myCharacter + uuid=" + uuidCharac);
System.out.println("s-3 myCharacter + toString=" + gattCharacteristic.toString());
System.out.println("s-3 myCharacter + Permissions=" + gattCharacteristic.getPermissions());
System.out.println("s-3 myCharacter + Properties=" + gattCharacteristic.getProperties());
System.out.println("s-3 myCharacter + WriteType=" + gattCharacteristic.getWriteType());
System.out.println("s-3 myCharacter + Value=" + gattCharacteristic.getValue());
charas.add(gattCharacteristic);
}
}输出结果如下:
08-14 07:59:02.626 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-1 myServices + uuid=0000fff0-0000-1000-8000-00805f9b34fb
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-2 myCharacter + uuid=0000fff1-0000-1000-8000-00805f9b34fb
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + toString=android.bluetooth.BluetoothGattCharacteristic@dee0c13
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + Permissions=0
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + Properties=10
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + WriteType=2
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + Value=null
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-2 myCharacter + uuid=0000fff2-0000-1000-8000-00805f9b34fb
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + toString=android.bluetooth.BluetoothGattCharacteristic@fbb1e50
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + Permissions=0
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + Properties=16
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + WriteType=2
08-14 07:59:02.627 15236-15236/com.klt.kamin.cgmbasedemo I/System.out: s-3 myCharacter + Value=null
二,任务:手机APP中输入指定命令,发送后,发射器会把执行结果返回到手机APP上显示
1蓝牙连接成功后,把所有Characteristic查找到
2执行下面代码使能notifyCharacteristic的notify, 将会在此通道(FFF2)产生有关命令操作的执行结果通知。
mSCharacteristic=mNotifyCharacteristic;
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, true);
3执行代码writeCharacteristic对通道FFF1进行写命令操作,每产生一次采集结果后,将会在FFF2通道产生一个 notify 通知事件,附带了本次采集结果, APP 可以直接在回调函数中进行处理和使用。
public void serialSend(String theString){
System.out.println("w-2-1 In CgmLibrary.serialSend(serialSendText),mConnectionState="+mConnectionState.toString());if (mConnectionState == connectionStateEnum.isConnected) {
mSCharacteristic=mWiriteCharacteristic;
mSCharacteristic.setValue(Conversion.hexStringToByteArray(theString));//写之前必须把输入的命令转换为十六进制字符串
mBluetoothLeService.writeCharacteristic(mSCharacteristic);
}}mBluetoothLeService.writeCharacteristic(mSCharacteristic)代码如下:
public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.writeCharacteristic(characteristic);}System.out.println("w-3-1 In BluetoothLeService.writeCharacteristic(characteristic)---->before mBluetoothGatt.writeCharacteristic(characteristic)/**********" );
mBluetoothGatt.writeCharacteristic(characteristic);如果把命令成功写到发射器,会触发:
BluetoothGattCallback的 onCharacteristicWrite方法:这个方法没有做任何事情可以删除掉
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
{
System.out.println("w-5 in onCharacteristicWrite,buttonSerialSend-->serialSend->writeCharacteristic-->status="+status);
//this block should be synchronized to prevent the function overloading
synchronized(this)
{ //CharacteristicWrite success
if(status == BluetoothGatt.GATT_SUCCESS)
{
System.out.println(" w-6 in onCharacteristicWrite-status == BluetoothGatt.GATT_SUCCESS--characteristicValue:"+ new String(Conversion.byteArrayToHexStr(characteristic.getValue())));
}
else //CharacteristicWrite fail
{
System.out.println("w-7 onCharacteristicWrite fail:"+ new String(characteristic.getValue()));
System.out.println(status);
}
}
}每产生一次采集结果后,将会在FFF2通道产生一个 notify 通知事件,附带了本次采集结果,
APP 可以直接在回调函数onCharacteristicChanged中进行处理和使用。处理完的结果通过广播返回到界面或者保存到数据库
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
System.out.println("w-5-1 In BluetoothLeService.onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)/$$$$$$$$$$$$");
System.out.println("w-5-2 onCharacteristicChanged characValue return from emmiter="+characteristic.getValue());
System.out.println("w-5-2 onCharacteristicChanged characValue return from emmiter with HexString=" + Conversion.byteArrayToHexStr(characteristic.getValue()));
System.out.println("w-5-2 onCharacteristicChanged characValue return from emmiter with new String=" + new String(characteristic.getValue()));
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
System.out.println("w-5-1 In BluetoothLeService.onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)$$$$$$$$$$$$/");
}
}private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
System.out.println("w-6-1 In BluetoothLeService.broadcastUpdate(String action, BluetoothGattCharacteristic characteristic),action=ACTION_DATA_AVAILABLE/@@@@@@@@@@@");
final Intent intent = new Intent(action);
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
if(Conversion.verifyCommand(data)){
System.out.println("w-6-2 after Verify and Success in broadcastUpdate,only data,cut first byte and last byte--->DATAascii:"+Conversion.getDataToPrint(data));
intent.putExtra(EXTRA_DATA,Conversion.getDataToPrint(data));
}
sendBroadcast(intent);
}
System.out.println("w-6-1 In BluetoothLeService.broadcastUpdate(String action, BluetoothGattCharacteristic characteristic),action=ACTION_DATA_AVAILABLE@@@@@@@@@@@/");
}
4要考虑十六进制转换
(1)输入的命令转换为十六进制字节数组
mSCharacteristic.setValue(Conversion.hexStringToByteArray(theString));
mBluetoothLeService.writeCharacteristic(mSCharacteristic);
在App输入框中输入执行命令:0155AA00这是个字符串,并不代表你的真实目的,你是把这个字符串看成4个字节的16进制形式的命令:00000001 01010101 10101010 00000000,但由于是String类型,计算机中每个字符是1个字节,所以计算机把你的输入当作11个字节的数据00000000 00000001 00000101 00000101 00001010 00001010 00000000 00000000,显然这是错误的,所以,首先需要把你输入的十六进制形式的命令转换为字节数组,代码如下:
/**
* Convert hex String to Byte Array
* example:String str="43474D"; byte[] result=Conversion.hexStringToByteArray(str); for(byte b:result) System.out.print(b+" ");
* System.out.println(); System.out.println("byteArry to StringAscii----"+new String(result));
* example result 67 71 77
* byteArry to StringAscii----CGM
* @param hexString
* @return byte[]
*/
public static byte[] hexStringToByteArray(String hexString) {
hexString=hexString.toUpperCase();
hexString=hexString.replace(" ", "");
int len = (hexString.length() / 2);
byte[] result = new byte[len];
char[] achar = hexString.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
}
return result;
}
(2)获取到的数据需要进行处理
三、执行结果
08-15 23:16:22.287 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-1 in MainActivity.onCreate()-->serialSend(serialSendText)/****************************************
08-15 23:16:22.287 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-2-1 In CgmLibrary.serialSend(serialSendText),mConnectionState=isConnected
08-15 23:16:22.287 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-2-2 CgmLibrary.serialSend(serialSendText),OLD mSCharacteristicUUID=0000fff2-0000-1000-8000-00805f9b34fb
08-15 23:16:22.287 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-2-2 CgmLibrary.serialSend(serialSendText),NOW NEW mSCharacteristicUUID=0000fff1-0000-1000-8000-00805f9b34fb
08-15 23:16:22.289 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-2-3 CgmLibrary.serialSend(serialSendText),mSCharacteristicWriteValueHex=0155AA00
08-15 23:16:22.289 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-2-3 CgmLibrary.serialSend(serialSendText),mSCharacteristicWriteValueByte=[B@bbc67ba
08-15 23:16:22.289 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-2-4 In CgmLibrary.serialSend(serialSendText)---->mBluetoothLeService.writeCharacteristic(mSCharacteristic)/********************
08-15 23:16:22.290 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-3-1 In BluetoothLeService.writeCharacteristic(characteristic)---->before mBluetoothGatt.writeCharacteristic(characteristic)/**********
08-15 23:16:22.292 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-3-2 In BluetoothLeService.writeCharacteristic(characteristic)---->after mBluetoothGatt.writeCharacteristic(characteristic)**********/
08-15 23:16:22.292 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-2-4 In CgmLibrary.serialSend(serialSendText)---->after mBluetoothLeService.writeCharacteristic(mSCharacteristic)********************/
08-15 23:16:22.292 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-1 in MainActivity.onCreate() after serialSend()****************************************/
08-15 23:16:23.413 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-5-1 In BluetoothLeService.onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)/$$$$$$$$$$$$
08-15 23:16:23.416 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-5-2 onCharacteristicChanged characValue return from emmiter=[B@aaf066b
08-15 23:16:23.417 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-5-2 onCharacteristicChanged characValue return from emmiter with HexString=01 53 4E 30 36 31 36 30 30 35 30 34
08-15 23:16:23.417 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-5-2 onCharacteristicChanged characValue return from emmiter with String=�SN061600504
08-15 23:16:23.417 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-6-1 In BluetoothLeService.broadcastUpdate(String action, BluetoothGattCharacteristic characteristic),action=ACTION_DATA_AVAILABLE/@@@@@@@@@@@
08-15 23:16:23.418 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-6-2 after Verify and Success in broadcastUpdate,only data,cut first byte and last byte--->dataByteWithHex:53 4E 30 36 31 36 30 30 35 30
08-15 23:16:23.418 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-6-2 after Verify and Success in broadcastUpdate,only data,cut first byte and last byte--->dataAscii:SN06160050
08-15 23:16:23.418 13742-13755/com.klt.kamin.cgmbasedemo I/SendBroadcastPermission: action:com.example.bluetooth.le.ACTION_DATA_AVAILABLE, mPermissionType:0
08-15 23:16:23.420 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-6-1 In BluetoothLeService.broadcastUpdate(String action, BluetoothGattCharacteristic characteristic),action=ACTION_DATA_AVAILABLE@@@@@@@@@@@/
08-15 23:16:23.420 13742-13755/com.klt.kamin.cgmbasedemo I/System.out: w-5-1 In BluetoothLeService.onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)$$$$$$$$$$$$/
08-15 23:16:23.421 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: mGattUpdateReceiver->onReceive->action=com.example.bluetooth.le.ACTION_DATA_AVAILABLE
08-15 23:16:23.421 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-7-1 In CgmLibrary.BroadcastReceiver.onReceive(Context context, Intent intent),action=ACTION_DATA_AVAILABLE/&&&&&&&&&
08-15 23:16:23.421 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-7-1 in BroadcastReceiver, writeuuid=0000fff1-0000-1000-8000-00805f9b34fb
08-15 23:16:23.422 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-7-1 displayData: SN06160050
08-15 23:16:23.422 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-8 In MainActivity.onSerialReceived
08-15 23:16:23.429 13742-13742/com.klt.kamin.cgmbasedemo I/System.out: w-7-1 In CgmLibrary.BroadcastReceiver.onReceive(Context context, Intent intent),action=ACTION_DATA_AVAILABLE&&&&&&&&&/
四、以上任务卡了3天做不出来,主要原因如下:
1,不清楚每个Characteristic的属性,fff1可读可写,fff2Notify,可以按一查看
2,不清楚流程:
(1)先使能notifyCharacteristic(二、2)
(2)对发射器进行write命令操作(二、3)
(3)子BluetoothGattCallback的onCharacteristicChanged方法里对发射器返回的数据进行处理。
mBluetoothGatt.writeCharacteristic(characteristic);如果把命令成功写到发射器,会触发:
BluetoothGattCallback的 onCharacteristicWrite方法,这里面不做什么可以不用要
执行代码writeCharacteristic对通道FFF1进行写命令操作,每产生一次采集结果后,
将会在FFF2通道产生一个 notify 通知事件,附带了本次采集结果, APP 可以直接在回调函数中进行处理和使用。
3,写到mSCharacteristic的值没有转成十六进制字符串(二、4)导致写进去的值是错误的
五、扫描广播、连接、绑定
1,Android手机为central,GATT client;发射器为peripheral,GATT server
Central vs. peripheral: 中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。
GATT server vs. GATT client:这两种角色取决于BLE连接成功后,两个设备间通信的方式。两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server。
问:Client和Server节点是如何定义呢?
答:通俗地说吧,Server(服务器)就是数据中心,Client(客户端)就是访问数据者。特别说明,它与主/从设备是独立的概念:一个主设备既可以充当Server,又可以充当Client;从设备亦然。
为了安全起见,一些数据的访问需要认证,它的完成是这样的:一方(可以是主节点,也可以是从节点)向另一方索要6位数字的密码,之后,两个节点彼此交换安全密钥用于加密和认证,此过程称为配对。认证的过程比较繁琐,BLE协议支持两节点保存认证的安全密钥(一般是非易失性存储器中),以便于两节点下次连接后快速认证,这就是绑定技术
BLE蓝牙4.0经典问答【转】 - 逗不过奇葩 - 博客园 最清晰的关于蓝牙ble的解答,适合初学者
网友评论