以前Raspberry Pi 2にUSBのBluetoothアダプタを接続し、WindowsおよびMacのPCとペアリングするところまでみた。
今回は、Bluetoothによるシリアル通信を行い、Raspberry PiとWindows-PC間でデータ送受信をやってみる。
シリアル通信は本来、Bluetoothとは関係のない、シリアルケーブルを使ったPCの標準的なデバイス通信用プロトコルだが、BluetoothのSPP(Serial Port Profile)というプロファイルを使うことで、仮想的なシリアルポートを用いてデバイス接続ができるようになる。
SPPはRFCOMM(Radio Frequency Communication) というシリアルポートをエミュレートして無線通信するためのプロトコルと、SDP(Service Discovery Protocol)というBluetoothで利用できるサービスを通知するためのプロトコルの二つを利用する。
事前準備
Raspberry PiとWindows-PCを前回の記事の通りにペアリングした状態にしておく。
pi@raspberrypi:~ $ bluetoothctl [NEW] Controller 00:1B:DC:XX:XX:XX raspberrypi [default] [NEW] Device 28:C2:DD:XX:XX:XX MY-WINDOWS-PC
SDPサーバ準備
Raspberry PiでSDPサーバが使えるか確認する。
前回のセットアップでBluetooth関連のツールはインストール済みの状態のはずのため、
以下のようにsdptoolコマンドでローカルのサービスを確認すればよい。
pi@raspberrypi:~ $ sdptool browse local Failed to connect to SDP server on FF:FF:FF:00:00:00: No such file or directory
実行するとエラーになった。
/etc/systemd/system/dbus-org.bluez.service
を編集してbluetoothdの設定変更が必要らしいので、以下のように修正する。
・変更前
ExecStart=/usr/lib/bluetooth/bluetoothd
・変更後
ExecStart=/usr/lib/bluetooth/bluetoothd --compat
変更後、bluetoothdを再起動する。
pi@raspberrypi:~ $ sudo systemctl daemon-reload pi@raspberrypi:~ $ sudo systemctl restart bluetooth
再実行すると、今度は別のエラーになった。
pi@raspberrypi:~ $ sdptool browse local Failed to connect to SDP server on FF:FF:FF:00:00:00: Permission denied
今度はパーミッションエラーなので/var/run/sdp
のアクセスレベルを変更する。
pi@raspberrypi:~ $ sudo chmod 777 /var/run/sdp
再実行すると、SDPサービスが確認できた。
pi@raspberrypi:~ $ sdptool browse local Browsing FF:FF:FF:00:00:00 ... Service RecHandle: 0x10000 Service Class ID List: "PnP Information" (0x1200) Profile Descriptor List: "PnP Information" (0x1200) Version: 0x0103 Browsing FF:FF:FF:00:00:00 ... Service Search failed: Invalid argument Service Name: Generic Access Profile Service Provider: BlueZ Service RecHandle: 0x10001 Service Class ID List: "Generic Access" (0x1800) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 31 "ATT" (0x0007) uint16: 0x0001 uint16: 0x0008 Service Name: Generic Attribute Profile Service Provider: BlueZ Service RecHandle: 0x10002 Service Class ID List: "Generic Attribute" (0x1801) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 31 "ATT" (0x0007) uint16: 0x0010 uint16: 0x0010 Service Name: AVRCP CT Service RecHandle: 0x10003 Service Class ID List: "AV Remote" (0x110e) "AV Remote Controller" (0x110f) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 23 "AVCTP" (0x0017) uint16: 0x0103 Profile Descriptor List: "AV Remote" (0x110e) Version: 0x0105 Service Name: AVRCP TG Service RecHandle: 0x10004 Service Class ID List: "AV Remote Target" (0x110c) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 23 "AVCTP" (0x0017) uint16: 0x0103 Profile Descriptor List: "AV Remote" (0x110e) Version: 0x0104
ただし、Service Name: Serial Port
というサービスがない状態であることが分かる。
そのため、SPPを追加する。
pi@raspberrypi:~ $ sudo sdptool add --channel=22 SP Serial Port service registered
もう一度実行すると、Service Name: Serial Port
が追加されていることが分かる。
pi@raspberrypi:~ $ sdptool browse local (・・・上と同じなので省略) Service Name: Serial Port Service Description: COM Port Service Provider: BlueZ Service RecHandle: 0x10005 Service Class ID List: "Serial Port" (0x1101) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 22 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Serial Port" (0x1101) Version: 0x0100
Serial Portが追加されたことが確認できる。
RFCOMMセットアップ
以下のコマンドでrfcommをリッスン状態にする。
pi@raspberrypi:~ $ sudo rfcomm listen /dev/rfcomm0 22 Waiting for connection on channel 22
これでシリアル通信のリッスン待ちの状態になる。シリアル通信が確立すると、/dev/rfcomm0
デバイスでデータ送受信ができるようになる。
シリアル通信でデータ送受信
ペアリングしたWindows 7のPCとシリアル通信してみる。
Windows側の準備として、ペアリングした状態で以下を開く。
コントロール パネル > ハードウェアとサウンド >デバイスとプリンター
デバイスからペアリングしたRaspberry Piデバイスのプロパティを開く。
「サービス」タブの「シリアルポート (SPP) 'Serial Port'」のチェックを入れると、仮想ポートが割り当てられる。
今回は「COM5」という名前のポートが使えるようになった。
Tera Termを開き、「シリアル」接続する。ポートは上記の「COM5」が選択できるので、それを指定する。
この時点でRasbperry Piのリッスン状態だったrfcommにConnectionと表示され、正常に接続できたことが確認できる。
pi@raspberrypi:~ $ sudo rfcomm listen /dev/rfcomm0 22 Waiting for connection on channel 22 Connection from28:C2:DD:XX:XX:XX to /dev/rfcomm0 Press CTRL-C for hangup
Windows PCからRaspberry Piへデータ送信
Tera Termで適当に文字列を入力してみる。
シリアル通信は一文字ずつの送信なので特にEnterとかせずともメッセージは送信される。
Raspberry Pi側でメッセージを確認するために、/dev/rfcomm0
をcatする。
pi@raspberrypi:~ $ sudo cat /dev/rfcomm0 1234
Tera Termで入力した文字が出力される。
Raspberry PiからWindows PCへデータ送信
今度はRaspberry Pi上で/dev/rfcomm0
デバイスにメッセージをechoしてみる。
pi@raspberrypi:~ $ sudo echo abcd > /dev/rfcomm0
するとTera Termの画面にechoされた文字列が表示される。
双方向でメッセージ通信ができていることが確認できた。
最後にRFCOMMはCtrl-Cで停止する。
pi@raspberrypi:~ $ sudo rfcomm listen /dev/rfcomm0 22 Waiting for connection on channel 22 Connection from28:C2:DD:XX:XX:XXto /dev/rfcomm0 Press CTRL-C for hangup Disconnected
まとめ
以上、Raspberry PiとBluetoothでペアリングした端末とシリアル通信によるデータ送受信ができることを確認した。
これでBluetoothのペアリングからデータ通信までできるようになったので、Wi-Fiがない状況下でも代替手段として使うこともできそう。
今回はシリアル通信という手段でデータ通信してみたが、PANとか他の方法も調査してみたい。
以上!