当调用didRangeBeacons方法时,最近的beacon beacons.first?或者它是具有最低准确度值的信标列表中的信标?两个都正确吗?感谢
答案 0 :(得分:1)
虽然didRangeBeacons:inRegion:
回调中的信标列表按精度字段排序(实际上是以米为单位测量距离),但依赖此问题存在许多问题:
如果在过去的第二天没有RSSI(信号强度)样本,有时信标的准确度值为-1。如果您继续进行自动排序,这会给您不正确的结果。
如果在最后一秒内未检测到信标,则有时信标会从列表中删除。这是嘈杂的蓝牙环境中常见的问题,并且不常发送信标。
了解最近的信标的一种更健壮的方法是自己实现一种算法,该算法忽略精度值-1,并且能够容忍信标检测中的临时丢失(比如说5秒)。
当然,这只是一个开始。您可以通过添加各种其他过滤器来调整它,以便根据您的确切用例进行调整。没有过于复杂的事情,这里有一些我用于基础知识的Swift代码:
let expirationTimeSecs = 5.0
public var closestBeacon: CLBeacon? = nil
var trackedBeacons: Dictionary<String, CLBeacon>
var trackedBeaconTimes: Dictionary<String, NSDate>
override init() {
trackedBeacons = Dictionary<String, CLBeacon>()
trackedBeaconTimes = Dictionary<String, NSDate>()
}
public func locationManager(manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], inRegion region: CLBeaconRegion) {
let now = NSDate()
for beacon in beacons {
let key = keyForBeacon(beacon)
if beacon.accuracy < 0 {
NSLog("Ignoring beacon with negative distance")
}
else {
trackedBeacons[key] = beacon
if (trackedBeaconTimes[key] != nil) {
trackedBeaconTimes[key] = now
}
else {
trackedBeaconTimes[key] = now
}
}
}
purgeExpiredBeacons()
calculateClosestBeacon()
}
func calculateClosestBeacon() {
var changed = false
// Initialize cloestBeaconCandidate to the latest tracked instance of current closest beacon
var closestBeaconCandidate: CLBeacon?
if closestBeacon != nil {
let closestBeaconKey = keyForBeacon(closestBeacon!)
for key in trackedBeacons.keys {
if key == closestBeaconKey {
closestBeaconCandidate = trackedBeacons[key]
}
}
}
for key in trackedBeacons.keys {
var closer = false
let beacon = trackedBeacons[key]
if (beacon != closestBeaconCandidate) {
if beacon!.accuracy > 0 {
if closestBeaconCandidate == nil {
closer = true
}
else if beacon!.accuracy < closestBeaconCandidate!.accuracy {
closer = true
}
}
if closer {
closestBeaconCandidate = beacon
changed = true
}
}
}
if (changed) {
closestBeacon = closestBeaconCandidate
}
}
func keyForBeacon(beacon: CLBeacon) -> String {
return "\(beacon.proximityUUID.UUIDString) \(beacon.major) \(beacon.minor)"
}
func purgeExpiredBeacons() {
let now = NSDate()
var changed = false
var newTrackedBeacons = Dictionary<String, CLBeacon>()
var newTrackedBeaconTimes = Dictionary<String, NSDate>()
for key in trackedBeacons.keys {
let beacon = trackedBeacons[key]
let lastSeenTime = trackedBeaconTimes[key]!
if now.timeIntervalSinceDate(lastSeenTime) > expirationTimeSecs {
NSLog("******* Expired seeing beacon: \(key) time interval is \(now.timeIntervalSinceDate(lastSeenTime))")
changed = true
}
else {
newTrackedBeacons[key] = beacon!
newTrackedBeaconTimes[key] = lastSeenTime
}
}
if changed {
trackedBeacons = newTrackedBeacons
trackedBeaconTimes = newTrackedBeaconTimes
}
}
答案 1 :(得分:0)
一旦检测到信标,为了查看最接近的信标,您需要遍历locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
回调中的信标数组,并比较每个信标的准确属性。具有最低精度值的信标是最接近的。