前回は USB シリアル変換アダプタによる通信だったので今回は Bluetooth で。
メインの Ubuntu から Raspberry Pi に Bluetooth で接続してシェルで操作できるようにするまで。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 17.04 Release: 17.04 Codename: zesty
pi@raspberrypi:~$ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 8.0 (jessie) Release: 8.0 Codename: jessie
とりあえず bluetoothctl でのペアリングが終わってるものとする。
まず、Bluetooth でシリアル通信を行うには bluetoothd を -C オプション付きで起動しなければならない。-C オプションが無い場合、sdptool が使えない。
サービスとして起動している bluetoothd を一旦止める。
pi@raspberrypi:~$ sudo systemctl stop bluetooth
bluetoothd を手動でバックグラウンド起動。アダプタが落ちていることがあるので立ち上げ直しておく。
pi@raspberrypi:~$ sudo bluetoothd -C & pi@raspberrypi:~$ sudo hciconfig hci0 up
この時点ではまだシリアル通信ができない。
pi@raspberrypi:~$ sudo sdptool browse local | grep -i serial
sdptool で SPP を追加する。add --channel={n} で任意のチャンネルも指定できる。
pi@raspberrypi:~$ sudo sdptool add SP
pi@raspberrypi:~$ sudo sdptool browse local | grep -i serial Service Name: Serial Port "Serial Port" (0x1101) "Serial Port" (0x1101)
/dev/rfcomm0 に端末を割り当てて待機状態にする。rfcomm コマンドの使い方がまだ掴めていない。getty は agetty へのリンク。
書式とオプションは以下の通り。
RFCOMM configuration utility ver 5.43
Usage:
rfcomm [options] <command> <dev>
Options:
-i, --device [hciX|bdaddr] Local HCI device or BD Address
-h, --help Display help
-r, --raw Switch TTY into raw mode
-A, --auth Enable authentication
-E, --encrypt Enable encryption
-S, --secure Secure connection
-M, --master Become the master of a piconet
-L, --linger [seconds] Set linger timeout
-a Show all devices (default)
Commands:
bind <dev> <bdaddr> [channel] Bind device
release <dev> Release device
show <dev> Show device
connect <dev> <bdaddr> [channel] Connect device
listen <dev> [channel [cmd]] Listen
watch <dev> [channel [cmd]] Watch
普通にログインさせる場合。
pi@raspberrypi:~$ sudo rfcomm watch 0 1 agetty rfcomm0 115200 linux
ユーザ pi でオートログインするさせる場合。
pi@raspberrypi:~$ sudo rfcomm watch 0 1 agetty rfcomm0 115200 linux -a pi
認証無しでルートログインさせる場合。
pi@raspberrypi:~$ sudo rfcomm watch 0 1 agetty -n -l /bin/bash rfcomm0 115200 linux
watch ではなく listen もあるが、こっちは接続を切るとサーバ側の rfcomm も終了する。
agetty のオプションがよくわからんのだが、ログイン後に下記のエラーが表示される。apt-get update なんかをやると躓く。
-bash: cannot set terminal process group (1825): Inappropriate ioctl for device -bash: no job control in this shell
接続元からは screen コマンドなどで接続しにいくので rfcomm connect ではなく rfcomm bind しておく。
■書式
bind <dev> <bdaddr> [channel]
チャンネルは指定しなくても勝手に見つけてくれる。
$ sudo rfcomm bind 0 01:23:45:67:89:AB $ rfcomm rfcomm0: 01:23:45:67:89:AB channel 1 clean
これで接続元の /dev/rfcomm0 を使って接続する準備ができた。
screen コマンドで rfcomm bind してある /dev/rfcomm0 に接続する。
$ screen /dev/rfcomm0 115200 Raspbian GNU/Linux 8 raspberrypi rfcomm0 raspberrypi login:
別の端末で watch なんかで状態のチェックをしておくといいかもしれない。
$ watch rfcomm -a rfcomm0: B8:27:EB:0D:F6:C4 channel 1 connected [tty-attached]
無事 Raspberry Pi に接続できたが、接続する度に最初に AT AT ??? みたいな AT コマンドを何か送ってるっぽいのだが何だこれ?
USB シリアル変換アダプタで接続しているときは出ないので多分 rfcomm 関係だが AT というワードで探すのは辛い…。なんとか見つけた「Disable AT command on rfcomm connect」に書いてあった。
ModemManager よ、またお前か…。
$ sudo systemctl stop ModemManager $ sudo systemctl disable ModemManager
コンソールのサイズが小さいのは stty で調整。tmux を使っている場合は一回 detach してから。
$ stty rows 44 cols 148 $ tmux
とりあえずプロセスグループが設定できない問題以外はなんとかなったので /lib/systemd/system/bluetooth.service を変更して起動時に Bluetooth シリアル通信ができるようにしておく。
pi@raspberrypi:~$ diff -u <(zcat /lib/systemd/system/bluetooth.service.gz) /lib/systemd/system/bluetooth.service --- /dev/fd/63 2017-07-02 14:53:53.958932366 +0900 +++ /lib/systemd/system/bluetooth.service 2017-07-02 13:35:31.721916663 +0900 @@ -5,7 +5,8 @@ [Service] Type=dbus BusName=org.bluez -ExecStart=/usr/lib/bluetooth/bluetoothd +ExecStart=/usr/lib/bluetooth/bluetoothd -C +ExecStartPost=/usr/bin/sdptool add SP NotifyAccess=main #WatchdogSec=10 #Restart=on-failure
pi@raspberrypi:~$ sudo systemctl daemon-reload pi@raspberrypi:~$ sudo systemctl restart bluetooth
/etc/systemd/system/rfcomm.service を作成。
[Unit] Description=RFCOMM service After=bluetooth.service Requires=bluetooth.service [Service] ExecStart=/usr/bin/rfcomm watch 0 1 /sbin/agetty rfcomm0 115200 linux [Install] WantedBy=multi-user.target
pi@raspberrypi:~$ sudo systemctl daemon-reload pi@raspberrypi:~$ sudo systemctl start rfcomm pi@raspberrypi:~$ sudo systemctl enable rfcomm
プロセスグループが設定できない問題はよくわからんが、とりあえず Raspberry Pi にログインしたあとに tmux 起動すればいいっぽいので今日はここまで。(ctrl+a と ctrl+b が…)