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