5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RustとLambdaでなんか作る 後編 (リクガメの食べ物しらべるghomeアプリ作った)

Last updated at Posted at 2019-01-21

RustとLambdaでなんか作る 前編
RustとLambdaでなんか作る 中編

はい。後編でございます。
作るアプリ考えました。
後編とはいうものの、ここまでHello worldしかやってないのでこれ一個で完結しちゃったりもします。

何を作る?

アプリ名:リクガメの食べもの

リクガメにあげてもいい餌を教えてくれるアプリ。

: リクガメの食べ物につないで
Home: はい、リクガメの食べ物です
: ピーマンあげていい?
Home: はい。ピーマンはあげていい食べ物です。カルシウムは少ないです。(終了)

みたいな、シンプルなものにします。
webhook側は一度リクエストを受け取ってレスポンスを返せばOK.
問いと回答は静的に用意しておく。

google home アプリのとこ

項目 内容
アプリ名 リクガメの食べもの
project name kamefood
Category Education & referrence
Actions Dialogflow
Intents askIntent, wellcome, fallback
Entities food

askIntentというのがあり、例えば「小松菜上げていい?」と問いかけます。
すると小松菜がfoodというEntityになってRequestに乗っかってきます。
それはqueryResult.queryTextではなく、queryResult.Parametersの中にfoodとして入ってきます。
それを受けてそれに対するワードを返すところをRustで作る。

ソース

main.rsのみとなっていましたが、分けたらどうなるのかなと思ってfood.rsというのも作成してみました。
foods.rsは単にHashを保持して、キーに応じてvalueをリターンしてるだけ。
キーが食べ物でgoogleが投げてくるやつです。
そしてmain.rsはそれを投げる人で受け取る人でdialogflowに返す人です。
少し苦戦した箇所はあるけどそれは最後のまとめで。ひとまず動きました。

foods.rs

pub mod foods {
  use std::collections::HashMap;

  pub fn get(s:&str) -> String {
    let mut f = HashMap::new();
    f.insert("小松菜".to_string(), "<speak>はい。小松菜は、<prosody volume=loud>あげても大丈夫です。</prosody>カルシウムも豊富でおススメの食べ物です。ではまた。</speak>");
    f.insert("水菜".to_string(), "<speak>はい。水菜は、<prosody volume=loud>あげても大丈夫です。</prosody>カルシウムも豊富でおススメの食べ物です。ではまた。</speak>");
    f.insert("チンゲンサイ".to_string(), "<speak>はい。チンゲンサイは、<prosody volume=loud>あげても大丈夫です。</prosody>カルシウムも豊富でおススメの食べ物です。ではまた。</speak>");

...()...
 
    return format!("{}", f.get(s).as_ref().unwrap());
  }
}
main.rs
use std::error::Error;

use lambda_http::{lambda, Request, Response, Body};
use lambda_runtime::{error::HandlerError, Context};
use log::{self, info};
use simple_logger;

mod foods;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

#[derive(Debug,Deserialize,Default)]
struct Req {
  #[serde(default)]
  queryResult: QueryResult
}

#[derive(Debug,Deserialize,Default)]
struct QueryResult {
  #[serde(default)]
  queryText: String,
  #[serde(default)]
  parameters: Parameters
}

#[derive(Debug,Deserialize,Default)]
struct Parameters {
  #[serde(default)]
  food: String
}

fn main() -> Result<(), Box<dyn Error>> {
    simple_logger::init_with_level(log::Level::Info).unwrap();
    lambda!(my_handler);

    Ok(())
}

fn my_handler(e: Request, c: Context) -> Result<Response<Body>, HandlerError> {
  let query: Req = serde_json::from_slice(e.body().as_ref()).unwrap();
  info!("{:#?}", query);
  let food: String = query.queryResult.parameters.food;
  info!("{}", foods::foods::get(&food));
  Ok(
    Response::builder()
     .status(200)
     .header("Content-Type", "application/json; charset=UTF-8")
     .body(
       format!(
        r#"
          {{
            "fulfillmentText": "{}"
          }}"#,
        foods::foods::get(&food)
        ).into(),
      )
     .expect("none")
  )
}

actions on google や dialog flowの設定

スクショなしで簡潔に書きますね。
基本的な手順は前回と同じです。

dialogflow

  • askIntentを追加しました
  • Traning phrasesには「小松菜は大丈夫」のようなパターンを羅列しています
  • 「小松菜」といった食べ物の名前には@foodのEntitiesを設定しています
  • webhookを有効にしています
  • Set this intent of conversationを有効にしています
  • @foodはREQUIREDなパラメータにして絶対入ってくるようにする
  • fullfillment
  • webhookurlをlabmda(api gateway)のURLにしています

actions on google

  • アプリ名とかもろもろは前述
  • 画像は192x192と1920x1080を用意して登録しないといけないです
  • プライバシーポリシーはwordpress上で一枚用意してます。たったこんだけ->http://ikegami.tokyo/2019/01/21/kamefood-pp/
  • simuraterでテストしてOKだったのでOverviewからReleaseを選択し、SUBMIT FOR PRODUCTION

まとめ

64.png

そんなわけで申請中です。
ちなみにgoogle home、alexa、clovaがスマートスピーカーの代表的なとこですが、googleが一番審査早く、審査自体も通りやすいと思ってます。リジェクトされても指摘箇所直せばサクッと通ります。逆にalexaが一番厳しいですかね。

さて、最後にRustを味見してみた感想。
まだ10%も使えてないと思うけどそれを加味して聞いてくださいませ。

  • 思ったよりは使いやすい
  • スクリプト言語出身な人でも、ミュータブルな変数もあるわけだし、意外と自由に書こうと思えば書ける(それが良いとは言ってない)。特にnodejsな人は馴染みやすそう。
  • 独特な記法についてはまだよくわからない
  • 調べてみるとawsのsdk的なの(rusoto)があるし、今回みたいな用途で使ってもいいのかも。
  • コンパイラが親切。根気よくダメ出ししてくれる。
  • Optionとかunwrapとか最初よくわかんなかったけど、慣れると恩恵大きそう
  • 好きか嫌いかと言えば好き

そんなわけでもうしばらく触ってみようと思います。
今回のも正常系しかほぼ想定してなくて、アカンコードですしね。まずはここを直していこう。テストコードも書いておきたい。
そしてその次は何つくろ。・・仕事でこっそりバッチ作ってみようかなぁ。

##追記
https://assistant.google.com/services/a/uid/0000008de1f59b3d?hl=ja
半日くらいで公開されました。画像適当すぎたなあ。。

そんなわけで、スマートスピーカー、めっちゃ敷居低いっすよ。なんか思いついたら是非。なんか使いたい言語使ってみるとなお良いかも。

5
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
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?