這裡介紹如何使用樹莓派實作一個 iBeacon 發射器,發送 iBeacon 訊號給手機等行動裝置。
Beacon 是一種以藍牙低功耗(BLE)資料傳輸技術為基礎,結合各種行動裝置的應用,這個技術可將少量的資料發送至附近的手機或平板等藍牙行動裝置,讓行動裝置上的應用程式獲得準確的位置相關資訊,非常適合用於室內定位、商場導覽等各種場合。
這裡我們需要安裝 BlueZ 5.11 以後的版本,如果 Linux 系統套件庫中的 BlueZ 套件版本,就可以使用 apt 安裝,如果系統套件庫的版本太舊,就必須下載 BlueZ 的原始碼自行編譯安裝。
檢查 apt 套件庫中的 bluez
版本:
apt-cache show bluez
Package: bluez Version: 5.23-2+rpi2 Architecture: armhf [略]
如果版本夠新,就可以直接用 apt 安裝 BlueZ:
sudo apt-get install bluez
檢查安裝的 BlueZ 套件版本:
dpkg --status bluez | grep '^Version:'
在編譯 BlueZ 時會需要許多的系統函式庫,這些可用 apt 來安裝:
sudo apt-get install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
準備好編譯環境之後,接著從 BlueZ 官方網站下載最新的原始碼:
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.43.tar.xz
解壓縮 BlueZ 原始碼:
tar Jxvf bluez-5.43.tar.xz cd bluez-5.43/
編譯 BlueZ:
./configure --disable-systemd
make
編譯完成後,要不要安裝都可以:
sudo make install
若不安裝的話,可直接從 tools
目錄中取的所需的執行檔。
以 hciconfig
檢查自己的藍牙設備是否有正常被偵測到,我這裡的測試環境是第三代的樹莓派,所以有內建的藍牙裝置,如果是比較舊的樹莓派,則可另外安插 USB 的藍牙傳輸器,用法也都相同:
hciconfig
hci0: Type: BR/EDR Bus: UART BD Address: B8:27:EB:FE:07:91 ACL MTU: 1021:8 SCO MTU: 64:1 DOWN RX bytes:661 acl:0 sco:0 events:34 errors:0 TX bytes:423 acl:0 sco:0 commands:34 errors:0
如果藍牙裝置的狀態處於未啟用的狀態(DOWN
),可先將其啟用:
sudo hciconfig hci0 up
確認藍牙裝置處於 UP RUNNING
的狀態:
hciconfig
hci0: Type: BR/EDR Bus: UART BD Address: B8:27:EB:FE:07:91 ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING RX bytes:5547 acl:0 sco:0 events:309 errors:0 TX bytes:5754 acl:0 sco:0 commands:309 errors:0
啟用藍牙的低耗能廣告(LE advertising)模式,並關閉掃描功能:
sudo hciconfig hci0 leadv 3 sudo hciconfig hci0 noscan
設定要送出的 iBeacon 資料:
sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 00 00 00 C8 00
< HCI Command: ogf 0x08, ocf 0x0008, plen 32 1E 02 01 1A 1A FF 4C 00 02 15 E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 00 00 00 C8 00 > HCI Event: 0x0e plen 4 01 08 20 00
這行指令指定的是封包的原始資料,比較跟使用者有關的有以下幾個欄位:
欄位 | 長度 | 說明 | 實際值(十六進位) |
---|---|---|---|
ID | uint8_t |
固定值 | 02 |
資料長度 | uint8_t |
payload 長度 | 15 |
UUID | uint8_t[16] |
128 bits 的 UUID 值 | E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 |
Major | uint16_t |
Major 值 | 00 00 |
Minor | uint16_t |
Minor 值 | 00 00 |
TX Power | uint8_t[16] |
傳送訊號的強度 | C8 |
我們可以使用 Wireshark 來將實際送出的封包抓下來看,封包中每個位置的欄位解釋可以從 Wireshark 中查看:
這時候我們就可以用手機上的 Beacon Scanner App 來檢查 iBeacon 的訊號了。
linux-ibeacon 是一個以 Python 寫成的指令稿,可以讓使用者非常簡單地在 Linux 系統上以藍牙設備建立 iBeacon 發射器。
使用這個 Python 指令稿可以很方便的指定各個 iBeacon 資料欄位,不需要自己換算十六進位碼:
sudo python ibeacon --uuid=E20A39F473F54BC4A12F17D1AD07A961 --major=123 --minor=456
Advertising on hci0 with: uuid: 0xE20A39F473F54BC4A12F17D1AD07A961 major/minor: 123/456 (0x007B/0x01C8) power: 200 (0xC8) LE set advertise enable on hci0 returned status 12
這是從手機上接收到的訊號:
除了蘋果公司的 iBeacon 之外,Beacon 應用中其實還有其他的標準,例如 Google 所推出的 Eddystone 格式就比 iBeacon 更有彈性,還可以傳送 URL 網址,打造實體網頁,這部份可參考樹莓派 Raspberry Pi 以 Eddystone 傳送 URL 的教學文章。
參考資料:adafruit、MUO、
orange narwhals、IT 技術家、阿舍