AWS IoT でスマートホームを自作する 〜ドアフォン編〜
Author : 市川 純
こんにちは、自宅のスマートホーム化を進めるために第二種電気工事士の資格を取った、プロトタイピング ソリューション アーキテクトの市川です。
最近はスマートスピーカーの普及によって、部屋の照明を ON/OFF をするようなスマートホーム化を試している人も多いと思いますが、今回の記事ではそのスマートホーム化を自作してみたいと思います。
さすがに皆さんに「第二種電気工事士を取って、壁の中までいじってスマートホーム化しましょう !」というのは無茶な話ですので、カメラ付きのドアホンを AWS のサービスを使って作ってみることにしました。
映像を見るために利用するデバイスは、Amazon Echo の画面付きデバイスの利用も可能です。
つまり、「アレクサ、玄関のカメラを見せて」と言うと、その映像が Echo デバイスで見れるので、わざわざ玄関まで行ってドアスコープ (のぞき穴) で見る必要がなく、快適なスマートホームライフをおくれるというわけです !
実際にお試しいただくために、あらかじめサンプルコードをダウンロードしておきましょう。
利用するデバイス
この記事で作った物は、以下のデバイスを利用しました。
- Raspberry Pi 4
- USB カメラ
- Echo Show (Alexa 連携する場合のみ)
その他、ラズパイを利用するための microSD カード、キーボード、マウス、microHDMI、USB Type-c の電源等、必要になります。
利用する AWS のサービス
全体の仕組みを作るために利用する AWS のサービスは以下のものになります。
- Amazon Kinesis Video Streams with WebRTC
- AWS IoT Core
- AWS Lambda (Alexa 連携する場合のみ)
これらのサービスについてこの後簡単に説明しますが、より詳しく知りたい場合は、「詳しくはこちらを」から各サービスの特徴ページをご覧ください。
Amazon Kinesis Video Streams (KVS) with WebRTC とは
デバイス間のリアルタイム通信を可能にするオープンソースプロジェクトである WebRTC をマネージドサービスとして提供するもの。完全マネージド型の機能として、シグナリングやメディアリレーサーバーなどの WebRTC 関連のクラウドインフラストラクチャを構築、運用、拡張する必要が無くなります。
AWS IoT Core とは
AWS IoT Core は、インターネットに接続されたデバイスから、クラウドアプリケーションやその他のデバイスに簡単かつ安全に通信するためのマネージド型クラウドサービスです。
AWS Lambda とは
AWS Lambda はイベント発生時にお客様のコードを実行し、基盤となるコンピューティングリソースをお客様に代わって管理する、サーバーレスコンピューティングサービスです。
全体のアーキテクチャ
ではさっそく作ってみましょう
Step 1 ラズパイで Kinesis Video Streams with WebRTC のサンプルアプリを使えるようにする
まずはラズパイのセットアップが必要になりますので、公式のサイトから最新のイメージをダウンロードして、SD カードに書き込みます。今回使用したのは Raspbian Buster with desktop です。4GB 以上のストレージを必要としますので、最低 8 GB の microSD カードを用意してください。
ラズパイのセットアップに初めてチャレンジされる場合は、公式のページに詳細な手順が公開されていますので、そちらを参考にセットアップしましょう。
ここから先の作業は、ラズパイのセットアップが終わっており、デスクトップにログインしている前提で進めます。
事前準備
ターミナルを開いて、以下のコマンドを入力して、最新の状態にします。
sudo apt-get update
sudo apt-get upgrade
sudo apt-get clean
sudo reboot
サンプルをビルド & 実行するのに必要なライブラリのインストール
sudo apt-get install pkg-config cmake libcap2 libcap-dev libssl-dev
今回は、Gstreamer を使ってカメラから映像を取り出して映像を扱うサンプルを利用しますので、Gstreamer のインストールも行います。
sudo apt-get install gstreamer1.0-tools libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-omx gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly
ここで一旦、Gstreamer からビデオを取り出して表示できるかを試してみます。
注) ラズパイ 3 では、 gst-launch-1.0 autovideosrc ! autovideosink で自動的にカメラから映像を取り出して、別ウィンドーに表示してくれましたが、ラズパイ 4 ではビデオ周りに色々と変更が入ったことからか、サイズやフレームレートを指定しないとうまく動きません。
つなげた USB カメラ(/dev/video0) が対応している解像度とフレームレートを調べるには以下のコマンドを入力します。
v4l2-ctl -d /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'MJPG' (Motion-JPEG, compressed)
Size: Discrete 1280x720
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 160x120
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x360
[1]: 'YUYV' (YUYV 4:2:2)
Size: Discrete 1280x720
Interval: Discrete 0.125s (8.000 fps)
Interval: Discrete 0.125s (8.000 fps)
Size: Discrete 160x120
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
今回は、height=640, width=360, framerate=30/1 で試してみます(あまり大きな解像度だと、映像の遅延が大きくなるため)。
以下のコマンドで、映像を表示しましょう。
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,width=640,height=360,framerate=30/1 ! autovideosink
カメラの映像が表示されました !
これで、カメラから映像を取り出す部分の確認ができましたので、次はこの映像を KVS with WebRTC のクライアントアプリで扱えるようにセットアップします。
KVS with WebRTC のセットアップ
今回はラズパイ上で利用できる C SDK を利用します。
以下のビルドについては SDK の Github にある README を参考にしています。
ソースコードの取得
この記事では、pi ユーザーのホームディレクトリに clone します。
git clone --recursive https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c.git
ビルド
mkdir -p amazon-kinesis-video-streams-webrtc-sdk-c/build; cd amazon-kinesis-video-streams-webrtc-sdk-c/build; cmake ..
上記のコマンドが正常に終わったら同じディレクトリで、以下のコマンドを実行します。
make
make が終わると以下のようなファイルが build ディレクトリにあるのが確認できます。
ls -l
-rw-r--r-- 1 pi pi 32383 Feb 01 05:51 CMakeCache.txt
drwxr-xr-x 9 pi pi 4096 Feb 01 07:50 CMakeFiles
-rw-r--r-- 1 pi pi 55991 Feb 01 05:51 Makefile
-rw-r--r-- 1 pi pi 1649 Feb 01 05:51 cmake_install.cmake
drwxr-xr-x 2 pi pi 20480 Feb 01 05:51 h264SampleFrames
-rwxr-xr-x 1 pi pi 44072 Feb 01 07:50 kvsWebrtcClientMaster
-rwxr-xr-x 1 pi pi 48796 Feb 01 07:50 kvsWebrtcClientMasterGstSample
-rwxr-xr-x 1 pi pi 38860 Feb 01 07:50 kvsWebrtcClientViewer
drwxr-xr-x 4 pi pi 4096 Feb 01 07:50 kvscproducer
-rwxr-xr-x 1 pi pi 314952 Feb 01 07:50 libkvsWebrtcClient.so
-rwxr-xr-x 1 pi pi 167656 Feb 01 07:50 libkvsWebrtcSignalingClient.so
drwxr-xr-x 2 pi pi 32768 Feb 01 05:51 opusSampleFrames
ビルドが成功することを確認できましたので、今回の環境に合わせて少しソースコードの修正を行います。
ソースコードの修正
Gstreamer のサンプルは固定で動画のサイズを指定しますが、ラズパイ 4 で動かす場合、このサイズが実際のカメラの対応しているサイズと一致しないと正しく動かないためソースコードを修正します。
../samples/kvsWebRTCClientMasterGstreamerSample.c の 134 行目と 141 行目に autovideosrc で始まる行がありますが、ここが Gstreamer のパイプラインとなっています。
autovideosrc ! queue ! videoconvert ! video/x-raw,width=1280,height=720,framerate=30/1
この部分を、最初に Gstreamer の動作確認を行ったときと同じ様に修正します。
v4l2src device=/dev/video0 ! queue ! videoconvert ! video/x-raw,width=640,height=360,framerate=30/1
これでもう一度ビルド(build ディレクトリで)を行います。
cmake ..
make
動作確認
WebRTC のサンプルを動かして、実際に別のデバイスからつないでみましょう。
クレデンシャルの準備
この作業は、自分の PC 上で作業します。
まずは、サンプルを動かすにあたって、AWS のクレデンシャルが必要になります。AmazonKinesisVideoStreamsFullAccess の権限を持つユーザーで aws cli のコマンドを実行し、一時的なクレデンシャルを取得します。(AWS CLI については、こちらを参考に準備してください)
aws sts get-session-token
結果
{
"Credentials": {
"SecretAccessKey": "〜〜",
"SessionToken": "〜〜",
"Expiration": "2020-02-01T10:00:00Z",
"AccessKeyId": "〜〜"
}
}
環境変数の設定
以下のコマンドで環境変数を設定します。ここからの作業はラズパイ上で行います。
export AWS_DEFAULT_REGION=今回利用するリージョン
export AWS_ACCESS_KEY_ID=AccessKeyId の値
export AWS_SECRET_ACCESS_KEY=SecretAccessKey の値
export AWS_SESSION_TOKEN=SessionToken の値
サンプルの実行
Gstreamer 用のサンプル kvsWebrtcClientMasterGstSample がありますので、これを使います。
1 つ目の引数は、WebRTC のシグナリングチャンネル名になります。存在しなければ新規で作成します。2 つ目の引数は video-only (映像のみ) か audio-video (映像と音声) が指定できます。
./kvsWebrtcClientMasterGstSample sample-channel video-only
このコマンドで Master として動作するので、別途クライアントが必要になります。クライアントは JavaScript のサンプルがブラウザから利用できるものですので、これを使います。
クレデンシャルには、先程環境変数に指定した ACCESS KEY、SECRET KEY、SESSION TOKEN と同じものを使います。リージョンには今回利用しているリージョン。Channel Nameには、上のコマンドの2つ目の引数に指定した sample-channel を入力します。
Use trickle ICE にチェックを付け (Step 3 まで行った場合は、このチェックは付けない)、Start Viewer をクリックします。
今回はブラウザ用のサンプルを利用しましたが、iOS、Android 用のサンプルを利用すると、スマフォから映像を見ることが出来ますので、出先から映像を見るといったことが簡単にできますね !
Step 2 よりセキュアな認証情報の利用について
ここまでの手順では、手動でクレデンシャルを発行して KVS の WebRTC のクライアントを実行しました。しかし、これを置きっぱなしなデバイスで利用するには使い勝手が悪いです。そこで、AWS IoT の証明書を使った一時的なクレデンシャルを発行する仕組みを利用し、起動時に一時的なクレデンシャルを作成して利用する方法について、対応したいと思います。
AWS IoT のセットアップ
AWS IoT 証明書の作成と有効化
注意) 初めて AWS IoT Core を利用する場合は、AWS IoT Core のコンソールで、設定 > カスタムエンドポイント にある ステータスの確認 をクリックしてエンドポイントを有効にしてください。
次の手順で利用しますので、作成した証明書の ARN を控えておいてください。
CloudFormation で AWS IoT に必要な環境と Role を作成する
サンプルソースに含まれているテンプレート cfn.yml を利用し、CloudFormation で必要な AWS IoT のサービスを設定します。(AWS IoT の証明書と同じリージョンを使います)
1. CloudFormation のマネージメントコンソールを開きます
2. スタックの作成 をクリックします
3. テンプレートの指定 で、テンプレートファイルのアップロード を選択し、ファイルの選択 でサンプルソースに含まれている cfn.yml を選び、次へ をクリックします
クリックすると拡大します
4. スタックの名前を入力し、WebRTCThingCertificateARN には、AWS IoT の手順で作成した証明書の ARN を指定し、次へ をクリックします
クリックすると拡大します
5. スタックオプションでは何も変更せずにそのまま 次へ をクリック
6. レビュー画面で内容を確認し、IAM Role の作成を承認するにチェックを付け、スタックの作成 をクリックします
クリックすると拡大します
以上で、AWS IoT の Thing と Policy、証明書が関連付けられました。
この CloudFormation テンプレートではさらに、ラズパイで実行する WebRTC のサンプルが必要とする権限を持つ Role と、Alexa Skill の Lambda で利用する Role が作成されています。
Role Alias の作成
AWS IoT で一時的なクレデンシャルを取得するには、対象となる Role のエイリアスを作成する必要があります。
以下の AWS CLI のコマンドを使って、エイリアスを作成します。(PC 上での作業)
aws iot create-role-alias --role-alias エイリアス名 --role-arn CloudFormation の出力タブにかかれているKVSCredentialRoleの値
実行結果
{
"roleAlias": "指定したエイリアス名",
"roleAliasArn": "Role エイリアスの ARN"
}
クレデンシャルエンドポイントの確認
クレデンシャル情報を取るためのエンドポイントをこの後利用するため、以下の AWS CLI コマンドで確認します。
aws iot describe-endpoint --endpoint-type=iot:CredentialProvider
実行結果
{
"endpointAddress": "xxxxx.credentials.iot.ap-northeast-1.amazonaws.com"
}
サンプルソースコードの修正
先程の手順でダウンロードした AWS IoT の証明書の秘密鍵と証明書をラズパイの /home/pi/amazon-kinesis-video-streams-webrtc-sdk-c/build の中にコピーします。コピー元の証明書のファイル名は実際にダウンロードしたものに合わせてください。(コピー先で名前を変えているので注意)
- xxxx-certificate.pem.crt -> certificate.pem
- xxxx-private.pem.key -> private.pem.key
AWS IoT の root CA 証明書のダウンロード
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O /home/pi/amazon-kinesis-video-streams-webrtc-sdk-c/build/cacert.pem
C SDK のサンプルは、デフォルトだと ACCESS_KEY を使った認証を行いますが、AWS IoT のクレデンシャルを使った認証方式に変更するため、先程の手順で作成したクレデンシャル情報をサンプルソースに反映します。(ラズパイ上での作業)
../samples/Common.c の 545-546行目をコメントアウト。
// CHK_ERR((pAccessKey = getenv(ACCESS_KEY_ENV_VAR)) != NULL, STATUS_INVALID_OPERATION, "AWS_ACCESS_KEY_ID must be set");
// CHK_ERR((pSecretKey = getenv(SECRET_KEY_ENV_VAR)) != NULL, STATUS_INVALID_OPERATION, "AWS_SECRET_ACCESS_KEY must be set");
../samples/Common.c の 555-559 行目を以下の内容に置き換えます。
createLwsIotCredentialProvider(
"調べたエンドポイントを入力",
"certificate.pem",
"private.pem.key",
"cacert.pem",
"作成したエイリアス名を入力",
channelName,
&pSampleConfiguration->pCredentialProvider));
最後に 637行目を以下の内容に置き換えます。
freeIotCredentialProvider(&pSampleConfiguration->pCredentialProvider);
これで再び build ディレクトリで以下のコマンドを実行してビルドし直します。
cmake ..
make
動作確認
これで、前の手順のように、ACCESS_KEY などのクレデンシャル情報を指定しなくても実行するだけで、AWS IoT より一時的な認証トークンを取得して、シグナリングチャンネルに接続 (無い場合は作成) します。
シグナリングチャンネルの名前には、CloudFormation の出力タブにかかれている ThingName の値を指定する必要があります。
export AWS_DEFAULT_REGION=ap-northeast-1
./kvsWebrtcClientMasterGstSample Mgz_KVSWebRTCDevice video-only
映像の確認は JavaScript のサンプルで確認します。JavaScript の方は先程と同様に、ACCESS KEY、SECRET KEY、SESSION TOKEN を使います。
Step 3 Amazon Alexa のスマートホームスキルを作成する
注意) 画面付きの Echo デバイスを持っていない場合は、この作業は不要です。
スマートホームスキルとは
スマートホームスキルは、クラウドに接続されたデバイスを Alexa デバイスから音声で操作できるようにするための仕組みを提供するものです。
今回のようにカメラを利用するアレクサスキルを作る場合は、カメラスキルを作る必要があります。
スマートホームスキルを作成するには、Amazon 開発者コンソールのアカウントが必要になります。アカウントを作成したらスキルの登録と、実際のプログラム (Lambda) の作成、アレクサアプリ上でスキルの有効化が必要です。
スマートホームスキルの具体的な作成手順については、こちらを参考に作成を行ってください。
Lambda の作成
Lambda のサンプルソースは、ダウンロードしたファイルの中の alexa_camera_skill に含まれている lambda_function.py を利用します。
スマートホームスキル用の Lambda は日本語で利用する場合、リージョンはオレゴン (us-west-2) を利用する必要があります。
環境変数の指定
Lambda にわたす環境変数は以下の物が必要です
- CHANNEL_ARN
- Kinesis Video Stream のシグナリングチャンネルの詳細に表示される ARN
- Kinesis Video Stream のシグナリングチャンネルの詳細に表示される ARN
- FRIENDLY_NAME
- 「アレクサ、玄関のカメラを見せて」のように呼びかける時の対象名 (例:玄関のカメラ) を指定
- 「アレクサ、玄関のカメラを見せて」のように呼びかける時の対象名 (例:玄関のカメラ) を指定
例)
もっとAlexa Skill について学びたい場合は、Alexa 公式 動画シリーズ「Alexa 道場」や、Alexa スキル開発トレーニングといったコンテンツがありますので、ぜひご参考ください。
ソースコードの修正
Gstreamer を使ったサンプルは、デフォルトで Trickle ICE をデフォルトで有効にしてしまいますが、Echo デバイスでは利用できないため、デフォルト値を変更します。
../samples/kvsWebRTCClientMasterGstreamerSample.c の 295 行目の値を、下記のように TRUE を FALSE に変更します。
CHK_STATUS(createSampleConfiguration(argc > 1 ? argv[1] : SAMPLE_CHANNEL_NAME,
SIGNALING_CHANNEL_ROLE_TYPE_MASTER,
FALSE,
TRUE,
&pSampleConfiguration));
これで再び build ディレクトリで以下のコマンドを実行してビルドします。
cmake ..
make
動作確認
アプリを実行し、Echo デバイスに、「アレクサ、〜〜を見せて」と話しかけます。(〜〜には FRIENDLY_NAME に指定した名称)
export AWS_DEFAULT_REGION=ap-northeast-1
./kvsWebrtcClientMasterGstSample Mgz_KVSWebRTCDevice video-only
動画を用意しましたので、実際に動いている様子が確認できます。
まとめ
スマートホーム自作化の第一歩は、いかがでしたか?
今回の仕組みは、Echo デバイスから利用する方法を紹介しましたが、KVS with WebRTC では様々なサンプルを用意してるので、スマフォから映像を確認したりと、さらに拡張が可能です。また、今回は映像のみを利用しましたが、音声も合わせて利用できますので、是非チャレンジしてみてください。
みなさんもスマートホーム化を楽しみましょう!
筆者紹介
市川 純
アマゾン ウェブ サービス ジャパン合同会社
技術統括本部 プロトタイピング ソリューションアーキテクト
2018年 に AWS へ入社した、Web サービスから家のデッキ作りまで、モノを作るという事であれば何でも好きな DIY おじさんです。最近は週末にバイクをイジるのにハマっています。
AWS を無料でお試しいただけます