zoukankan      html  css  js  c++  java
  • android IBeacon 开发(二)修改IBeacon参数

    开发(一)中,我们介绍了怎么扫描到IBeacon。这节我们去看看怎么修改IBeacon的参数。

    IBeacon里的参数,主要有这几个

    name:设备名称

    major:主参数

    minor:副参数

    mac:mac地址

    UUID:IBeacon的UUID,相当与使用这个模块对映的应用的标识

    rssi:信号强度

    txPower:1m距离的信号强度参考值,他和rssi通过公司,可大体计算出距离来

    通过上一章的扫描,我们获得了一个IBeacon的列表ArrayList,当我们想修改某个IBeacon的信息的时候,就要用到这个IBeacon的mac了

    通过点击等等方式呢,我们可以获得某IBeacon的mac,

     1     /**
     2      * Connects to the GATT server hosted on the Bluetooth LE device.
     3      * 
     4      * @param address
     5      *            The device address of the destination device.
     6      * @return Return true if the connection is initiated successfully. The
     7      *         connection result
     8      *         is reported asynchronously through the
     9      *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
    10      *         callback.
    11      */
    12     public boolean connect(final String address)
    13     {
    14         if (mBluetoothAdapter == null || address == null)
    15         {
    16             Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
    17             return false;
    18         }
    19         
    20         // Previously connected device.  Try to reconnect.
    21         if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null)
    22         {
    23             Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
    24             if (mBluetoothGatt.connect())
    25             {
    26                 return true;
    27             }
    28             else
    29             {
    30                 return false;
    31             }
    32         }
    33         
    34         final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
    35         if (device == null)
    36         {
    37             Log.w(TAG, "Device not found.  Unable to connect.");
    38             return false;
    39         }
    40         // We want to directly connect to the device, so we are setting the autoConnect
    41         // parameter to false.
    42         mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
    43         Log.d(TAG, "Trying to create a new connection.");
    44         mBluetoothDeviceAddress = address;
    45         return true;
    46     }
    47     

    根据大神的代码呢,我们connect (mac地址),这样呢我们就可以获得BluetoothGatt。但是,连接完成了,再干嘛???

    我们少了N步。

    在大神的代码BluetoothLeClass类里,我们看到了好几个接口,这些接口是干嘛的?

    OnConnectListener:当连接成功时调用

    OnDisconnectListener:连接关闭是调用

    OnServiceDiscoverListener:当services被发现的时候调用

    OnDataAvailableListener:当有数据交互的时候调用

    这里有个问题了,services是啥,是干神马的?

    看了大神的解释,还是一头雾水啊。然后我就去看了BLE蓝牙的协议栈和其他N种东西,搞明白了他。

    services是这样滴。每个IBeacon 都是基于BLE的,而BLE信息交互的时候,需要有个东西当接口啊,services就是这种东东。

    就例如 BLE要做一个钟表,那就得有个service能不断的发送当前时间给显示器,like

    同理,我们和IBeacon 通信,就是去调用BLE里的某个Service。

    我们知道IBeacon里的参数有好几个呢,一个service够吗?跟你说,够了。

    每个service下边还有多个Characteristic,就相当于service是端口,Characteristic是程序,不同的程序处理不同的东西,但数据都通过同一个端口(service)进出。

    当然,service下边还有多个Descriptor,就是描述符,没啥大用。

    对了,services,Characteristic这些东东,都是通过UUID来标识的,就相当于UUID是service、Characteristic的名字一样。

    下边我们看看大神定义的接口都是怎么工作的。

     1     // Implements callback methods for GATT events that the app cares about.  For example,
     2     // connection change and services discovered.
     3     private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
     4     {
     5         @Override
     6         public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
     7         {
     8             Log.e(TAG, "onConnectionStateChange完成");
     9             if (newState == BluetoothProfile.STATE_CONNECTED)
    10             {
    11                 if (mOnConnectListener != null)
    12                     mOnConnectListener.onConnect(gatt);
    13                 Log.i(TAG, "Connected to GATT server.");
    14                 // Attempts to discover services after successful connection.
    15                 Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
    16                 
    17             }
    18             else if (newState == BluetoothProfile.STATE_DISCONNECTED)
    19             {
    20                 if (mOnDisconnectListener != null)
    21                     mOnDisconnectListener.onDisconnect(gatt);
    22                 Log.i(TAG, "Disconnected from GATT server.");
    23             }
    24         }
    25         
    26         @Override
    27         public void onServicesDiscovered(BluetoothGatt gatt, int status)
    28         {
    29             Log.e(TAG, "onServicesDiscovered完成");
    30             if (status == BluetoothGatt.GATT_SUCCESS && mOnServiceDiscoverListener != null)
    31             {
    32                 mOnServiceDiscoverListener.onServiceDiscover(gatt);
    33             }
    34             else
    35             {
    36                 Log.w(TAG, "onServicesDiscovered received: " + status);
    37             }
    38         }
    39         
    40         @Override
    41         public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
    42         {
    43             Log.e(TAG, "onCharacteristicRead完成");
    44             if (mOnDataAvailableListener != null)
    45                 mOnDataAvailableListener.onCharacteristicRead(gatt, characteristic, status);
    46         }
    47 
    48         @Override
    49         public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
    50         {
    51             Log.e(TAG, "onCharacteristicWrite完成");
    52             if (mOnDataAvailableListener != null)
    53                 mOnDataAvailableListener.onCharacteristicWrite(gatt, characteristic, status);
    54         }
    55         @Override
    56         public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
    57         {
    58             Log.e(TAG, "onCharacteristicChanged完成");
    59             if (mOnDataAvailableListener != null)
    60                 mOnDataAvailableListener.onCharacteristicChanged(gatt, characteristic);
    61         }
    62     };

    这里我改了下代码,

    1     public interface OnDataAvailableListener
    2     {
    3         public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status);
    4         
    5         public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
    6         
    7         public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status);
    8     }

    OnConnectListener、OnDisconnectListener这两个接口,一看就是一对

    onCharacteristicRead、onCharacteristicWrite、onCharacteristicChanged这三个,从函数名上也能看出作用来。

    那么,定义好这些个listener,嗯,C#里边就是委托了,我就就得看看他是怎么工作的了。

    本文一开始就说connect函数了,当connect成功后,就回去调用  onConnectionStateChange(连接状态改变事件),然后根据某值,分离出是连接成功还是连接失败。

    在大神的代码了,我看到了调用OnConnectListener,但是怎么发现service呢。

    大神开了个玩笑啊,将最重要的一句代码写在了Log.i里边,我狂晕啊,找了好半天呢。

    mBluetoothGatt.discoverServices()就这句。。。。。。解释一下这句代码?——发现service

    发现services,发现的services在哪?

    好吧,android还是调用回调,onServicesDiscovered

    发现services完成后,调用onServiceDiscover,这样我们就能获得BluetoothGatt,然后调用BluetoothGatt.getServices()获取所有的services了,当然你还可以根据你所开发的IBeacon的文档中定义的service的UUID,通过调用BluetoothGatt.getService(某个UUID)直接找这个service。

    我所用的service的UUID是  0000fff0-0000-1000-8000-00805f9b34fb

    我们获取了service,就可以通信了。

     1     private void displayGattServices(List<BluetoothGattService> gattServices)
     2     {
     3         if (gattServices == null)
     4             return;
     5         
     6         for (BluetoothGattService gattService : gattServices)
     7         {
     8             //-----Service的字段信息-----//
     9             int type = gattService.getType();
    10             Log.e(TAG, "-->service type:" + Utils.getServiceType(type));
    11             Log.e(TAG, "-->includedServices size:" + gattService.getIncludedServices().size());
    12             Log.e(TAG, "-->service uuid:" + gattService.getUuid());
    13             
    14             //-----Characteristics的字段信息-----//
    15             List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
    16             for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
    17             {
    18                 Log.e(TAG, "---->char uuid:" + gattCharacteristic.getUuid());
    19                 
    20                 int permission = gattCharacteristic.getPermissions();
    21                 Log.e(TAG, "---->char permission:" + Utils.getCharPermission(permission));
    22                 
    23                 int property = gattCharacteristic.getProperties();
    24                 Log.e(TAG, "---->char property:" + Utils.getCharPropertie(property));
    25                 
    26                 byte[] data = gattCharacteristic.getValue();
    27                 if (data != null && data.length > 0)
    28                 {
    29                     Log.e(TAG, "---->char value:" + new String(data));
    30                 }
    31                 
    32                 //UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic
    33                 if (gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA))
    34                 {
    35                     //测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
    36                     mHandler.postDelayed(new Runnable()
    37                     {
    38                         @Override
    39                         public void run()
    40                         {
    41                             mBLE.readCharacteristic(gattCharacteristic);
    42                         }
    43                     }, 500);
    44                     
    45                     //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
    46                     mBLE.setCharacteristicNotification(gattCharacteristic, true);
    47                     //设置数据内容
    48                     byte[] bytes = new byte[6];
    49                     
    50                     bytes[0] = 1;
    51                     bytes[1] = 2;
    52                     bytes[2] = 3;
    53                     bytes[3] = 4;
    54                     bytes[4] = 5;
    55                     bytes[5] = 6;
    56                     gattCharacteristic.setValue("123456");
    57                     //往蓝牙模块写入数据
    58                     mBLE.writeCharacteristic(gattCharacteristic);
    59                     Log.v(TAG, "写入");
    60                 }
    61                 
    62                 //-----Descriptors的字段信息-----//
    63                 List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();
    64                 for (BluetoothGattDescriptor gattDescriptor : gattDescriptors)
    65                 {
    66                     Log.e(TAG, "-------->desc uuid:" + gattDescriptor.getUuid());
    67                     int descPermission = gattDescriptor.getPermissions();
    68                     Log.e(TAG, "-------->desc permission:" + Utils.getDescPermission(descPermission));
    69                     
    70                     byte[] desData = gattDescriptor.getValue();
    71                     if (desData != null && desData.length > 0)
    72                     {
    73                         Log.e(TAG, "-------->desc value:" + new String(desData));
    74                     }
    75                 }
    76             }
    77         }//
    78         
    79     }

    大神的代码里,把所有的services,Characteristic都显示出来了,每个Characteristic也都读取了一遍。然后又在   UUID_KEY_DATA  表示的那个Characteristic里边写了点什么。

    一开始我不太懂,为啥还得等500毫秒,后来我知道了,BLE是单双工通信的。

    解释一下,“双工通信”是指的两边都可以发送信息,也都可以接收信息,“单”代表通信双方不能同时收发信息。

    就是说,我发送信息(读、写)给IBeacon,在IBeacon返回信息之前,我不能有任何操作。

    好了,言归正传。

    我们只看到了mBLE.readCharacteristic(gattCharacteristic);mBLE.writeCharacteristic(gattCharacteristic);,但是读写出来的数据呢?

    在这个mBLE.setCharacteristicNotification(gattCharacteristic, true);之前的注释里,我们看到

    //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()

    好吧,我们知道了,他会去调用mOnDataAvailable里的函数。

    大体流程就是这样滴。

  • 相关阅读:
    PopuWindow和软件盘共存时的设置
    sql语句备份/导入 mysql数据库或表命令
    Cocos2d-x3.0游戏实例之《别救我》第八篇——TiledMap实现关卡编辑器
    mongodb文档支持的数据类型
    Longest Common Prefix -最长公共前缀
    【JDBC】java程序通过jdbc连接oracle数据库方法
    大型站点技术架构(五)--站点高可用架构
    CF981H K Paths
    带WHERE子句的UPDATE语句
    简单的数据更新
  • 原文地址:https://www.cnblogs.com/sdwdjzhy/p/4521633.html
Copyright © 2011-2022 走看看