やりたかったこと
いつもコーヒーをタイマー付きのスケールを使って時間と湯量と計りながらコーヒーのドリップをしていたのですが、ぼーっとしているとお湯を注ぎそびれたり、どれくらいお湯を注ごうかなと迷ってしまったり。スケールさえあれば美味しいコーヒーが淹れられたら素敵だなあとおもったのが動機です。
Bespoke Coffee Roastersの畠山さんの基本レシピを使用させていただきました。(ご本人に許可をいただきました)
スキルの概要
- スキルを発動する
- 準備ができたらタイマーを作成・開始する
- 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
コーヒーを淹れる準備ができた時のインデントハンドラー
- タイマーの制御権限を許可してもらう
- 時間差をつけてタイマーを作成・開始する
- 応答を返す
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でも安定した挙動を確認する
スキルを公開する