Java(JSoup)でルーターを自動再起動させる【無料】
ズバット引越し比較
Posted on 2021/10/7 at 4:24
目的
最近になってBUFFALOのWZR-HP-AG300Hに接続している無線端末のネットワークが、月に1回ほどルーターで詰まってしまうという現象が発生し、
その度アダプターの抜き差しによる再起動をして復旧していました。原因は不明なのですが、再起動によって復旧できるため定期的に自動で再起動させることにしました。
デジタルタイマーを使用するのが安価で最も簡単な方法ですが、今回はお金をかけない事を目標にしていましたので、JavaによるWebスクレイピングによく使用されるJSoupを利用し 自動再起動プログラムを書き、それをタスクスケジューラーに登録することにより、定期的に再起動プログラムを実効させることにしました。
JSoupのダウンロード
jsoupのダウンロードページから最新版のjsoup.jarをダウンロードします。今回は2021/9/30時点での最新版であるjsoup-1.14.2.jarをダウンロードしました。
ダウンロードしたらビルド・パスに追加して、クラスパスを通しておきます。
サンプルコード
WZR-HP-AG300Hはベーシック認証によるログイン方式となっています。ブラウザでルーターのIPアドレスにアクセスするとルーターは401を返してくるため、 ブラウザがそれを認識しとログイン画面が表示されます。最初、プログラムからログイン情報を送っても初回のみ401が返ってきて、ログインができなかったためブラウザのこの動きを真似てみたところ上手くいきました。
そして、WZR-HP-AG300Hにはやっかいな点があります。管理画面がフレーム構造となっていてしかも再起動へのアドレスが接続のたび変更されているため、 再起動するためのページに一発でたどり着けず、フレームと変更されたアドレスを順番にたどっていく必要がありました。
以下、サンプルコードです。
import java.io.IOException;
import java.util.Base64;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.HttpStatusException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
public class AutoRebooter {
private final String baseURL = "http://ルーターのIPアドレス";
private final String username = "ユーザー名";
private final String password = "パスワード";
private final String auth = username + ":" + password;
private final String base64login = new String(Base64.getEncoder().encodeToString(auth.getBytes()));
public static void main(String[] args) {
AutoRebooter rebooter = new AutoRebooter();
try {
int status = rebooter.connect();
if (status == 401)
rebooter.login();
} catch (IOException e) {
e.printStackTrace();
}
}
// まず、ログイン情報を持たず普通にHTTP接続を行い401を返してもらう
private int connect() throws IOException {
try {
Response response = Jsoup.connect(baseURL).method(Method.GET).execute();
return response.statusCode();
} catch (HttpStatusException e) {
return e.getStatusCode();
}
}
// ベーシック認証のため接続のたびログイン情報をヘッダに入れてあげる必要があります。
private void login() throws IOException {
// 「TOP」画面のメニューframeURLの取得
Document document = Jsoup.connect(baseURL + "/cgi-bin/cgi?req=tfr&tag=tag_setup")
.header("Authorization", "Basic " + base64login).get();
// 「管理設定」のframeURLの取得
Elements frame = document.select("frame[name='mnu']");
String src = frame.get(0).attr("src");
document = Jsoup.connect(baseURL + src).header("Authorization", "Basic " + base64login).get();
// 「管理設定」URLの取得
Elements elements = document.select(".TTL_MENU1_BRI a");
String href = elements.get(4).attr("href");
document = Jsoup.connect(baseURL + href).header("Authorization", "Basic " + base64login).get();
// 「初期化/再起動」のframeURLの取得
frame = document.select("frame[name='mnu']");
src = frame.get(0).attr("src");
document = Jsoup.connect(baseURL + src).header("Authorization", "Basic " + base64login).get();
// 「初期化/再起動」のURLの取得
elements = document.select(".TTL_MENU2 a");
href = elements.get(8).attr("href");
document = Jsoup.connect(baseURL + href).header("Authorization", "Basic " + base64login).get();
// 再起動ボタンのframe
frame = document.select("frame[name='frm']");
src = frame.get(0).attr("src");
document = Jsoup.connect(baseURL + src).header("Authorization", "Basic " + base64login).get();
Elements forms = document.select("form");
String action = forms.get(0).attr("action");
String rebootURL = baseURL + action;
Elements hiddens = document.select("input[type='hidden']");
String val1 = hiddens.get(0).attr("value");
String val2 = hiddens.get(1).attr("value");
// 再起動するためのURLには「sWebSessionnum」、「sWebSessionid」とsubmitボタンのname属性が必要となります。
// 特にsubmitのnameが「reboot」の場合は再起動となりますが、「init」にするとルーターが初期化されてしまうため注意してください。
document = Jsoup.connect(rebootURL).data("reboot", "", "sWebSessionnum", val1, "sWebSessionid", val2)
.header("Authorization", "Basic " + base64login).post();
if (document.body().getElementsMatchingOwnText("^再起動.*").size() > 0)
System.out.println("無線ルーターを再起動しています。");
else
System.out.println("無線ルーターの再起動に失敗しました。");
}
}
プログラムの実行結果
実行可能JARを作成し、Windowsのタスクから毎日1回実行するよう設定しました。現在のところ以前のような症状は出ておりません。
実行可能JARの作成と実効方法
Eclipseから実行可能JARを作成し、それを実行する方法について紹介します。
実行可能JARをWindowsタスクスケジューラから実行する方法
実行可能JARをWindowsタスクスケジューラに登録して実行する必要があったので、その備忘録です。