質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Bluetooth

Bluetoothとは短距離の間でデータを交換するための無線通信規格である。固定・モバイル両方のデバイスから、短波の電波送信を行うことで、高いセキュリティをもつパーソナルエリアネットワーク(PAN)を構築する。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

4824閲覧

iOS同士のBLE通信、connect方法

saku_panda

総合スコア20

Bluetooth

Bluetoothとは短距離の間でデータを交換するための無線通信規格である。固定・モバイル両方のデバイスから、短波の電波送信を行うことで、高いセキュリティをもつパーソナルエリアネットワーク(PAN)を構築する。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2019/10/29 02:57

編集2019/10/29 04:22

##前提・実現したいこと
iOS同士のセントラル、ペリフェラルの接続(connect)

##発生している問題
おそらくセントラルのスキャンが上手く機能していません。
ログ出しで確認しましたが、
centralManager.scanForPeripherals のメソッドには入っています。
しかしその先のcentralManager(:didDiscover::_)のログが表示されず、ペリフェラルを一つも検知していません。
上記判断の根拠として、ログ出しの他に、
ペリフェラル側は peripheralManagerDidStartAdvertisingを成功させており、
nordic社の nRF Connect でアドバタイズを飛ばしていることも確認できたからです。

##該当のソースコード

Swift5

1// セントラル側 2import Foundation 3import CoreBluetooth 4 5 6// セントラルマネージャーのデリゲートとペリフェラルマネージャーを持つ 7class CentralService: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate { 8 9 private let Log = Logger(category: "Central" )! 10 11 // オリジナルUUID。 12 static let serviceUUID: CBUUID = CBUUID(string: "566F2065-450F-4633-0123-456789ABCDEF") 13 var serviceUUIDList: [CBUUID] = [serviceUUID] 14 static let charReadUUID: CBUUID = CBUUID(string: "A1F86134-652D-1234-0123-456789ABCDEF") 15 static let descriptorUUID: CBUUID = CBUUID(string: "97A4D0DD-1556-4454-0123-456789ABCDEF") 16 static let charNotifyUUID: CBUUID = CBUUID(string: "A1F86134-652D-1234-FEDC-BA9876543210") 17 18 var centralManager: CBCentralManager? // センタラルマネージャーのインスタンス 19 var peripherals: [CBPeripheral] = [] // CBPeripheral型の配列.見つけ出したペリフェラルを一時保存する 20 var cbPeripheral: CBPeripheral? = nil // ペリフェラルマネージャーのインスタンス 21 var readCharacteristic: CBCharacteristic? = nil // メッセージ読み取りのキャラクタリスティック 22 var notifyCharacteristic: CBCharacteristic? = nil // メッセージ読み取り可能通知のキャラクタリスティック 23 var mssLen: Int = 0 24 25 var VC :ViewController? = nil 26 27 // 初期化 28 override init () { 29 super.init() 30 Log.i("init") 31// serviceUUIDList = [CentralService.serviceUUID] 32 centralManager = CBCentralManager(delegate: self, queue: nil) 33 } 34 35 36 func centralManagerDidUpdateState(_ central: CBCentralManager) { 37 switch (central.state) { 38 case .poweredOn: 39 Log.i("BLE Power On") 40 scanStart() 41 42 case .poweredOff: 43 Log.i("BLE Power off") 44 break 45 case .resetting: 46 Log.i("BLE resetting") 47 break 48 case .unauthorized: 49 Log.i("BLE unauthorized") 50 break 51 case .unknown: 52 Log.i("BLE unknown") 53 break 54 case .unsupported: 55 Log.i("BLE unsupported") 56 break 57 @unknown default: 58 Log.i("BLE unknown Default") 59 break 60 } 61 } 62 63// サービスUUID検索 64 func scanStart() { 65 Log.i("scan start") 66 /* 重複フィルタリングの設定、 67 trueなら同じPeripheralからのアドバタイズで毎回イベント発生させる 68 ※このフィルタリングを利用するとバッテリーの消耗を抑えられる */ 69 let options = [CBCentralManagerScanOptionAllowDuplicatesKey : true] 70 71 if centralManager!.isScanning == false { 72 73// 探し出すサービスのUUIDを配列に入れて指定する. 74 let UUIDArray :[CBUUID] = [CentralService.serviceUUID] 75 76 Log.d("UUIDArray = (UUIDArray)") 77 78 /* scanForPeripherals(withServices 79 @param 80 withServices: [CBUUID]? 検索するCBUUIDを集めたの配列。 81 options: nil オプション 82 */ 83 centralManager!.scanForPeripherals(withServices: UUIDArray, options: options) 84 } 85 } 86 87/* ペリフェラル発見時に呼び出される 88 @param 89 central: CBCentralManager セントラルマネージャー 90 peripheral: CBPeripheral 発見したペリフェラル 91 advertisementData: [String : Any] 発見したペリフェラルの広告 92 rssi RSSI: NSNumber 発見したペリフェラルのRSSI 93*/ 94 func centralManager(_ central: CBCentralManager, 95 didDiscover peripheral: CBPeripheral, 96 advertisementData: [String : Any], 97 rssi RSSI: NSNumber) { 98 Log.i("append Peripheral") 99 /* 見つけ出したペリフェラルを配列に入れて保存する */ 100 peripherals.append(peripheral) 101 connect() 102 } 103 104/* 105 検索したペリフェラルとコネクト(ペアリング)する 106*/ 107 func connect() { 108 Log.d("connect") 109 // 見つけ出したペリフェラル全てを調べる 110 for peripheral in peripherals { 111 // ペリフェラルの名前が一致したら 112 if ((peripheral.name != nil) && (peripheral.name == "Test Device")) { 113 cbPeripheral = peripheral 114 centralManager?.stopScan() 115 Log.d("scan stopped") 116 break 117 } 118 } 119 120 // 上のループでペリフェラルを見つけられていたらコネクトする 121 if (cbPeripheral != nil) { 122 centralManager!.connect(cbPeripheral!, options: nil) 123 } 124 } 125 126/***************** 127 以下長いので省略 128******************/

###セントラルのログ
[Central] [INF] init
[Central] [INF] BLE Power On
[Central] [INF] scan start
[Central] [DEB] isScanning == false in
[Central] [DEB] UUIDArray = [566F2065-450F-4633-0123-456789ABCDEF]

###該当ソースコード

Swift5

1// ペリフェラル側 2import Foundation 3import CoreBluetooth 4 5class PeripheralService: NSObject, CBPeripheralManagerDelegate { 6 private let Log = Logger(category: "Peripheral" )! 7 8 var myPeripheralManager: CBPeripheralManager? 9 let advertisementData = [CBAdvertisementDataLocalNameKey: "Test Device"] // アドバタイズに乗せるデータ 10 static let serviceUUID: CBUUID = CBUUID(string: "566F2065-450F-4633-0123-456789ABCDEF") 11 static let characteristicUUID: CBUUID = CBUUID(string: "A1F86134-652D-1234-0123-456789ABCDEF") 12 static let descriptorUUID: CBUUID = CBUUID(string: "97A4D0DD-1556-4454-0123-456789ABCDEF") 13 static let charNotifyUUID: CBUUID = CBUUID(string: "A1F86134-652D-1234-FEDC-BA9876543210") 14 15 // サービスの設定、UUIDと 16 let service = CBMutableService(type: PeripheralService.serviceUUID, primary: true) 17 18 // プロパティの設定、このキャラクタリスティックに対して何ができるかを設定している 19 let readProperties: CBCharacteristicProperties = [.read] 20 21 // 認可の設定、キャラクタリスティックの読み取り、書き込み、暗号化の認可 22 let permissions: CBAttributePermissions = [.readable] 23 24 // キャラクタリスティックが属するサービスと、プロパティおよびその認可を設定 25 var characteristic: CBMutableCharacteristic? = nil 26 27 var requestList: [CBATTRequest] = [] 28 29 // 初期化 30 override init () { 31 super.init() 32 Log.i("init") 33 myPeripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil) 34 } 35 36 37 func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) { 38 switch peripheral.state { 39 case .poweredOn: 40 Log.i("bluetooth Success") 41 characteristic = CBMutableCharacteristic(type: PeripheralService.characteristicUUID, properties: readProperties, value: nil, permissions: permissions) 42 setService_Charactaristic() 43 44 case .unknown: 45 Log.i("bluetooth error") 46 case .resetting: 47 Log.i("bluetooth error") 48 case .unsupported: 49 Log.i("bluetooth error") 50 case .unauthorized: 51 Log.i("bluetooth error") 52 case .poweredOff: 53 Log.i("bluetooth error") 54 @unknown default: 55 Log.i("bluetooth error") 56 } 57 } 58 59 60 func setService_Charactaristic(){ 61 Log.i("set Service and Characteristic") 62 // キャラクタリスティックが属するサービスと、プロパティおよびその認可を設定 63 characteristic = CBMutableCharacteristic(type: PeripheralService.characteristicUUID, properties: readProperties, 64 value: nil, permissions: permissions) 65 66 // 作成したサービスのキャラクタリスティックに、作成したキャラクタリスティックを設定 67 // 設定は配列で複数個所持できる 68 service.characteristics = [characteristic!] 69 70 // ペリフェラルへ上記サービスを設定 71 myPeripheralManager?.add(service) 72 73 advStart() 74 } 75 76 // アドバタイズ開始 77 func advStart(){ 78 Log.i("Start Advetising") 79 myPeripheralManager!.startAdvertising(advertisementData) 80 } 81 82 83/* peripheralManager(_: didAddService:_) 84 addServiceメソッドを呼び出してローカル周辺機器のGATTデータベースにサービスを公開すると、 85 Core Bluetoothがこのメソッドを呼び出します 86 87 peripheralManager:(CBPeripheralManager *)peripheral //サービスを追加したペリフェラル 88 didAddService:(CBService *)service // GATTデータベースへ追加されたサービス 89 error:(NSError *)error; //失敗したエラー理由 失敗しなかった場合nilが入る 90*/ 91 func peripheralManager(peripheral: CBPeripheralManager, didAddService service: CBService, error: NSError?) { 92 93 if error != nil { 94 Log.i("サービス追加失敗! error: (error!)") 95 return 96 } else { 97 myPeripheralManager!.stopAdvertising() 98 Log.i("Stop Advertising") 99 } 100 101 } 102 103 104/* peripheralManagerDidStartAdvertising 105 アドバタイズが正常に開始できたかを確認 106 @param 107 peripheral: CBPeripheralManager アドバタイズを始めるペリフェラル 108 error: NSError? 失敗理由。失敗しなかった(成功した)場合はnil 109*/ 110 func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) { 111 112 if (error != nil) { 113 Log.i("Advertise Failed error: (error!)") 114 return 115 } 116 else { 117 Log.i("Advertise Succeeded!") 118 } 119 120 } 121 122/***************** 123 以下長いので省略 124******************/

ペリフェラルのログ

[Peripheral] [INF] init
[Peripheral] [INF] bluetooth Success
[Peripheral] [INF] set Service and Characteristic
[Peripheral] [INF] Start Advetising
[Peripheral] [INF] Advertise Succeeded!

##その他
動作させている室内には、このペリフェラル以外にもBluetoothの電波が多数飛んでいます。
もし、不特定多数の電波が多すぎることが原因なら、
そういった環境下でもコネクトが行える方法があればご教授いただけると幸いです。

##使っているツールのバージョンなど補足情報
Swift 5.0
Xcode 11.0
iOS 12.3
MacOS Mojave 10.14.6

都合上、アップデートができません。
ご助力いただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

解決しました。
Peripheral側のアドバタイズデータにCBAdvertisementDataServiceUUIDsKeyを乗せていなかったのが原因です。

Swift5

1// PeripheralService 2 3/* 修正前 */ 4let advertisementData = [CBAdvertisementDataLocalNameKey: "Test Device"] 5 6/* 修正後 */ 7let advertisementData: Dictionary<String, Any> = [CBAdvertisementDataLocalNameKey: "TEST", CBAdvertisementDataServiceUUIDsKey: [serviceUUID] ]

advertisementData: Dictionary<String, Any> =....
上記の太字部分を明記しないとエラーが出てビルドできませんでした。
CBAdvertisementDataLocalNameKeyを配列([ ]を付ける)にしたり、
CBAdvertisementDataServiceUUIDsKeyを配列にしない([ ]を付けない)と、
ビルドは通っても正常に動作しませんでした。

投稿2019/10/30 02:48

saku_panda

総合スコア20

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問