iosのcentralの対応について書きたいと思います。
androidのperipheral・central
Blutoothの必要な基礎知識はこちら
CoreBluetooth FrameWorkを追加する
iosでBluetoothLowEnergyを使用する場合CoreBluetoothFrameWorkが必要になりますので、
そちらLibraryとして追加してください
必要なクラスをプロパティへと追加する
1 2 3 4 5 6 7 8 9 |
@import CoreBluetooth; #define CHARACTERISTIC_UUID @"c54e5502-0c99-11e8-ba89-0ed5f89f718b" #define SERVICE_UUID @"bdb57744-0c99-11e8-ba89-0ed5f89f718b" @interface CentralController() @property (strong, nonatomic) CBCentralManager *ccmCentralManager; @property (strong, nonatomic) CBPeripheral *peripheral; @property (strong, nonatomic) CBCharacteristic *chrDiscoveredChacteristic; |
CoreBluetoothをインポートし、
必要なクラスをプロパティとして持ちます。
CBCentralMangerの初期化とdelegateの登録
1 2 3 4 5 |
- (void) initCentralController { // CentralManagerの初期化. _ccmCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; } |
peripheral端末のscan
scanを開始するためにscanForPeripheralsWithServices関数を呼んでいます。
第1引数に検索対象となるserviceのuuidを渡しますが、nilにすると全てのサービスが対象になります。
第2引数はoptionとなり今回は重複したキーを許可を設定する
CBCentralManagerScanOptionAllowDuplicatesKeyに@NOを入れています。
今回のサンプルでは、トリガーとなっているボタンを押すとscanNewDevice関数を呼び、
scanを開始する流れになっています。
1 2 3 4 5 |
- (void) scanNewDevice { [_ccmCentralManager scanForPeripheralsWithServices:[NSArray arrayWithObjects:[CBUUID UUIDWithString:SERVICE_UUID], nil] options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @NO}]; } |
対象のPeripehral端末が見つかると、delegate methodである
centralManager:didDiscoverPeripheral:advertisementData:RSSI:が呼ばれます。
peripheralに接続を試みる
対象のperipehralが見つかったら接続試みます。
接続するためにはCBCentralMangerクラスのconnectPeripheralを呼びます。
今回第2引数のoptionにはnilを設定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** peripheralが見つかったら実行される */ - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { NSLog(@"call didDiscoverPeriperal"); // peripheralを発見したらscanを止める [_ccmCentralManager stopScan]; // 未接続のPeripheralのみ追加. if (self.peripheral != peripheral) { self.peripheral = peripheral; // Peripheralに接続する. [_ccmCentralManager connectPeripheral:peripheral options:nil]; } } |
接続に成功すると、delegate methodであるcentralManager:didConnectPeripheral:
関数が呼ばれます。
delegateを登録し、サービスを探索する
didConnectPeripheral関数で、delegateを登録し、サービスを探索します。
サービスを探索するには、discoverServices関数を呼び出します。
引数にはserviceのuuidを指定しますが、nilにすると全てのサービスを検索します。
1 2 3 4 5 6 7 8 9 |
/** Peripheralに接続されたら実行される */ - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { peripheral.delegate = self; // Serviceを探索する. [peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]]; } |
サービスを発見すると、delegate関数であるperipheral:didDiscoverServices:
が呼ばれます。
サービスの検出、Characteristicの探索
サービスが検出されたら、今度はCharacteristicを検索します。
Characteristicを探索するために、discovercharacteristics関数を呼びます。
第1引数にnilを入れると、全てのcharacteristicを検索します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// 接続したPeripheralでServiceが見つかったら実行. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { if (error) { // Errorならリターン. NSLog(@"Service Error: %@", [error localizedDescription]); return; } // Characteristicの探索. for (CBService *service in peripheral.services) { [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:CHARACTERISTIC_UUID]] forService:service]; } } |
Characteristicを発見すると、
delegate関数 peripheral:didDiscoverCharacteristicsForService:error:
が呼ばれます。
Peripehralからの更新通知を受け取るようにする
対象のcharacteristicが見つかったらperipheral側がcharacteristicの値を更新したら、
central側に通知が届くように設定します。
その通知をするのがsetNotifyValue関数です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/** 見つかったServiceからCharacteristicが見つかったら実行. */ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { if (error) { // Errorならリターン. NSLog(@"Characteristics Error: %@", [error localizedDescription]); return; } for (CBCharacteristic *characteristic in service.characteristics) { // 見つかったCharacteristicからUUIDの合致しているものを検出. if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARACTERISTIC_UUID]]) { _chrDiscoveredChacteristic = characteristic; // Peripheralで値が更新されたら、通知が届くようにする. [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } } } |
Peripheral側がcharacteristicを変えて通知を出すと、
delegate関数didUpdateValueForCharacteristicが呼ばれますので、この関数内で
Peripheralの値を受け取ることができます。
ここでは、NSString型のstrGotValueにPeripheral側でセットされたCharacteristicの値を代入しています。
1 2 3 4 5 6 7 8 9 10 11 |
/** Peripheralからデータ更新の通知が届いたら実行される */ - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { NSLog(@"UpdateValue Error: %@", [error localizedDescription]); return; } _strGotValue = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding]; } |
Peripehralにデータを送信する
続いて、Periperal側にデータを送信する箇所をみていきたいと思います。
送りたいデータが文字列型の場合NSMutableDataに変換し,
writeValue:forCharacteristic:type:関数を呼び出します。
1 2 3 4 5 6 |
- (void)sendValue:(NSString*)sendValue { // Peripheralへの書き込みリクエスト. _mdtSendValue = (NSMutableData *)[sendValue dataUsingEncoding:NSUTF8StringEncoding]; [self.peripheral writeValue:_mdtSendValue forCharacteristic:_chrDiscoveredChacteristic type:CBCharacteristicWriteWithResponse]; } |
書き込みに成功し、Peripheral側に送られたかどうかの結果は、
delegate関数であるdidWriteValueForCharacteristicで受け取ることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 書き込みリクエストを送信して、返答があれば実行. - (void)peripheral:(CBPeripheral*)peripheral didWriteValueForCharacteristic:(CBCharacteristic*)characteristic error:(NSError*)error { if (error) { NSLog(@"WriteValue Error: %@", [error localizedDescription]); _isValueWrote = NO; } else { _isValueWrote = YES; } } |
また、didWriteValueForCharacteristicが呼ばれるためには、Android端末のPeripheral側では、
onCharacteristicWriteRequest callback関数内で、BluetoothGattServerクラスのsendResponse関数を呼ぶ必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@Override public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value); if (responseNeeded) { // BluetoothGattServer mBtGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, value); } } |
Peripheralから切断されたことを検知する
Peripheralから切断されるとdelegate関数didDisconnectPeripheral関数が呼ばれます。
サンプルでは、再度Peripheral用の検索関数を読んでいます。
1 2 3 4 5 6 7 8 |
// Peripheralとの接続が切れたら実行. - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { // 接続したPeripheralを破棄してScanの再実行. self.peripheral = nil; [self scanNewDevice]; } @end |
以上で、Peripheralの検索・接続と値の更新の受け取りと値の送信が完了しました。
UIは省略していますので、全体のコードはgithubを参照してください。
ios・android
参考サイト
https://developer.apple.com/jp/documentation/CoreBluetoothPG.pdf