Speed Wi-Fi HOME 5G L13の5G接続を安定化させる

## はじめに
Speed Wi-Fi HOME 5G L13の接続がたまに安定しない。通常40msぐらいのレイテンシが、300ms程度にまで低下することがおそらく原因だ。色々とL13のコンソールを弄っていると、LTE/5Gを再接続させると一度落ちたレイテンシが回復することが分かった。宅内でストリーミングを再生しているとき、以下記事のように本体再起動までしてしまうとユーザー体験が悪い。本体を再起動させず、速度低下の原因となるWAN接続だけリセットさせて、最小限のダウンタイムで、速度回復させることを考えた。

>参考記事：Speed Wi-Fi HOME 5G L13 を定期的に再起動する
※認証方法の部分が非常に参考になった。

https://qiita.com/bugcity/items/28c23b378c32e6f0f8eb

# 今回やること
- L13設定変更時のAPI情報を抜き出す
- 複数のプロファイルを作成
- REST APIでWANリセットさせるpythonを作成

#### 構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/4f36420c-1be4-7a32-a471-2018bf6e9252.png)


## 1. API情報を抜き出す
開発者ツールにて送受信リクエストを見ると、ブラウザからL13のパラメータを操作する際、
すべて`http://{ipAddr}/goform_set_cmd_process`で実行されていることが分かる。LTE/5Gのプロファイルを切り替えるようなブラウザ操作のタイミングで、POSTリクエストで送っているヘッダー、データを抜き出しておく。

※参考記事によれば、RESTで送信しているヘッダー、データともにパスワードを暗号化した情報が含まる。管理方法に注意。

下図：Chromeの開発者ツールでAPIを抜き出す  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/4d997d40-e495-4a4e-430b-7aa850c61c2e.png)


## 2. 複数のプロファイルを作成
デフォルトプロファイルを、現在設定のプロファイルから別のプロファイルに切り替えればWAN接続がリセットされることが分かった。切り替え先のプロファイルの設定の中身が全く同じでも、違うプロファイルを設定しさえすればWANにリセットがかかる様子･･･。全く同じ内容のプロファイルを複数作成しておく。

下図：今回はrakuten/rakuten02を作成  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/5cd16405-5348-80a9-9ab9-15f0a722ad20.png)


## 3. pythonでスクリプト化
speedtest-cliを使って、レイテンシが低下したときだけWANリセットを実行するようにする。[前回の記事](https://qiita.com/bd8z/items/b6e88b2bd4dd84af218c
)で調べたように、使用率の高そうな時間帯には速度(Mbps)が下がる現象は確認しているので、下り・登り速度で、WANリセットをトリガするのは得策ではなさそう。レイテンシが異常に低下したときだけWANをリセットするようにする。


現在のプロファイルを確認して、別のプロファイルに変更する･･･という風に書くのは面倒だったので、2回連続でプロファイルを書き換えて、WAN接続を強制リセットする。プロファイルの参照は`index`で指定されているようなので、今回は1,2で指定して切り替えることにした。作ったpythonは、RaspiberryPiのsystemdから定期的に呼び出すようにしておく。


```python:main.py
import configparser
import json
import subprocess

import requests


def cahnge_profile(host, cookie, idx):
    hostUrl = "http://" + host
    headers_ = {
        "Accept": "application/json, text/javascript, */*; q=0.01",
        "Accept-Language": "ja,en-US;q=0.9,en;q=0.8",
        "Connection": "keep-alive",
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Cookie": "stok="+cookie,
        "DNT": "1",
        "Origin": hostUrl,
        "Referer": hostUrl +"/",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
        "X-Requested-With": "XMLHttpRequest"
    }
    data_ = {
        "isTest":"false",
        "goformId":"APN_PROC_EX",
        "apn_mode":"manual",
        "apn_action":"set_default",
        "set_default_flag":"1",
        "pdp_type":"IPv4v6",
        "index":str(idx),
        "AD":cookie
    }
    response = requests.post(url=hostUrl + '/goform/goform_set_cmd_process', headers=headers_, timeout=(3.0, 7.5) ,data=data_)
    if (response.status_code != 200):
        raise Exception("netwrok error!")
    else:
        print("change profile to " + str(idx) + " success!")

if __name__ == '__main__':
    config = configparser.ConfigParser()
    config.read('config.ini')
    host = config.get('L13', 'host')
    cookie = config.get('L13', 'cookie')
    speedtest_timeout = int(config.get('L13', 'speedtest_timeout'))
    ping_thresh = int(config.get('L13', 'ping_thresh'))

    try:
        stdout_ = subprocess.run(["speedtest-cli","--json"],capture_output=True, text=True,timeout=speedtest_timeout)
        if (stdout_.returncode == 0):
            try:
                json_ = json.loads(stdout_.stdout)
                if (json_["ping"] > ping_thresh):
                    raise Exception("error")
                else:
                    print("ping is " + str(json_["ping"]) + "ms")
            except:
                raise Exception("error")
        else:
            json_ = json.loads(stdout_.stdout)
            raise Exception("error")
    except:
        cahnge_profile(host, cookie, 2)
        cahnge_profile(host, cookie, 1)
```

# おわりに
Wi-Fiがもたつかなくなった（ように感じる）。
今後も定期的にな観測を続け、WANおよび宅内LANの安定化に努めていく。

今回作ったものは全部以下に公開

https://github.com/bd8z/L13_resetWAN