Alexaに喋るのも面倒な時に使うiotボタン

皆さん、Amazon Echo(Alexa)便利に使ってますか？

我が家でも便利に使っています。

...

ところで。

Amazon Echo、便利に使っていますが、こちらの発音が悪いとEchoもなかなか上手く反応してくれませんよね。
(ちなみに我が家の娘の場合だと、発音が「アレクサ」ではなく「あれくしゃ」になってしまう事が多く、これだとEchoが起動してくれない事もしばしば)

定型処理の場合や喋るのが面倒なくらい弱っている時は、誰かが面倒な時に自分の代わりにEchoに指令してくれないものか...


...そうだ。喋って貰えばいいじゃないですか、この方法で！


という事で、メシ、風呂、寝る的な決まりきったEcho(Alexa)への指令をIoTボタンで実装したらどうなるか？
という興味と、今年学んだ技術を使って何かしてみたい、という事でこんな感じに実装してみました。

# 実装した仕組み
今回はLTE-M ButtonでAWS Lambdaを動作、AWS IoT CoreとクライアントPCをMQTT/MQTTSで繋ぎ、PC上で音声を再生、Echo dotに3種類の指令を与えられるようにします。

LTE-M IoT Button <---> Lambda <---> AWS IoT Core <-(MQTTS)-> Local PC <-(音声)-> Amazon Echo

## Amazon Polly
https://aws.amazon.com/jp/polly/

Echoに与える音声指令については、Amazon Pollyを使ってみます。

![スクリーンショット 2018-12-16 22.21.53.png](https://qiita-image-store.s3.amazonaws.com/0/32688/1865cfa9-7162-8b10-e366-f0a7ad26f5a6.png)

「深層学習を使用して文章をリアルな音声に変換」とあります。これなら自分が喋らなくても大丈夫そうですね。

Amazon Echoに喋りかけるのにAmazonの技術を集めた音声変換機能を使う、考えるだけでもワクワクしてきますw

Amazon Pollyにはテキスト読み上げ機能がありますが、重要なのはこれをMP3として保存する事が出来ます。
(上図の赤枠で囲んだ部分)

なので喋らせたいキーワードは選びたい放題！
今回は3つのコマンドを何に割り当てるか悩みましたが、以下の3つにしました。

* (SINGLE)Alexa、今日の天気は？
* (DOUBLE)Alexa、Queenの曲を流して
* (LONG)Alexa、ストップ

曲は何でも良かったのですが、最近巷で流行しているQueenの曲でも流してみましょうか...

## LTE-M Buttonのセットアップ
これは他のエントリの方が詳しく書かれているので割愛w

## Lambda側ソース
Labmdaのソースは簡単にこんな感じです。

lambda_function.py

```
import json
import boto3


# AWS IoT Data Planeオブジェクトを取得
iot = boto3.client('iot-data')


def lambda_handler(event, context):
    button_type = event['deviceEvent']['buttonClicked']['clickType']

    # MQTT PubSubトピックを指定
    topic = 'talking_to_alexa/to'
    # メッセージの内容
    payload = {
        "button_type": button_type
    }

    try:
        # MQTTメッセージをPublish
        iot.publish(
            topic=topic,
            qos=1,
            payload=json.dumps(payload, ensure_ascii=False)
        )
        print('published')

    except Exception as e:
        print(e)
        return "Failed."
    
    return "Ok."
```


## ローカルPC側ソース
ローカル側はMP3を再生させるためにpygameとmutagenを使っています。

talkalexa.py

```
import paho.mqtt.client
import ssl
import subprocess
import json
from mutagen.mp3 import MP3 as mp3
import pygame
import time


def playMp3(button_type):
    if (button_type == 'SINGLE'):
        filename = 'speech_weather_today.mp3'
    elif (button_type == 'DOUBLE'):
        filename = 'speech_play_music.mp3'
    elif (button_type == 'LONG'):
        filename = 'speech_stop_alexa.mp3'
    pygame.mixer.init()
    pygame.mixer.music.load(filename)
    mp3_length = mp3(filename).info.length
    pygame.mixer.music.play(1)
    time.sleep(mp3_length + 0.25)
    pygame.mixer.music.stop()


endpoint = "yourendpoint.iot.ap-northeast-1.amazonaws.com"
port = 8883
topic_to = "talking_to_alexa/to"
topic_from = "talking_to_alexa/from"
rootCA = "YourAmazonRootCA1.pem"
cert = "certificate.pem.crt"
key = "private.pem.key"


def on_connect(client, userdata, flags, respons_code):
    print('connection...')
    client.subscribe(topic_to)


def on_message(client, userdata, msg):
    print('Recieve message.')
    data = json.loads(msg.payload.decode("utf-8"))
    button_type = data["button_type"]
    print(button_type)
    playMp3(button_type)


if __name__ == '__main__':
    client = paho.mqtt.client.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.tls_set(rootCA, certfile=cert, keyfile=key, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
    client.connect(endpoint, port=port, keepalive=60)
    client.loop_forever()

```

## 動作
Echo dotの近くにPCを持って行って、PC上のtalkalexa.pyをpowershell上から実行します。
connectの文字が表示されたら、おもむろにLTE-M Buttonをクリックすれば、明日の天気を聞いてくれるはず！

## 自分的気を付ける点
AWS IoT CoreやAlexa Skillを使っている際に気を付けている点として、Labmdaを実行したい場合は先にLambdaを作成しておくって事ですね。
チュートリアルとかだと、順を追って説明していますが、手順でいきなりLambda作成とかが途中で入るので逆に分かり辛いんですよね...

また、今回は久々にAWS IoTを触ったため、ポリシーのアタッチを忘れていて10分ぐらい通信が出来ない、という事で悩みましたw

## その他いろいろ
スピーカーも付いているPCが楽なので、その環境上で実行しましたが、本当であればRaspberryPiとかに置き換えた方がもうちょっとは実用的です。

今回はAWS IoT Core、Amazon Polly、LambdaそしてLTE-M Buttonと色々覚えた技術を復習の意味も込めてシステムを組んでみました。

来年は個人的に興味のあるKryptonとか弄ってみたいな～。
ではまた！