概要
簡単にRaspberry PiでSORACOM Airを使う(FS01BU USBモデムを用いて自動接続)で紹介されているような方法を使うとFS01BU USBモデム+SORACOM AirのSIMの組み合わせでブート時に自動接続できるようになりますが、デバイス挿入時に自動接続させたかったので、その方法をまとめます。OS は Raspbian です。
udev
でデバイス挿抜時に ifup/ifdown
を実行することで実現します。
準備
必要なパッケージをインストールします。
pi@raspberrypi:~ $ sudo apt-get install wvdial usb-modeswitch
手動接続用のスクリプトをダウンロードします。
pi@raspberrypi:~ $ curl -O http://soracom-files.s3.amazonaws.com/connect_air.sh
pi@raspberrypi:~ $ chmod 755 ./connect_air.sh
モデムを挿した状態で実行して手動接続できることを確認します。
pi@raspberrypi:~ $ sudo ./connect_air.sh
この際、 /etc/wvdial.conf が生成されるので、以下ではそれを編集して使います。私の環境では以下が生成されます。
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CGDCONT=1,"IP","soracom.io"
Dial Attempts = 3
Stupid Mode = 1
Modem Type = Analog Modem
Dial Command = ATD
Stupid Mode = yes
Baud = 460800
New PPPD = yes
Modem = /dev/ttyUSB2
ISDN = 0
APN = soracom.io
Phone = *99***1#
Username = sora
Password = sora
Carrier Check = no
Auto DNS = 1
Check Def Route = 1
ifup で接続できるようにする
/etc/network/interfaces
に以下を追記します。
allow-hotplug soracom
iface soracom net wvdial
ifup soracom
で接続されることを確認します。
pi@raspberrypi:~ $ sudo ifup soracom
pi@raspberrypi:~ $ ifconfig ppp0
ppp0 Link encap:Point-to-Pointプロトコル
inetアドレス:10.xxx.xxx.xxx P-t-P:10.64.64.64 マスク:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 メトリック:1
RXパケット:7 エラー:0 損失:0 オーバラン:0 フレーム:0
TXパケット:8 エラー:0 損失:0 オーバラン:0 キャリア:0
衝突(Collisions):0 TXキュー長:3
RXバイト:130 (130.0 B) TXバイト:181 (181.0 B)
ifdown soracom
で切断できます。
pi@raspberrypi:~ $ sudo ifdown soracom
pi@raspberrypi:~ $ ifconfig ppp0
ppp0: インタフェース情報を取得中にエラーが発生しました: デバイスが見つかりません
接続が切れても自動で再接続できるようにする
/etc/ppp/peers/wvdial
で persist
オプションを有効にします。
--- a/ppp/peers/wvdial
+++ b/ppp/peers/wvdial
@@ -2,3 +2,5 @@ noauth
name wvdial
usepeerdns
replacedefaultroute
+persist
+holdoff 10
デバイス名を固定する
USBシリアルデバイスが1つしか接続されていない場合、ブート時に FS01BU が認識されると、
/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyUSB2
の3つのデバイスファイルを作成され、ダイヤルアップに使われるのは /dev/ttyUSB2
です。しかし、他の USB シリアルデバイスが接続されていると認識順序によってこれがずれます。また、 FS01BU だけ接続されていても活線挿抜によりデバイス番号がずれることがあります。
このため、デバイス名を固定するを参考にデバイス名を固定します。ただし、誤判定を避けるため bNumEndpoints
と bInterfaceNumber
だけではなく idVendor
と idProduct
も ATTRS{../
によって参照します。
KERNEL=="ttyUSB*", ATTRS{../idVendor}=="1c9e", ATTRS{../idProduct}=="6801", ATTRS{bNumEndpoints}=="02", ATTRS{bInterfaceNumber}=="02", SYMLINK+="modem"
リブートしてシンボリックリンクが張られていることを確認します。
pi@raspberrypi:~ $ ls -l /dev/ttyUSB* /dev/modem
lrwxrwxrwx 1 root root 7 2月 26 07:48 /dev/modem -> ttyUSB2
crw-rw---- 1 root dialout 188, 0 2月 26 07:48 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 2月 26 07:48 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 2月 26 07:48 /dev/ttyUSB2
wvdial
はデフォルトで /dev/modem
を使うので、 /etc/vwconf.conf
で /dev/ttyUSB2
を指定している箇所を削除します。
--- a/wvdial.conf
+++ b/wvdial.conf
@@ -9,7 +9,6 @@ Dial Command = ATD
Stupid Mode = yes
Baud = 460800
New PPPD = yes
-Modem = /dev/ttyUSB2
ISDN = 0
APN = soracom.io
Phone = *99***1#
再度 ifup soracom
で接続されることを確認します。
デバイス挿入時に接続する
Raspberry Pi 2 + systemd + udevで、USBデバイス挿入時にサービスを起動するに倣って先程の udev
ルールを以下のように書き換えます。後述するように action
を記述しないのがポイントです。
KERNEL=="ttyUSB*", ATTRS{../idVendor}=="1c9e", ATTRS{../idProduct}=="6801", ATTRS{bNumEndpoints}=="02", ATTRS{bInterfaceNumber}=="02", SYMLINK+="modem", ENV{SYSTEMD_WANTS}="ifup@soracom"
リブートすると、デバイス認識時に ifup soracom
が自動実行されて接続されます。
pi@raspberrypi:~ $ ls -l /dev/ttyUSB* /dev/modem
lrwxrwxrwx 1 root root 7 2月 26 20:55 /dev/modem -> ttyUSB2
crw-rw---- 1 root dialout 188, 0 2月 26 20:55 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 2月 26 20:55 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 2月 26 22:10 /dev/ttyUSB2
pi@raspberrypi:~ $ ifconfig ppp0
ppp0 Link encap:Point-to-Pointプロトコル
inetアドレス:10.xxx.xxx.xxx P-t-P:10.64.64.64 マスク:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 メトリック:1
RXパケット:7 エラー:0 損失:0 オーバラン:0 フレーム:0
TXパケット:8 エラー:0 損失:0 オーバラン:0 キャリア:0
衝突(Collisions):0 TXキュー長:3
RXバイト:130 (130.0 B) TXバイト:181 (181.0 B)
この状態でデバイスを抜いて挿すと、デバイス番号がずれますが、シンボリックリンクが追従し、再接続されます。
pi@raspberrypi:~ $ ls -l /dev/ttyUSB* /dev/modem
lrwxrwxrwx 1 root root 7 2月 26 23:10 /dev/modem -> ttyUSB3
crw-rw---- 1 root dialout 188, 0 2月 26 23:10 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 2月 26 23:10 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 3 2月 26 23:12 /dev/ttyUSB3
pi@raspberrypi:~ $ ifconfig ppp0
ppp0 Link encap:Point-to-Pointプロトコル
inetアドレス:10.xxx.xxx.xxx P-t-P:10.64.64.64 マスク:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 メトリック:1
RXパケット:7 エラー:0 損失:0 オーバラン:0 フレーム:0
TXパケット:8 エラー:0 損失:0 オーバラン:0 キャリア:0
衝突(Collisions):0 TXキュー長:3
RXバイト:130 (130.0 B) TXバイト:181 (181.0 B)
補足
wvdial で他の接続先も使う場合
/etc/wvdial.conf
に Defaults
以外の Dialer セクションを作りそちらに SORACOM 用の設定を移します。
その上で、 /etc/network/interfaces
で provider としてそのセクションを指定します。
例
--- a/wvdial.conf
+++ b/wvdial.conf
@@ -1,4 +1,4 @@
-[Dialer Defaults]
+[Dialer soracom]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CGDCONT=1,"IP","soracom.io"
--- a/network/interfaces
+++ b/network/interfaces
@@ -25,3 +25,4 @@ iface wlan1 inet manual
allow-hotplug soracom
iface soracom inet wvdial
+ provider soracom
ifdown
について
systemd
の Unit ファイルには ifup@.service
はあっても、 ifdown@.service
はないのですが、
pi@raspberrypi:~ $ systemctl list-unit-files | grep 'if.*@'
ifup@.service static
ifup@.service
の中身が以下のようになっており、 udev
ルールで action
を書かなければ add
時に ifup
、 remove
時に ifdown
が実行されます。
pi@raspberrypi:~ $ cat /lib/systemd/system/ifup@.service
[Unit]
Description=ifup for %I
After=local-fs.target network-pre.target networking.service
Before=network.target
BindsTo=sys-subsystem-net-devices-%i.device
ConditionPathIsDirectory=/run/network
DefaultDependencies=no
[Service]
ExecStart=/sbin/ifup --allow=hotplug %I
ExecStop=/sbin/ifdown %I
RemainAfterExit=true
参考
下記の手法を組み合わせることで実現できました。ありがとうございます。
簡単にRaspberry PiでSORACOM Airを使う(FS01BU USBモデムを用いて自動接続)
デバイス名を固定する
Raspberry Pi 2 + systemd + udevで、USBデバイス挿入時にサービスを起動する