技術的なメモです。
IoT(Internet of Things)の開発に興味があり、実験としてmbedとiOSデバイスをBluetooth Low Energy(以下、BLE)で通信させるプロトタイプを作ってみています。
iOSからmbedを制御するサンプルとしては、下記の記事が大変参考になりました。iOS側のコードも公開されていてありがたいです。
・iPhoneからmbedをBluetooth LE (BTLE)で制御する
http://todotani.cocolog-nifty.com/blog/2013/02/iphonembedbulet.html
ただ、こちらのコードはiOS6.1の頃に書かれたものようで、iOS6では正常に動作するのですが、iOS7ではうまく動きませんでした。具体的には、LED1のON/OFFの制御ができません。
これを解決するために以下のように修正しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
- (void) updateLed1 { const unsigned char onData[] = {0x01}; const unsigned char offData[] = {0x00}; if ([self.led1Sw isOn]) { [self.peripheral writeValue:[NSData dataWithBytes:onData length:1] forCharacteristic:self.led1Characteristic // type:CBCharacteristicWriteWithoutResponse]; type:CBCharacteristicWriteWithResponse]; // 修正 self.statusLabel.text = @"LED On"; } else { [self.peripheral writeValue:[NSData dataWithBytes:offData length:1] forCharacteristic:self.led1Characteristic // type:CBCharacteristicWriteWithoutResponse]; type:CBCharacteristicWriteWithResponse]; // 修正 } } |
原因がよく分からなかったので、検索してみると下記のサイトに同様の問題が書かれていました。同じようにiOS7にしてから書き込みに問題が生じたが、CBCharacteristicWriteWithoutResponseからCBCharacteristicWriteWithResponseに変更したら問題が解消したというものです。
http://lists.apple.com/archives/bluetooth-dev/2013/Aug/msg00046.html
そこには、
Apparently Core Bluetooth on iOS 7 is being more stringent about operations on characteristics and the setting of the properties on those characteristics.
とあって、iOS7ではキャラクタリスティックの扱いが厳格になったのではないかという指摘がされていました。
mbed側の実装では、LED1を制御するキャラクタリスティック(0xFFF2)のプロパティは、ReadとWriteで、Write without Responseは指定されていません。そのため、本来はCBCharacteristicWriteWithResponsを指定するべきだが、iOS6ではその辺りの扱いがアバウトだったためCBCharacteristicWriteWithoutResponsでも処理が成功していた、ということなのかもしれません。(正しく理解できていないかもしれないので、もし間違っていたら教えていただけると嬉しいです。)
あと、上記の修正で一応動作はしますが、iOS7になってからCBPeripheralのUUIDとisConnectedプロパティがDeprecatedになっているので、そちらの修正も。
参考: 【連載】Bluetooth LE (6) iOS 7 での CoreBluetooth の変化
http://blog.fenrir-inc.com/jp/2013/11/bluetooth-le-ios-3.html