ラズパイ1個で2個の4GPiを同時使用する際の、LTE回線自動切換え

## はじめに.
今回は 4GPi を __2台__ 使用して、自動的な LTE 回線の切換えを実装します。
2種類（ホットスタンバイ、コールドスタンバイ）の実装方法を紹介します。
各実装の動作検証では、SORACOM Air for セルラーの SIM を操作して通信回線を切断、復旧させます。

実行環境は [前回記事](https://qiita.com/kiyonaga/items/f1ed69f794c0e7ad7054#%E5%AE%9F%E8%A1%8C%E7%92%B0%E5%A2%83) をご参照ください。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/cb9da685-6e00-28c4-9981-33fafae949e2.jpeg">

::: note info
* この記事は [ラズパイ1個に4GPiを2個スタックし、LTE 回線の冗長化＆障害耐性を向上](https://qiita.com/kiyonaga/items/f1ed69f794c0e7ad7054) からの続きとなります。
セットアップがお済みでない場合は前回記事をご参照ください。
* SORACOM SIM の操作は [SORACOM ユーザーコンソール](https://users.soracom.io/ja-jp/docs/user-console/) から行います。あらかじめ SORACOM アカウント等の登録は済ませておいてください。
* この記事に記載されているネットワークの通信速度や応答時間に関する情報は、使用している SIM や環境、ネットワークの混雑度などにより異なる可能性があります。あらかじめご了承ください。
:::

## {ホット, ウォーム, コールド} スタンバイ構成の利点と欠点
<dl>
<dt>ホットスタンバイ</dt>
<dd>
ネットワークデバイスが常時アクティブな状態を維持します。バックアップデバイスは常にメインデバイスと同様にオンラインのネットワークで構成され、データ通信が継続的に行われます。

利点: フェイルオーバーが迅速で、ほとんどの場合、サービスの中断がほとんどないか、非常に短いです。

欠点: オンラインの維持や再接続のために消費電力がかかります。
</dd>

<dt>ウォームスタンバイ</dt>
<dd>
ネットワークデバイスが常時アクティブな状態を保っている一方で、バックアップデバイスのネットワークはオフラインで構成されます。フェイルオーバーによりバックアップデバイスのネットワークがオンラインに切り替わります。

利点: オンラインのネットワークを切り替えるため、ホットスタンバイよりも消費電力が低いことがあります。

欠点: フェイルオーバーまでの時間がホットスタンバイよりも遅いため、サービスの一時的な中断が発生する可能性があります。
</dd>

<dt>コールドスタンバイ</dt>
<dd>
バックアップデバイスはアクティブな状態ではなく、メインデバイスのフェイルオーバー時に起動する必要があります。これにより、冗長性が提供されますが、フェイルオーバーまでの時間が最もかかります。

利点: 消費電力が最小です。

欠点: フェイルオーバーまでの時間がほかのスタンバイモデルよりもかかり、サービスの中断が比較的大きい可能性があります。
</dd>
</dl>

## SORACOM ユーザーコンソールでの SIM 休止と使用開始の手順
ブラウザでの操作手順を示します。

### 休止手順
手順は次の a ~ c の通りです。

a. SORACOM ユーザーコンソールにログイン後、「SIM 管理」を選択

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/95cc4f0f-f4c4-5c71-50b6-cce591f532d9.jpeg">

b. 該当 SIM をチェックして、「操作」から「休止」を選択

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/bff2245e-bc6e-795d-b27d-948af48b7b9e.jpeg">

c.「休止する」ボタンをクリック

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/af65ac4f-2d00-42a3-a085-60c3579fa724.jpeg">

### 使用開始手順
手順は次の d ~ f の通りです。

d. SORACOM ユーザーコンソールにログイン後、「SIM 管理」を選択

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/95cc4f0f-f4c4-5c71-50b6-cce591f532d9.jpeg">

e. 該当 SIM をチェックして、「操作」から「使用開始」を選択

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/19830c5f-86a0-018f-62bc-fa6dece0abf1.jpeg">

f. 「使用開始する」ボタンをクリック
<img width="430" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174732/b57a0558-f77e-1f12-d350-e33992ac3071.jpeg">

## ホットスタンバイ構成の実装
本項では2台の 4GPi を LTE 回線に接続し、障害が発生した場合にはもう一方の回線に自動的に通信を切換える仕組みを実装します。

実装とは言うものの、実際には NetworkManager が提供している機能を活用します。

### ネットワーク設定
nmcli コマンドでルーティングメトリックを設定します。
ルーティングメトリックは値が小さいほど優先順位が高いため、主回線の soracom を 500、副回線の ntt を 700 に設定します。

次のコマンドを実行してください。

```:ターミナル
sudo nmcli c m soracom ipv4.route-metric 500
sudo nmcli c m ntt ipv4.route-metric 700
sudo nmcli c down soracom
sudo nmcli c down ntt
sudo nmcli c up soracom
sudo nmcli c up ntt
```

route コマンドで設定が適用されているかどうか確認します。

```:コマンド実行結果例
mtx@raspberrypi:~$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         10.230.***.***    0.0.0.0         UG    500    0        0 wwan0
default         10.128.***.***  0.0.0.0         UG    700    0        0 wwan1
10.128.***.***  0.0.0.0         255.255.***.*** U     700    0        0 wwan1
10.230.***.***    0.0.0.0         255.255.***.*** U     500    0        0 wwan0
```

10.230...が soracom、10.128...が ntt となります。

### 動作検証
SORACOM の SIM を一時的に休止して、soracom のセッションを切断します。
休止後、使用開始してネットワークに再接続します。

#### 回線の切換わり確認
[休止手順](https://qiita.com/kiyonaga/items/3ec36d6d6625ae85414a#%E4%BC%91%E6%AD%A2%E6%89%8B%E9%A0%86) を実行します。

※ 以降の " ... " 部分はログを省略しています

```:システムログ
mtx@raspberrypi:~$ journalctl | less
...
Jan 12 09:42:34 raspberrypi NetworkManager[571]: <warn>  [1705020154.3782] devic
e (cdc-wdm0): Activation: failed for connection 'soracom'
Jan 12 09:42:34 raspberrypi NetworkManager[571]: <info>  [1705020154.3837] devic
e (cdc-wdm0): state change: failed -> disconnected (reason 'none', sys-iface-sta
te: 'managed')
Jan 12 09:42:34 raspberrypi dbus-daemon[488]: [system] Activating via systemd: s
ervice name='org.freedesktop.nm_dispatcher' unit='dbus-org.freedesktop.nm-dispat
cher.service' requested by ':1.7' (uid=0 pid=571 comm="/usr/sbin/NetworkManager
--no-daemon")
Jan 12 09:42:34 raspberrypi systemd[1]: Starting NetworkManager-dispatcher.servi
ce - Network Manager Script Dispatcher Service...
Jan 12 09:42:34 raspberrypi NetworkManager[571]: <info>  [1705020154.4728] polic
y: set 'ntt' (wwan1) as default for IPv4 routing and DNS
Jan 12 09:42:34 raspberrypi dbus-daemon[488]: [system] Successfully activated se
rvice 'org.freedesktop.nm_dispatcher'
Jan 12 09:42:34 raspberrypi systemd[1]: Started NetworkManager-dispatcher.servic
e - Network Manager Script Dispatcher Service.
```

soracom が切断され、デフォルトルートが ntt に切換わったログが見えます。

#### 通信中の切断
通信中に [休止手順](https://qiita.com/kiyonaga/items/3ec36d6d6625ae85414a#%E4%BC%91%E6%AD%A2%E6%89%8B%E9%A0%86) を実行した際の挙動を確認します。
システムログをバックグラウンドで流しながら、ping を実行します。

```:システムログ
mtx@raspberrypi:~$ journalctl -f &
...
ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=119 time=107 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=119 time=63.5 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=119 time=62.7 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=119 time=59.6 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=116 time=238 ms
Jan 12 09:45:11 raspberrypi ModemManager[580]: <info>  [modem1/bearer3] verbose call end reason (6,39): [3gpp] reattach-required
Jan 12 09:45:11 raspberrypi ModemManager[580]: <info>  [modem1] state changed (connected -> registered)
Jan 12 09:45:11 raspberrypi ModemManager[580]: <info>  [modem1/bearer3] connection #10 finished: duration 30s, tx: 0 bytes, rx: 0 bytes
Jan 12 09:45:11 raspberrypi NetworkManager[571]: <info>  [1705020311.9676] device (cdc-wdm0): state change: activated -> failed (reason 'modem-no-carrier', sys-iface-state: 'managed')
Jan 12 09:45:11 raspberrypi NetworkManager[571]: <warn>  [1705020311.9743] device (cdc-wdm0): Activation: failed for connection 'soracom'
Jan 12 09:45:11 raspberrypi dbus-daemon[488]: [system] Activating via systemd: service name='org.freedesktop.nm_dispatcher' unit='dbus-org.freedesktop.nm-dispatcher.service' requested by ':1.7' (uid=0 pid=571 comm="/usr/sbin/NetworkManager --no-daemon")
Jan 12 09:45:11 raspberrypi NetworkManager[571]: <info>  [1705020311.9797] device (cdc-wdm0): state change: failed -> disconnected (reason 'none', sys-iface-state: 'managed')
Jan 12 09:45:12 raspberrypi systemd[1]: Starting NetworkManager-dispatcher.service - Network Manager Script Dispatcher Service...
Jan 12 09:45:12 raspberrypi NetworkManager[571]: <info>  [1705020312.0656] policy: set 'ntt' (wwan1) as default for IPv4 routing and DNS
Jan 12 09:45:12 raspberrypi dbus-daemon[488]: [system] Successfully activated service 'org.freedesktop.nm_dispatcher'
Jan 12 09:45:12 raspberrypi systemd[1]: Started NetworkManager-dispatcher.service - Network Manager Script Dispatcher Service.
...
64 bytes from 8.8.8.8: icmp_seq=6 ttl=116 time=63.2 ms
...
64 bytes from 8.8.8.8: icmp_seq=7 ttl=116 time=41.5 ms
...
64 bytes from 8.8.8.8: icmp_seq=8 ttl=116 time=67.8 ms
...
64 bytes from 8.8.8.8: icmp_seq=9 ttl=116 time=67.7 ms
64 bytes from 8.8.8.8: icmp_seq=10 ttl=116 time=64.7 ms
64 bytes from 8.8.8.8: icmp_seq=11 ttl=116 time=65.8 ms
64 bytes from 8.8.8.8: icmp_seq=12 ttl=116 time=62.7 ms
64 bytes from 8.8.8.8: icmp_seq=13 ttl=116 time=50.7 ms
^C
--- 8.8.8.8 ping statistics ---
13 packets transmitted, 13 received, 0% packet loss, time 12020ms
rtt min/avg/max/mdev = 41.508/78.096/237.977/48.277 ms
```

ping の応答時間が `time=238 ms` となった際に、デフォルトルートが ntt に切換わったログを確認できました。

通信の応答時間は増加しましたが、通信自体は途切れることなく継続しています。

#### 自動再接続の確認

NetworkManager は定期的に再接続を試行するため回線復旧時には自動で soracom に切換わります。
SIM を休止した状態で [使用開始手順](https://qiita.com/kiyonaga/items/3ec36d6d6625ae85414a#%E4%BD%BF%E7%94%A8%E9%96%8B%E5%A7%8B%E6%89%8B%E9%A0%86) を実行します。

```:システムログ
Jan 12 10:00:38 raspberrypi ModemManager[580]: <info>  [modem1] state changed (registered -> connecting)
Jan 12 10:00:38 raspberrypi ModemManager[580]: <info>  [modem1/bearer5] couldn't start network: QMI protocol error (14): 'CallFailed'
Jan 12 10:00:38 raspberrypi ModemManager[580]: <info>  [modem1/bearer5] verbose call end reason (2,211): [internal] pdn-ipv6-call-throttled
Jan 12 10:00:38 raspberrypi ModemManager[580]: <warn>  [modem1/bearer5] connection attempt #21 failed: Call failed: internal error: pdn-ipv6-call-throttled
Jan 12 10:00:38 raspberrypi ModemManager[580]: <info>  [modem1] state changed (connecting -> registered)
Jan 12 10:00:38 raspberrypi ModemManager[580]: <info>  [modem1/bearer5] connection #21 finished: duration 0s
Jan 12 10:05:39 raspberrypi NetworkManager[571]: <info>  [1705021539.1542] policy: auto-activating connection 'soracom' (55188339-48f5-42a8-8cd9-f6763f7fc753)
...
Jan 12 10:05:40 raspberrypi NetworkManager[571]: <info>  [1705021540.4672] device (cdc-wdm0): Activation: successful, device activated.
Jan 12 10:05:50 raspberrypi systemd[1]: NetworkManager-dispatcher.service: Deactivated successfully.
```

10:02 ごろに使用開始手順を実行しました。
再接続が完了するまで3分程度でした。

## コールドスタンバイ構成の実装
本項では1台の 4GPi を LTE 回線に接続しておき、障害が発生した場合には、もう1台の 4GPi を起動させて回線を切換える仕組みを実装します。

実装内容としては、[nmcli コマンド](https://people.freedesktop.org/~lkundrak/nm-docs/nmcli.html) と [4gpictl コマンド](https://github.com/mechatrax/4gpi-utils?tab=readme-ov-file#usrsbin4gpictl) を使用した bash スクリプトファイルを作成し、[systemd.service](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#) と組み合わて回線の定期監視をします。

### bash スクリプトファイル配置
次の4つのファイルを /opt/dual に配置します。
※ /opt/dual フォルダはあらかじめ作成しておいてください

* dual-functions.sh
他スクリプトから呼び出される関数群

```:/opt/dual/dual-functions.sh
#!/bin/bash

DIR=$(dirname $0)
. $DIR/properties.txt

get_online_conname () {
  conname=$(nmcli d | grep -P 'cdc-wdm\d.*\s+connected' | awk '{print $4}')
  echo "Online: $conname"
}

switch_lte () {
  local max_retry=$1
  local wait_interval=$2
  local online_tmpfile=$3
  local tmp_online=$4

  if [ "$tmp_online" == "$CONN_4GPI_1" ]; then
    target_conn=$CONN_4GPI_2
    target_conf=$CONF_4GPI_2
    offline_conn=$CONN_4GPI_1
    offline_conf=$CONF_4GPI_1
  else
    target_conn=$CONN_4GPI_1
    target_conf=$CONF_4GPI_1
    offline_conn=$CONN_4GPI_2
    offline_conf=$CONF_4GPI_2
  fi

  for ((retry_count=0; retry_count < $max_retry; retry_count++)); do
    echo "$target_conn up"
    4gpictl -c $target_conf poweron
    sleep $wait_interval
    nmcli c up $target_conn
    if [[ "$(get_online_conname)" == *"$target_conn"* ]]; then
      break
    fi
  done
  echo $target_conn > $online_tmpfile

  echo "$offline_conn down"
  nmcli c down $offline_conn >/dev/null 2>&1 || true
  for ((retry_count=0; retry_count < $max_retry; retry_count++)); do
    4gpictl -c $offline_conf poweroff || true
    if [ "$(4gpictl -c $offline_conf status)" == "off" ]; then
      break
    fi
  done
}
```

* initialize-lte.sh
1つの回線のみを有効化するスクリプト
今回は SORACOM Air が有効となる設定にしています。

```:/opt/dual/initialize-lte.sh
#!/bin/bash

DIR=$(dirname $0)
. $DIR/properties.txt
. $DIR/dual-functions.sh

switch_lte $MAX_RETRY $WAIT_INTERVAL $ONLINE $CONN_4GPI_2
```

* properties.txt
他スクリプトに読み込まれる設定ファイル

```:/opt/dual/properties.txt
ONLINE=/tmp/dual-online
CONN_4GPI_1=soracom
CONN_4GPI_2=ntt
CONF_4GPI_1=/etc/default/4gpi-1
CONF_4GPI_2=/etc/default/4gpi-2
MAX_RETRY=3
WAIT_INTERVAL=5
MONITORING_INTERVAL=10
```

::: note info
CONN_4GPI_* や CONF_4GPI_* 等の設定値は適宜変更してください。
:::

* monitoring-lte.sh
回線接続をもう一方の登録済み回線に切換えるスクリプト
```:/opt/dual/monitoring-lte.sh
#!/bin/bash

DIR=$(dirname $0)
. $DIR/properties.txt
. $DIR/dual-functions.sh

while :; do
  online_conn=$(get_online_conname)
  if [[ "$online_conn" == *"$CONN_4GPI_1"* ]] || [[ "$online_conn" == *"$CONN_4GPI_2"* ]]; then
    echo $online_conn
  else
    tmp_online=$(cat $ONLINE)
    switch_lte $MAX_RETRY $WAIT_INTERVAL $ONLINE $tmp_online
  fi
  sleep $MONITORING_INTERVAL
done
```

### スクリプトファイル動作確認
自動化前に initialize-lte.sh と monitoring-lte.sh を手動実行して動作確認します。

#### initialize-lte.sh
あらかじめ次のコマンドで 4GPi-1 の回線接続を切ります。

```:ターミナル
sudo nmcli c down soracom
```

```:接続断後
mtx@raspberrypi:~$ nmcli d
DEVICE         TYPE      STATE                   CONNECTION
cdc-wdm1       gsm       connected               ntt
lo             loopback  connected (externally)  lo
cdc-wdm0       gsm       disconnected            --
wlan0          wifi      disconnected            --
p2p-dev-wlan0  wifi-p2p  disconnected            --
eth0           ethernet  unavailable             --
```

次のコマンドでスクリプトを実行します。

```:ターミナル
sudo bash /opt/dual/initialize-lte.sh
```

```:スクリプト実行結果例
mtx@raspberrypi:~$ sudo bash /opt/dual/initialize-lte.sh
soracom up
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/27)
ntt down
```

```:スクリプト実行後の接続状態
mtx@raspberrypi:~$ nmcli d
DEVICE         TYPE      STATE                   CONNECTION
cdc-wdm0       gsm       connected               soracom
lo             loopback  connected (externally)  lo
cdc-wdm1       gsm       disconnected            --
wlan0          wifi      disconnected            --
p2p-dev-wlan0  wifi-p2p  disconnected            --
eth0           ethernet  unavailable             --
```

soracom が connected となり、ntt が disconnected であれば問題ありません。

念のため、4gpictl コマンドで 4GPi-2 の電源状態も確認します。
```:コマンド実行結果例
mtx@raspberrypi:~$ 4gpictl -c /etc/default/4gpi-2 status
off
```

#### monitoring-lte.sh
このスクリプトは接続中の回線がある場合、回線切換えを行いません。
次のコマンドであらかじめ接続中の回線を切ります。

```:ターミナル
sudo nmcli c down soracom
sudo nmcli c down ntt
```

接続断後、次のコマンドでスクリプトを実行します。

```:ターミナル
sudo bash /opt/dual/initialize-lte.sh
```

```:スクリプト実行結果例
mtx@raspberrypi:~$ sudo bash /opt/dual/monitoring-lte.sh
ntt up
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/31)
soracom down
Online: ntt
Online: ntt
```
※ スクリプトはループ処理なので `Online:*` が見えたら、Ctrl+c 等で終了してください

```:スクリプト実行後の接続状態
mtx@raspberrypi:~$ nmcli d
DEVICE         TYPE      STATE                   CONNECTION
cdc-wdm1       gsm       connected               ntt
lo             loopback  connected (externally)  lo
cdc-wdm0       gsm       disconnected            --
wlan0          wifi      disconnected            --
p2p-dev-wlan0  wifi-p2p  disconnected            --
eth0           ethernet  unavailable             --
```

もともと soracom が接続されていた場合は、ntt が connected となれば問題ありません。

### サービスファイル配置
次の2つのファイルを /etc/systemd/system フォルダに作成します。

* 4gpi-lte-initialize.service
起動時、initialize-lte.sh を実行するサービスファイル

```:/etc/systemd/system/4gpi-lte-initialize.service
[Unit]
Description=Initialize 4GPi LTE Networks
DefaultDependencies=no
BindsTo=dev-tty4GPI.device dev-tty4GPI-1.device dev-tty4GPI-2.device
After=4gpi-1-setup.service 4gpi-2-setup.service dev-tty4GPI.device

[Service]
Type=oneshot
ExecStart=/bin/bash /opt/dual/initialize-lte.sh

[Install]
WantedBy=multi-user.target
```

* 4gpi-lte-monitoring.service
monitoring-lte.sh を実行するサービスファイル

```:/etc/systemd/system/4gpi-lte-monitoring.service
[Unit]
Description=4GPi LTE Networks monitoring
After=4gpi-lte-initialize.service
Wants=4gpi-lte-initialize.service

[Service]
Type=simple
ExecStart=/bin/bash /opt/dual/monitoring-lte.sh
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target
```

### サービス有効化
ファイル配置後、次のコマンドを実行してサービスを有効化してください。
```:ターミナル
sudo systemctl enable 4gpi-lte-initialize.service
sudo systemctl enable 4gpi-lte-monitoring.service
sudo systemctl start 4gpi-lte-monitoring.service
```

### サービス動作確認

#### 4gpi-lte-initialize.service
起動時、soracom が接続され、ntt が切断されます。
※ 切断の際、4GPi-2 も電源オフとなります

```:起動時のシステムログ
mtx@raspberrypi:~$ journalctl -u 4gpi-lte-initialize.service | less
Jan 05 13:41:33 raspberrypi systemd[1]: Starting 4gpi-lte-initialize.service - Initialize 4GPi LTE Networks...
Jan 05 13:41:33 raspberrypi bash[783]: soracom up
Jan 05 13:41:51 raspberrypi bash[891]: Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)
Jan 05 13:41:51 raspberrypi bash[783]: ntt down
Jan 05 13:42:52 raspberrypi systemd[1]: 4gpi-lte-initialize.service: Deactivated successfully.
Jan 05 13:42:52 raspberrypi systemd[1]: Finished 4gpi-lte-initialize.service - Initialize 4GPi LTE Networks.
```

#### 4gpi-lte-monitoring.service
10 秒間隔で接続状態を監視します。
接続中の回線があれば Online: soracom のような出力となります。

```:接続状態監視中のシステムログ
mtx@raspberrypi:~$ journalctl -u 4gpi-lte-monitoring.service -f
Jan 12 10:46:46 raspberrypi systemd[1]: Started 4gpi-lte-monitoring.service - 4GPi LTE Networks monitoring.
Jan 12 10:46:47 raspberrypi bash[993]: Online: soracom
Jan 12 10:47:13 raspberrypi bash[993]: Online: soracom
Jan 12 10:47:24 raspberrypi bash[993]: Online: soracom
```

接続中の回線がなければ、次のログのように回線の切換えが行われます。

```
mtx@raspberrypi:~$ journalctl -u 4gpi-lte-monitoring.service -f &
[1] 1011
mtx@raspberrypi:~$ Jan 12 10:52:06 raspberrypi systemd[1]: Started 4gpi-lte-monitoring.service - 4GPi LTE Networks monitoring.
Jan 12 10:52:06 raspberrypi bash[994]: Online: soracom
Jan 12 10:52:16 raspberrypi bash[994]: Online: soracom
sudo nmcli c down soracom
Connection 'soracom' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)
mtx@raspberrypi:~$ Jan 12 10:52:26 raspberrypi bash[994]: ntt up
Jan 12 10:52:49 raspberrypi bash[1140]: Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/5)
Jan 12 10:52:49 raspberrypi bash[994]: soracom down
Jan 12 10:53:13 raspberrypi bash[994]: Online: ntt
```

### 動作検証
ホットスタンバイ時と同様に SIM を一時休止して、soracom のセッションを切断します。

#### 回線の切換わり確認
[休止手順](https://qiita.com/kiyonaga/items/3ec36d6d6625ae85414a#%E4%BC%91%E6%AD%A2%E6%89%8B%E9%A0%86) を実行します。

```:システムログ
mtx@raspberrypi:~$ journalctl -u 4gpi-lte-monitoring.service -f
Jan 12 10:55:42 raspberrypi systemd[1]: Started 4gpi-lte-monitoring.service - 4GPi LTE Networks monitoring.
Jan 12 10:55:42 raspberrypi bash[997]: Online: soracom
Jan 12 10:55:52 raspberrypi bash[997]: Online: soracom
Jan 12 10:56:02 raspberrypi bash[997]: ntt up
Jan 12 10:56:25 raspberrypi bash[1137]: Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/8)
Jan 12 10:56:25 raspberrypi bash[997]: soracom down
Jan 12 10:56:49 raspberrypi bash[997]: Online: ntt
```

soracom から ntt に接続が切換わったログが確認できました。

#### 通信中の切断
通信中に [休止手順](https://qiita.com/kiyonaga/items/3ec36d6d6625ae85414a#%E4%BC%91%E6%AD%A2%E6%89%8B%E9%A0%86) を実行した際の挙動を確認します。
システムログをバックグラウンドで流しながら、ping を実行します。

```:システムログ
mtx@raspberrypi:~$ journalctl -u 4gpi-lte-monitoring.service -f &
Jan 12 11:01:23 raspberrypi bash[993]: Online: soracom
Jan 12 11:01:33 raspberrypi bash[993]: Online: soracom
ping 8.8.8.8 | xargs -I_ date +'%c _'
Fri 12 Jan 2024 11:01:35 JST PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
Fri 12 Jan 2024 11:01:35 JST 64 bytes from 8.8.8.8: icmp_seq=1 ttl=119 time=249 ms
Fri 12 Jan 2024 11:01:36 JST 64 bytes from 8.8.8.8: icmp_seq=2 ttl=119 time=57.7 ms
Fri 12 Jan 2024 11:01:37 JST 64 bytes from 8.8.8.8: icmp_seq=3 ttl=119 time=61.3 ms
Fri 12 Jan 2024 11:01:38 JST 64 bytes from 8.8.8.8: icmp_seq=4 ttl=119 time=50.9 ms
Jan 12 11:01:43 raspberrypi bash[993]: ntt up
Jan 12 11:02:06 raspberrypi bash[1636]: Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/13)
Fri 12 Jan 2024 11:02:06 JST 64 bytes from 8.8.8.8: icmp_seq=31 ttl=57 time=86.0 ms
Jan 12 11:02:06 raspberrypi bash[993]: soracom down
Fri 12 Jan 2024 11:02:07 JST 64 bytes from 8.8.8.8: icmp_seq=32 ttl=57 time=42.7 ms
Fri 12 Jan 2024 11:02:08 JST 64 bytes from 8.8.8.8: icmp_seq=33 ttl=57 time=40.9 ms
Fri 12 Jan 2024 11:02:09 JST 64 bytes from 8.8.8.8: icmp_seq=34 ttl=57 time=39.7 ms
Fri 12 Jan 2024 11:02:10 JST 64 bytes from 8.8.8.8: icmp_seq=35 ttl=57 time=37.8 ms
Fri 12 Jan 2024 11:02:11 JST 64 bytes from 8.8.8.8: icmp_seq=36 ttl=57 time=56.6 ms
Fri 12 Jan 2024 11:02:12 JST 64 bytes from 8.8.8.8: icmp_seq=37 ttl=57 time=54.6 ms
```

ntt への切換わりを確認できましたが、ping が約 30 秒間途切れました。
なお、xargs で付加した日時は目安であり、ping の結果と同期しない場合もあります。

通信が一時的に途切れましたが、もう一方の 4GPi で通信が再開されています。

## おわりに. 
今回は、通信障害発生時の回線切換え方法として、ホットスタンバイとコールドスタンバイの2種類を紹介しました。

用途に応じて、適切な回線切換え方法を実装してみてください。