Raspberry Pi bluetoothシリアル通信
raspberry piでbluetooth PANを構築したかったのですが現在のBlueZは大分仕様が変更になっているようでうまく動かすことができませんでした。
今回はRaspberry Pi同士でbluetoothシリアル通信の確認ができたので簡単に纏めておきたいと思います。
環境
Raspberry Pi 3 stretch デスクトップ クライアント
Raspberry Pi zero stretch lite ホスト名 piz0
Raspberry Pi zero(w) stretch lite ホスト名 lite
Raspberry Pi 2 stretch lite ホスト名 dip
BTアダプタ
無印 BT2.0アダプタ
CSR 4.0アダプタ
zero(w)は内蔵BTアダプタ
ペアリング
ペアリングについては詳しく紹介されているサイトがあると思うので簡単に!
デスクトップのpi3からbluetoothアイコンをクリックMake Discoverableを実行
Add Deviceダイアログをだします。
zero(w)にログインしてroot権限でbluetoothctlを実行します。
stretch-liteでもBT接続に必要なパッケージはデフォルトでインストールされています。
zero(w)から以下を実行していきます。
power on
discoverable on
agent on
default-agent
1分位待っているとzero(w)のホスト名liteが表示されます。
liteを選択してPairをクリック、pinコードダイアログが出るのでOK
zero(w)はpinコードを確認してyesを入力してペア完了、exitで終了します。
このときpi3側でもターミナルを起動しておいて同様にbluetoothctlだけを実行しておくと通信の様子がよくわかります。
root@lite:~ # bluetoothctl [NEW] Controller B8:27:EB:6A:xx:xx lite [default] [bluetooth]# power on Changing power on succeeded [bluetooth]# discoverable on Changing discoverable on succeeded [CHG] Controller B8:27:EB:6A:xx:xx Discoverable: yes [bluetooth]# agent on Agent registered [bluetooth]# default-agent Default agent request successful [CHG] Device B8:27:EB:24:xx:xx UUIDs: 00001101-0000-1000-8000-00805f9b34fb ------- snip ------- [CHG] Device B8:27:EB:24:xx:xx UUIDs: 00001801-0000-1000-8000-00805f9b34fb [CHG] Device B8:27:EB:24:xx:xx ServicesResolved: yes [CHG] Device B8:27:EB:24:xx:xx Paired: yes [CHG] Device B8:27:EB:24:xx:xx ServicesResolved: no [CHG] Device B8:27:EB:24:xx:xx Connected: no [CHG] Controller B8:27:EB:6A:xx:xx Discoverable: no [bluetooth]# exit Agent unregistered [DEL] Controller B8:27:EB:6A:xx:xx lite [default]
同様にzero(w)で2個のUSB-BTアダプタのペアリングをします。
無印 BT2.0アダプタ
同様にペアリングは可能ですがPINコードを双方とも指定して打ち込む必要があります。
よく使われるのは0000とか1234という数字ですね。手早くしないとタイムアウトになってやり直しになってしまいます。
CSR 4.0アダプタ
このアダプタは特にPINコードも出ることもなくペアリングが完了します。
但しzero(w)では抜き差しした時点で固まってしまいます。
zero,pi2.pi3では問題ありません。
zero(w)で3個のBTアダプタがペアリングできました。
pi3のBTマネージャーにはペアリングしたデバイスが表示されていますがここからConnectしても接続できません。
これはbluetoothのプロファイルを利用する何かしらのアプリケーションが待ち受けているときに接続できるものと思います。
シリアル通信
シリアル通信はこちらのページが良く纏まっていますね。 Raspberry Pi と Bluetooth 経由でシリアル通信する
Raspberry Pi 3 stretch(デスクトップ)接続元の設定
今回は3台に接続するということで3台分のrfcommを用意します。
/etc/rc.local
if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi # rfcomm rfcomm bind 0 00:1A:7D:DA:xx:xx # zero(piz0) rfcomm bind 1 B8:27:EB:6A:xx:xx # zero(w)(lite) rfcomm bind 2 00:15:83:0C:xx:xx # pi2(dip) exit 0
また表示が乱れるのでModemManagerを停止します。
# systemctl stop ModemManager # systemctl disable ModemManager
シリアル通信のソフトはいろいろありますがscreenとpicocomをインストールしてみました。
# apt install screen picocom
ここで再起動(reboot)
/devには3個のrfcommができているはずです。
$ ls -la /dev/rfcomm* crw-rw---- 1 root dialout 216, 0 4月 18 16:36 /dev/rfcomm0 crw-rw---- 1 root dialout 216, 1 4月 18 16:37 /dev/rfcomm1 crw-rw---- 1 root dialout 216, 2 4月 18 16:36 /dev/rfcomm2
シリアル通信接続先の設定
zero(w)で3個のBTアダプタを登録しましたがこのペアリング情報はアダプタ固有の情報になるため内臓のBTアダプタ以外はほかのマシンで流用が可能になります。
設定ファイルは/var/lib/bluetooth/以下に保存されています。
# ls -l /var/lib/bluetooth drwx------ 4 root root 4096 4月 17 18:38 00:15:83:0C:xx:xx drwx------ 4 root root 4096 4月 17 22:21 00:1A:7D:DA:xx:xx drwx------ 4 root root 4096 4月 17 22:43 B8:27:EB:6A:xx:xx
各アダプタのID以下にはpi3のペアリング情報が入っています。
直接カードをマウントしてコピーを取る場合の例は
# mount /dev/sda2 /mnt # cp -rp /var/lib/bluetooth/00:15:83:0C:xx:xx /mnt/var/lib/bluetooth # cp -rp /var/lib/bluetooth/00:1A:7D:DA:xx:xx /mnt/var/lib/bluetooth
もう1台も同じくコピーします。
これで3台ともペアリングが完了しました。再ペアリングしない限りUSB-BTアダプタはペアリングなしに自由に使い廻しが可能になります。
sdptool設定
[Service]の3行目に-Cを追加、4行目を新規に追加
/lib/systemd/system/bluetooth.service
[Service] Type=dbus BusName=org.bluez ExecStart=/usr/lib/bluetooth/bluetoothd -C ExecStartPost=/usr/bin/sdptool add SP
待受起動は/etc/rc.localから
シリアルは1接続のみなのでrfcomm0、速度は115200、ホスト名、ユーザーpiのオートログイン
/etc/rc.local
if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi rfcomm watch 0 1 agetty rfcomm0 115200 lite -a pi > /dev/null 2>&1 exit 0
ここで再起動(reboot)
zero(w)にログインしてsdptoolを実行、Serial Portが見えてたらOK
# sdptool browse local Service Name: Serial Port ---- "RFCOMM" (0x0003) Channel: 1
ほかの2台もホスト名を変えて同じ設定をします。
bluetoothシリアル通信をしてみる
pi3ディスクトップから3つのターミナルを起動して実行してみましょう。
$ picocom -b 115200 /dev/rfcomm0 $ screen /dev/rfcomm1 115200 $ picocom -b 115200 /dev/rfcomm2
コマンドを実行すると数秒で接続を開始します。1回目で失敗するときもありますが再度実行すると繋がってくれます。
ジョブコントロールが無効なのはシリアルターミナルの仕様と思います。raspi-configなどバックグランドで動かす必要があるコマンドは実行できません。
rfcomm0〜rfcomm2は/etc/rc.localで設定したデバイスIDが使われます。したがってzero(w)の内蔵BTデバイス以外は差し込んだUSB-BTアダプタによってはホストが入れ替わることがあります。
USB-BTアダプタは必要になったとき差し込んでもシリアル通信は可能です。
pi3のBTマネージャーはホスト名を読み取って自動的に変更してくれます。
さてこのbluetoothによるシリアル通信はどんなときに使えば有効かなと考えると通常のLan環境ではあまり出番がないですね。
ですが今回いろいろとネットワークの設定を含めて変更をするとこのシリアル通信の便利さがわかります。繋がらないネットワークを設定しても取り敢えずシリアル通信でなんとかなります。
但し再起動時正常にOSが起動、BTアダプタを認識、/etc/rc.localまで起動しないとシリアル通信も不可になってしまいます。
別の使い途としてraspbianインストール時の補助にも使えそうです。
ddしたディスクにペアリング情報をコピーbluetooth.service,rc.localを編集しておけばシリアル通信は可能になります。
ネットワークを一切設定していないディスクを作成、起動してみました。
無事シリアル通信は繋がってくれました。dhcpでipを取得できなかったときなどはこれで調査、修復も可能と思います。
またシリアル通信では無いのですがraspbianディスクトップインストール時の際にはbluetoothキーボード、マウスのペアリング情報があれば予め/var/lib/bluetoothをコピーしておけば初期設定からペアリングなしに使用ができます。