iBeaconの自作

# 記事の概要
太陽誘電の販売するnRF52480搭載BLEモジュールを用いてiBeaconを自作します。

# iBeacon仕様

iBeaconの発信するデータは30バイトのアドバタイジングパケットであり、以下の構造を持ちます

| Byte|       初期値 |    意味    |
|:--------------:|:---------------:|:---------------:|
| 0| 0x02| データ長さ 2バイト |
| 1| 0x01| データタイプ|
| 2| 0x06| LE and BR/EDRフラグ |
| 3| 0x1a| データ長さ 26バイト |
| 4| 0xff| データタイプ |
| [5:6]| 0x004c | Manufacturerデータ|
| 7| 0x02| iBeaconタイプ|
| 8| 0x15| iBeacon長さ 21バイト|
| [9:24]| --- | UUID 16バイト|
| [25:26]| --- | Major 2バイト|
| [27:28]| --- | Minor 2バイト |
| 29| 0xc3 |　信号出力|


iBeaconの仕様については、以下をご参照ください。

- [Understanding the different types of BLE Beacons](https://os.mbed.com/blog/entry/BLE-Beacons-URIBeacon-AltBeacons-iBeacon/)
- [iBeacon advertising packet structure](https://support.kontakt.io/hc/en-gb/articles/201492492-iBeacon-advertising-packet-structure)

# 作成
まずは、以下の記事を参照して開発環境を構築してください。
[Nordic社製BLEの開発環境構築と動作確認](https://qiita.com/Kosuke_Matsui/items/5d61ce77e928b9f117cc)

次に、以下の記事を参照してBLEモジュールを購入し、プログラム書き込みができるようにしてください。

[表面実装部品の太陽誘電BLEモジュールを強引に電子工作で利用する方法](https://qiita.com/Kosuke_Matsui/items/8132bee58323126a0cd7)

以下のサンプルプロジェクトを開いてください。

~\nRF5SDK160098a08e2\examples\ble_peripheral\ble_app_beacon\pca10056\s140\arm5_no_packs\ble_app_beacon_pca10056_s140.uvprojx

nRF52480以外の製品の場合も、ble_app_beaconという名称のフォルダがあるので、そちらをご使用ください。


iBeaconのデータはサンプルプログラム中の以下の箇所で設定します。

```c:main.c
#define APP_BEACON_INFO_LENGTH          0x17                               /**< Total length of information advertised by the Beacon. */
#define APP_ADV_DATA_LENGTH             0x15                               /**< Length of manufacturer specific data in the advertisement. */
#define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
#define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
#define APP_COMPANY_IDENTIFIER          0x004C                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
#define APP_MAJOR_VALUE                 0x01, 0x02                         /**< Major value used to identify Beacons. */
#define APP_MINOR_VALUE                 0x03, 0x04                         /**< Minor value used to identify Beacons. */
#define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                        0x45, 0x56, 0x67, 0x78, \
                                        0x89, 0x9a, 0xab, 0xbc, \
                                        0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */
```

サンプルプログラムにおいて、APP_COMPANY_IDENTIFIERの初期値は0x0059ですが、これはAndroidのManufacturerデータなので、AppleのManufacturerデータの0x004cに書き換えて下さい。

UUID、Major、Minorは自由に書き換えできます。

なおアドバタイジングパケットのGAP Advertisement Flagsは、関数advertising_init()においてBLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTEDに設定されています。

```c:main.c
uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
```

これはアドバタイジングパケットを発信しますが、セントラル機器などとのBLE接続は行わない設定です。
GAP Advertisement Flagsについては以下の記事をご参照ください。

[BLE General Discoverable ModeとLimited Discoverable Modeの比較](https://qiita.com/Kosuke_Matsui/items/c46a7e0b2299fe2e611f)


Beaconの発信周期を変更したい場合は以下の設定を修正します。

```
#define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(300, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
```

Beaconの発信強度を修正したい場合は、`sd_ble_gap_tx_power_set`関数を実行します。
設定できる定数はあらかじめ決められています。
-40, -20, -16, -12, -8, -4, 0, +2, +3, +4, +5, +6, +7, +8から選択します。
例えば、BLE初期設定完了後ならば、任意のタイミングでtx_power_set関数を実行すれば発信強度が変更されます。

```C
// Supported tx_power values: 
// -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, 
// -4dBm, 0dBm, +2dBm, +3dBm, +4dBm, +5dBm, 
// +6dBm, +7dBm and +8dBm.
#define TX_POWER_LEVEL (-12)

/**@brief Function for changing the tx power.
 */
static void tx_power_set(void)
{
    ret_code_t err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, TX_POWER_LEVEL);
    APP_ERROR_CHECK(err_code);
}
```


プログラムを書き込み、ボタン電池に接続すれば、以下のような自作iBeaconの完成です。

<img width="50%" alt="iBeacon.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/f07b7476-52be-9b64-c82a-6acfc332902f.jpeg">

# 動作確認
iPhoneに適当なBeaconスキャンアプリをインストールします。

私は[Beacon Scan](https://apps.apple.com/us/app/beacon-scan/id1011834079)というアプリを使用しています。

設定で、プログラムと同じUUIDを入力してください。

<img width="50%" alt="IMG_1883.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/651d0866-5b02-4de2-2973-237838ec45ae.png">

スキャンでBeacon検知するはずです。
MajorとMinorもプログラムで設定した値、0x0102=258と0x0304=772になっています。

<img width="50%" alt="IMG_1886.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/7e45732a-ecc6-7e7f-10b8-bbbabf085186.png">

iBeaconから離れるとRSSIが下がり、検知圏外に出ると0になります。

<img width="50%" alt="IMG_1887.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/4a773470-c888-177b-c9e0-1a6b6e8b691f.png">