##前提・実現したいこと
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
都合上、アップデートができません。
ご助力いただけますと幸いです。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。