ios - Proper way to find the closest beacon -
when didrangebeacons method called, closest beacon beacons.first? or beacon in list of beacons has lowest accuracy value? both correct? thanks
while list of beacons in didrangebeacons:inregion:
callback sorted accuracy field (which measures distance in meters), there number of problems relying on this:
sometimes beacons have accuracy value of -1 if no rssi (signal strength) samples available in past second. gives incorrect results if relay on automatic sorting.
sometimes beacons drop out of list if aren't detected in last second. common problem in noisy bluetooth environments , infrequently transmitting beacons.
a more robust way know closest beacon implement algorithm ignores accuracy values of -1 , tolerant of temporary dropouts (say 5 seconds) in beacon detections.
or course, beginning. can fancier adding kinds of other filters tune exact use case. without on complicating things, here's swift code use basics:
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 = nsdate() beacon in beacons { let key = keyforbeacon(beacon) if beacon.accuracy < 0 { nslog("ignoring beacon negative distance") } else { trackedbeacons[key] = beacon if (trackedbeacontimes[key] != nil) { trackedbeacontimes[key] = } else { trackedbeacontimes[key] = } } } purgeexpiredbeacons() calculateclosestbeacon() } func calculateclosestbeacon() { var changed = false // initialize cloestbeaconcandidate latest tracked instance of current closest beacon var closestbeaconcandidate: clbeacon? if closestbeacon != nil { let closestbeaconkey = keyforbeacon(closestbeacon!) key in trackedbeacons.keys { if key == closestbeaconkey { closestbeaconcandidate = trackedbeacons[key] } } } 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 = nsdate() var changed = false var newtrackedbeacons = dictionary<string, clbeacon>() var newtrackedbeacontimes = dictionary<string, nsdate>() key in trackedbeacons.keys { let beacon = trackedbeacons[key] let lastseentime = trackedbeacontimes[key]! if now.timeintervalsincedate(lastseentime) > expirationtimesecs { nslog("******* expired seeing beacon: \(key) time interval \(now.timeintervalsincedate(lastseentime))") changed = true } else { newtrackedbeacons[key] = beacon! newtrackedbeacontimes[key] = lastseentime } } if changed { trackedbeacons = newtrackedbeacons trackedbeacontimes = newtrackedbeacontimes } }
Comments
Post a Comment