iBeacon 教學(swift 3, iOS)

最終專案如下:

iBeacon為apple於iOS 7推出的一套新技術,使用低功耗藍芽(Bluetooth Low Energy、BLE)來進行室內定位。

搭配iBeacon技術的發射器,可以提供智慧型手機偵測到他們大概的位置及距離。在實際應用上,iBeacon能讓手機接收到附近商品的通知或任何店家想推播的訊息。

iBeacon還有另一項優點,因搭配BLE,功耗極低十分省電。依照iBeacon發射器好壞的不同,iBeacon皆有一個月以上的壽命,使用較大電量電池的情況下,甚至可維持至一年以上,最多到兩年的壽命。

但也因低功耗的關係,iBeacon的訊號傳輸距離有限,平均約10幾公尺左右,且容易受到障礙物的影響,如牆壁、人體、甚至iPhone面向不同的方向,皆會有接受訊號程度的差異。

p.s. 在iPhone 4s以上皆可接收iBeacon,並將iPhone作為iBeacon的發射器。

以下為官方iBeacon 文件,請務必詳讀!

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html#//apple_ref/doc/uid/TP40009497-CH9-SW1

https://developer.apple.com/ibeacon/Getting-Started-with-iBeacon.pdf


在iBeacon的世界裡,最重要的是如何識別任何一個偵測到的iBeacon。

每個iBeacon發出的訊號內皆帶著UUID、Major、Minor,三個重要的數值。

在實際應用中,UUID可以為一整棟百貨公司,Major代表不同樓層,Minor代表不同的櫃位。因此,兩顆iBeacon若有一樣的UUID,不同的Major值,代表是在同一棟百貨公司內,但不同樓層;若有同樣的UUID、Major值,但Minor不同,代表的是在同一樓層,但不同的櫃位。

依照上面的概念,偵測到任何一顆iBeacon的訊號,就可以判斷手機使用者接近哪個櫃位,大概距離多少,該櫃位也能推播商品資訊給客戶。

同一家公司使用一個UUID,依照城市不同用不同的Major value,依照商品不同用不同的Minor Value

若手邊無iBeacon發射器,也可把Mac作為iBeacon發射器。請參考以下他人的git專案,下載後打開裡面的“MactsAsBeacon”檔案即可使用。

下載後,直接點選MacsAsBeacon執行檔

以下,以程式碼來說明整個iBeacon在iOS app內的大概流程。

首先先演示最後的app畫面:

開啟app後的畫面
偵測到iBeacon後,背景變為紅色,秀出iBeacon相關資訊,並顯示“已在region中”
離開region後,背景變為白色,並顯示“離開region”

在iOS內,要使用iBeacon相關的API,必須使用Core Location 框架。手機部分也必須開啟GPS追蹤和藍牙。

開啟GPS追蹤

在iBeacon的世界中,每顆iBeacon發出的訊號內皆帶著UUID、Major、Minor。如同在地圖應用內一樣,每個iBeacon的訊號形成一個region,手機要“monitor”這個region,當進入或離開region時,做出相對的反應(如:推播訊息。)

手機是否能monitor任一顆iBeacon的region,如上所提,必須要iPhone 4S以後的手機才支援。故在ViewController中,首次開啟app,先判斷硬體是否支援接收iBeacon訊號,若支援的話,則要求使用者使用GPS。

如同正常的地圖應用,使用CoreLocation時,需創建CLLocationManager的實體,並使用CLLocationManagerDelegate這個protocol來實現各種功能。

iBeacon的訊號,會形成一個region,而這個region可透過UUID、Major、Minor Value,並給定一個identifier來創建。

給定identifier的好處在於,透過identifier的名稱,可輕易分辨接收到的每個region訊號分別為哪家櫃位。

如上面百貨公司的例子,這家百貨公司有20顆iBeacon供使用者搜尋。在程式碼中,給定UUID,即可一次鎖定20顆在此UUID之下的iBeacon。也就是說,一個region,不一定只代表一顆iBeacon。

透過如下第3行,建立region後,第8行透過locationManager即可開始monitor各個region,判斷使用者是否進入或離開region。

第4,5行內,要求當進入region和離開region時通知。預設即是開啟,在此只是演示此功能。

一個app最多一次可同時monitor 20個region!

一開始monitor,就會呼叫CLLocationManagerDelegate內的didStartMonitoringForregion的函數,在此函數內使用requestState函數,判斷開始monitor的當下,使用者是否在region內。

使用requestState函數得到的目前狀態,會傳到didDetermineState函數內

這裡來了一個重點,使用者可能同時偵測到多顆iBeacon的訊號,但一般來說,我們想要的是一個由遠到近的iBeacon距離排列順序,而這個距離排列行為就稱為ranging。

在didDetermineState函數內,第3行判斷目前狀態是否位於任一個region內,若進入region內,第5行接著開始ranging,排列出所有目前偵測到的iBeacon距離。

同樣的,在第4行內,判斷此手機是否支援接收iBeacon訊號,可進行ranging。

在使用者與各個iBeacon region的關係中,只有在進入region或離開region才會觸發通知,在region內任何的移動並不會造成持續一直接收通知。

進入region或離開region時,會呼叫didEnterRegion、didExitRegion和上面的didDetermineState函數。

在函數內決定開始ranging或停止ranging。

ranging完成後,呼叫didRangeBeacons函數,取得beacons參數,此為一個array,即為使用者接收到的所有iBeacon,經過排序後,依照距離由近到遠列出。

第4行可知,其內只取出離使用者最近,也就是array當中的第一個element。

在此獲取的每個iBeacon都是一個CLBeacon class的實體,其內有3個重要的屬性:proximity、accuracy、rssi

proximity:與此iBeacon的距離,由近到遠分為immediate、near、far和unknown

accuracy:proximity的準確程度,單位是meter,數值越高表示proximity的準確程度越不能相信,負值表示無法計算。但千萬別把這個數值作為實際距離,此數值受到很多外在因素干擾,且距離越遠越無參考性。

rssi:接收到的iBeacon訊號強弱程度,單位為decibels

以上三個數值,會綜合起來參考,用來衡量目前使用者與iBeacon的距離。

最後,處理所有錯誤情況發生的時候。


當iOS接收到iBeacon訊號時,使用rssi來判斷proximity,以及proximity的accuracy。

當rssi越強時,所得到的距離結果越為準確。而accuracy可想像為GPS的訊號強弱。

accuracy類似GPS的概念,accuracy數值最大表最左邊的圖,此時的距離定位誤差最大最不精準。
距離遠時
距離近時

BLE發射的是2.4 GHz的訊號,這也表示,任何的物理阻礙物、水、甚至是人體,皆會影響iBeacon的訊號。

甚至訊號打到牆壁反彈回來,也會造成手機誤判,使得預估失準。

Proximity的數值由近到遠分為immediate、near、far和unknown。

immediate:有很高的信心說iBeacon離使用者很近

near :約1~3公尺

far:只能代表訊號可被偵測,不一定代表距離很遠。因accuracy數值過大,沒信心判斷是near或immediate。

unknown:代表ranging剛開始,還在判斷,或者是無法判斷距離。


使用iBeacon的過程中,主要分成兩部分,monitor和ranging,關於ranging,官方不建議在背景執行,提供的使用情境如下:

一名消費者進入超市後,monitor到進入了region,因而接收到推播,拿起手機進行查看,推播上顯示歡迎光臨,並提示使用者打開此app。

此時消費者拿著手機,打開著app,進入超市的各個走道。在每條走道的底部皆會擺放一個iBeacon,接收到各個訊號後,開始ranging。

透過判斷ranging出的結果,app秀出目前消費者所在的走道,且秀出離消費者較近,或消費者較喜歡的幾樣商品。畢竟,提供越多資訊供消費者選擇越好,不該侷限消費者接收到的商品資訊!