LoginSignup
1
1

More than 1 year has passed since last update.

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

Posted at

やりたかったこと

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

スキルの概要

  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://github.com/alexa-samples/skill-sample-python-helloworld-classes/tree/master/lambda/py

コーヒーを淹れる準備ができた時のインデントハンドラー

  1. タイマーの制御権限を許可してもらう
  2. 時間差をつけてタイマーを作成・開始する
  3. 応答を返す
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でも安定した挙動を確認する
スキルを公開する

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1