Raspberry PiでSIMの電波強度を測定する

## 概要
LTEのSIM通信で電波がぎりぎり届く場所の電波強度を測定する必要が発生し、先ずは電波環境の良い自宅でRaspberry Piを使ってSIMの電波強度を測定したので、その結果をまとめてみました。
![IMG_8437.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/98a735a8-d261-0ac6-898f-64004e6a1668.jpeg)
## 環境
今回用意したSIMはドコモのエリアをカバーするSORACOMのplan-Dです。
機材は以下の構成で試験しました。
・Raspberry Pi3 ＋ LTE通信モジュール（4GPI）
・Raspberry Pi4 + USBモデム（MS2372-607）
OSはいずれもRaspbianですが、Raspberry Pi3の方は4GPI用の4gpi-buster-lite-20200612.zipを用いて、最新の状態にアップデートして利用しました。
### Raspberry Pi4 + USBモデム（MS2372-607）環境構築例
4GPI利用の例は省略し、一般的なUSBモデムの環境構築例を簡単に説明します。
USBモデムを差し込み、コマンド lsusb を実行すると、Device 004 でモデムが認識されていることが確認できます。

```bash
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 12d1:1506 Huawei Technologies Co., Ltd. Modem/Networkcard
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```
USBモデム（MS2372-607）は /dev/ttyUSB0 で認識されています。
参考までに、4GPI の場合は /dev/tty4GPI となります。

```bash
$ ls -al /dev/ttyUSB*
crw-rw-rw- 1 root dialout 188, 0 Sep 22 00:19 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 Sep 22 00:11 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 Sep 22 00:11 /dev/ttyUSB2
```
SORACOM Air は以下で利用できるようになります。

```bash
$ curl -O https://soracom-files.s3.amazonaws.com/setup_air.sh
$ sudo bash setup_air.sh
```
以下のようにネットワークインタフェース wwan0 の接続を確認できます。

```bash
$ ifconfig wwan0
wwan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 169.254.62.145  netmask 255.255.0.0  broadcast 169.254.255.255
        ether 00:1e:10:1f:00:00  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49  bytes 14994 (14.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

## SIMの電波強度の計測
SIMの電波強度を計測するためには、モデムや通信モジュールとシリアル通信で該当するATコマンドを送って、結果を受信する必要があります。
電波強度を取得できるATコマンドは **AT+CSQ** で、この出力結果をもとに電波強度を判定します。

### 電波強度の判定
電波強度はATコマンド **AT+CSQ** ですが、結果は **+CSQ: 19,99** のような表記で表されます。
上記結果例の **19** はRSSI (Received Signal Strength Indicator) で、0～31若しくは99の表記になります。（99は不明または検出不可。）
上記結果例の **99** はBER (Bit Error Rate) で、99はビットエラーが起きたか不明な場合または検出できなかったという意味のようです。
これを電波強度を現すdBm値に変換するには、**-113 + (RSSI値 * 2)** の式を用いて計算します。RSSI値とdBmc値、電波強度を以下の表にまとめてみましたが、大まかな電波強度を知りたい場合はRSSI値でも十分ですね。

| RSSI | dBm | Connection status |
|---|---|---|
| 0 | -113 or less | - |
| 1 | -111 | - |
| 2～9 | -109～-95 | Marginal |
| 10～14 | -93～-85 | OK |
| 15～19 | -83～-75 | Good |
| 20～30 | -73～-53 | Excellent |
| 31 | -51 or greater | - |
| 99 | - | Not known or not detectable |

### 電波強度を計測するプログラム

今回はPython2.7で電波強度を計測するプログラムを作成しました。Pythonのシリアル通信にはpyserialが必要です。

```bash
$ pip install pyserial
```

Webの情報などを参考に、以下のプログラムを作成しました。
**/dev/ttyUSB0** はUSBモデム（MS2372-607）の場合で、4GPIの場合は ** /dev/tty4GPI ** です。

```LteSimLevel.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import serial

modem = serial.Serial("/dev/ttyUSB0",baudrate=115200,timeout=1)

def sendAt(cmd):
   modem.write('AT+'+cmd+'\r')
   time.sleep(0.1)
   return modem.read(32798)

def calcDbm(csq):
   csq = csq.replace('OK','')
   csq = csq.replace('+CSQ: ','')
   csq = csq.replace('\n','')
   csq = csq.replace('\r','')
   dec = csq.split(',')
   if unicode(dec[0]).isdecimal():
     dbm = -113 + (int(dec[0]) * 2)
     return dbm
   else:
     return -113

def connStatus(dbm):
  if dbm >= -73:
    return "Excellent"
  elif dbm >= -83:
    return "Good"
  elif dbm >= -93:
    return "OK"
  elif dbm < -93:
    return "Alert:Marginal"

try:
   if modem.inWaiting()>0: modem1.flushInput()
   csq = sendAt('CSQ')
   print("AT command response")
   print(csq)
   print("SIM signal strength")
   dbm = calcDbm(csq)
   print(connStatus(dbm) + " (" + str(dbm) + "dbm)" )
finally:
   modem.close()
```

### 電波強度の計測結果
USBモデム（MS2372-607）の場合は以下でした。

```bash
$ python LteSimLevel.py
AT command response

+CSQ: 19,99

OK

SIM signal strength
Good (-75dbm)
```
4GPIの場合は以下でした。

```bash
$ python LteSimLevel.py
AT command response

+CSQ: 27,99

OK

SIM signal strength
Excellent (-59dbm)
```
USBモデム（MS2372-607）の場合はUSBドングルにアンテナが内蔵されアンテナの利得が低く、専用ボードでアンテナがしっかりしている4GPIはその分のアンテナの利得があると推測されるので、上記は納得の結果です。
電波強度の差がしっかり確認できましたので、これでLTEのSIM通信で電波がぎりぎり届く場所の電波強度をしっかり測定できそうです。

## 参考サイト
__各種デバイスで SORACOM Air を使用する__
https://dev.soracom.io/jp/start/device_setting/
__pySerialでATコマンドのデータを読み取る__
https://stackoverrun.com/ja/q/6675281
__3G/LTEを使用する際、設置場所決定に必要な参考情報__
https://armadillo.atmark-techno.com/howto/armadillo_3g-lte_installation-location
__AT Command AT+CSQ__
https://m2msupport.net/m2msupport/atcsq-signal-quality/
__SORACOM を使って学ぶ AT コマンド - 3. 実践編（AT+CSQ コマンド）__
https://bearmini.hatenablog.com/entry/at-command3
__AT Commands__
https://wiki.teltonika-networks.com/view/AT_Commands
__MS2372-607__
https://blog.soracom.com/ja-jp/2018/08/17/ms2372/
__4GPI__
https://mechatrax.com/products/4gpi/