关于iBeacon检测的一些整理

Posted by Kriz on 2017-05-20

这是专综要用到的一个小部分,因为非常乱而且网上基于swift 3.0+的iBeacon教程一个球也找不到,所以整理一下纪念踩过的所有坑。

查百科

官方的说法是这样的:

iBeacon是苹果公司2013年9月发布的移动设备用OS(iOS7)上配备的新功能。其工作方式是,配备有低功耗蓝牙(BLE)通信功能的设备使用BLE技术向周围发送自己特有的ID,接收到该ID的应用软件会根据该ID采取一些行动。比如,在店铺里设置iBeacon通信模块的话,便可让iPhone和iPad上运行一资讯告知服务器,或者由服务器向顾客发送折扣券及进店积分。此外,还可以在家电发生故障或停止工作时使用iBeacon向应用软件发送资讯。

那么主要的问题就集中在,“信号源发送的信息是什么”和“如何收发信息”这两个部分上了。

翻属性

与beacon集群相关的最重要的一个类是CLBeaconRegion,它包括了所有相似的beacon(这里之后会解释),其中每一项是一个CLBeacon对象。一个CLBeacon包含的属性有:

  • proximityUUID:近邻beacon的UUID(其实就是判定检测范围用的)
  • major:与组关联最强的值属性
  • minor:与组关联最弱的值属性
  • proximity:粗略距离
  • accuracy:表示以米为单位的西格玛水平精度,在beacon装置处参考测量装置的位置(受环境影响比较大)
  • rssi:指定beacon的分贝接收信号强度(是自上次报告该beacon后收集的RSSI样本的平均值)

其中前三项也是CLBeaconRegion的属性,声明为@NSCopying open var。【open是swift3.0的新修饰符,别问我我也搞不清楚【反正也用不着

我们使用seekcy的iBeacon设备作为信号发射源,以开启蓝牙的iPhone 6s作为接收设备。

seekcy提供了一套完整的SDK并附上了贴心的demo,糟糕的是这个demo一打开就报错而且是里世界乱码错误,完全无从下手,这导致我在这个东西上面凭空消耗了半周时间。冷漠。最终发现这个demo的原始编译环境是Xcode4-6的样子,封装的Framework是静态32位,可以说是早已被淘汰的时代的眼泪了。试问谁能想到一个大型(?)公司两年都没有升级过其明星产品的代码呢?!就很不能理解。【而且没有swift ver也可以说不是人了

其实我在看到它的git上只有三个star的时候就该放弃的

但是这个seekcy的iBeacon有一点好,它有个附带的iOS app,可以用来检测和调整附近iBeacon的参数。虽然bug多得如萍听了想射击然而至少还是能用的。就很欣慰。

要讲为什么需要借助这个app,首先说说beacon的各个参数。

proximityUUID是推荐指数最高的用来检测一个(组)beacon设备的属性。以我们使用的设备为例,我们将附近所有的beacon的该属性都设置为E2C56DB5-DFFB-48D2-B060-D0F5A71096E0,则可以使用

1
2
3
4
5
let beaconRegion: CLBeaconRegion = {
let region = CLBeaconRegion(proximityUUID: UUID(uuidString: "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")!, identifier: "Identifier")
region.notifyEntryStateOnDisplay = true
return region
}()

进行同一组beacon的检测和记录。这里有个很烦的地方,苹果原生SDK的proximityUUID必须提供详细值,也就是只有被钦定的beacon才会被检测到。所以这里必须首先使用这个app来调教一下,虽然不知道它的运作原理但是能用就行【

一个系列的beacon的major一般也是相同的,用来确定是同一个领域。我们需要使用beacon做室内定位部分,那么可以把一楼所有beacon的major设置为1,二楼设置为2,以此类推。而minor用来辨识单独的一个beacon,做详细的联动定位。所以我刚才打上粗体的“相似”二字,一般就是指相同的proximityUUID,或是相同的major的一组beacon(CLBeaconRegion是可以使用major来定义实例的)。

接下来判定一下收发源的距离。最粗略的是proximity属性,这玩意疑似是个enum,只有near、immidiate、far和unknown。所以一般使用这个属性的话只能:

1
2
3
4
5
6
7
8
9
10
11
let proximityText: String
switch proximity {
case .near:
proximityText = "Near"
case .immediate:
proximityText = "Immediate"
case .far:
proximityText = "Far"
case .unknown:
proximityText = "Unknown"
}

啊真是丑死了我的眼睛【

但并没有其他的办法。摊手。

ps.似乎accuracy和rssi结合使用的话,能得到更加具体的距离信息。不过似乎受环境影响大得过分了,目前还没发现什么补救措施。【亲测塞进裤子里信号就会弱一半【请不要脑补奇怪的画面

找方法

搞明白了beacon发送的信息,接下来只要用客户端执行检测就可以了。这里具体的Table View配置部分略过不表,主体只要调用CLLocationManager实例的startRangingBeacons方法,分次加入tableview,附近的beacon就可以被显示出来了。

didRangeBeacons方法会每秒循环调用,用来检测周围的设备。

rst

不过细节还是挺多的可惜我忘光了欢迎一起讨论