Nakajijapan

生きるのに必死です。

IRKit + iBeacon

先日IRKitとEstimote Beaconsを購入しまして、せっかくなんでこの二つ合わせてなにかできないかなーと思いまして 自宅で活用できるものを作ってみました。

IRKit

IRKit - iPhone,iPadを使って外出先からエアコン等の家電を操作できる学習リモコン

Estimote Beacons

仕様としては、

  • beaconに近づいたら(家に帰ってきたら)テレビをつける
  • beaconから離れたら(外出したら)テレビを消す

ってことを試してみました。

下準備

まずはそれぞれのライブラリを追加してpod installする。

SDKのインストール。

1
2
3
4
target "irkit_ibeacon" do
  pod 'IRKit', :git => 'https://github.com/irkit/ios-sdk.git'
  pod 'EstimoteSDK'
end

frameworkの追加。

1
2
CoreLocation.framework
CoreBluetooth.framework

IRKit

ここでは、IRKit SDKを利用してシグナルを登録してテーブルのセルにボタンを追加する処理を行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- (void)viewDidLoad
{

(snip..)

    // find IRKit
    if ([IRKit sharedInstance].countOfReadyPeripherals == 0) {
        IRNewPeripheralViewController *vc = [[IRNewPeripheralViewController alloc] init];
        vc.delegate = self;
        [self presentViewController:vc
                           animated:YES
                         completion:^{
                             NSLog(@"presented");
                         }];


    }

    IRSignals *tmpSignals = [[IRSignals alloc] init];

    // and add a signal to the collection
    [tmpSignals loadFromStandardUserDefaultsKey:@"xxxxxxxxxxxxxxxxxxxxxx"];

    for (int i = 0; i < [[tmpSignals signals] count]; i++) {
        NSLog(@"%@", [[tmpSignals signals] objectAtIndex:i]);
    }

}

IRNewPeripheralViewControllerDelegateで信号の登録が終了したときに呼ばれるメソッドの実装を行います。 ここでは、ハード側で学習が完了した信号をNSUserDefault側でも保存させるようにしておきます。(実際にはそのシグナルを識別できるようにするためのハッシュ値のようなもの)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#pragma mark - IRNewPeripheralViewControllerDelegate

- (void)newSignalViewController:(IRNewSignalViewController *)viewController
            didFinishWithSignal:(IRSignal *)signal {
    NSLog( @"signal: %@", signal );

    if (signal) {
        [_datasource addSignalsObject:signal];
        [_datasource.signals saveToStandardUserDefaultsWithKey:@"SIGNALS"];
        [self.tableView reloadData];
    }
    [self dismissViewControllerAnimated:YES
                             completion:^{
                                 NSLog(@"dismissed");
                             }];
}

#pragma mark - IRNewSignalViewControllerDelegate

- (void)newPeripheralViewController:(IRNewPeripheralViewController *)viewController
            didFinishWithPeripheral:(IRPeripheral *)peripheral {
    NSLog( @"peripheral: %@", peripheral );

    [self dismissViewControllerAnimated:YES
                             completion:^{
                                 NSLog(@"dismissed");
                             }];
}

登録した信号を実行するときは以下のような実装で呼び出せるようになります。

1
2
3
4
5
6
7
8
9
10
11
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"indexPath: %@", indexPath);
    [tableView deselectRowAtIndexPath:indexPath
                             animated:YES];

    IRSignal *signal = [_datasource objectAtIndex:indexPath.row];

    [signal sendWithCompletion:^(NSError *error) {
        NSLog(@"sent error: %@", error);
    }];
}

iBeacon

ここでは、ビーコンで領域を観測し出たか入ったかを監視して、IRKitに信号を送る処理を行います。

まず、ESTBeaconManagerをインスタンス化してstartMonitoringForRegion: で監視を開始します。 startRangingBeaconsInRegion:で距離の観測を開始します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)viewDidLoad
{

(snip...)

    self.beaconManager = [[ESTBeaconManager alloc] init];
    self.beaconManager.delegate = self;

    ESTBeaconRegion *region = [[ESTBeaconRegion alloc] initWithProximityUUID:MY_ESTIMOTE_PROXIMITY_UUID
                                                                       major:36605
                                                                       minor:43679
                                                                  identifier:@"EstimoteSampleRegion"];


    [self.beaconManager startMonitoringForRegion:region];
    [self.beaconManager startRangingBeaconsInRegion:region];

}

位置情報を利用した領域観測の方法と同様に、ビーコン領域の出入りのイベントをハンドリングします。その処理内でIRKitへ信号の送信する処理を実行します。 メソッドとしては、locationManager:didEnterRegion:と、locationManager:didExitRegion:をハンドリングして処理を行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-(void)beaconManager:(ESTBeaconManager *)manager didEnterRegion:(ESTBeaconRegion *)region
{

    IRSignals *signals = [[IRSignals alloc] init];
    [signals loadFromStandardUserDefaultsKey:@"SIGNALS"];
    IRSignal *signal = [signals objectAtIndex:0];

    if (signal) {
        [signal sendWithCompletion:^(NSError *error) {
            [self say:[NSString  stringWithFormat:@"%@を実行しました。", signal.name]];
        }];
    }

    NSLog(@"beaconの近くに入りました。");
}

-(void)beaconManager:(ESTBeaconManager *)manager didExitRegion:(ESTBeaconRegion *)region
{
    IRSignals *signals = [[IRSignals alloc] init];
    [signals loadFromStandardUserDefaultsKey:@"SIGNALS"];
    IRSignal *signal = [signals objectAtIndex:1];

    if (signal) {
        [signal sendWithCompletion:^(NSError *error) {
            [self say:[NSString  stringWithFormat:@"%@を実行しました。", signal.name]];
        }];
    }

    NSLog(@"beaconから離れました。");
}

まとめ

これで上記の仕様が実現できます。 今回の実装はまだIRKitにしてもEstimote Beaconsにしてもさわりの部分しか実装していないのですが、他の仕様も合わせたりするとまだまだ面白いことでできるかと思います。 最近、生活が変わるような技術がどんどんでてきていて楽しいですね♪(ただハードを購入しなきゃいけないのでお金がかかってしまいますがw) まだまだこれからも、生活を変えるような技術がでてくると思うのでそれキャッチアップして試せるものは試していこうと思います!!

Enjoy Technology!!!

Ref