美文网首页
蓝牙项目开发心得

蓝牙项目开发心得

作者: kamin | 来源:发表于2016-10-12 17:20 被阅读2796次

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

    相关文章

      网友评论

          本文标题:蓝牙项目开发心得

          本文链接:https://www.haomeiwen.com/subject/nrpdsttx.html