d.sunnyone.org
sunnyone.org

ページ

ラベル Bluetooth の投稿を表示しています。 すべての投稿を表示
ラベル Bluetooth の投稿を表示しています。 すべての投稿を表示

2013-09-25

AndroidからBluetooth機器にSPP (Serial Port Profile) で接続する

作ったデバイスにAndroidからつないでみようと思ってやってみた。まっとうに使ってもらおうとすると、他にもけっこういろいろ必要なのだけど、自分で使うくらいならわりと簡単にできる。

やりかた

  1. BluetoothAdapter.getDefaultAdapter()を使って、アダプタを得る。
  2. アダプタにisEnabled()を呼び出して、Bluetooth設定が有効なことを確認する。
    • インテントを出してユーザーに有効にしてもらうことも可能だけど、ここではしない。
  3. アダプタにgetBondedDevices()を呼び出して、ペアリングされたデバイスの一覧を得る。
    • 探索してペアリングされたデバイス以外から探すことも可能だけど、ここではしない。
  4. デバイスのプロパティを見て、欲しいデバイスを探し出す。
    • 本当はUI出して選んでもらうのがいいと思うけど、ここではしない。
  5. 欲しいデバイスにcreateRfcommSocketToServiceRecord()を呼び、必要なサービスのBluetoothSocketを得る。
    • SPP (Serial Port Profile)のUUID(00001101-0000-1000-8000-00805F9B34FB)を渡す必要があるので、定数定義しておく。
  6. BluetoothSocketにconnect()を呼ぶ。
  7. BluetoothSocketにgetInputStream() / getOutputStream()を呼んで、適当に操作する。
  8. BluetoothSocketにclose()を呼ぶ。


このへんのページのほうが詳しいので、「ここではしない」ことがしたければこちらを参考に...

罠1) getDefaultAdapter()は、Gingerbread (2.3)では、UIスレッドでしか呼べない。


いかにもUIなんか関係なさげなメソッドなのに、Handlerが取れなくて例外が出る。4.1では起きないらしいけど、2.3じゃダメだと…ねぇ?
cf: https://groups.google.com/forum/#!msg/android-developers/wFbD5V2DWRc/gv0VF4Y6ICwJ

罠2) BluetoothSocket#connect()は「Service discovery failed」でたまに失敗する

Webを見るとよくある話のようで、ウエイトを入れたり、アダプタにcancelDiscoveryをさせろとか、リフレクションで中のメソッドを呼び出せとか、いろいろある。どうにもすっきりしないし、時間がかかってNGなので、何かのタイムアウトなんだと思う。なので、とりあえずリトライすることにした(リトライの条件はもう少ししっかりしたほうがいいかも)
cf:  http://stackoverflow.com/questions/3397071/service-discovery-failed-exception-using-bluetooth-on-android

コード

ASCIIで1行書き込むと、1行返ってくる感じのサンプル。

本当はすべてUIじゃないスレッドの中でのコードにしたかったのだけど、上述の罠があって、getDefaultAdapter()だけUIスレッドで渡すようにしているので、コピペでは現実的に動かない。

close()漏れとかあるので、ためしに書いてみるてな感じの参考程度に。sendLogMessage()は、適当なTextViewにログを出すためのメソッドなので、Log.dとかでよいです。


2013-09-21

Arduino + USB ホストシールド + BTドングルでBluetooth Lチカ

このあたりを参考にしたら、思ったよりも圧倒的に簡単にできたので、思わず記事にする。ArduinoとUSBホストシールドにBluetoothドングルを使うと、SPP (Serial Port Profile)を使って簡単にLEDチカチカできちゃう。

1. 機器を準備する

必要なものは、ArduinoとUSBホストシールド2.0とBluetoothドングル。今回は、以下を使った。
最後のBluetoothドングルはもう売ってないと思うけど、似たようなやつが千円くらいで買えると思う。だいたい使えそうな気がするけど、Linuxで使える報告があがってるやつとかが無難なのかな?

USBホストシールドは2.0なものを選ばないとたいへんらしい

2. つなぐ

USBホストシールドにBluetoothドングルを差して、Arduino Unoに重ねて、適当なデジタルピンにLEDと抵抗のセットをつなげばいい。ただし、デジタル8~13は使っているらしいので注意。今回は6番を使った。

3. Arduino IDEの所定のディレクトリにzipを展開する

https://github.com/felis/USB_Host_Shield_2.0 から、zipアーカイブをダウンロードして、/usr/share/arduino/libraries/USB_Host_Shield_20 に展開する。

4. SPPサンプルを開く

Arduino IDEのメニューからUSB_Host_Shield_20のBluetoothのSPPのサンプルを開く。

5. ちょちょいと書き換えて転送する

サンプルはSerialとSerialBTでお互いにechoする感じなので、適当にif文を書き換えてdigitalWrite(ピン, HIGH/LOW); でチカチカさせるようにする。

変更した部分はこんなかんじ(全体は最後に)。
if (SerialBT.available()) {
  char c = SerialBT.read();
  if (c == '1') {
    digitalWrite(6, HIGH);
  } else {
    digitalWrite(6, LOW);
  }
  Serial.write(c);
}

あとは転送する。

6. ペアリングして通信する


ターミナル的なソフトが使えれば、WindowsでもLinuxでもなんでもいいと思うけど、今回はAndroidとS2 Terminal for Bluetooth Free を使った。1とか0とか送ってチカチカすれば成功!

ソース全体でもこれだけ。eneloop スティックブースターで動くし、お手軽にライトな無線機器を作るのにいいと思う。