おいしいコーヒーの淹れ方を教えてくれるAlexaスキルの作成に失敗した

 ## やりたかったこと
いつもコーヒーをタイマー付きのスケールを使って時間と湯量と計りながらコーヒーのドリップをしていたのですが、ぼーっとしているとお湯を注ぎそびれたり、どれくらいお湯を注ごうかなと迷ってしまったり。スケールさえあれば美味しいコーヒーが淹れられたら素敵だなあとおもったのが動機です。
[Bespoke Coffee Roastersの畠山さんの基本レシピ](https://www.youtube.com/watch?v=KHwliRyBWKU)を使用させていただきました。（ご本人に許可をいただきました）

## スキルの概要
1. スキルを発動する
2. 準備ができたらタイマーを作成・開始する
    * 1湯目 0:00 「30ccまでお湯を注いでください」
    * 2湯目 0:30 「120ccまでお湯を注いでください」
    * 3湯目 1:00 「150ccまでお湯を注いでください」
    * 4湯目 1:20 「190ccまでお湯を注いでください」
    * 5湯目 1:40 「230ccまでお湯を注いでください」
    * 2:20 落とし切りで終了、「コーヒータイムを楽しんでください！」

## 失敗している箇所
Androidアプリのアレクサでは問題なかったのですが、公開してEcho showで試したところ、制御不能となり本体の電源を切る羽目となりました。
* 想定外のタイマーの終了音が鳴ってしまう
* タイマーをキャンセルしてもタイマーの画面が閉じられない
* 作成されたタイマーを全てキャンセルしても、タイマーの終了音が止められない

## Alexaスキルの開発の始め方
2つのサービスのアカウントが必要です。
* Amazon開発者アカウント
* AWSアカウント

https://alexa-skills-kit-python-sdk.readthedocs.io/ja/latest/DEVELOPING_YOUR_FIRST_SKILL.html#id2

## スキルの開発
公開されているサンプルコードを使って開発をはじめました。
https://github.com/alexa-samples/skill-sample-python-helloworld-classes/tree/master/lambda/py

### コーヒーを淹れる準備ができた時のインデントハンドラー
1. タイマーの制御権限を許可してもらう
1. 時間差をつけてタイマーを作成・開始する
1. 応答を返す

```
class LetsCoffeeTimeIntentHandler(AbstractRequestHandler):

    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return ask_utils.is_intent_name("LetsCoffeeTimeIntent")(handler_input)

    def handle(self, handler_input):

        accessToken = ask_utils.get_api_access_token(handler_input)
        rb = handler_input.response_builder
        request_envelope = handler_input.request_envelope
        permissions = request_envelope.context.system.user.permissions
        if not (permissions and permissions.consent_token):
            print("user hasn't granted reminder permissions")
            res = (
                rb
                .add_directive(
                    SendRequestDirective(
                        name="AskFor",
                        payload={
                            "@type": "AskForPermissionsConsentRequest",
                            "@version": "1",
                            "permissionScope": "alexa::alerts:timers:skill:readwrite",
                        },
                        token=""
                    )
                )
                .response
            )
            print(res)
            return res
        else: 
            get_custom_task_launch_timer(accessToken, "PT30S", "2湯目", "お湯を120ccまでそそいでください")
            get_custom_task_launch_timer(accessToken, "PT60S", "3湯目", "お湯を150ccまでそそいでください")
            get_custom_task_launch_timer(accessToken, "PT80S", "4湯目", "お湯を190ccまでそそいでください")
            get_custom_task_launch_timer(accessToken, "PT100S", "5湯目", "お湯を230ccまでそそいでください。注いだ後は、お湯が落とし切れるまで待ちましょう。")
            get_custom_task_launch_timer(accessToken, "PT140S", "落とし切ります", "できあがりです！コーヒータイムをたのしんでください！")
            return (
                handler_input.response_builder
                .speak("タイマーを開始しました。お湯を30cc注いでください").response
            )
```


### タイマーを作成する関数
```
def get_custom_task_launch_timer(accessToken, duration, timerLabel, textToAnnounce):
    options = {"Authorization": "Bearer " + accessToken,"Content-Type": "application/json"}
    timer = { "duration": duration, "timerLabel": timerLabel, "creationBehavior": { "displayExperience": { "visibility": "VISIBLE" } }, "triggeringBehavior": { "operation": { "type": "ANNOUNCE", "textToAnnounce": [ { "locale": "ja-JP", "text": textToAnnounce } ] }, "notificationConfig": { "playAudible": False } } }
    res = requests.post("https://api.fe.amazonalexa.com/v1/alerts/timers", data=json.dumps(timer), headers=options)
 ```
* タイマーの終了音をミュートにする
playAudibleにFalseを設定することでミュートにすることができました。（AndroidのAlexaアプリ上では無音になりました…）
* タイマーのAPIのリクエスト先
タイマーのAPIは、日本の場合「api.fe.amazonalexa.com/v1/alerts/timers」であることに気づかずなかなか苦戦しました。
https://developer.amazon.com/ja-JP/docs/alexa/smapi/alexa-timers-api-reference.html#create-timer

## 次回
タイマーをキャンセルしてもキャンセルできない挙動の解決
Echo Showでも安定した挙動を確認する
スキルを公開する