前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >蓝牙项目开发心得

蓝牙项目开发心得

作者头像
用户1733354
发布2018-05-22 15:09:06
1.6K0
发布2018-05-22 15:09:06
举报

一,发射器情况:有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)

代码语言:javascript
复制
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)产生有关命令操作的执行结果通知。

代码语言:javascript
复制
mSCharacteristic=mNotifyCharacteristic;
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, true);

3执行代码writeCharacteristic对通道FFF1进行写命令操作,每产生一次采集结果后,将会在FFF2通道产生一个 notify 通知事件,附带了本次采集结果, APP 可以直接在回调函数中进行处理和使用。

代码语言:javascript
复制
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)输入的命令转换为十六进制字节数组

代码语言:javascript
复制
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,显然这是错误的,所以,首先需要把你输入的十六进制形式的命令转换为字节数组,代码如下:

代码语言:javascript
复制
/**
  * 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)获取到的数据需要进行处理

三、执行结果

代码语言:javascript
复制
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方法里对发射器返回的数据进行处理。

代码语言:javascript
复制
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的解答,适合初学者

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.10.12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档