株式会社インデペンデンスシステムズ横浜

システム開発エンジニアの西田五郎が運営しております。Raspberry Pi や Arduino その他新規開発案件のご依頼をお待ちしております。

Bluetooth Low Energy iOS

Core BluetoothでBLE通信(その2)ペリフェラル

投稿日:2015年2月16日 更新日:

Core BluetoothでBLE通信の2回目です。前回はBLE通信の仕様について簡単にですが確認しました。今回はそれを踏まえて実際にCore BluetoothでHello World的なペリフェラルを実装してみます。ここではペリフェラルをiPhone4S上で起動してセントラルはiPad miniで前回のBLExplrを使います。

Core Bluetoothの仕様詳細等は以下のマニュアル等を参照して下さい。
Core Bluetooth プログラミングガイド

今回のペリフェラルのアプリの画面は以下です。ペリフェラルの内容としてはサービスがひとつあり、そのサービスにキャラクタリスティックがひとつあります。そのキャラクタリスティックでNotifyを実行します。このNotityで単純な通信を確認するための処理のみ実行出来ます。細かい実装は行っていないテスト的なプログラムということでご了承下さい。

IMG_0317

ソース一式は以下からダウンロード出来ます。(※テスト的なプログラムです。一切無保証ということをご了承下さい。)
ソース一式

実際のプログラムを見ながら動作も見ていきます。ViewControllerのヘッダファイルです。

#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>

@interface ViewController : UIViewController
        <CBPeripheralManagerDelegate,UITextFieldDelegate>
{
    CBPeripheralManager *manager;
    
    CBMutableCharacteristic *characteristic;
    CBMutableService *services;
    
    NSString* UUIDService;
    NSString* UUIDCharacteristics;
}

@property (weak, nonatomic) IBOutlet UIButton *btnAdvertising;

@property (weak, nonatomic) IBOutlet UIButton *btnNotify;

@property (weak, nonatomic) IBOutlet UITextField *txtNotify;

@property (weak, nonatomic) IBOutlet UITextField *txtStatus;

- (IBAction)onAdvertising:(id)sender;

- (IBAction)onNotify:(id)sender;

@end

CoreBluetoothに関係するクラスは、CBPeripheralManager、CBMutableCharacteristic、CBMutableServiceです。

初期処理の実装です。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //ペリフェラルを初期化 ここでは、queueは使わない
    //ここでは初期化だけでサービスの追加はステート変更後に行う
    //このmanagerオブジェクトをペリフェラルとして以降使う
    manager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];
    
    //独自のサービスとキャラクタリスティスクを一つずつ定義
    UUIDService = @"C52D11BC-C2EE-422D-955A-D834930CF567";
    UUIDCharacteristics = @"F13167B2-1FAE-4E7D-9200-B2DFA35510F8";
    
    btnNotify.enabled = false;
    btnAdvertising.enabled = false;
    
    txtNotify.delegate = self;
}

コメントの通りですが、ここではペリフェラルの初期化だけ行います。このmanagerオブジェクトを既定のペリフェラルとして利用します。あと、uuidgenで生成したuuidを文字列で設定しておきます。

次にステート変更時のデリゲートでの処理です。

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{

    switch (manager.state) {
        case CBPeripheralManagerStatePoweredOn:
        {
            CBUUID *sUDID = [CBUUID UUIDWithString:UUIDService];
            CBUUID *cUDID = [CBUUID UUIDWithString:UUIDCharacteristics];
       
            services = [[CBMutableService alloc]initWithType:sUDID primary:YES];
            characteristic = [[CBMutableCharacteristic alloc]initWithType:cUDID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
        
            services.characteristics = @[characteristic];
            [peripheral addService:services];
        }
            
        default:
            break;
    }
}

実際にはステート変更時にはいろいろな処理が必要となってくると思いますが、ここではBluetoothが有効の時にサービスとキャラクタリスティスクの追加処理のみを行っています。Bluetoothをオンにしておくと、このデリゲートが呼ばれます。Bluetoothがオフの状態では「Bluetoothがをオンにして下さい」といったメッセージが表示されます。

このサービスの登録が完了すると、以下のサービス登録完了のデリゲートが呼ばれます。

- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{

    txtStatus.text = @"Service追加完了";
    btnAdvertising.enabled = true;
}

これで最初のスクリーンショットの状態になります。

ここでアドバータイズのボタンを有効します。このボタンでアドバータイズを開始するとセントラル(ここではiPad miniのBLExplr)が見つけることが出来ます。以下がアドバータイズ開始の処理とデリゲートです。

- (IBAction)onAdvertising:(id)sender {
    
    NSDictionary *advertisingData =
    @{CBAdvertisementDataLocalNameKey : @"ISYJP",
      CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:UUIDService]]};
    
    [manager startAdvertising:advertisingData];
    
    btnAdvertising.enabled = false;
}

- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error{
    txtStatus.text = @"Advertis開始";
}

以下の画面のようになります。

IMG_0319

BLExplrで接続します。
IMG_0178

一番下のUUIDが今回のサービスです。
IMG_0188

今回のキャラクタリスティスクUUIDがあります。それを選択します。
IMG_0189

Nofityを可能にします。
IMG_0190

ここでペリフェラルのSubscribe時のデリゲートが呼ばれます。以下です。

- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic12{
    
    [manager stopAdvertising];
    
    NSString *stra = @"Init";
    NSData *dataa = [stra dataUsingEncoding:NSUTF8StringEncoding];
    
    bool isOK = [peripheral updateValue:dataa forCharacteristic:characteristic onSubscribedCentrals:nil];
    if(isOK){
        txtStatus.text = @"初回通知完了";
    }
    else{
        txtStatus.text = @"初回通知エラー";
    }
    
    btnNotify.enabled = true;
}

BLExplrに以下のように表示されます。”Init”という文字が表示されました。
IMG_0191

ここでペリフェラルのNotify実行ボタンが有効になるので実行します。
IMG_0320

Valueのところに何か文字を入力して送信することが出来ます。以下がペリフェラルのNotifyの処理です。

- (IBAction)onNotify:(id)sender {
    NSData *dataa = [txtNotify.text dataUsingEncoding:NSUTF8StringEncoding];
    
    bool isOK = [manager updateValue:dataa forCharacteristic:characteristic onSubscribedCentrals:nil];
    if(isOK){
        txtStatus.text = @"通知処理完了";
    }
    else{
        txtStatus.text = @"通知処理エラー";
    }
}

ここではNotifyの通知が届いたかどうかは判定出来ないです。isOKでの判定は送信キューがフルの場合等にNOが返るようなので、その場合は以下が呼ばれるようです。ここでは何もしていないです。

- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral
{
    //送信が再度可能になった場合に呼ばれる
}

BLExplrで以下のように表示されます。
IMG_0192

これでNotifyだけですが、ペリフェラルの通信が出来ました。次回はこのペリフェラルからのNotifyを受け取れるセントラルの方を実装してみます。


AdSense

AdSense

-Bluetooth Low Energy, iOS

執筆者:

関連記事

SHARP製スマホSHL23でBLE通信を試してみた

SHARP製のスマホSHL23でBLE(Bluetooth Low Energy)通信のプログラミングを試してみました。わざわざSHARP製のスマホSHL23と書かないで普通にAndroidのスマホと …

Core BluetoothでBLE通信(その1)BLEの仕様概要

iOSでCore Bluetoothを使ってBLE(Bluetooth Low Energy)の通信をプログラミングしてみます。今回はまずはBLEの仕様概要についてです。ただしですが、BLEの仕様につ …

Core BluetoothでBLE通信(その3)セントラル

Core BluetoothでBLE通信(Bluetooth Low Energy通信)の3回目です。前回はペリフェラルを実装してみました。今回は前回のペリフェラルと通信をするためのセントラルを実装し …