#外出先からWOLでPCやHDDレコーダーの電源ON
外出先からスマホでPCやHDDレコーダーの電源をONし、外出先から機器を遠隔操作できるようにしています。インターネットからWOLパケットを送信し、パケットのフォワーディングで、自宅内LANへブロードキャストすることで実現していました。
[送信機器] ---> [ルーター] ---ブロードキャスト---> [PC1], [PC2]
のような構成です。
#引越し後に問題発生
引越し先はJ:COMのCATVインターネットが無料で使え、WiFi親機付きのルーターも無料でレンタルできますが、ここで問題発生。引っ越し前と同じくWiFi親機からWOLパケットのフォワーディングを設定し、転送先をブロードキャストアドレスにしたのですが、WOLパケットが転送されません。どうやらJ:COMのWiFi親機の問題のようです。
#Wake On LANリピータ?
http://www.starstonesoft.com/WOLRepeater.htm
のような機器を使えば、問題を解決できそうです。
つまり、
[ルーター] ---ブロードキャスト---> [PC1], [PC2]
が無理なので、ルーターから先を
[ルーター] ---ユニキャスト---> [WOL中継機] ---ブロードキャスト---> [PC1], [PC2]
とすればよいはずです。
PC1, PC2に対して何故ブロードキャストでないといけないのかというと、ルーターやスイッチングハブはある程度時間が経過すると、電源OFFの機器のMACアドレスを忘れてしまうからです。忘れてしまうとユニキャストの場合は転送されません。ブロードキャストなら転送されるのでこれを利用しています。
WOL中継機の仕事は、特定のポート宛のUDPパケットをブロードキャストアドレス宛に転送するだけです。つまり、右から来たものを左に受け流す仕事をします。通信ライブラリ等が整備されたボードでなら機能を絞れば簡単に作れそうです。
#ESP8266搭載ボード
安いものを探したところ、これを見付けました。
https://www.amazon.co.jp/gp/product/B07K2VQ4J7/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1
最初はEthernet搭載ボードを探していたのですが、WiFi搭載のほうが安いということに気付きました。まあ性能は低いでしょうが、今回の目的には十分ですし、何と言っても激安です。¥422で1個注文したのですが、何故か2個セットが届きました(支払いは1個分だけです)。因みに、中国からの発送で、届くまでに約3週間かかりました。
#Arduino IDE
Arduino IDEで開発できますが、とにかく簡単に作れます。nodeMCU 1.0を指定し、正味わずか50行足らずでWOLリピータのようなものができました(WOL_helperと名付けました)。
以下、ソースコードです。
// WOL_helper
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
// Settings
#define SSID "SSIDをここに書く"
#define PASSWORD "パスワードをここに書く"
#define SRC_PORT 8888 // 待受ポート番号
#define DST_PORT 9
WiFiUDP UDP;
IPAddress broadcastIP;
void setup(void)
{
Serial.begin(115200);
// Connect to WiFi
WiFi.begin(SSID, PASSWORD);
// while wifi not connected yet, print '.'
// then after it connected, get out of the loop
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
broadcastIP = (uint32_t)WiFi.localIP() | ~(uint32_t)WiFi.subnetMask();
UDP.begin(SRC_PORT);
//print a new line, then print WiFi connected and the IP address
Serial.println("\nWiFi connected");
// Print the IP address
Serial.print(WiFi.localIP());
Serial.printf(":%d->", SRC_PORT);
Serial.print(broadcastIP);
Serial.printf(":%d\n", DST_PORT);
}
void loop()
{
static unsigned char buf[200];
int packetSize = UDP.parsePacket();
if (0 < packetSize && packetSize <= sizeof(buf)) {
int len = UDP.read(buf, packetSize);
Serial.print(UDP.remoteIP());
Serial.print(" /");
for (int i = 0; i < len; i++) {
Serial.printf(" %02X", buf[i]);
}
Serial.println("");
UDP.beginPacket(broadcastIP, DST_PORT);
UDP.write(buf, len);
UDP.endPacket();
} else {
delay(1000);
}
}
以上