android蓝牙4.0(BLE)开发之ibeacon初步

此文使用的ibeacon模块是april beacon,至于什么是ibeacon。本文不做解释,具体请自查。

一个april beacon里携带的信息如下

?
1
<code class = " hljs " >0201061AFF4C0002159069BDB88C11416BAC3F33468C2788A3044B0378C60C09417072696C426561636F6E051250002003020A0000000000000000000000</code>

具体是什么意思呢

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<code class = " hljs vhdl" > 02  Number of bytes that follow in first AD structure
01  Flags AD type
06
     Flags value 0x1A = 000011010
        bit 0 (OFF) LE Limited Discoverable Mode
        bit 1 (ON) LE General Discoverable Mode
        bit 2 (OFF) BR/EDR Not Supported
        bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
        bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
1a Number of bytes that follow in second (and last) AD structure
前面是常规智能硬件广播包部分
 
ff (FF代表后面是Manufacture Data)
 
 
4c 00   (组织标识, 0x4c00 苹果公司标识,https: //www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers)
02 0x02 ibeacon标识位)
15 0x15 , 22 个字节标识长度,uuid,major,minor总和的长度)
90 69 bd b8-8c 11 - 41 6b-ac 3f- 33 46 8c 27 88 a3 (Proximity UUID)
04 4b( 1099 ,major)
03 78 ( 888 ,minor)
c6  (切记这里是补码,转化为原码就是- 58 ,iBeacon的信号发出强度值,用来作为和RSSI一起测距的基准 ,txPower)
         计算
             C6
             1100 0110 补码
             1100 0101 反码
             1011 1010 原码
             -( 32 + 16 + 8 + 2
             - 58
0c09    (未知)
417072696c426561636f6e(AprilBeacon字符串对应的十六进制)
051250002003020a0000000000000000000000(未知)
</code>

Proximity UUID :这是将你所有的beacon与其他人的beacon设备区别开的id!例如,目前在商店里某个区域分布着多个beacon形成一条“链带”,用于为顾客提供特定的服务,那么归属于同一条“链带”的beacon将分配到相同的proximity UUID。为这条“链带”设计的专用应用程序将会在后台使用这个UUID扫描到这条“链带”中的beacon设备。

major 编号:用于将相关的beacon标识为一组。例如,一个商店中的所有beacon将会分配到相同的major编号。通过这种方式,应用程序就能够知道顾客位于哪一家商店。

minor 标号:用于标识特定的beacon设备。例如一个商店中的每一个beacon设备都拥有唯一的minor编号,这样你才能够知道顾客位于商店中的哪个位置。

Measuring distance(测量距离) 
最后一个值, TX power ,用于确定你和beacon之间距离有多近。根据这个值不但可以获得粗略的信息(比如靠近/远离/不在范围内等),也可以获取精确到米的距离(当然你也可以转换为以步为单位的距离)。那么如何实现?

TX power (上面例子中为0xC6=198,根据2的补码测得256-198=-58dBm)是距离设备1米测得的信号强度值(RSSI- Received Signal Strength Indication,接收到的信号强弱指标)。假如接收到的信号强度减弱了,那么我们可能在远离。只要知道1米距离的RSSI,以及当前的RSSI(我们可以从接收到的信号中一块获取到这些信息),那么计算出当前的距离是可能的。IOS已经实现了个这个功能,对于其它平台需要自己手动编码计算 。

一个简单的测距函数

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<code class = "language-java hljs " > protected static double calculateAccuracy( int txPower, double rssi) {
         if (rssi == 0 ) {
             return - 1.0 ; // if we cannot determine accuracy, return -1.
         }
 
         double ratio = rssi * 1.0 / txPower;
         if (ratio < 1.0 ) {
             return Math.pow(ratio, 10 );
         } else {
             double accuracy = ( 0.89976 ) * Math.pow(ratio, 7.7095 ) + 0.111 ;
             return accuracy;
         }
     }</code>

在使用蓝牙时需要加权限

?
1
2
3
4
<code class = "language-xml hljs " > <uses-permission android:name= "android.permission.BLUETOOTH" >
     <uses-permission android:name= "android.permission.BLUETOOTH_ADMIN" >
     <uses-permission android:name= "android.permission.RECEIVE_BOOT_COMPLETED" >
</uses-permission></uses-permission></uses-permission></code>

关键代码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<code class = "language-java hljs " > package cn.edu.zafu.ble;
 
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
 
public class MainActivity extends Activity {
     private BluetoothAdapter mBluetoothAdapter;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 
         BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
         mBluetoothAdapter = bluetoothManager.getAdapter();
         if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
             Intent enableBluetooth = new Intent(
                     BluetoothAdapter.ACTION_REQUEST_ENABLE);
             startActivityForResult(enableBluetooth, 1 );
         }
         mBluetoothAdapter.startLeScan(mLeScanCallback);
 
     }
 
     private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
         @Override
         public void onLeScan( final BluetoothDevice device, final int rssi,
                 final byte [] scanRecord) {
             int startByte = 2 ;
             boolean patternFound = false ;
             // 寻找ibeacon
             while (startByte <= 5 ) {
                 if ((( int ) scanRecord[startByte + 2 ] & 0xff ) == 0x02 && // Identifies
                                                                         // an
                                                                         // iBeacon
                         (( int ) scanRecord[startByte + 3 ] & 0xff ) == 0x15 ) { // Identifies
                                                                             // correct
                                                                             // data
                                                                             // length
                     patternFound = true ;
                     break ;
                 }
                 startByte++;
             }
             // 如果找到了的话
             if (patternFound) {
                 // 转换为16进制
                 byte [] uuidBytes = new byte [ 16 ];
                 System.arraycopy(scanRecord, startByte + 4 , uuidBytes, 0 , 16 );
                 String hexString = bytesToHex(uuidBytes);
 
                 // ibeacon的UUID值
                 String uuid = hexString.substring( 0 , 8 ) + "-"
                         + hexString.substring( 8 , 12 ) + "-"
                         + hexString.substring( 12 , 16 ) + "-"
                         + hexString.substring( 16 , 20 ) + "-"
                         + hexString.substring( 20 , 32 );
 
                 // ibeacon的Major值
                 int major = (scanRecord[startByte + 20 ] & 0xff ) * 0x100
                         + (scanRecord[startByte + 21 ] & 0xff );
 
                 // ibeacon的Minor值
                 int minor = (scanRecord[startByte + 22 ] & 0xff ) * 0x100
                         + (scanRecord[startByte + 23 ] & 0xff );
 
                 String ibeaconName = device.getName();
                 String mac = device.getAddress();
                 int txPower = (scanRecord[startByte + 24 ]);
                 Log.d( "BLE" ,bytesToHex(scanRecord));
                 Log.d( "BLE" , "Name:" + ibeaconName + "\nMac:" + mac
                         + " \nUUID:" + uuid + "\nMajor:" + major + "\nMinor:"
                         + minor + "\nTxPower:" + txPower + "\nrssi:" + rssi);
 
                 Log.d( "BLE" , "distance:" +calculateAccuracy(txPower,rssi));
             }
         }
     };
     static final char [] hexArray = "0123456789ABCDEF" .toCharArray();
 
     private static String bytesToHex( byte [] bytes) {
         char [] hexChars = new char [bytes.length * 2 ];
         for ( int j = 0 ; j < bytes.length; j++) {
             int v = bytes[j] & 0xFF ;
             hexChars[j * 2 ] = hexArray[v >>> 4 ];
             hexChars[j * 2 + 1 ] = hexArray[v & 0x0F ];
         }
         return new String(hexChars);
     }
 
     protected static double calculateAccuracy( int txPower, double rssi) {
         if (rssi == 0 ) {
             return - 1.0 ; // if we cannot determine accuracy, return -1.
         }
 
         double ratio = rssi * 1.0 / txPower;
         if (ratio < 1.0 ) {
             return Math.pow(ratio, 10 );
         } else {
             double accuracy = ( 0.89976 ) * Math.pow(ratio, 7.7095 ) + 0.111 ;
             return accuracy;
         }
     }
}
</code>

至此,本文也就结束,所谓初步,就是获取ibeacon模块的基本信息。

源码下载 
http://download.csdn.net/detail/sbsujjbcy/8503507

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值