这很容易,只涉及基本数学。将其分解为两个部分:
- 找到您的水平位置(没有高度)。
要找到您的位置,需要三个点,但只关注两个点一会儿。通过使用两个点,您可以创建一个三角形,并根据两个点之间的信号强度找到自己的位置。这将找出您在两个路由器之间的位置。例如,如果您在第3个和第4个路由器之间,与第3个的信号强度相比为-89,与第4个的信号强度为-54,则知道您更靠近第3个而不是第4个。如果您对距离与信号强度进行近似,就可以得出您在第3个和第4个路由器之间的准确位置。然后,剩下的问题就是确定您在3和4之间的哪一边,因为您可能具有相同的信号强度值(-89,-54)位于路由器的上方或下方(请参阅图表)。
6
You could be here
3--------------------------4
You could also be here
5
只需找到另一个路由器,并注意您的信号强度。通过观察5到6个路由器之间的信号强度关系,您应该很容易确定自己处于哪一侧(在图表中)。
您也可以使用高度来做同样的事情。
要完成以上所有操作,您实际上只需要近似计算距离与信号强度之间的关系以及各个路由器之间的距离。根据我的测试(我编写了自己的Wi-Fi三角定位代码),移动设备上的信号强度相当均匀,因此一个设备应该与旁边的设备具有相同的结果。
Skyhook可能是通过GPS定位(可能被硬编码)或基本上与此原理相同的方式来实现这一点。 Skyhook是仅得到苹果批准的服务,因此苹果基本上也做了同样的事情,然后确保其他应用程序无法使用它(使用受限制的802.11库的任何iPhone应用程序都将被拒绝进入App Store)。
如何找到距离:
您需要进行一些简单的近似计算。根据您的环境,这些近似值可能并不相同,因此-89英尺(27米)可能意味着您距离路由器3有15英尺(4.5米),但是-89英尺(27米)可能意味着您距离路由器4只有13英尺(4米)。无论您做什么,这都不会是100%准确的,但没关系,因为您可以确保在5英尺(1.5米)内。
所以您需要找到一堆从路由器3得到读数为-89的点,并记录下您的距离。然后,您取平均值,并将其用于放入数据库中(其中表示当您距离路由器3为-89时,您距离为15英尺(4.5米))。然后,您可以对其他值(例如-50或其他任何值)执行此操作,并记录下您的值并找到平均值。现在,如果-89意味着您距离为15英尺(4.5米),而-50意味着您距离为25英尺(4.5米)(仅举个例子),则除非您想手动为-75获取近似值,否则必须近似计算您距离路由器3的距离。对于大量值来说,这将是繁琐的,但您需要进行实验以查看您可以获得多少数据点并保持准确。
信号强度是对数的,所以可以估算出两个信号强度的平均值之间的差距。由于-89表示15英尺(4.5米),因此您可以估计-75比-89的距离更远,其距离因素为14/100(基于10或2的对数,我记不清了,但我倾向于基于10)。
请求代码。
我有这段代码,但是它是几年前写的,所以我需要翻阅很多东西才能找到它。我认为从概念上讲,应该可以在没有代码的情况下轻松复制。我使用Java代码测试了一些Android设备,大约用了50行代码。
基本上,我拿起了一台安卓手机,并创建了一个应用程序,允许我随时显示已连接Wi-Fi设备的当前ID、信号强度、其他附近Wi-Fi ID及其信号强度,然后是GPS位置。所有这些都可以通过Android的API访问。我想你需要一个API 4或更高版本的Android设备。这大约是三到四年前的事情,所以我只是根据自己的记忆说了一些。
GPS位置部分是为了使物理和Wi-Fi信号强度之间的映射更容易,而不必通过其他方式创建我的设施的蓝图地图,我可以在同一时间内只需叠加他们的地图和GPS坐标即可让Google地图为我完成。你仍然需要深度图来映射楼层,我们可以很容易地手工完成,找到您是否在两个路由器中间。
我们知道信号强度最强的是相同楼层的Wi-Fi中心,然后可以通过确保您对不同楼层的Wi-Fi中心具有较弱的信号来进行双重检查。这张深度图基本上是Wi-Fi中心及其各自楼层的列表。
我们不需要它们的位置,因为我们可以将信号强度最佳拟合到我们在设施周围行走并获取与某些中心的信号强度时捕获的GPS位置上。这是一些简单的数学。因此,对于从上向下看的二维平面位置,我们有像这样的一堆对象:
BestFitObject{
Tuple<long, long> GPSLocation;
List<Tuple<WifiDevice, signedInt>> WifiReadings; //WifiDeviceName(through UUID or some other way), tupled with the signalStrength when that bestFit reading was taken
}
WifiDevice{
UUID ID; // Think a string should work fine, might be an internal type that encompasses UUID which would be better.
int floorNumber;
Tuple<long, long> GPSLocation; // Not entirely necessary, could provide better accuracy though
}
然后当我们对客户端设备进行ping测试并希望最佳匹配时,它会返回如下对象:
ClientPosition{
List<Tuple<UUID, signedIt> NearbySignals; // Tuple of the UUID of the Wi-Fi device and the signal strength taken during the time of the ping.
}
然后我们可以很容易地将ClientPosition最佳匹配到上述两个对象创建的2D地图上。
以上非常简单,我认为深度图甚至更简单。
理想情况下,您希望尝试使用涵盖几种不同无线技术(一些是a设备,一些是b设备,n、g等)的几个不同设备,以获得更准确的结果。但我发现,准确性并不是那么重要,你会在5英尺(1.5米)左右内。这已经足够满足我的需求了。理想情况下,所有Wi-Fi中心都是相同型号的,而在大型设施/公司中通常都是如此,但即使如此也没什么大不了的。变异性非常小,如果你不需要疯狂的精确性,这并不重要。