メディアフォース 開発者ブログ

株式会社メディアフォースの開発者による非公式ブログです。

Pepperくん秘書化計画 ~スケジュール編~

Zenfone 3につづいて Zenbook 3 を発売日に購入したメディアフォース齊藤です。
Zenfone 3 Laserを購入しようか迷ってます。

本記事はアプレッソ Advent Calendar 2016 の16日目の記事です。
qiita.com

去年も書かせていただいてますが、偶然にも 同じく16日でした。

スクリプト開発時に気をつけるべき3つのポイント - Appresso Engineer Blog

毎年12月16日は齊藤の日として広めて参りたいと思います。

Pepperくん秘書化計画とは

さて、Pepperくん秘書化計画についてご説明しましょう。

みんなだいすき顔面蒼白のPepperくんですが、説明係だったり案内係だったりとめんどくさい客来客対応として使われるケースが多いように思います。

Pepperくんを個人で購入される方はあまり多くはないと思いますが、なかなかに値が張ります
せっかくなので自分のために使いたい!ということでPepperくんには秘書として存分に働いてもらおう計画です。

構成図

f:id:mf_sol_eai:20161215110923p:plain

  1. Pepperくんに教えを乞う
  2. PepperくんがDataSpider Cloud(以下、DSC)にHTTPリクエスト飛ばす
  3. DSCがGoogle API経由でスケジュールを取得
  4. DSCでスケジュールをセリフ状のテキストに整形し、レスポンスボディで返す
  5. Pepperくんが受け取ったテキストを喋る

やろうと思えばPepper -> Google APIの直接でも出来ると思うんですが、GoogleのOAuth2認証やテキスト整形がめんどくさかったので簡単にできそうなDataSpiderを利用しました。
ちなみにDSCはまだリリースされていないので、DSC想定で普通のDataSpiderをEC2に置いてある感じです。

Google APIを取得する

DataSpiderによるGoogle API連携についてはこの記事を参考にしてます。
DataSpider RESTアダプタを使ってGoogleカレンダーの予定を取得する。 - Qiita

記事からちょっと変えた点

  • 認証情報の「APIを呼び出す場所」をその他のUIに変更してます。

f:id:mf_sol_eai:20161215112414p:plain

この場合、リダイレクトURLは不要ですが、http://localhost:7700 を指定しておきます。

また、最近 Google アカウントは二段階認証を導入しましたが、検証時点では二段階認証があると認証のレスポンスが受け取れなかったので無効にしてます。

DataSpider側のアプリをつくる

github.com

DSC_GoogleCalendar.zip に DataSpider プロジェクトを置いてあります。

  1. OAuth認証のグローバルリソースを作成しておく。
  2. 変数のcalendarIdに取得したいカレンダーIDを入れておく。カレンダーIDについてはここでは説明しないのでググってください。
  3. 実行すると、returnText にセリフ状のテキストが入ります。
  4. サービス登録し、HTTPトリガーを作成する。HTTPトリガーでreturnTextをレスポンスボディに含める設定にします。
  5. HTTPトリガーの設定が完了したら、ブラウザからHTTPトリガーにアクセスする。
  6. ブラウザにテキストが表示されたらOKです。

スクリプトの流れ

f:id:mf_sol_eai:20161215130754p:plain

  1. Google APIでカレンダーを取得する
  2. Mapperを使ってサマリ、開始日時、終了日時を取得する。
  3. 一旦CSVに吐いておく
  4. 吐いたCSVを読んでPepper用テキストに整形する。

Pepperアプリ

Pepperアプリの開発にはChoregrapheを使っています。
Pepperは「今日のスケジュール」といったワードに反応してスケジュールを教えて欲しいところです。

  • Choregrapheプロジェクト全体像

f:id:mf_sol_eai:20161215131049p:plain

ということでChoregrapheプロジェクトはPepper_DSC.zipに置いてます。

プロジェクトの構成

  1. Speech Reco. で「今日;明日;ありがとう」を登録しておきます。「今日」と「明日」でそれぞれのスケジュールを通知し、「ありがとう」で終了します。
  2. TextEditの「DataSpiderのURL」には先程ブラウザで確認したURLを設定しておきます。
  3. HTTP Getはこちらの記事を参考にしていますが、変えた部分があるのでコード全文載せておきます。
class MyClass(GeneratedClass):
    def __init__(self):
        GeneratedClass.__init__(self)

    def onLoad(self):
        #put initialization code here
        pass

    def onUnload(self):
        #put clean-up code here
        pass

    def onInput_onStart(self, url):
        from HTMLParser import HTMLParser
        import urllib2, contextlib

        class ContentParser(HTMLParser):
            def __init__(self):
                HTMLParser.__init__(self)
                self.inscript = False
                self.inbody = False
                self.text = ""

            def handle_starttag(self, tag, attrs):
                if tag == "body":
                    self.inbody = True
                if tag == "script":
                    self.inscript = True

            def handle_endtag(self, tag):
                if tag == "body":
                    self.inbody = False
                if tag == "script":
                    self.inscript = False

            def handle_data(self, data):
                if self.inbody and not self.inscript:
                    self.text = self.text + data

        try:
            timeout = int(self.getParameter("Timeout"))
            self.logger.info("Loading... %s" % url)
            response = urllib2.urlopen(url)
            text = response.read()

            self.logger.info("Loaded: %s" % text)
            self.onStopped(text)
        except urllib2.URLError, message:
            self.logger.warn("Failed to open: %s, message=%s" % (url, message))
            self.onFailed(message)

コードはやっつけですみません。。。

デモ

中々おもしろい感じにできたんじゃないでしょうか

あいだにDataSpiderを経由することで実装がやや難しい認証周りが比較的簡単に実装できたり、DeepLearningに学習用データも一緒に登録したりもできたりするのでPepper単体で完結できるものでも挟んでおくと色々はかどりそうですね :D