「Alexaから新型ゾイドをボイスコントールするシステム」を作ってみた

Amazon Echo（Alexa）、AWS Lambda、IFTTT、Sony MESH、ZOIDS（ゾイドワイルド ワイルドライガー）を使用して、「Alexaからゾイドをボイスコントロールするシステム」を作ってみました。


![zoid1.png](https://qiita-image-store.s3.amazonaws.com/0/191401/428ea003-3187-24c6-302d-8fdb727aeea3.png)




# 使い方

使い方を解説します。

Amazon Echoに話しかけ、Alexaスキルを起動し、命令します。

（私）　「アレクサ、ジャービスを起動」
（Echo）「ジャービスです、いかがなさいましたか？」
（私）　「ゾイドを起動！」
（Echo）「承知しました。ワイルドライガーを発進します」
　　↓
ゾイドが動く！！

![zoid3.PNG](https://qiita-image-store.s3.amazonaws.com/0/191401/f0e52788-314a-aae0-6b04-89d247202da9.png)


こちら動画です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「Alexaから新型ゾイドをボイスコントールするシステム」を作ってみました。作り方詳細はこちら。<a href="https://t.co/cHtdjDXV0X">https://t.co/cHtdjDXV0X</a> <a href="https://t.co/dnJnUxp1cy">pic.twitter.com/dnJnUxp1cy</a></p>&mdash; すぐる (@Neuro_educator) <a href="https://twitter.com/Neuro_educator/status/1010725492482142208?ref_src=twsrc%5Etfw">2018年6月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>




システムの概要図は以下の通りです。

![zoid2.png](https://qiita-image-store.s3.amazonaws.com/0/191401/82068760-7a91-f166-7f00-9915d49e6c9e.png)

# 作り方

## Alexaスキルを作成

スキル作成には、以下の書籍を参考にさせていただきました。
[●スマートスピーカー × AIプログラミング ~自分でつくる人工知能 Amazon Echo、Google Home対応~](https://www.amazon.co.jp/%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%82%B9%E3%83%94%E3%83%BC%E3%82%AB%E3%83%BC-AI%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E8%87%AA%E5%88%86%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E4%BA%BA%E5%B7%A5%E7%9F%A5%E8%83%BD-Echo%E3%80%81Google-Home%E5%AF%BE%E5%BF%9C/dp/4839965803/ref=sr_1_1?ie=UTF8&qid=1528543116&sr=8-1&keywords=%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%82%B9%E3%83%94%E3%83%BC%E3%82%AB%E3%83%BC%E3%80%80AI%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

Alexaスキルの作成の詳細は省略します。
概要だけ記載します。

1. スキルの呼び出し名を設定します。今回は「ジャービス」にしました
※ 別のスキルと呼び出し名が被っていると誤動作する原因になります。別の名前にするのが無難です

2. インテントに、新たに「zoidStart」を追加します。このインテントでゾイドを起動させます
4. サンプル発話に、「ゾイドを起動」と設定します
5. これでビルドすれば、スキル作成完了です。Amazon Echoのアプリから「DEVスキル」をチェックし、作成したスキルを有効化します
6. 最後にエンドポイントにAWS Lambdaのアドレスを設定します。ここには後ほど作成するLamda関数のアドレスを設定します


作成した内容のJSONは以下の通りです。
単純にインテントを新たにひとつ作成しただけになります。

```Python:JSONエディター
{
    "interactionModel": {
        "languageModel": {
            "invocationName": "ジャービス",
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "zoidStart",
                    "slots": [],
                    "samples": [
                        "ゾイドを起動"
                    ]
                }
            ],
            "types": []
        }
    }
}
```

## AWS Lambda関数の作成
Lambda関数作成には、以下のサイトを参考にさせていただきました。
[●Alexa Skills Kit入門シリーズ(Python、AWS Lambda使用)](https://torina.top/detail/441/)

AlexaとIFTTTをつなげたいので、必ずしもLambda関数は必要ではありません。
しかし、AlexaとIFTTTをダイレクトにつなぐと、Alexaから望みの応答音声を出力できないなど、自由度が低くなります。

そこでAlexaに自由な音声応答を返してもらうために、Lambda関数を間に挟みます。

私はPythonで作るのが慣れているので、Lambda関数もPythonで作成しました。

ポイントは
・立ち上げの「LaunchRequest」に対しては、'shouldEndSession': False を明示して、会話を続けるようにすること
・urllib.requestを使って、IFTTTにPOSTすること
です。



```Python:AWS_Lambda
# Alexaからeventを受け取り、zoidを起動するJSONをAlexaに返却する。同時にIFTTTを叩く
# 参考：https://qiita.com/hoto17296/items/8fcf55cc6cd823a18217
# 参考：http://tech.mof-mof.co.jp/blog/amazon-echo-alexa-skill-trash-day.html

import json
import urllib.request


def lambda_handler(event, context):
    if event['request']['type'] == "LaunchRequest":
        response = {
            'version': '1.0',
            'response': {
                'outputSpeech': {
                    'type': 'PlainText',
                    'text': 'ジャービスです。いかがなさいましたか？'
                },
                'shouldEndSession': False    
            },
            
        }
        return response

    else:
        intent = event['request']['intent']['name']  # intentの取得


        if intent == "zoidStart":
            # Alexaに返すJSONを作成
            response = {
                'version': '1.0',
                'response': {
                    'outputSpeech': {
                        'type': 'PlainText',
                        'text': '承知しました。ワイルドライガーを発進します'
                    }
                }
            }
            
            # IFTTTを叩く
            url = 'https://maker.ifttt.com/trigger/zoid_start_ifttt/with/key/[個人のIFTTTのWebhookのIDみたいなの]'
            data = {}  # JSONの中身はとくになし
            headers = {
                'Content-Type': 'application/json',
            }

            req = urllib.request.Request(url, json.dumps(data).encode(), headers)
            with urllib.request.urlopen(req) as res:
                body = res.read()
            
            return response
        else:
            raise ValueError("Invalid intent")
```


## IFTTTのWebhook作成
続いてIFTTTのWebhookを作成します。

このWebhookはLambda関数からのpostを受けて、Sony MESHにイベントを送ります。

Webhook作成には、以下のサイトを参考にさせていただきました。
[●SONY MESHのGPIOタグとスマホで本格IoT！大事な人の位置を知らせるメーターを作ろう！](http://deviceplus.jp/hobby/mesh-06/)

## Sony MESHのアプリ作成
続いてSony MESHのアプリを作成します。MESHタグには汎用なGPIO（General Purpose Input Output）タグを使用します。

GPIOのアプリ作成にはIFTTTと同じく、以下のサイトを参考にさせていただきました。
[●SONY MESHのGPIOタグとスマホで本格IoT！大事な人の位置を知らせるメーターを作ろう！](http://deviceplus.jp/hobby/mesh-06/)

![P_20180624_121314.jpg](https://qiita-image-store.s3.amazonaws.com/0/191401/449944bf-ca7d-b779-b3c9-0efde1a4c19a.jpeg)


## ゾイドとMESH GPIOをつなぐ
ここはMESH GPIOタグ用モータドライバを使用し、ゾイドの電池ボックスのプラスマイナスの端子にワニ口クリップで強引に接続しました。

GPIOと電池ボックスをひっぱっていて、カッコ悪いのはご愛敬ということで・・・

![zoid3.PNG](https://qiita-image-store.s3.amazonaws.com/0/191401/40de7a2f-977c-dbaa-43f2-5b70e641716a.png)


以上で完成です。







画像引用
http://takaratomymall.jp/shop/g/g4904810111955/
http://monoist.atmarkit.co.jp/mn/articles/1509/16/news139.html