Jak*_*keP 20 android bluetooth rssi bluetooth-lowenergy android-bluetooth
我有一个简单的iOS应用程序,显示它使用诸如"立即","近"等表达式检测到的蓝牙LE信标的接近度.我需要在Android上编写类似的东西.
我已经按照Android开发人员的教程进行了操作,我能够列出检测到的设备,现在想要估算距离/接近度 - 这就是它成为问题的地方.根据这个SO线程,它只是一些数学计算.但是,它们要求我提供txPower值.
根据Dave Smith的本教程(以及与此蓝牙SIG声明的交叉引用),它应该由信标设备广播为类型的"AD结构" 0x0A.所以我所做的是解析AD结构并查找与该类型匹配的有效负载.
问题:我有4个信标 - 2个estimotes和2个appflares.estimotes根本不播放txPower,appflares将它们广播为0.
这里有什么我想念的吗?iOS应用程序似乎没有任何问题处理它,但使用iOS SDK它在幕后做,所以我不知道如何产生完全相同或类似的行为.还有其他方法可以解决我的问题吗?
如果您想查看我用来解析AD结构的代码,可以从前面提到的Dave Smith的github中获取,可以在这里找到.我对该类所做的唯一更改是添加以下方法:
public byte[] getData() {
return mData;
}
Run Code Online (Sandbox Code Playgroud)
这就是我处理扫描回调的方法:
// Prepare the callback for BLE device scan
this.leScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
if (!deviceList.contains(device)) {
MyService.this.deviceList.add(device);
Log.e("Test", "Device: " + device.getName());
List<AdRecord> adRecords = AdRecord.parseScanRecord(scanRecord);
for (AdRecord adRecord : adRecords) {
if (adRecord.getType() == AdRecord.TYPE_TRANSMITPOWER) {
Log.e("Test", "size of payload: " + adRecord.getData().length);
Log.e("Test", "payload: " + Byte.toString(adRecord.getData()[0]));
}
}
}
}
};
Run Code Online (Sandbox Code Playgroud)
而我在控制台中看到的是:
04-01 11:33:35.864: E/Test(15061): Device: estimote
04-01 11:33:36.304: E/Test(15061): Device: estimote
04-01 11:33:36.475: E/Test(15061): Device: n86
04-01 11:33:36.475: E/Test(15061): size of payload: 1
04-01 11:33:36.475: E/Test(15061): payload: 0
04-01 11:33:36.525: E/Test(15061): Device: f79
04-01 11:33:36.525: E/Test(15061): size of payload: 1
04-01 11:33:36.525: E/Test(15061): payload: 0
Run Code Online (Sandbox Code Playgroud)
tep*_*tep 30
在txPower 通过@davidgyoung提到由下式给出:
RSSI = -10 n log d + A
哪里
d =距离A = txPowern =信号传播常数RSSI = dBm在自由空间n = 2,但它会根据本地的几何形状-例如,墙壁会减少RSSI通过~3dBm,并会影响n相应.
如果您希望获得尽可能高的准确度,则可能值得通过实验确定特定系统的这些值.
参考文献:有关推导和校准的更详细说明,请参阅Qian Dong和Waltenegus Dargie对室内定位RSSI可靠性的评估.
dav*_*ung 22
目前还不清楚您是否无法读取"txPower"或"measuredPower"校准常数是由于AdRecord课堂原因还是由于您尝试解析的广告中缺少信息.我不认为该类会解析标准的iBeacon广告.无论哪种方式,都有一个解决方案:
解决方案1:如果您的信标发送包含校准常量的标准iBeacon广告,您可以使用开源Android iBeacon Library的IBeacon类中的代码解析它.
解决方案2:如果您的信标不发送标准iBeacon广告或不包含校准常数:
对于您可能使用的每种设备类型,您必须在应用程序中对校准常数进行硬编码.从广告到估算距离真正需要的是RSSI测量.在传输中嵌入校准常数的整点是允许具有完全不同的发射机输出功率的各种信标与相同的距离估计算法一起工作.
Apple定义的校准常数基本上表示如果您的设备距离信标一米,RSSI应该是什么.如果信号更强(RSSI负值较小),则设备距离不到一米.如果信号较弱(更负的RSSI),则设备距离超过一米.您可以使用公式来估算距离. 看这里.
如果您不处理包含"txPower"或"measuredPower"校准常数的广告,则可以在应用程序中对查找表进行硬编码,以存储各种发射器的已知校准常数.您首先需要测量距离一米远的每个发射机的平均RSSI.然后,您需要某种键来查找表中的这些校准常数.(也许你可以使用AD结构中的字符串的某些部分,或者mac地址?)所以你的表可能如下所示:
HashMap<String,Integer> txPowerLookupTable = new HashMap<String,Integer>();
txPowerLookupTable.put("a5:09:37:78:c3:22", new Integer(-65));
txPowerLookupTable.put("d2:32:33:5c:87:09", new Integer(-78));
Run Code Online (Sandbox Code Playgroud)
然后解析广告后,您可以在onLeScan方法中查找校准常量,如下所示:
String macAddress = device.getAddress();
Integer txPower = txPowerLookupTable.get(macAddress);
Run Code Online (Sandbox Code Playgroud)
ser*_*y.n 22
double getDistance(int rssi, int txPower) {
/*
* RSSI = TxPower - 10 * n * lg(d)
* n = 2 (in free space)
*
* d = 10 ^ ((TxPower - RSSI) / (10 * n))
*/
return Math.pow(10d, ((double) txPower - rssi) / (10 * 2));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
68881 次 |
| 最近记录: |