蓝牙项目开发心得

一,发射器情况:有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的解答,适合初学者

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容

  • 蓝牙 蓝牙的波段为2400-2483.5MHz(包括防护频带)。这是全球范围内无需取得执照(但定不是无管制的)的工...
    苏永茂阅读 6,151评论 0 11
  • Key Terms And Concepts 关键术语和概念 Here is a summary of key B...
    Jaesoon阅读 2,431评论 0 5
  • 安卓4.3(API 18)为BLE的核心功能提供平台支持和API,App可以利用它来发现设备、查询服务和读写特性。...
    风雨byt阅读 14,047评论 3 43
  • 除了单位的后花园,我们家楼下的平台是我赏绿的又一好去处。那个平台从我的小房间望出去就能看到,平台上种了很多...
    温暖的简阅读 174评论 0 0