我有一个简单的iOS应用程序,它显示了它使用诸如"立即","附近"等表达式检测到的蓝牙LE信标的接近程度。我需要在Android上写一些类似的内容。
我已经按照Android developer上的教程进行了操作,并且我能够列出检测到的设备,现在想要估算距离/接近度 - 这就是它成为问题的地方。根据{{3}},它只是一些数学计算。但是,它们要求我提供txPower值。
根据this SO thread(以及与此this tutorial by Dave Smith的交叉引用),它应该由信标设备广播为" AD结构"类型为0x0A
。所以我所做的是解析AD结构并查找与该类型相匹配的有效负载。
问题:我有4个信标 - 2个estimotes和2个appflares。 estimotes根本不播放txPower,appflares将他们广播为0。
这里有什么我想念的吗? iOS应用程序似乎没有任何问题处理它,但使用iOS SDK它在幕后进行,所以我不确定如何产生完全相同或类似的行为。还有其他方法可以解决我的问题吗?
如果你想查看我用来解析AD结构的代码,可以从前面提到的Dave Smith的github中找到它,并且可以找到Bluetooth SIG statement。我对该课程所做的唯一更改是添加以下方法:
public byte[] getData() {
return mData;
}
这就是我处理扫描回调的方式:
// 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]));
}
}
}
}
};
我在控制台中看到的是:
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
答案 0 :(得分:30)
@davidgyoung提到的txPower
由公式给出:
RSSI = -10 n log d + A
,其中
d
=距离A
= txPower n
=信号传播常数RSSI
= dBm 在自由空间n = 2
中,它会因本地几何图形而异 - 例如,墙会RSSI
减少~3dBm
并相应地影响n
。< / p>
如果您希望获得尽可能高的准确度,则可能值得通过实验确定特定系统的这些值。
参考文献:请参阅钱东和Waltenegus Dargie的论文Evaluation of the Reliability of RSSI for Indoor Localization,以获得更详细的推导和校准说明。
答案 1 :(得分: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));
}
答案 2 :(得分:21)
目前还不清楚您是否无法阅读&#34; txPower&#34;或&#34; measuredPower&#34;校准常量是由于AdRecord
类或由于您尝试解析的广告中缺少信息而导致的。我并不认为该课程会解析标准的iBeacon广告。无论哪种方式,都有一个解决方案:
解决方案1:如果您的信标发送包含校准常量的标准iBeacon广告,您可以使用开源Android iBeacon Library的IBeacon类中的代码解析它here.
解决方案2:如果您的信标不发送标准的iBeacon广告或不包含校准常数:
您必须在应用中为您可能使用的每种设备类型硬编码校准常量。从广告到估算距离真正需要的是RSSI测量。在传输中嵌入校准常数的重点是允许具有完全不同的发射机输出功率的各种信标使用相同的距离估计算法。
Apple定义的校准常数基本上表示如果您的设备距离信标一米,RSSI应该是什么。如果信号更强(RSSI负值较小),则设备距离不到一米。如果信号较弱(更负的RSSI),则设备距离超过一米。您可以使用公式来估算距离。 See here.
如果您不处理包含&#34; txPower&#34;或&#34; measuredPower&#34;校准常数,然后您可以在应用程序中硬编码查找表,该表存储各种发射器的已知校准常数。您首先需要测量距离一米远的每个发射机的平均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));
然后在分析广告后,您可以在onLeScan
方法中查找校准常数,如下所示:
String macAddress = device.getAddress();
Integer txPower = txPowerLookupTable.get(macAddress);
答案 3 :(得分:-2)
使用库中的getAccuracy()方法,它为您提供信标的距离