スイッチでAlexa定型アクションを起動~導入編~

Alexaは音声でいろいろ動作するので便利なのですが、声に出すのが面倒だったり、声を出したくない場面があったりするので、スイッチで定型アクションを起動できる方法がないか探してみました。
そうするとSTREAM DECKでそれを実現しているページが見つかりました。

STREAM DECKでAlexaの定型アクションを起動!IFTTTを使わずスマートコントロールパネルを作る方法【Mac向け】
https://misc-log.com/streamdeck-alexa/

STREAM DECKは1万円以上もする高価なものですし、自分はMacユーザーでもないのでそのまま実行するのは躊躇してしまいますが、核となる部分は「あんスマ」の以下の記事のものであり、一読するとSTREAM DECKやMacを使わなくてもできそうでした。

実質有料化のIFTTT代替!自作Alexaスキルでスマートホーム機器を自在に活用しよう
https://android-smart.com/2020/10/alexa_smarthomeskill.html

今回、ラズベリーパイとダイソーのテンキーで同様の機能を実現することができました。

「あんスマ」の記事通りにやれば半日もあればできると思いますが、私にとっては結構な時間がかかりました。理由には以下が挙げられます。
1)記事に書かれている通りにやっていない。手順を間違えている。記事には手順しか書かれておらず、Alexaスキルに対する知識がないので、間違っていても原因にたどり着くのに時間がかかってしまいました。
2)Alexaスキルについてわかりやすく書かれているページや書籍が少なく、どういう仕組みで動作するのか理解するのに時間がかかりました。

今回でそれなりにAlexaスキルについての知識が付きましたので、それについても記載したいと思います。

購入品

自分の場合、ラズベリーパイは持っていましたので、購入したものはダイソーのテンキー(税込330円)のみとなります。

写真ではラズベリーパイ3B+を使用していますが、新たにラズベリーパイを購入する場合は、ラズベリーパイ ゼロ W(税込1,540円)で充分です。最近はラズベリーパイが品薄になっており、高値で取引されていますが、ラズベリーパイゼロ2 W(税込2,508円)が出回るようになってきました。

SWITCH SCIENCE Raspberry Pi Zero 2 W
https://www.switch-science.com/catalog/7600/

ラズベリーパイZEROはUSB microBで給電すれば起動できるので、その辺に転がっているUSBのACアダプタや100均のケーブルで賄えます。しかし、HDMI(mini HDMI)とUSBコネクタが特殊なので実際に使うにはさらなる購入品が必要です。mini HDMIケーブルは稼働時には不要ですが、インストール時に必要です。1つあれば十分でしょう。USB-microBオス-USB-Aメス変換コネクタはCan★Doで売っておりました。Amazonの怪しい最安品でも400円程するのでこれは助かります。

microSDカードはCan★Doの16GB(税込550円)で充分です。Amazonでは32GB 約600円程度が最安値でした。

スマートホームスキル

スイッチで定型アクションを動作するにはAlexaスマートホームスキルというものを作成する必要があります。
以下はAmazon alexa developer documentation(https://developer.amazon.com/ja-JP/docs/alexa/smarthome/understand-the-smart-home-skill-api.html)に掲載のスマートホームスキルの概要図です。

どうやらスマートホームスキルとは、Alexaクラウドとスマートホームデバイスメーカーのクラウドを仲介するプログラムであるようです。
例えばNature Remoのような赤外線リモコンで電気をつける場合、以下のような動きになると考えられます。
1) echoに「アレクサ、電気を点けて」というとechoは音声をAlexaクラウドに送信する。
2) Alexaクラウドは音声を解析し、Remoのスマートホームスキルに指令(ディレクティブ)を送る。
3) スマートホームスキルは電気を点けるようにNature Remoのクラウドに送信する。
4) Nature Remoのクラウドは家庭のRemoに電気をつける信号を出すように送信する。
5)各家庭のRemoは電気をつける赤外線信号を送出し、照明がそれを感知して点灯する。

温度などの状態をechoにたずねる場合も同じ経路をたどりますが、逆の経路で温度データが戻ってきてechoに届くという処理が追加されます。

センサーが自発的に通知する場合、例えばモーションセンサーが人の動きを察知してechoに通知する場合は、図中の「非同期応答、プロアクティブな状態更新」で示されるように、スマートホームスキルを経由せずにメーカーのクラウドからAlexaクラウドに直接通信され、echoに届きます。この時のAlexaクラウドの受け口をイベントゲートウェイといいます。

今回作成するスマートホームスキル

上記で説明される通常のスマートホームスキルに対して、今回作成するスキルは以下のようになります。

一見してわかるように今回作成するスマートホームスキルにはメーカーのクラウドや家の中のデバイスは存在しません。
今回作成するスキルは以下のような働きをします。
1) スキルが有効になった際にデバイスの検出を行いますが、その際にスキルは実際には存在しない架空のセンサーがあるかのように振舞います。今回はテンキーのそれぞれのキーに割り当てる10個のセンサーがあるとAlexaクラウドに返します。
2) ユーザーからの状態要求や変更要求にはテキトーに応答したり、無視したりします。そもそもデバイス検出時のプロパティにはそのような機能はないとしています。イベントの変更通知だけは可能なプロパティとなっています。
3) テンキーでキーが押されるとラズベリーパイはAlexaクラウドのイベントゲートウェイに対してセンサーが検出したというイベントの送信を行います。Alexaクラウドはechoにセンサーが検出したことを通知します。

Alexaアプリでセンサーの検出を実行条件にした定型アクションを作成しておくことで、キー操作によって定型アクションを起動することができます。

AWS lambdaとは何か

上図で示されているように今回作成するスマートホームスキルはAWS lambda上で動作します。
AWSとはAmazon Web Servicesの略で、要するにレンタルサーバーです。通常のレンタルサーバーはサーバー上のリソースを一定期間定額でレンタルするものですが、AWSは動作した分だけ課金する、というのが特徴です。
例えばある会社がキャンペーンを行った際、アクセスが多すぎてサーバーがダウンしてしまった、というのは聞いたことがあると思います。このような時、AWSに頼めばアクセスが発生した分だけAWSのサーバー割り当てが自動的に拡大されていき、決してサーバーダウンすることはありません。料金もCPUが稼働した分だけかかるという仕組みなので自社サーバーを増設するコストと手間を考えると圧倒的に安上がりになるらしいのです。自社サーバーの全てをAWSに移行することもできるし、一時的に自社サーバーとAWSを連携させるような運用をすることもできます。AWSのページにログインしページ上から簡単な設定を行うことで、あらゆるサービスを利用することができるようなのです。
Lambdaというのはサーバー上でプログラムを実行するというAWSのサービスの一つです。料金は発生しますが、その料金はリクエストの数とコードの実行時間に基づいて課金されます。100万リクエストまでは無料で利用できますので、今回のスキルでは何かの間違いがない限り料金は発生しないでしょう。
今回の作業でいろいろな画面を行ったり来たりして非常に煩わしかったのですが、使っているのはAWSのサービスのごく一部で、それを無料で使わせてもらっているのだな、という事が本を読んでわかりました。Alexaスキル専用のものではないということで、多少の煩わしさにも仕方がないと納得しました。この本を読んだからと言って技術的に何かできるようになるわけではないですが、非常に興味深く、なおかつ、わかりやすかったので紹介します。

図解 Amazon Web Servicesの仕組みとサービスがたった1日でよくわかる
\2,200 SBクリエイティブ (2022/2/2) ISBN-13: 978-4815612818

AWSのサーバーは世界各地にありますが、日本でホームスキルを作成する場合、米国西部(オレゴン)のAWSにプログラムを置く必要があります。これはエンドポイント(デバイス)が世界のどこにあるかによって、どのリージョンのAWSサーバーにディレクティブが送信されるのかが自動的に決められているからです。日本のAWSにプログラムを置いても動作しないので注意が必要です。

使用する必要のあるエンドポイントのリージョンと関連するAWSのリージョン
https://developer.amazon.com/ja-JP/docs/alexa/smarthome/develop-smart-home-skills-in-multiple-languages.html#deploy

Alexaイベントゲートウェイへのアクセス権限

センサーが検知したとの通知はAlexaクラウドのイベントゲートウェイへイベントを送信しますが、これを行うためにはアクセス権限が必要になります。
具体的にはAmazon LWA OAuthサーバーからアクセストークンというものを発行してもらい、そのアクセストークンというものを使ってイベントゲートウェイに通信します。
LWAとはLogin with Amazonの略です。
アクセストークンには有効期限と言うものがあって、これはトークンと同時に発行されますが、3600秒=1時間となります。1時間を過ぎたらLWA OAuthサーバーにアクセスして新しいアクセストークンを発行してもらわなくてはなりません。
アクセストークンを発行してもらう際には、リフレッシュトークンが必要になります。
リフレッシュトークンは次のようにして取得します。スキルが有効になった際に、Alexaクラウドからスキルに対してAcceptGrantディレクティブが送信されます。AcceptGrantを受け取ったスキルはそこに含まれているcodeと、クライアントID/クライアントシークレットを添えてLWA OAuthサーバーに要求するとリフレッシュトークンが返されます。リフレッシュトークンはスキルが有効な間は有効で、スキルを無効にすると無効になります。再度スキルを有効にすると新たなリフレッシュトークンが発行されます。
イベントゲートウェイに送信するスキルのみがAcceptGrantディレクティブが必要になります。AcceptGrantディレクティブを受け取るには、スキルの作成時にアクセス権限をデフォルトの無効から有効へ変更をしなければなりません。
以下はAmazonDeveloperDocument記載のOAuth2.0メッセージフローの図です。

詳細は以下に記載されています。

Alexaイベントゲートウェイへのアクセス権限のリクエスト
https://developer.amazon.com/ja-JP/docs/alexa/smarthome/authenticate-a-customer-permissions.html

デバイスの検出

スキルが有効になった後、デバイスの検出がされますが、その時AlexaからDiscoveryディレクティブが送信されます。Discoverディレクティブを受け取ったスキルはデバイスの種類別の形式に則ったフォーマットでデバイスのプロパティを返信します。
今回はMotionSensorとして登録します。フォーマットは以下に示されています。

Alexa.MotionSensor Interface Discovery
https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-motionsensor.html#discovery

上記で示されたサンプルフォーマットで注意するべき点は各インターフェースのRetrievable、ProactivelyReportedという2つのプロパティです。
Retrievableプロパティをtrueにするとそのデバイスの状態をスキルに照会できるようになります。サンプルフォーマットではtrueになっていますが、今回の目的には不要でプログラムも実装しないため、falseにします。
ProactivelyReportedプロパティをtrueにするとイベントゲートウェイで検出イベントを受け取ると、AlexaにChangeReportイベントを送信するようになります。
プロパティについての詳細は以下のDeveloper Documentを参照してください。

状態および変更レポートのサポートを指定する
https://developer.amazon.com/ja-JP/docs/alexa/smarthome/state-reporting-for-a-smart-home-skill.html#discovery

以上で導入編は終わりになります。
「あんスマ」の記事にあるプログラムがやろうとしていることの一通りの説明、または理解へのヒントは示せたのではないかと思います。私が躓いたことを中心に書きましたが、もっと理解したい方はAmazonのDeveloper Documentを読み進めていけばよいと思います。Alexaスキルに関してはあまりよさげな本がありませんし、探し方が悪いのかもしれませんが、Amazon以外のサイトでは記事が少ないように感じました。
次は具体的な方法を記載します。殆ど「あんスマ」の手順とプログラムをなぞっただけです。記事が消えてしまうかもしれないので、忘備録として書きます。このサイトの方が寿命短いと思いますが。