AlexaにPCの電源をコントロールして貰おうとしたらWindows10標準のOpenSSHの独自仕様で引っかかった話

これは前に30分くらいで書いた[AlexaにWindows PCの電源を切ってもらおうと思ったらすごく苦労した話](https://qiita.com/nlr_cmsp/items/19874cdcb525e3a26f55)の続編です。でも、前の記事を読む必要はないと思います。

Alexa経由でIoTしたい人多いですよね？というかAlexaでもGoogle HomeでもSiriでもとりあえずIoTと連携してボイスコマンドで家電を操作したい人がほとんどな訳で、自分もそうだった訳です。
先日の記事と内容がほとんど被ってしまうかと思いますが、今回はなるだけスマートな方法でAlexaでWindowsPCの電源をコントロール出来る様にする記事です。

大まかな説明をすると、Alexaのボイスコマンドをラズパイ（RaspberryPi 3B+ Rev1.3）に渡してシェルスクリプトを実行してWindowsPC（Windows10 1909）の電源をコントロールする感じです。
![フロー図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/48e3b467-1213-f59f-53bf-3b47534d2f4f.png)

#Node-REDの導入

まず、Alexaのボイスコマンドをラズパイで処理するため、Node-REDをラズパイにインストールします。[Node-RED User Group JapanのRaspberry Piで実行する](https://nodered.jp/docs/getting-started/raspberrypi)を参考にしてインストールします。

```
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
```

それからラズパイ起動時にNode-REDを自動起動する設定をして準備完了。

```
sudo systemctl enable nodered.service
```

#Node-RED Alexa Home Skill Bridgeの導入

Node-REDの導入が終わったら、AlexaとNode-REDを連携するための[Node-RED Alexa Home Skill Bridge](https://alexa-node-red.bm.hardill.me.uk/)というサービスを使い、PCの電源を操作できるデバイスとして登録します。
![スクリーンショット 2021-03-03 15.30.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/d4f83b04-f4e8-394e-e96d-552150dba829.png)
こんな感じで分かりやすい（ボイスコマンドで呼ぶので呼びやすい）名称でOnとOffの項目にチェックを入れて登録すればOKです。

#Node-REDの編集（前準備）

Node-RED Alexa Home Skill Bridgeの設定が終わったらラズパイのNode-REDの設定に入ります。
Node-REDが立ち上がっている状態ならローカルネットワーク内のブラウザから設定画面にアクセスできます。
http://raspberry.local:1880

アクセスするとこんな感じの画面が出てくると思います。
![スクリーンショット 2021-03-03 15.34.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/815247e1-7963-cbfc-2d86-870f165f6dcc.png)
いきなり完成型ですが、まず左のAlexa Homeと中央のSwitchノードを配置します。

Alexa Homeを配置してダブルクリックするとノードの編集が出来るのでこんな感じに。アカウントを選べば登録したデバイスが表示されます。
![スクリーンショット 2021-03-03 15.37.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/f94aa25d-cb5b-d0d7-01ac-dfaffe2b1904.png)

次にSwitchノードの編集、こちらは1にオンにした時、2にオフにした時を設定します。
![スクリーンショット 2021-03-03 15.36.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/60600bb8-2835-fb58-5f13-4c54620f118c.png)

Node-REDとラズパイの設定はひとまずこれで置いておき、次にWindows10に対しSSHでログインできるようにWindows側の設定をします。

#Raspberry PiからWindows10への公開鍵認証

ぶっちゃけこれが一番の難関です。知人の協力がなければ詰まってる部分から抜け出せませんでした、超感謝。ラズパイ側のSSHの設定は一通り終わってる物として説明します。

###Windows10（1909）のOpenSSHの導入と自動実行の設定
WindowsにOpenSSHが導入されているかどうかは「設定」→「アプリ」→「アプリと機能」→「オプション機能の管理」の「機能の追加」で確認できると思います。もしくはタスクマネージャのサービスタブにsshdがあるか確認してください。なければ先ほどの機能の追加からインストールできます。

しかしこのままではWindowsが起動した際に自動でsshdとssh-agentが立ち上がってくれないので、サービス管理画面でこの二つを自動実行するように設定を変更します。
![service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/c7bf9676-801d-d56b-7ddc-4c3e25815ba0.png)
こんな感じで2つともスタートアップの種類を「自動」にすればOKです。

###sshdが読み込む公開鍵ファイルの変更

ですが、この初期状態ではWindows10のsshdはユーザーディレクトリ直下の.ssh\authorized_keysを読み込みません。原因はPROGRAMDATA\ssh\sshd_configの最後に記述されている項目です。こちらのサイトを参考にしてsshd_configを書き換えます。
[Configure SSH Server With Windows 10 Native Way](https://medium.com/dev-genius/set-up-your-ssh-server-in-windows-10-native-way-1aab9021c3a6)

```
Match Group administrators
  AuthorizedKeysFile
  __PROGRAMDATA__/ssh/administrators_authorized_keys
```
この部分をコメントアウトして無効化する事によって、ユーザーディレクトリ直下の.ssh/authorized_keysを読み込みます。
sshd_configの編集が終わったらラズパイ側からssh-add等でユーザーディレクトリにあるauthorized_keysに公開鍵を追加し、sshdを再起動します。コマンドラインからうまく再起動できない場合はタスクマネージャからサービスの停止→開始で問題ありません。
再起動後、ラズパイ側からSSHで公開鍵認証でログインできるか確認します。確認後はsshd_configでパスワード認証を無効化しておくことをお勧めします。（PasswordAuthenticationのコメントアウトを外してnoにする）

#Windows10のWake on LAN設定を有効にする

BIOS画面とネットワークアダプタの設定でWake on LANを有効にします。各メーカーによって設定項目の名称が違うので気合いで探すか検索してください。Windows側の設定はネットワークアダプタの「電源管理」設定で「このデバイスで、コンピュータのスタンバイ状態を解除できるようにする」にチェックを入れておきます。

この時にWindowsのMACアドレスも調べて控えておきます。PowerShellなりコマンドプロンプトなりでipconfig /allを打てば表示されます。

#wakeonlanパッケージの導入

こんなんしたっけ……いやしたな多分。ラズパイ側からWake on LanのMagicPacketを送るための必要なのでインストールします。

```
sudo apt install wakeonlan
```

#シェルスクリプトの作成

まずWindowsPCをオンにするためのシェルスクリプトを作成します。wakeonlanを実行するだけなので非常に簡単です。wakeonlanの後にはWindowsのMACアドレスを入力します。

```wol.sh
#!/bin/sh

sudo /usr/bin/wakeonlan xx:xx:xx:xx:xx:xx
```

次にWindowsPCをオフにするためのシェルスクリプトを作成します。こちらもSSHでログインしてshutdownコマンドを実行するだけなので簡単です。

```shutdown.sh
#!/bin/sh

ssh user@192.168.xx.xx "shutdown -s"
```

二つとも作成したらシェルスクリプトを実行してWindowsの電源がオンオフされるかテストし、問題が無ければNode-REDの編集画面に戻ります。

#Node-REDでシェルスクリプトを実行できるように設定する

先ほどのNode-REDの画面で未設定だった右部分のノードを追加します。その他の項目にあるexecノードを2つ、オンにするときが上（Wake ON LAN）でオフにする時が下(Shutdown)になります。
![スクリーンショット 2021-03-03 15.34.372.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/105cd004-fc0a-b71b-6467-2935d629cdfa.png)

オンにするexecノードはwakeonlanを実行するシェルスクリプトを設定（sh [シェルスクリプトへのパス]）します。
![スクリーンショット 2021-03-03 16.58.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/e3c5e0f1-9652-d8f4-ecf3-b42842c0ad9a.png)

オフにするexecノードはshutdownコマンドを実行するシェルスクリプトを設定します。
![スクリーンショット 2021-03-03 17.00.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533021/a7f9475d-8a0b-5cc3-2132-9bd2b579d250.png)

両方とも設定が終わったら編集画面右上のデプロイをクリックして有効化します。

#完成！

これでAlexaから「PCの電源をオン」や「PCの電源をオフ」でWindowsPCの電源をコントロール出来る様になるはずです。お疲れ様でした。