iBeaconを使ってみた


BLEを触ってみたかったのでiBeaconを使ってみました。

iBeaconはBluetooth LEを利用したAppleのテクノロジで、iPhone4s, 第3世代iPad以降の機種で利用することが出来ます。BLEデバイスのアドバタイズメント・パケットのフォーマットを工夫して実装しているようです（[上原さんのブログ](http://reinforce-lab.github.io/blog/2013/10/21/ibeacon/)より）。

AppleのBluetooth LE利用可能機種は次の通り（2014年1月時点）。

* iPhone4
* iPhone5
* iPhone5s
* iPhone5c
* iPad mini
* iPad mini Retina
* iPad 3rd gen
* iPad 4th gen
* iPad Air

とりあえず触ってみよう、ということで早速実装してみます。

iBeaconはBluetooth関連技術のためCoreBluetoothフレームワークが必要かと思いましたが、Appleでは位置情報サービスの一部として位置づけられており、CoreLocationフレームワークを必要とします。

CoreLocationフレームワークをプロジェクトに追加します。

![kobito.1392736919.088672.png](https://qiita-image-store.s3.amazonaws.com/0/29860/82dbb592-5856-75c2-92be-f1841acb3c74.png "kobito.1392736919.088672.png")


iBeaconのアクターはビーコンとロケーションマネージャに分かれます。ビーコンは発信、ロケーションマネージャは受信を担当します。どちらもiOSで実装可能なのでデバイスが複数あれば、1つをビーコン、もう1つをロケーションマネージャとして使用することが出来ます。

適当なViewControllerでロケーションマネージャとNSUUID, CLBeaconRegionを初期化します。CLBeaconRegionがiBeaconの発信を行うオブジェクトです。なお、UUID文字列はコマンドラインから`uuidgen`コマンドで作成してください。

```bash
$ uuidgen
A7622281-1189-4B1F-B890-A5F2E8D9A4D0  # この文字列を使う
```



```objectivec
static NSString *kMBBeaconIdentifier = @"com.mybikenote.beacon";
static NSString *kMBUUID = @"A7622281-1189-4B1F-B890-A5F2E8D9A4D0";

- (void)viewDidLoad
{
    [super viewDidLoad];

    _locationManager = [[CLLocationManager alloc] init];
    _locationManager.delegate = self;

    self.proximityUUID = [[NSUUID alloc] initWithUUIDString:kMBUUID];

    // CLBeaconRegionを作成
    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID
                                                           identifier:kMBBeaconIdentifier];
}
```

# ロケーションマネージャの実装

## iBeaconのモニタ開始処理

ロケーションマネージャの`startMonitoringForRegion`メソッドを呼び出して、ビーコンのモニタリングを開始します。

```objectivec
[self.locationManager startMonitoringForRegion:self.beaconRegion];
```

## iBeaconのモニタ終了処理

モニタリングの終了は`stopMonitoringForRegion`メソッドを呼び出します。この辺りは位置情報の取得とほとんど一緒ですね。

```objectivec
[self.locationManager stopMonitoringForRegion:self.beaconRegion];

```

## ビーコンの検知、受信

ビーコンの検知はロケーションマネージャのdelegateメソッドを実装します。

```
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
    [self.locationManager requestStateForRegion:self.beaconRegion];
}

// requestStateForRegionを呼ぶとコールバックされる
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    switch (state) {
        case CLRegionStateInside: // 既にリージョン内にいる
            if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
                [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
            }
            break;
        case CLRegionStateOutside:
        case CLRegionStateUnknown:
        default:
            break;
    }
}

// リージョン内に入ったら呼び出される
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"Enter Region"];
}

// リージョンから出たら呼び出される
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@"Exit Region"];
}
```


----

あわせて読みたい。

* [iOS: iBeaconについて](http://support.apple.com/kb/HT6048?viewlocale=ja_JP)
* [[iOS 7] 新たな領域観測サービス iBeacon を使ってみる](http://dev.classmethod.jp/references/ios7-ibeacon-api/)
* [iBeacon Tips: 正しいビーコン監視方法](http://brightechno.com/blog/archives/220)
* [iBeaconの解説](http://reinforce-lab.github.io/blog/2013/10/21/ibeacon/)
* [What is the iBeacon Bluetooth Profile](http://stackoverflow.com/questions/18906988/what-is-the-ibeacon-bluetooth-profile) iBeaconが利用するadvertising packetについて記載あり