Core Bluetooth の Swift コード + Objective-C のおまけ付きスニペット集です。
Core Bluetooth の各種メソッドでは実行キューを指定できたりオプションを指定できたりとか色々ありますが、シンプルにするためここでは省けるものはできるだけ省くようにしています。
###更新メモ
- 2015.10.12 Swift 2 対応
##(本題に入る前に・・・)
このスニペット集は、下記書籍の執筆にあたりまとめたものです。セントラルとペリフェラルの実装の基礎的なところは、ObjC・Swift両方のサンプルを載せています。
ソシム
売り上げランキング: 1,106
本記事はコードだけですが、書籍内ではかなり丁寧に解説してあります!
iOS x BLE というニッチな内容で480ページ! どうぞよろしくお願いします。
-
技術書『iOS×BLE Core Bluetooth プログラミング』の紹介 - Qiita
- 書籍の詳しい紹介
-
BLEと私 - Over&Out その後
- 書籍を書くまでの経緯
##インポート
何はともあれまずは import から。
@import CoreBluetooth;
import CoreBluetooth
#セントラルマネージャ編
##スキャン、接続
セントラルマネージャを初期化して、スキャン、発見したペリフェラルに接続するところまで。
###プロトコル準拠の宣言とプロパティ定義
@interface SomeClass () <CBCentralManagerDelegate>
@property (nonatomic, strong) CBCentralManager *centralManager;
@property (nonatomic, strong) CBPeripheral *peripheral;
@end
class SomeClass: SomeSuperclass, CBCentralManagerDelegate {
var centralManager: CBCentralManager!
var peripheral: CBPeripheral!
###CBCentralManagerを初期化する
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
centralManager = CBCentralManager(delegate: self, queue: nil)
###セントラルマネージャの状態変化を取得する
※このデリゲートメソッドは @required
なので必須。
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
NSLog(@"state:%ld", (long)central.state);
}
func centralManagerDidUpdateState(central: CBCentralManager) {
print("state: \(central.state)")
}
###スキャンを開始する
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
centralManager.scanForPeripheralsWithServices(nil, options: nil)
###スキャン結果を受け取る
- (void) centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData
RSSI:(NSNumber *)RSSI
{
NSLog(@"peripheral:%@", peripheral);
}
func centralManager(central: CBCentralManager,
didDiscoverPeripheral peripheral: CBPeripheral,
advertisementData: [String : AnyObject],
RSSI: NSNumber!)
{
print("peripheral: \(peripheral)")
}
###スキャンを停止する
[self.centralManager stopScan];
centralManager.stopScan()
###ペリフェラルへの接続を開始する
[self.centralManager connectPeripheral:peripheral options:nil];
centralManager.connectPeripheral(peripheral, options: nil)
###接続結果を取得する
// ペリフェラルへの接続が成功すると呼ばれる
- (void) centralManager:(CBCentralManager *)central
didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"connected!");
}
// ペリフェラルへの接続が失敗すると呼ばれる
- (void) centralManager:(CBCentralManager *)central
didFailToConnectPeripheral:(CBPeripheral *)peripheral
error:(NSError *)error
{
NSLog(@"failed...");
}
// ペリフェラルへの接続が成功すると呼ばれる
func centralManager(central: CBCentralManager,
didConnectPeripheral peripheral: CBPeripheral)
{
print("connected!")
}
// ペリフェラルへの接続が失敗すると呼ばれる
func centralManager(central: CBCentralManager,
didFailToConnectPeripheral peripheral: CBPeripheral,
error: NSError?)
{
print("failed...")
}
##サービス・キャラクタリスティック探索
接続したペリフェラルのサービス・キャラクタリスティックを探索する
###CBPeripheralDelegate プロトコルへの準拠を宣言する
@interface SomeClass () <CBCentralManagerDelegate, CBPeripheralDelegate>
class SomeClass: SomeSuperclass, CBCentralManagerDelegate, CBPeripheralDelegate {
###サービス探索を開始する
peripheral.delegate = self;
[peripheral discoverServices:nil];
peripheral.delegate = self
peripheral.discoverServices(nil)
###サービス探索結果を受け取る
- (void) peripheral:(CBPeripheral *)peripheral
didDiscoverServices:(NSError *)error
{
if (error) {
NSLog(@"error: %@", error);
return;
}
NSArray *services = peripheral.services;
NSLog(@"Found %lu services! :%@", (unsigned long)services.count, services);
}
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
if let error = error {
print("error: \(error)")
return
}
let services = peripheral.services
print("Found \(services.count) services! :\(services)")
}
###キャラクタリスティック探索を開始する
[peripheral discoverCharacteristics:nil forService:service];
peripheral.discoverCharacteristics(nil, forService: service)
###キャラクタリスティック探索結果を取得する
- (void) peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error
{
if (error) {
NSLog(@"error: %@", error);
return;
}
NSArray *characteristics = service.characteristics;
NSLog(@"Found %lu characteristics! : %@", (unsigned long)characteristics.count, characteristics);
}
func peripheral(peripheral: CBPeripheral,
didDiscoverCharacteristicsForService service: CBService,
error: NSError?)
{
if let error = error {
print("error: \(error)")
return
}
let characteristics = service.characteristics
print("Found \(characteristics.count) characteristics! : \(characteristics)")
}
##Read
###Readを開始する
[peripheral readValueForCharacteristic:characteristic];
peripheral.readValueForCharacteristic(characteristic)
###Read結果を取得する
- (void) peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error) {
NSLog(@"Failed... error: %@", error);
return;
}
NSLog(@"Succeeded! service uuid:%@, characteristice uuid:%@, value%@",
characteristic.service.UUID, characteristic.UUID, characteristic.value);
}
func peripheral(peripheral: CBPeripheral,
didUpdateValueForCharacteristic characteristic: CBCharacteristic,
error: NSError?)
{
if let error = error {
print("Failed... error: \(error)")
return
}
print("Succeeded! service uuid: \(characteristic.service.UUID), characteristic uuid: \(characteristic.UUID), value: \(characteristic.value)")
}
##Write
###データ書き込みを開始する
[peripheral writeValue:data
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
peripheral.writeValue(data, forCharacteristic: characteristic, type: CBCharacteristicWriteType.WithResponse)
####NSData オブジェクトの生成例その1:文字列から
NSData *data = [@"hello" dataUsingEncoding:NSUTF8StringEncoding];
let data = "hello".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:true)
####NSData オブジェクトの生成例その2:1バイトのunsignedな整数値
unsigned char value = 0x01;
NSData *data = [[NSData alloc] initWithBytes:&value length:1];
var value: CUnsignedChar = 0x01
let data = NSData(bytes: &value, length: 1)
###データ書き込み結果を取得する
- (void) peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error) {
NSLog(@"Write失敗...error:%@", error);
return;
}
NSLog(@"Write成功!");
}
func peripheral(peripheral: CBPeripheral,
didWriteValueForCharacteristic characteristic: CBCharacteristic,
error: NSError?)
{
if let error = error {
print("Write失敗...error: \(error)")
return
}
print("Write成功!")
}
##Notify
###データ更新通知の受け取りを開始する
[peripheral setNotifyValue:YES
forCharacteristic:characteristic];
peripheral.setNotifyValue(true, forCharacteristic: characteristic)
###データ更新通知の受け取りを停止する
[peripheral setNotifyValue:NO
forCharacteristic:characteristic];
peripheral.setNotifyValue(false, forCharacteristic: characteristic)
###データ更新通知受け取り開始/停止結果を取得する
- (void) peripheral:(CBPeripheral *)peripheral
didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error) {
NSLog(@"Notify状態更新失敗...error:%@", error);
}
else {
NSLog(@"Notify状態更新成功! isNotifying:%d", characteristic.isNotifying);
}
}
func peripheral(peripheral: CBPeripheral,
didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic,
error: NSError?)
{
if let error = error {
print("Notify状態更新失敗...error: \(error)")
} else {
print("Notify状態更新成功! isNotifying: \(characteristic.isNotifying)")
}
}
###データ更新通知を受け取る
- (void) peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error) {
NSLog(@"データ更新通知エラー:%@", error);
return;
}
NSLog(@"データ更新! characteristic UUID:%@, value:%@",
characteristic.UUID, characteristic.value);
}
func peripheral(peripheral: CBPeripheral,
didUpdateValueForCharacteristic characteristic: CBCharacteristic,
error: NSError?)
{
if let error = error {
print("データ更新通知エラー: \(error)")
return
}
print("データ更新! characteristic UUID: \(characteristic.UUID), value: \(characteristic.value)")
}
#ペリフェラル編
##アドバタイズ
###プロトコル準拠の宣言とプロパティ定義
@interface SomeClass () <CBPeripheralManagerDelegate>
@property (nonatomic, strong) CBPeripheralManager *peripheralManager;
@end
class SomeClass: SomeSuperclass, CBPeripheralManagerDelegate {
var peripheralManager: CBPeripheralManager!
###CBPeripheralManager を初期化する
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self
queue:nil
options:nil];
peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
###ペリフェラルマネージャの状態変化を取得する
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
NSLog(@"state:%ld", (long)peripheral.state);
}
func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager) {
print("state: \(peripheral.state)")
}
###アドバタイズを開始する
NSDictionary *advertisementData = @{CBAdvertisementDataLocalNameKey: @"Test Device"};
[self.peripheralManager startAdvertising:advertisementData];
let advertisementData = [CBAdvertisementDataLocalNameKey: "Test Device"]
peripheralManager.startAdvertising(advertisementData)
###アドバタイズ開始処理の結果を取得する
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
error:(NSError *)error
{
if (error) {
NSLog(@"Failed... error:%@", error);
return;
}
NSLog(@"Succeeded!");
}
func peripheralManagerDidStartAdvertising(peripheral: CBPeripheralManager, error: NSError?) {
if let error = error {
print("Failed... error: \(error)")
return
}
print("Succeeded!")
}
###アドバタイズを停止する
[self.peripheralManager stopAdvertising];
peripheralManager.stopAdvertising()
##サービス追加
###サービスを作成する
CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
CBMutableService *service = [[CBMutableService alloc] initWithType:serviceUUID
primary:YES];
let serviceUUID = CBUUID(string: kServiceUUID)
let service = CBMutableService(type: serviceUUID, primary: true)
###キャラクタリスティックを作成する
CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
CBCharacteristicProperties properties = (
CBCharacteristicPropertyNotify |
CBCharacteristicPropertyRead |
CBCharacteristicPropertyWrite
);
CBAttributePermissions permissions = (CBAttributePermissionsReadable | CBAttributePermissionsWriteable);
CBMutableCharacteristic *characteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID
properties:properties
value:nil
permissions:permissions];
let characteristicUUID = CBUUID(string: kCharacteristicUUID)
let properties: CBCharacteristicProperties = [.Notify, .Read, .Write]
let permissions: CBAttributePermissions = [.Readable, .Writeable]
let characteristic = CBMutableCharacteristic(type: characteristicUUID, properties: properties,
value: nil, permissions: permissions)
###サービスにキャラクタリスティックを追加
service.characteristics = @[characteristic];
service.characteristics = [characteristic]
###ペリフェラルにサービスを追加
[self.peripheralManager addService:service];
peripheralManager.addService(service)
###サービス追加結果を取得する
- (void)peripheralManager:(CBPeripheralManager *)peripheral
didAddService:(CBService *)service
error:(NSError *)error
{
if (error) {
NSLog(@"サービス追加失敗! error:%@", error);
return;
}
NSLog(@"サービス追加成功! service:%@", service);
}
func peripheralManager(peripheral: CBPeripheralManager, didAddService service: CBService, error: NSError?) {
if let error = error {
print("サービス追加失敗! error: \(error)")
return
}
print("サービス追加成功!")
}
##Readリクエストに応答
- (void)peripheralManager:(CBPeripheralManager *)peripheral
didReceiveReadRequest:(CBATTRequest *)request
{
if ([request.characteristic.UUID isEqual:self.characteristic.UUID]) {
// CBMutableCharacteristicのvalueをCBATTRequestのvalueにセット
request.value = self.characteristic.value;
// リクエストに応答
[self.peripheralManager respondToRequest:request
withResult:CBATTErrorSuccess];
}
}
func peripheralManager(peripheral: CBPeripheralManager, didReceiveReadRequest request: CBATTRequest) {
if request.characteristic.UUID.isEqual(characteristic.UUID) {
// CBMutableCharacteristicのvalueをCBATTRequestのvalueにセット
request.value = characteristic.value
// リクエストに応答
peripheralManager.respondToRequest(request, withResult: .Success)
}
}
##Writeリクエストに応答
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests {
for (CBATTRequest *aRequest in requests) {
if ([aRequest.characteristic.UUID isEqual:self.characteristic.UUID]) {
// CBCharacteristicのvalueに、CBATTRequestのvalueをセット
self.characteristic.value = aRequest.value;
}
}
// リクエストに応答
[self.peripheralManager respondToRequest:requests[0]
withResult:CBATTErrorSuccess];
}
func peripheralManager(peripheral: CBPeripheralManager, didReceiveWriteRequests requests: [CBATTRequest]) {
for request in requests {
if request.characteristic.UUID.isEqual(characteristic.UUID) {
// CBCharacteristicのvalueに、CBATTRequestのvalueをセット
characteristic.value = request.value
}
}
// リクエストに応答
peripheralManager.respondToRequest(requests[0], withResult: .Success)
}
##Notification / Indication への応答
###Subscribeリクエストを受け取る
- (void) peripheralManager:(CBPeripheralManager *)peripheral
central:(CBCentral *)central
didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
{
NSLog(@"Subscribeリクエストを受信");
NSLog(@"Subscribe中のセントラル: %@", self.characteristic.subscribedCentrals);
}
func peripheralManager(peripheral: CBPeripheralManager, central: CBCentral, didSubscribeToCharacteristic characteristic: CBCharacteristic)
{
print("Subscribeリクエストを受信")
print("Subscribe中のセントラル: \(characteristic.subscribedCentrals)")
}
###Unsubscribeリクエストを受け取る
- (void) peripheralManager:(CBPeripheralManager *)peripheral
central:(CBCentral *)central
didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
{
NSLog(@"Unsubscribeリクエストを受信");
NSLog(@"Subscribe中のセントラル: %@", self.characteristic.subscribedCentrals);
}
func peripheralManager(peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFromCharacteristic characteristic: CBCharacteristic)
{
print("Notify停止リクエストを受信")
print("Notify中のセントラル: \(characteristic.subscribedCentrals)")
}
###値を更新し、通知する
self.characteristic.value = data;
[self.peripheralManager updateValue:data
forCharacteristic:self.characteristic
onSubscribedCentrals:nil];
characteristic.value = data
peripheralManager.updateValue(data, forCharacteristic: characteristic, onSubscribedCentrals: nil)