【发布时间】:2018-04-06 23:18:04
【问题描述】:
我正在设计一个 iBeacon 设备以与 iPhone 上的应用程序配合使用。问题是与识别信标的应用程序存在非常奇怪的不一致。我主要从这份文档中了解到信标:https://developer.apple.com/ibeacon/Getting-Started-with-iBeacon.pdf 以下是对我的系统的简短介绍:
设备: - 按下设备上的按钮会以 10Hz 的频率触发 iBeacon BLE 广告约两秒钟。 - 设备循环通过 20 个 UUID,以便用于每个不同的按钮按下。这是为了在应用程序没有时间“超出范围”时快速按下按钮时区分按钮按下。 20 UUID 是 Apple 规定的允许应用监控的限制。
应用程序: - 应用程序搜索 20 个 UUID 中的任何一个。 - 检测时,进入和退出事件会触发一些应用程序事件,并在其简短分配的后台时间中简要使用测距来提取 Maj. Min。对值。
测试: 为了进行测试,应用程序设置为在发生输入、范围和退出事件时显示弹出窗口。测试在前台应用程序进行。我按下按钮,观察输入和范围事件,并等到它退出该区域后再按下。使用 BLE 扫描仪进行的测试表明,该设备运行良好,并且正在广播 100% 的按钮按下,正确循环通过 20 个 UUID。
问题: 在应用内测试中,问题出现并遵循一种奇怪的模式。该应用程序可以很好地识别前 9 次左右的按钮按下/UUID。之后,通常在第 10 次按下按钮时,应用程序会停止响应信标。没有弹出窗口。在我的 BLE 扫描仪上,我可以清楚地看到设备正在正确广播。当设备循环回到第一个 UUID 时,设备通常会再次开始识别信标。我说“通常”是因为它有时会在第 11 个 UUID 处停止,有时会在第 20 个 UUID 重新开始,甚至有一次我什至随机看到了第 12 个 UUID,但通常在后半部分存在这个间隙或“死区” UUID 的。如果我快速按下按钮,我可以让它工作。弹出窗口会很快出现并显示 UUID 的循环一直到 20,所以我知道 UUID 很好,并且应用程序有能力。当按钮按下之间的时间超过一分钟左右时,就会出现问题。 我可以做的另一件奇怪的事情是捣碎按钮,成功地看到应用程序弹出窗口,然后当我处于 10-20 的 UUID“死区”范围内时停止,比如列表中的 UUID 14。如果我等待一分钟并再次按下,则在按下 7 次按钮后再次到达第一个 UUID 之前它不会起作用。 其他注意事项: - 我并不总是看到区域退出弹出窗口,有时它们退出非常快,有时需要更长的时间。 - 模式不是严格一致的。它有时会有所不同。有时它会工作一个完整的周期,但它通常属于这种间隙模式。 - 我在 iOS 11 和 10 的两部手机上进行测试。
想法: 奇怪的是,它几乎总是想在第一个 UUID 处重新开始工作。所以这让我觉得这不是一个绝对的时间问题,否则差距会在时间上存在,而不是在 UUID 列表中。 奇怪的是,它在快速循环时起作用。
Apple 是否在 10 之后将另一个 UID 列入黑名单,因为它认为我正在向 UUID 发送垃圾邮件,或者扫描太多 UUID 太快? 这是我不知道的更深层次的 iOS BLE 缓存问题吗? 这是某种iOS BLE后台扫描调度程序的时间问题吗? 这听起来像是应用代码中的错误吗?
感谢任何帮助或想法!
这是我的信标事件应用代码-
func locationManager(_ manager: CLLocationManager, didRangeBeacons 信标: [CLBeacon], in region: CLBeaconRegion) {
let knownBeacons = beacons.filter{ $0.proximity != CLProximity.unknown }
for closestBeacon in knownBeacons
{
let closestBeaconFound = closestBeacon as CLBeacon
var beaconProximity = ""
switch (closestBeaconFound.proximity)
{
case CLProximity.unknown: beaconProximity = "Unknown"
case CLProximity.far: beaconProximity = "Far"
case CLProximity.near: beaconProximity = "Near"
case CLProximity.immediate: beaconProximity = "Immediate"
}
if inDidRangeShowPopup == false{
HelperClass.showAlert(value: "identifier and proximityUUID in did Range: \(region.identifier) \(region.proximityUUID)")
inDidRangeShowPopup = true
let when = DispatchTime.now() + 5 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
inDidRangeShowPopup = false
}
}
let status = "Ranging"
let uuid = String(describing: region.proximityUUID)
let major = closestBeaconFound.major as! Int
let minor = closestBeaconFound.minor as! Int
var pressType = ""
print("closestBeacon",closestBeaconFound.proximityUUID, closestBeaconFound.major,closestBeaconFound.minor,closestBeaconFound.proximity.rawValue, beaconProximity, closestBeaconFound.accuracy,closestBeaconFound.rssi)
let majorHex = String( closestBeaconFound.major as! Int, radix : 2)
print("Hex Major : \(majorHex)")
let paddedBits = HelperClass.paddedBinaryString(with: majorHex)
print("paddedBits : \(paddedBits)")
let emergencyCode = paddedBits.substring(to: 8).asBinaryInt()
let deviceID = paddedBits.substring(from: 8).asBinaryInt()
if emergencyCode == 0
{
if iBeaconOption1Done == false
{
iBeaconOption1Done = true
let when = DispatchTime.now() + 10 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
iBeaconOption1Done = false
}
for addressStr in HelperClass.getMyMacAddres()
{
let address = addressStr as! String
if address == String(deviceID!)
{
pressType = "option1"
self.setDeviceStatusAndSetTimer(mac_address: address , deviceId : deviceID!, status: status, uuid: uuid, major: major, minor: minor, pressType: pressType)
if HelperClass.getAppFlagValueForAttribute (attribute : "isHomeViewed") == true {
self.option1Service(flag : "option1", deviceId: deviceID!)
}
else{
self.option1Service(flag : "test_option1", deviceId: deviceID!)
}
}
}
}
}
else if emergencyCode == 1
{
print("Call option2")
for addressStr in HelperClass.getMyMacAddres()
{
let address = addressStr as! String
if address == String(deviceID!)
{
pressType = "Option2"
self.setDeviceStatusAndSetTimer(mac_address: address , deviceId : deviceID!, status: status, uuid: uuid, major: major, minor: minor, pressType: pressType)
}
}
if HelperClass.getAppFlagValueForAttribute (attribute : "isHomeViewed") == true {
self.sendOption2 (flag : "device" ,deviceId : deviceID!)
}
}
else if emergencyCode == 2
{
print("Call Advertisement")
if iBeaconStatusSent == false
{
iBeaconStatusSent = true
let when = DispatchTime.now() + 5 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
iBeaconStatusSent = false
}
for addressStr in HelperClass.getMyMacAddres()
{
let address = addressStr as! String
if address == String(deviceID!)
{
pressType = "Check in"
self.setDeviceStatusAndSetTimer(mac_address: address , deviceId : deviceID!, status: status, uuid: uuid, major: major, minor: minor, pressType: pressType)
}
}
}
}
}
}
func getDefaultBeacons() -> [CLBeaconRegion] {
return [
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+3)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+4)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+5)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+6)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+7)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+8)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+9)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+10)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+11)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+12)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+13)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+14)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+15)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+16)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+17)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+18)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+19)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+20)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+21)"),
CLBeaconRegion(proximityUUID: UUID(uuidString: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")!, identifier: "Fl\(BeaconIdentifierIntValue+22)")
]
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
print("iBeacon delegate:didEnterRegion called")
DispatchQueue.main.async() {
if let beaconRegion = region as? CLBeaconRegion {
print("identifier and proximityUUID in didEnterRegion: \(beaconRegion.identifier) \(beaconRegion.proximityUUID)")
HelperClass.showAlert(value: "identifier and proximityUUID in didEnterRegion: \(beaconRegion.identifier) \(beaconRegion.proximityUUID)")
}
else{
print("Wrong Format in didEnterRegion")
Answers.logCustomEvent(withName: "didEnterRegion", customAttributes: [
"error_text": "CLBeaconRegion Object Not Created",
"app_version" : AppVersion,
"app_build" : AppBuild
])
}
}
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
print("iBeacon delegate:didExitRegion called")
DispatchQueue.main.async() {
if let beaconRegion = region as? CLBeaconRegion {
print("identifier and proximityUUID in didExitRegion: \(beaconRegion.identifier) \(beaconRegion.proximityUUID)")
HelperClass.showAlert(value: "identifier and proximityUUID in didExitRegion: \(beaconRegion.identifier) \(beaconRegion.proximityUUID)")
}
else{
print("Wrong Format in didExitRegion")
Answers.logCustomEvent(withName: "didExitRegion", customAttributes: [
"error_text": "CLBeaconRegion Object Not Created",
"app_version" : AppVersion,
"app_build" : AppBuild
])
}
}
}
【问题讨论】:
标签: swift cllocationmanager ibeacon locationmanager beacon