🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Bluetooth

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

Swift

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

Q&A

解決済

1回答

2721閲覧

同じcharacteristicへreadとwriteをする方法

saku_panda

総合スコア20

Bluetooth

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

Swift

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

0グッド

0クリップ

投稿2019/12/04 02:35

##前提・実現したいこと
iOS同士のBLE通信です。
CentralでCharacteristic.valueを初期化(write)し、
それをきっかけにPeripheralが同characteristic.valueを更新したいです。
更新後はCentralへ通知し、Centralが値をreadするという一連の流れを実現したいです。

##発生している問題
ペアリング、各種サービス、キャラクタリスティックの設定まではうまく動作しています。
その後のCentralでいうところのreadValue,writeValueがうまく動きません。
具体的には、
Central → Peripheralへのwriteは成功していますが、
Peripheral → Centralへの通知(read要求)がうまくいっていません。
PeripheralはupdateValueを正常に行えた場合"Success"と出力するよう組んでおり、Successは出力されます。
しかしCentralが通知を受けると出力される、"in didUpdateValueFor" は出ません。

##該当のソースコード

Swift

1// Central 2private var myPeripheral: CBPeripheral? = nil 3private var myCharacteristic: CBCharacteristic? = nil 4private let myServiceUUID: CBUUID = CBUUID(string: "service") 5private let myCharacteristicUUID: CBUUID = CBUUID(string: "characteristic") 6private var timer: Timer? 7private var timerFlag: Bool = false 8 9...... 10 11func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { 12 print("didDiscoverCharacteristicsFor") 13 guard (error == nil) else { 14 ...... 15 } 16 guard ( (peripheral == myPeripheral! ) 17 && (service.characteristics != nil)) else{ 18 ...... 19 } 20 21 for characteristic in service.characteristics!{ 22 if (characteristic.uuid == myCharacteristicUUID){ 23 print("get UUID") 24 myCharacteristic = characteristic 25 26 /* 一定感覚でvalueを要求するタイマーを設定 */ 27 if !timerFlag { 28 timer = Timer.scheduledTimer(withTimeInterval: 20, repeats: true){ timer in 29 self.initValue } 30 timerFlag = true 31 } 32 timer!.fire() 33 } 34 } 35} 36 37 38func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { 39 print("in didUpdateValueFor") 40 41 guard error == nil else { 42 ...... 43 } 44 guard ( peripheral == myPeripheral! ) else { 45 ...... 46 } 47 48 if (characteristic.uuid == myCharacteristicUUID){ 49 /* peripheralがvalueを更新した時に入る */ 50 print("read value") 51 52 ...... 53 54 } else { 55 print("unknown UUID") 56 } 57} 58 59 60func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { 61 print("didWriteValueFor characteristic") 62 63 guard ( peripheral == myPeripheral! ) else { 64 ...... 65 } 66 guard error == nil else{ 67 ...... 68 } 69 if (characteristic == myCharacteristic){ 70 /* Peripheral側でvalueの初期化が成功したら入る */ 71 print("Success to write Value") 72 } 73} 74 75 76func initValue(){ 77 guard ( (myCharacteristic != nil) && (myPeripheral != nil) ) else{ 78 ...... 79 } 80 /* peripheralのvalueをwriteで初期化する */ 81 let data: [UInt8] = [] 82 let writeData: Data = Data(data) 83 myPeripheral!.writeValue(writeData, for: myCharacteristic!, type: CBCharacteristicWriteType.withResponse) 84} 85

Swift

1// Peripheral 2private var myService: CBMutableService? = nil 3private var myCharacteristic: CBMutableCharacteristic? = nil 4private let prop: CBCharacteristicProperties = [.notify,.read,.write] 5private let perms: CBAttributePermissions = [.readable,.writeable] 6private let myServiceUUID: CBUUID = CBUUID(string: "service") 7private let myCharacteristicUUID: CBUUID = CBUUID(string: "characteristic") 8 9...... 10 11func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) { 12 print("didReceiveRead") 13 guard myCharacteristic != nil else{ 14 ...... 15 } 16 17 if ( request.characteristic.uuid == myCharacteristicUUID ) { 18 print("recieve request") 19 peripheralManager.respond(to: request, withResult: .success) 20 } else { 21 ...... 22 } 23} 24 25 26func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]){ 27 print("didReceiveWrite") 28 guard myCharacteristic != nil else{ 29 ...... 30 } 31 32 for request in requests { 33 if ( request.characteristic.uuid == myCharacteristicUUID ){ 34 print("get write") 35 /* write requestに対するレスポンス */ 36 peripheralManager.respond(to: request, withResult: CBATTError.success) 37 setValue(request: request) 38 39 } else { 40 ...... 41 } 42 } 43} 44 45 46func setValue(request: CBATTRequest) { 47 let newValue:Data = makeValue() 48 myCharacteristic!.value = newValue 49 let result = peripheralManager.updateValue(myCharacteristic!.value!, for: myCharacteristic!, onSubscribedCentrals: nil) 50 51 if (result == true){ 52 print("update Success") 53 peripheralManager.respond(to: request, withResult: CBATTError.success) 54 } else { 55 print("update Failed") 56 peripheralManager.respond(to: request, withResult: CBATTError.invalidHandle) 57 } 58} 59 60 61func makeValue() -> Data{ 62 63 var year: UInt16 = 2019 64 var month: UInt16 = 12 65 var day: UInt16 = 4 66 var byteArray: [UInt8] = [] 67 let array = SmartfinderScanCtrl.get_neighbor_array 68 69 byteArray.append( contentsOf: withUnsafeBytes( of: &year ){ $0.map{ UInt8( $0 )}}) 70 byteArray.append( contentsOf: withUnsafeBytes( of: &month ){ $0.map{ UInt8( $0 )}}) 71 byteArray.append( contentsOf: withUnsafeBytes( of: &day ){ $0.map{ UInt8( $0 )}}) 72 73 let data: Data = Data(byteArray) 74 75 return data 76}

##自分で試したこと
newValueにデータが書き込まれていることは確認できています。
解決法はもちろんですが、コード不備、や仕様上の見落とし等もありましたらお教えください。
どうぞよろしくお願いします。

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

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

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

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

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

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

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

guest

回答1

0

自己解決

自己解決しました。

myPeripheral!.setNotifyValue(true, for: myCharacteristic!)

上記の更新通知を受ける設定をしなければいけないところが抜けていました。
何かの修正の際に誤って消してしまっていたようです...
真っ先に疑うべきなのに、失礼しました。

投稿2019/12/04 07:33

saku_panda

総合スコア20

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問