【CoreBluetooth】Objective-cでのBluetooth通信について



#概要
Objective-cでのBluetooth接続についてまとめました。
CoreBluetoothを使用しIOS端末とBluetooth機器を接続、バッテリー等の機器情報の取得を行います。

以下の流れで情報を取得します。

1.Blutooth機器の検索→Bluetooth機器の情報取得
2.Blutooth機器に接続
3.通信している情報の取得
4.通信内容から機器情報等の取得

環境
Xcide10.3 
Objective-c
端末：IOS12.4
Bluetooth機器：TrackR pixel

#初期設定
CoreBluetoothをインポートさせ、centralManagerの初期化を行います。

```objective_c

@import CoreBluetooth;

@interface ViewController () <CBCentralManagerDelegate, CBPeripheralDelegate, CBPeripheralManagerDelegate>

@property (nonatomic, strong) CBCentralManager *centralManager;
@property (nonatomic, strong) CBPeripheral *get_peripheral;
@property (nonatomic, strong) NSArray *get_services;
@property (nonatomic, strong) CBPeripheralManager *peripheralManager;

@end

- (void)viewDidLoad {
   [super viewDidLoad];

   //CBCentralManagerの初期化
   self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}

//セントラルマネージャ_状態変化
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
   NSLog(@"%ld", (long)central.state);
}
```


#通信するBluetooth機器の情報取得
接続する際に、Bluetooth機器の情報が必要になります。
使用可能なBluetoothを検索してBluetooth機器が存在するか確認します。

```objective_c
//スキャン_開始
[self.centralManager scanForPeripheralsWithServices:nil options:nil];

//スキャン_停止
[self.centralManager stopScan];
```

呼び出されるメソッドの、peripheralから機器の情報を取得できます。
peripheral.identifierのUUIDを使用し、通信するBluetooth機器の情報のみ取得します。

```objective_c
//スキャン結果_取得
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    
   //通信するBlutooth機器のUUID
   NSUUID *UUID = [[NSUUID alloc] initWithUUIDString:@"Bluetooth機器のUUID"];

   if ([peripheral.identifier isEqual: UUID]) {
      //一致時のみ取得
      NSLog(@"%@", peripheral);
      self.get_peripheral = peripheral;
   }

}
```

```:出力結果
<CBPeripheral: 0x280f48000, identifier = Bluetooth機器のUUID, name = tkr, state = disconnected>
```

#ペリフェラルへ接続

Bluetooth機器の情報を使用し、Bluetooth機器に接続を行います。


```objective_c
//ペリフェラルに接続開始
[self.centralManager connectPeripheral:self.peripheral options:nil];
```

呼び出されるメソッドは、成功時と失敗時で２つあります。

```objective_c
//ペリフェラルに接続成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
   NSLog(@"接続に成功しました");
}

//ペリフェラルに接続失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
   NSLog(@"接続に失敗しました");
}
```




#サービスの取得
Bluetooth機器に接続が完了したら、Bluetoothで通信しているサービスを取得します。

```objective_c
//サービス_探索開始
self.get_peripheral.delegate = self;
[self.get_peripheral discoverServices:nil];
```


呼び出されるメソッドの、peripheral.servicesから通信しているサービスを取得できます。


```objective_c
//サービス_探索結果
- (void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
- 
   if (error) {
      NSLog(@"error");
      return;
   }
   self.get_services = peripheral.services;
  
}
```

#キャラクタリスティックの取得
取得したサービスからキャラクタリスティックを取得します。
サービスは複数あるため、各サービスごとにキャラクタリスティックを取得させる必要があります。
キャラクタリスティックの情報から端末等の情報を確認することができます。

```objective_c
//キャラクタリスティック_探索開始
for (int i=0; i<self.get_services.count; i++) {
        
   NSLog(@"%@",  self.get_services[i]);
   [self.get_peripheral discoverCharacteristics:nil forService:self.get_services[i]];

}
```


```objective_c
//キャラクタリスティック_探索結果
- (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    
   if (error) {
      NSLog(@"error");
      return;
   }
   NSLog(@"%@",  service);
   
}
```

```:出力結果
//Bluetooth機器情報
<CBService: 0x282b11ec0, isPrimary = YES, UUID = Device Information>

<CBCharacteristic: 0x281a480c0, UUID = Manufacturer Name String, properties = 0x2, value = < xxxx >, notifying = NO>

<CBCharacteristic: 0x281a48060, UUID = Model Number String, properties = 0x2, value = < xxxx >, notifying = NO>

<CBCharacteristic: 0x281a48120, UUID = Firmware Revision String, properties = 0x2, value = < xxxx >, notifying = NO>

<CBCharacteristic: 0x281a48180, UUID = Software Revision String, properties = 0x2, value = < xxxx >, notifying = NO>

// バッテリー情報
<CBService: 0x280c8c540, isPrimary = YES, UUID = Battery>

<CBCharacteristic: 0x283dd4120, UUID = Battery Level, properties = 0x12, value = <64>, notifying = NO>

・・・・
```

#参考
[Core Bluetooth with Swift （ObjCのおまけ付き）](https://qiita.com/shu223/items/78614325ce25bf7f4379)
[CoreBluetooth で出来る事](https://qiita.com/rnamiki/items/ea912393c4fb58e7a9b9)