はじめに
TechSummitのちょまどさんセッション(ちょまどさんのブログ)に触発されて、Alexaを購入しました。
が、特にカスタムすることなく、音楽を聴く置物と化していました。
話は変わりますが、私の上司にヨーグルトが大好きな方がいます。
そこで、Alexaを使っておススメされたこれまでのヨーグルト通知機能を作成してみることにしました。
環境
- Visual Studio 2017 Professional(Community Edtion以上)
- 言語:C#
- Azureサブスクリプション
なかなかうまくいかずに苦戦していましたが、
この方の記事を見ながらやったらあっさりできました。感謝です。
Azure Functions + C# を利用してAlexaスキルを開発してみる
AzureFunctions側の作成
AzureFunctionsのソリューションを作成
新規作成→プロジェクトより、Azure Functionsを選択します。
上記、記事の方もおっしゃっているように、AzureFunctions v2を選択します。
OKを押せば、ソリューションの完成です。
処理
まず、NuGetパッケージマネージャーよりAlexa.NETを追加します。
作成したソリューションに下記コードをかきました。
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Alexa.NET.Request;
using Alexa.NET.Request.Type;
using Alexa.NET.Response;
using System.Linq;
using AlexaSkill.Models;
namespace AlexaSkill
{
public static class Function1
{
private static string HelloMessage { get; } = "こんにちは!ヨーグルトスキルです!";
private static string IntroductionMessage = "今日のヨーグルトスキルです!おすすめのヨーグルトを教えてと話しかけてください。";
private static string ErrorMessage { get; } = "すみません、わかりませんでした!";
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
string requestJson = "";
using (var sr = new StreamReader(req.Body))
{
requestJson = await sr.ReadToEndAsync();
}
SkillRequest skillRequest = JsonConvert.DeserializeObject<SkillRequest>(requestJson);
var skillResponse = new SkillResponse
{
Version = "1.0",
Response = new ResponseBody()
};
switch (skillRequest.Request)
{
case LaunchRequest lr:
skillResponse.Response.OutputSpeech = new PlainTextOutputSpeech
{
Text = IntroductionMessage,
};
break;
// インテント使って返事されるやつ
case IntentRequest ir:
{
var r = HandleIntent(ir.Intent.Name);
skillResponse.Response.OutputSpeech = new PlainTextOutputSpeech
{
Text = r.ResponseMessage,
};
skillResponse.Response.ShouldEndSession = r.ResponseFinishFlg;
}
break;
default:
skillResponse.Response.OutputSpeech = new PlainTextOutputSpeech
{
Text = "すみません。わかりません",
};
break;
}
return new OkObjectResult(skillResponse);
}
//インテントの処理を記述
private static HandleIntentResult HandleIntent(string intent)
{
switch (intent)
{
case "HelloIntent":
return new HandleIntentResult
{
ResponseMessage = HelloMessage,
ResponseFinishFlg = false,
};
case "AskYogurutoIntent":
{
string[] yogurutWord = new[] { "ローソンの飲むりんごヨーグルト", "セブンの期間限定ヨーグルト", "ごろごろ果実のはっさく" };
// ランダムソート
string[] yogurutWords = yogurutWord.OrderBy(i => Guid.NewGuid()).ToArray();
return new HandleIntentResult
{
ResponseMessage = yogurutWords[0],
ResponseFinishFlg = false,
};
}
case "AMAZON.StopIntent":
return new HandleIntentResult
{
ResponseMessage = "また明日",
ResponseFinishFlg = true,
};
default:
return new HandleIntentResult
{
ResponseMessage = ErrorMessage,
ResponseFinishFlg = false,
};
}
}
}
}
namespace AlexaSkill.Models
{
class HandleIntentResult
{
public string ResponseMessage { get; set; }
public bool ResponseFinishFlg { get; set; }
}
}
基本的にちょまどさんのコードに一部変更を加えているのみの実装です。
LaunchRequestが「Alexa,~開いて!」と言った後に走るみたいです。
一方、IntentRequestは、後ほど設定するAlexa Developer Consoleの
インテントに設定した言葉が読み取られると、走るみたいです。
今回は、とりあえずAlexaに言って欲しい言葉を配列にいれて、ランダムに返してくるようにしました。
発行
AzureFunctionsを先にAzureで作成しておくという手段もありますが、新規作成にて発行しました。
Alexa Developer Consoleにて設定の作成
公式の説明がわりとわかりやすいです。
Alexaスキル開発トレーニング
ここでは軽く説明したいと思います。
-
alexa developer consoleにログインします。
-
上の方に「あなたのAlexaダッシュボード」欄があると思うので、そちらからSkillsを選択。
-
スキルの作成を選択。
-
スキル名や呼出名を指示に従って入力していきます。
-
インテントを追加します。インテントを追加することによって、
先ほどコードにかいたIntentRequest部分が走ります。
追加したインテントはこちら
テストするとこんな感じでJsonに送られます。
-
追加が完了したら、モデルを保存し、モデルをビルドします。
終わったら再びモデルを保存し、ビルドします。
テスト
テストタブを選択し、スキルテストが有効になっているステージを開発中とします。
はまったこと
AMAZON.StopIntent(もとからあるもの)に「また明日」というセリフを言って、
スキルを終了して欲しかったのですが、
スキルが終わらずに永遠に「こんにちは!」と言い続けていました。
調べたところ、スキルを終わらすには、shouldEndSessionをtrueにする必要があったそうですね。。
しばらくAlexaのコンセントを抜いてテストをしていました。
「標準ビルドインテント」
さいごに
Alexaが音楽を聴くただの置物から卒業できそうです。