Alexaでパソコンの起動/終了

 Alexaで「おはよう」「おやすみ」で日常の動作は自動化しているが、パソコンの立ち上げ、終了もできないかと試してみた。

2023/11/01追記

Amazon AlexaとIFTTTの連携が終了したため、IFTTT経由での操作は不可能となったらしい。

起動方法

・アレクサのスキルでAlexa.WakeOnLANControllerを使うスキルを作っ/使ってEchoデバイスからマジックパケットを送出する

 既存のスキルがあるらしいが、外部サイトにAmazonアカウントでログインしてPCを登録しないとならないようだ
 Wake on Lan Alexa Skill

スキルを自作する
 Amazon Echo (Alexa) でPCの電源を付ける

・スマートプラグでPCの外部電源をon/off

実行中に切ると、ファイルシステムが破損し、OSが立ち上がらなくなる可能性があるので、やってはいけない。
外部電源が切れていると、CMOS&時計のバックアップ用電池が早く消耗する。

・ローカルエリアのUNIXパソコン内のNode-RED(アレクサから見える仮想デバイス)経由でマジックパケットを送出する

アレクサでWindows PCをOn / Off

・IFTTTからPushbullet経由で一旦スマホにSMSで情報を渡して起動させる

Androidの自動化アプリ(Automagic,Taskerなど)で、スマホからマジックパケットを送出する

・IFTTTから共有フォルダー(OneDriveなど)経由で中継マシンにEventGhost経由で情報を渡す

 俺のパソコン起動して! Wake On LAN を Alexa で実現する

終了方法

・IFTTTから共有フォルダー(OneDriveなど)経由で中継マシンに情報を渡す

中継マシンではAssistant Computer Controlを実行

【プログラミング不要】スマートスピーカーでパソコンをシャットダウン&スリープモードにする方法

本題:Alexaでパソコンの起動/終了

・IFTTTから共有フォルダー(OneDriveなど)経由で中継マシンに情報を渡し、中継マシンはOneDriveのファイルを監視するスクリプトを実行する

事前準備としてIFTTTでAlexaの「パソコン起動」「シャットダウン」に応答するアプレットを作成する

アプレットの作り方は以下などを参考にしてください

【プログラミング不要】スマートスピーカーでパソコンをシャットダウン&スリープモードにする方法

IFTTTのサイトでアプレットを作成する

スマホのIFTTTアプリでも可能

  Googleアカウントなどでログイン
  My Apletts
  Create
  if then:Amazon Alexa
  Choose a trigger:Say a specific phrase
    What phrase?:パソコン起動
    Create trigger
  Then That:Add
  Choose a service:OneDrive
  Choose an action:Create text file
  Connect service:Connect
    Microsoftアカウントでサインインする
  Create text file
    Filename:computerAction
    OneDrive folder path:Amazon Alexa/
    Contenet:Wakeup
    Create action
  Finish
  Create
  if then:Amazon Alexa
  Choose a trigger:Say a specific phrase
    What phrase?:シャットダウン
    Create trigger
  Then That:Add
  Choose a service:OneDrive
  Choose an action:Create text file
  Connect service:Connect
  Create text file
    Filename:computerAction
    OneDrive folder path:Amazon Alexa/
    Contenet:Shutdown
    Create action
  Finish

ちなみに、アプレットの削除はHelpから”Can I delete an Applet”を選ぶと行えるらしい。

Can I delete an Applet?

スクリプトファイルを作成する

“%OneDrive%\Amazon Alexa”に以下のファイルを作成する。

  computerAssistant.bat ファイルを監視して対応するバッチファイルを実行する
  Wakeup.bat  実際にパソコンを起動させるバッチファイル
  Shutdown.bat 実際にパソコンを終了させるバッチファイル

computerAction.bat
 ”%OneDrive%\Amazon Alexa\computerAction”ファイルがあれば、その内容に従ってバッチファイルを実行する。

@echo off
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*

setlocal enabledelayedexpansion
cd /D %~dp0

rem 画面制御のエスケープシーケンスを環境変数に作成する
call SetEscVar.bat

set ALEXA=%OneDrive%\Amazon Alexa
set COMPUTER_ACTION=%ALEXA%\%~n0
echo COMPUTER_ACTION=%COMPUTER_ACTION%

set /a WAIT=10

set WAITING=Waiting...
set /a MSG_CNT=0
:CHAR_COUNT
call set w=%%WAITING:~%MSG_CNT%,1%%
if not "%w%" == "" (
  set /a MSG_CNT+=1
  goto :CHAR_COUNT
)

@echo|set /p=%ESC_BLINK%

set /a COUNT=0
:LOOP

if exist "%COMPUTER_ACTION%" (
  for /f "usebackq delims=" %%f in ("%COMPUTER_ACTION%") do (
    echo.
    @echo|set /p=%ESC_LINEUP%
    if exist "%ALEXA%\%%f.bat" (
      @echo|set /p=%DATE%-%TIME: =0% : start %%f.bat
        start %%f.bat
    )
  )
  del "%COMPUTER_ACTION%"

  set /a COUNT=0
  timeout /T %WAIT% > nul
  goto :LOOP
)

set /a MSG_POS=%COUNT% %% (%MSG_CNT% + 1) - 1
if %MSG_POS% equ -1 (
  echo.
  @echo|set /p=%ESC_LINEUP%

  @echo|set /p=%DATE%-%TIME: =0% : 
) else (
  @echo|call set /p=%%WAITING:~%MSG_POS%,1%%
)

set /a COUNT+=1
timeout /T %WAIT% > nul
goto :LOOP

endlocal
exit 0

SetEscVar.bat
 画面制御用のエスケープシーケンスを環境変数に作成する

@echo off
:TEMP_NAME
set ESC_FILE=%TEMP%\%~n0_%RANDOM%
set ESC_HEX_FILE=%ESC_FILE%_hex.tmp
set ESC_BIN_FILE=%ESC_FILE%_bin.tmp
if exist %ESC_HEX_FILE% goto :TEMP_NAME
if exist %ESC_BIN_FILE% goto :TEMP_NAME

echo 1B 5B>%ESC_HEX_FILE%
certutil.exe -decodehex %ESC_HEX_FILE% %ESC_BIN_FILE% >NUL 2>&1
set /P ESC=<%ESC_BIN_FILE%
del %ESC_HEX_FILE% >NUL 2>&1
del %ESC_BIN_FILE% >NUL 2>&1

rem The code to go to first column and n lines up is ESC[nF
rem The code to delete to the end of the line is ESC[0J
set   ESC_LINEUP=%ESC%1F%ESC%0J
set  ESC_LINETOP=%ESC%999D
set ESC_CLRRIGHT=%ESC%0K
set  ESC_CLRLEFT=%ESC%1K
set  ESC_CLRLINE=%ESC%2L
set   ESC_NORMAL=%ESC%39m
set    ESC_BLINK=%ESC%5m

exit /b 0

Wakeup.bat (Windowsの機能だけを使う場合)
 PowerShellを使ってマジックパケットを送出する。forの行は改行なしの1行です。

@echo off
echo.
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*

setlocal enabledelayedexpansion

set PC1=192.168.0.11,XX:XX:XX:XX:XX:XX
set PC2=192.168.0.12,XX:XX:XX:XX:XX:YY
set PC3=192.168.0.13,XX:XX:XX:XX:XX:ZZ
set PCs=192.168.0.14,%PC1% %PC2% %PC3%

rem ping.exe で応答しないもののみマジックパケットを送出する
for %%p in (%PCs%) do (
  for /f "tokens=1,2 delims=," %%q in ("%%~p") do (
    echo ping.exe %%q
    set WAKE=
    for /f "usebackq skip=2 tokens=1,2" %%i in (`ping -n 1 %%q`) do (
      if "%%j" == "からの応答:" if not "%%i" == "%%q" set WAKE=1
      if "%%i" == "要求がタイムアウトしました。" set WAKE=1
    )
    if "!WAKE!" == "1" (
        PowerShell.exe "$macAddr=[byte[]]("""%%r""".split(""":""") | ForEach-Object{[Convert]::ToInt32($_, 16)}); $magicPacket=([byte[]](@(0xFF)*6)) + $macAddr * 16; $udpClient=new-object System.Net.Sockets.UdpClient; $WakeUpTarget=[System.Net.IPAddress]::Broadcast; $udpClient.Connect($WakeUpTarget, 9); $udpClient.Send($magicPacket, $magicPacket.Length) | out-null; $udpClient.Close();"
        echo %%qを起動しました。
      )
    )
  )
)
@rem for %%p in (%PCs%) do C:\Winapp\WinWol_v303\WinWol.exe /C /H %%p

endlocal

timeout /T 60

exit 0

Wakeup.bat (WinWolを使う場合)
あらかじめインストールしたWinWolにパソコンのホスト名やMACアドレスなどを登録しておく。バッチファイルではC:\Winapp\WinWol_v303にあるWinWol.exeを利用して他のPCを起動する。

@echo off
echo.
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*

setlocal

set PCs=PC1 PC2 PC3

set WOL_CMD=C:\Winapp\WinWol_v303\WinWol.exe /C /H

for %%p in (%PCs%) do %WOL_CMD% %%p

endlocal

echo PCを起動しました。

timeout /T 60

exit 0

ちなみに、WinWolでは一台のPCでクライアントリストを作成した後、WinWol.iniファイルをOneDriveに移動した後、以下のコマンドでリンクを作成してすべてのPCから同じクライアントリストを使用している

del WinWol.ini
mklink WinWol.ini %OneDrive%\Backup\WinWol.ini

Shutdown.bat
Shutdown.exeを利用して、他のPCを終了させる。自分自身も終了させることはできるか、立ち上げるには手動で電源を入れるしかなくなる。

@echo off
echo.
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*

setlocal

set PCs=PC1 PC2 PC3

for %%p in (%PCs%) do start shutdown.exe /s /f /m \\%%p

echo.
@echo シャットダウンが進行中です。
@echo シャットダウンをキャンセルするには、何かキーを押してください
timeout /T 120
for %%p in (%PCs%) do start shutdown.exe /a /m \\%%p

echo.
@echo シャットダウンをキャンセルしました

endlocal
exit 0

Windows起動時にスクリプトを実行させる

スクリプトは表示しない、または最小化させた状態で実行させたい。

タスクスケジューラーにタスクとして登録する方法(表示しない)
全般
  名前:Amazon Alexa computerAction
  説明:Amazon AlexaからIFTTT経由で作成されたコマンドファイルを読み取り、対応する処理を実行します。
  セキュリティオプション:ユーザがログオンしているかどうかにかかわらず実行する
トリガー
  システム起動時、遅延時間を指定する:1分間
操作
  プログラムの実行
    プログラム/スクリプト:"C:\Users\xxxxx\OneDrive\Amazon Alexa\computerAction.bat"
設定
  タスクを停止するまでの時間;オフ

OKを押すとパスワードの入力を求められるので、入力する。この設定だとタスクバーにも表示されない。

start /minや、Wscript.Shell.runを使って最小化する方法はあるが、別プロセスとなるためタスクマネージャーで実行状態を管理できない。

セキュリティオプションで、「ユーザーがログオンしているときのみ実行する」にすると、通常の窓で表示されてしまう。

スタートアップフォルダーにショートカットを入れて実行させる方法(最小化)

“%OneDrive%\Amazon Alexa\computerAction.bat”ファイルのショートカットをスタートアップフォルダー(“%ProgramData%\Microsoft\Windows\Start Menu\Programs\StartUp”)に作成し、プロパティの実行時の大きさを最小化に変更する。

サービスとして実行させる方法(表示しない)

いくつかツールがあるらしいが、sexeを利用してみた。以下からダウンロードして適当なフォルダーに展開する。

https://www.nanshiki.co.jp/software/sexe.html

sexe64.exeを実行し、以下の設定で、テスト起動して開始・終了した後OKボタンでサービスとして登録する。

  プログラム
    ファイル:C:\WINDOWS\System32\cmd.exe
    起動時オプション:/c "C:\Users\[ユーザー名]\OneDrive\Amazon Alexa\computerAction.bat"
    優先度:通常
  サービス
    名前:Amazon Alexa computerAction
    説明:Amazon AlexaからIFTTT経由で作成されたコマンドファイルを読み取り、対応する処理を実行します。
    自動起動:on
  起動・終了
    終了方法:WM_SYSCOMMAND→WM_CLOSE
    シャットダウン以外でプログラムが終了したら再起動:on

このままでは実行するアカウントの権限が問題で外部バッチファイルが実行できない。サービスマネージャーで一旦Amazon Alexa computerActionサービスを停止し、ログオンタブでOneDrive所有者のアカウント情報を入力して再度開始すると、実際の起動・終了処理を実行できるようになる。

設定を削除したときなどは再起動しないと、サービスが削除予定で残ることがある。

Alexaの定型アクションに追加する

現状でも”アレクサ、トリガー パソコン起動”と発話すれば、パソコンを起動できる。Alexaアプリで定型アクションに「パソコン起動」として、IFTTTのアクションを追加すると簡単な発話で実行できるようになる。

さらに「おはよう」「おやすみ」「ただいま」などの定型アクションにも追加すると一連の動作と一緒にパソコンも一緒に操作できるようになる。また、アレクサアプリを使えば、外出先からでもパソコンを起動できる。

なぜか、IFTTTのアクションは元のアプレットを削除してもそのままの名前で残っている、何とか消せないのだろうか。似たような名前なので間違えて登録しても実行されないことがあった。