Grow up

生活とプログラミング

iOS Core Bluetooth "Writing is not permitted"の解決方法

はじめに

先週初めて Swift を使ってマイコンと通信をしてみました。
knkomko.hatenablog.com

データは送れてもエラーが返ってきて苦労したので書き残しておきます。

エラー内容

マイコンにデータを送ると以下のエラー内容が返ってきます。

Errpr Domain=CBATTErrorDomain Code=3 "Writing is not permitted."
UserInfo={NSLocalizedDescription=Writing is not permitted.}

以下のデリゲートメソッドがエラーを受信していました。
正常であればNotificationが返ってきます。

    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        if let error = error {
            println("error \(error)")
            return
        }

        println("received Notification")
    }
解決方法

WriteValueの3番目のパラメータをキャラクタリスティックの仕様と合わせます。
指定できるパラメータは「.withoutResponse」「.withResponse」2種類です。
そのため仕様が分からない場合はどちらかに変更して試します。

私が使用したマイコンの取説には明記されていなかったので「.withoutResponse」に変更しました。

    func  sendMessage(message: String) {
        var command = message + "\n"
        let data = command.data(using: String.Encoding.utf8, allowLossyConversion:true)
        // type:を下記に変更 cbPeripheral!.writeValue(data! , for: writeCharacteristic!, type: .withResponse)
        cbPeripheral!.writeValue(data! , for: writeCharacteristic!, type: .withoutResponse)
    }
感想

"Writing is not permitted."というエラーメッセージを読んでから書き込みの種類を「withoutReponse」に変更しようという考えに至るまでに時間がかかりました。
ドキュメントの概要を確認すると、詳細を理解するためにはBluetooth 4.0の仕様を理解する必要がありそうでした。

以下、概要を抜粋した内容です。

原文:

Characteristic write types have corresponding restrictions on the length of the data that you can write to a characteristic’s value.

日本語訳:

特性書き込みタイプには、特性の値に書き込むことができるデータの長さに対する対応する制限があります。書き込みタイプについては、Bluetooth 4.0仕様の第3部、パートG、セクション4.9.3〜4に制限が定義されています。

developer.apple.com

Bluetooth 4.0 のセントラルからペリフェラルへの書き込みの種類について調べてみたものの、仕様についてはよく分かりませんでした。
仕様を理解できればエラー原因の特定が早くなると思うのですが、現状はまだ手探りの状態です。