awake daemon

awaked version 0.0

Copyright(c)2022 by Hiroaki Sengoku
sengoku@gcd.org

awaked (「アウェイク ディー」と発音してください) は、 Windows PC がスリープ状態になるのを防ぐ Windows サービス (デーモン) です。 指定したポートに UDP パケットが届き続ける限り、 Windows PC がアイドル状態 (キーボードもマウスも使用しない状態) でもスリープしないようにします。 リモートから UDP パケットを送り続けることで、 Windows PC を「起きている状態」に保つことができます。

awaked には以下のような特徴があります。

1. GUI を持たない
Windows がスリープに入ることを防ぐツールは既にあります (PowerToys Awake など) が、 いずれもスリープ回避動作を始めるには、 当の Windows PC で操作する必要がありました。 awaked は GUI が無く、スリープ回避をリモートからコントロールできます。 Wake-on-LAN と組合わせることで、 普段はスリープさせて節電しつつ、 リモートから使いたい時だけ Windows PC を 「起こす」ことが可能になります。 私はテレビにつないだ Windows PC を、 テレビの電源を入れているときだけ自動的に起こすようにしています。
2. 単純
わずか 400 行 (C 言語) ですので、 セキュリティホールが生じる可能性を最小限にできます。 非常にシンプルなコードなので、 他のシステムに組み込むことも容易でしょう (GPL ライセンス)。 cl.exe (VC++ の C/C++ コンパイラ) だけでビルドできるので、 フルセットの VC++ を必要とせず、 Build Tools for Visual Studio をインストールするだけでビルドできます。
3. Windows 11 対応
SetThreadExecutionState API は、 Windows 10 と Windows 11 では挙動が異なり (ES_SYSTEM_REQUIRED 単独では機能しない)、 同種のツールには Windows 11 で動作しないものもあります。 SetThreadExecutionState の引数に ES_CONTINUOUS を指定することで awaked は Windows 11 でも安定して動作します。
4. ECHOプロトコル (RFC 862) 準拠
UDP パケットの送受信は ECHOプロトコル に準拠しているので、 UDP パケットを送るクライアントは、 ECHOプロトコルを用いるツール (例えば perl の Net::Ping) を流用できます。

スナップショット (2022-07-02)


使用例

C:\>awaked.exe -v -p 55084
  • UDP ポート 55084番に UDP パケットが届くと、 その時点から 3分間はスリープに入ることを防ぐ。
  • 届いた UDP パケットの内容を、 そのまま UDP で送り返す (ECHOプロトコル)。
  • Windows サービスとして登録する前に、 まずコマンドラインで実行してみることで、 Windows ファイアウォールの設定を確認できます。
C:\>awaked.exe -p 55084 -M install waker
  • awaked を Windows サービス 「awaked waker」 として登録する。 「waker」の部分は任意に設定できます。
  • 「コンピューターの管理」⇒「サービスとアプリケーション」⇒「サービス」 でサービスを「開始」してください。 「スタートアップの種類」を「自動」にすれば、 Windows の起動時に awaked を自動的に実行します。
C:\>awaked.exe -p 55084 -M remove waker
  • Windows サービス 「awaked waker」 を削除する。

UDPパケットを送る perl スクリプトの例:

#!/usr/bin/perl
use Net::Ping;
my $p = Net::Ping->new("udp");
$p->port_number(55084);
for (;;) {
    my @ret = $p->ping("hostname", 10);
    sleep 60;
}

開発の背景

WSL2 で物理ディスクが使えるようになったことで、 Windows をサーバとして使う機会が増えました。 もちろん従来から VMware 等の仮想マシンを Windows 上で走らせ、 サーバとして使うこともあったのですが、 VMware だとメモリも CPU もそれなりに食うので、 常に走らせておくのは躊躇しますが、 WSL2 は軽いので常に走らせておくことができます。

Linux が常に使えるとなると、 Windows PC の前にいなくても ssh でログインして使いたくなるのが人情で、 スリープ状態になっていたら Wake-on-LAN で起こして使うようになりました。

また、 動画等の再生専用のテレビにつないだ Windows PC があるのですが、 テレビをつけたときに自動的に Wake-on-LAN が飛ぶようにしてみました。 テレビ放送より Windows PC で動画等を見ることが多いので、 テレビをつけたときに勝手にスリープから復帰していてくれると便利なのです。

こうなってくると問題になるのがスリープまでのタイムアウト時間です。 ふつうは 2時間くらいに設定するのだと思いますが、 Wake-on-LAN で起こした場合、 キーボードもマウスも全く使わなければ、 数分程度で再びスリープしてしまいます。 「システム」⇒「電源」⇒「画面とスリープ」で設定するタイムアウト時間は、 あくまで最後にキーボード/マウスを使用した時点からカウントするようです。

テレビにつないだ Windows PC も、 テレビをつけたあとすぐにマウスに触れればいいのですが、 少しテレビ放送を見ていたりして Windows PC を操作しないとすぐスリープしてしまい、 マウスもキーボードも Bluetooth 接続なのでスリープ状態では使うことができず、 スリープを解除するには Windows PC の電源ボタンを押す必要があって面倒です。

というわけで、 Wake-on-LAN で Windows PC を起こした後、 起きた状態を維持するための方法を模索したのですが、 既存のソフトウェアではなかなか丁度良いものが見つかりません。 スリープを回避するプログラムはいくつか見つかりましたが、 回避するには当の Windows PC を操作しなければならない、 という私にとっては本末転倒なものばかりだったのです。

マウスに触ればスリープ時間は延びるのですから、 スリープを回避する必要性はそれほど感じません。 必要なのはリモートから「マウスを触れずに」スリープを回避する方法です。 無いなら作ってしまえということで、 2022年6月18日(土曜日) 朝ご飯の後に書き始めたのがこの awaked.c です。

#10425. 仙石 浩明
https://www.gcd.org/sengoku/ Hiroaki Sengoku <sengoku@gcd.org>

| home | up | english | Last modified: 2022-06-21
sengoku@gcd.org