Raspberry Pi Zero WにBluetooth経由のシリアル通信でログインする

Raspberry Pi Zero WにBluetooth経由のシリアル通信でWindows PCからログインしてみました。

はじめに

Raspberry Pi Zero WはWi-Fi経由のsshでログインすることができますが、Wi-Fiに繋がらない時やsshでログインすることができなくなった場合に備えてシリアル通信でログインできるように設定しておこうと思いました。

ケーブル等を用意しなくても接続したかったためBluetooth経由でのシリアル通信でログインできるように設定しました。

前提

sshでログインして設定を行いますので、Raspberry Pi Zero WがWi-Fiに接続できていてsshでログインできることが前提です。

動作環境

Raspberry Pi Zero WのSDカードはRaspbianをRaspberry Pi Imagerでインストールしました。久しぶりに使用したのですがWi-Fiの接続設定もRaspberry Pi Imagerからできるようになっていました。

使用したRaspbianのバージョンなどは以下です。

pi@raspberrypi:~ $ cat /etc/os-release

PRETTY_NAME="Raspbian GNU/Linux 11 (bullseye)"
NAME="Raspbian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

BluetoothでPCとペアリングする

まずはRaspberry Pi Zero WとWindows PCをBluetoothでペアリングします。

Raspberry Pi Zero Wでbluetoothctlを起動します。

bluetoothctl

以下のような表示になります。

bluetoothctl

BluetoothをONにします。

power on

スキャンをONにします。

scan on

Windows PCで「bluetoothデバイスの追加」を開きます。

bluetoothデバイスの追加

デバイスの一覧を表示します。

devices

以下のように表示されると思います。

Device 01:23:45:67:89:01 PC-01
Device 01:23:45:67:89:02 PC-02
Device 01:23:45:67:89:03 Echo Show

ペアリングしたいデバイスのMACアドレスを指定してペアリングします。

pair 01:23:45:67:89:01

パスキーの確認が表示されますので yes を入力して確定します。

Request confirmation
[agent] Confirm passkey 344700 (yes/no): yes

Windows PC側でもパスキーの確認が表示されますので「はい」を押します。

パスキーの確認

接続成功と表示されればペアリングは完了です。

最後にペアリングしたデバイスを信頼するデバイスに設定しておきます。

trust 01:23:45:67:89:01

bluetoothctlはexitコマンドで終了します。

exit

シリアル通信の設定

シリアルポート通信の追加

まずはシリアルポートで通信ができるようにbluetoothサービスのユニットファイルに設定を追加します。

念のためユニットファイルをバックアップしておきます。

cp /etc/systemd/system/dbus-org.bluez.service ./

viエディターでbluetoothサービスのユニットファイルを開きます。(お好みのテキストエディタを使用してください)

sudo vi /etc/systemd/system/dbus-org.bluez.service

編集した内容は以下です。

ExecStart=/usr/libexec/bluetooth/bluetoothd --compat
ExecStartPost=/usr/bin/sdptool add --channel 22 SP

sdptoolでシリアルポートにチャネルを追加しました。チャネルの番号の指定は任意ですが、この後に設定するrfcommに指定するチャネルと合わせる必要があります。

編集した差分は以下です。

編集した差分

ユニットファイルを編集したのでデーモンをリロードします。

sudo systemctl daemon-reload

bluetoothサービスを再起動します。

sudo systemctl restart bluetooth.service

Windows PCから接続

Windows PCでコントロールパネルを開いてアドレス欄に「コントロール パネル\ハードウェアとサウンド\デバイスとプリンター」を入力します。以下のように raspberrypi が追加されているのが確認できます。

コントロールパネル

コントロールパネルのデバイスとプリンターに表示されているraspberrypiを右クリックしてコンテキストメニューからプロパティを選択します。

デバイスのプロパティーを表示

プロパティのダイアログのサービスタブを選択して「シリアル ポート」にチェックを入れて「適用」をクリックします。

「シリアル ポート」にチェック

チェックしたシリアルポートの右側にCOMポートが表示されました。Windows PCからはこのCOMポートを使用してRaspberry Pi Zero Wに接続します。

疎通確認

rfcommでチャネル「22」を watch して agetty につなぎます。チャネルはbluetoothサービスの設定の時にsdptoolに指定したチャネルの番号と合わせます。rfcommにチャネルを指定しない場合は「1」が使用されます。

sudo rfcomm watch 0 22 /sbin/agetty rfcomm0 linux

watchに指定している「0」はデバイス番号で、agettyにはこのデバイス番号と対応するデバイス名の「rfcomm0」を指定しています。「0」を指定しましたが任意のデバイス番号を指定することができます。

ここでWindows PCからCOMポート経由で接続ができるか疎通確認を行いました。

COMポート経由での接続は「Putty」や「Tera Term」、「RLogin」などのターミナルエミュレータを使用して接続します。

私は Putty に付属する plink を使用して接続を行いました。

plinkの場合は以下のコマンドで接続します。COMポートはコントロールパネルから確認したCOMポートを指定します。

plink -serial \\.\com5

ユーザー名とパスワードを入力してログインします。

plinkで接続

Bashの警告が出ていますがログインはできましたのでいったん良しとします。

rfcommのサービス登録

rfcomm コマンドを systemd のサービスに登録して自動起動するようにユニットファイルを作成しました。

ユニットファイルは「/etc/systemd/system/rfcomm22.service」としました。

/etc/systemd/system/rfcomm22.service
[Unit]
Description=rfcomm (0;22) agetty service
After=bluetooth.service
Requires=bluetooth.service

[Service]
ExecStart=/usr/bin/rfcomm watch 0 22 /sbin/agetty rfcomm0 linux

[Install]
WantedBy=multi-user.target

bluetooth.serviceに依存するようにAfterとRequiresを設定しています。

新たにユニットファイルを作成したのでデーモンをリロードします。

sudo systemctl daemon-reload

サービスの自動起動を有効にします。

sudo systemctl enable rfcomm22.service

再起動しての疎通確認

Raspberry Pi Zero Wを再起動して接続できるか確認します。

sudo reboot now

再起動が完了したらWindows PCから疎通の確認を行いました。

疎通の確認

無事つながりました。

まとめ

以下の手順でRaspberry Pi Zero WにWindows PCからBluetooth経由のシリアル通信でログインを行いました。

  1. ラズパイとPCをBluetoothでペアリングする
  2. ラズパイのBluetoothサービスの起動コマンドにcompatオプションを追加する
  3. ラズパイのBluetoothのシリアルポートにチャネルを追加する
  4. rfcommでシリアルポートのチャネルを待ち受けてagettyにつなぐ
  5. PCからターミナルエミュレータでCOMポート経由で接続する

Bashの警告が表示されるのは課題として残りました。