気楽なソフト工房

プログラミングについていろいろな記事を書いています。



mykonos2008

Author:mykonos2008
システムエンジニアとして働いている30代の会社員です。
仕事や趣味でプログラムを書いている方の役に立つ記事を書いていきたいと思っています。
ご意見、ご感想はこちらまで
If you are an english speaker,Please visit my english blog.

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
前回の記事でCore BlueToothを使用して、iOSデバイスをBLE機器として動作させるサンプルコードを紹介しました。
そこで今回は、そのサンプル機器にiPhoneから接続するセントラル(Central)を作成するサンプルコードを紹介します。



前回の記事では接続されるとHello!と返すだけの単純なペリファレル(BLE機器)を作成しました。
ペリファレルに1つのサービスを追加し、さらにそのサービスにキャラクタリスティックを1つ持たせる形になっていました。

ペリファレルを作成する際は、CBPeripheralManagerが中心的な役割を担っていましたが、セントラルを作成する場合は
CBCentralManagerがその役割を担います。
処理を行うViewControllerにはCBCentralManagerDelegateとCBPeripheralDelegateの2つのプロトコルを採用します。

#import "ViewController.h"

#define SERVICE_UUID @"9EA08FC0-FFCF-46D1-ABE3-A1A726699681"
#define CHARACTERISTIC_UUID @"1E222259-9612-4139-B3CB-19BA1DFB9C0E"

@interface ViewController ()

@end

@implementation ViewController{
    CBCentralManager *_centralManager;
    CBPeripheral *_peripheral;
    CBService *_service;
    IBOutlet UIButton *_startConnect;
    IBOutlet UILabel *_resultLabel;
}

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if(self) {
        _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    }
    return self;
}

//CBCentralManagerのステータスが更新されるとコールされる
-(void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    NSLog(@"State Updated");
    if(central.state == CBCentralManagerStatePoweredOn) {
        NSLog(@"ready");
        //接続開始ボタンを有効にする
        _startConnect.enabled = YES;
    }
}


CBPeripheralManagerと同じく、CBCentralManagerの場合も、Bluetoothが使用可能な状態になったことを
確認してから、後続の処理を行う必要があります。CBCentralManagerのインスタンスを生成すると、
centralManagerDidUpdateState:がコールされるので、そこで状態を確認するようにしています。

//接続開始ボタンのハンドラ
-(IBAction)startConnectTouched:(id)sender
{
    CBUUID *serviceUUID = [CBUUID UUIDWithString:SERVICE_UUID];
    [_centralManager scanForPeripheralsWithServices:@[serviceUUID] options:nil];
}

接続開始ボタンがおされると、scanForPeripheralsWithServices:options:で、アドバタイズをしているペリファレルを
探し始めます。第一引数に特定のサービスのUUIDを指定することで、そのUUIDに該当するサービスを提供するペリファレルのみを
取得出来ます。

//ペリファレルを発見するとコールされる
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    NSLog(@"Peripheral discoverd :%@",advertisementData);
    //スキャンを停止し、ペリファレルに接続する
    _peripheral = peripheral;
    [_centralManager stopScan];
    [_centralManager connectPeripheral:peripheral options:nil];
}

ペリファレルが発見されると、centralManager:didDiscoverPeripheral:advertisementData:RSSI:がコールされます。
目的のペリファレルが発見されたので、これ以上のスキャンは必要無いので、まずスキャンを停止します。
そして、発見されたペリファレルにconnectPeripheral:options:で接続を試みます。

//ペリファレルに接続すると、コールされる
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"Connected to peripherel");
    //サービスを検索する    
    _peripheral.delegate = self;
    [_peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];
}

ペリファレルへ接続すると、centralManager:didConnectPeripheral:がコールされます。
CBPeripheralのdelegateに自身を設定し、次にCBPeripheralのdiscoverServices:を使用して
ペリファレルが持つ、サービスをもう一度検索します。
scanする際にサービスを指定してscanしているので、冗長な処理に思えますが、CBService
のインスタンスを取得するためには、この作業が必要になります。

//ペリファレルのサービスを発見するとコールされる
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    NSLog(@"Services discovered");
    for (CBService *service in peripheral.services) {
        NSLog(@"Service :%@",service);
        [_peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:CHARACTERISTIC_UUID]]
                                  forService:service];
    }
}

//サービスのキャラクタリスティックを発見するとコールされる
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    for (CBCharacteristic *characteristic in service.characteristics) {
        NSLog(@"Discovered characteristic:%@",characteristic.UUID);
        [_peripheral readValueForCharacteristic:characteristic];
    }
}

サービスが発見されるとperipheral:didDiscoverServices:がコールされますので、今度は
CBPeripheralのdiscoverCharacteristics:forService:でキャラクタリスティックの検索を開始します。

キャラクタリスティックが発見されると、peripheral:didDiscoverCharacteristicsForService:error:が
コールされますので、そこでキャラクタリスティックから値の取得を行います。

//キャラクタリスティックの値を取得するとコールされる
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    NSData *data = characteristic.value;
    NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"data = %@",result);
    _resultLabel.text = result;
    
    [_centralManager cancelPeripheralConnection:_peripheral];
}

キャラクタリスティックの値が取得されると、peripheral:didUpdateValueForCharacteristic:error:がコールされますので、
そこで画面のラベルに結果の値を設定しています。


コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://csfun.blog49.fc2.com/tb.php/122-1770eab4

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。