Pepper の自律モード（オートノマスライフ）のカスタマイズ（２）ーコラボラティブダイアログ

この記事は「[Pepper の自律モード（オートノマスライフ）のカスタマイズ（１）ーカスタムサービスを常駐させる](http://qiita.com/tkawata1025/items/a036e98e16ad1dbcad2e)」の続編です。

ここでは自律モード（オートノマスライフ）をカスタマイズする方法を紹介します。
ここでは、オートノマスライフの会話モードで「マイ天気予報」と話しかけると天気予報を伝えてくれるという機能を追加してみます。

（自律モードで「天気」というと天気アプリが起動され、天気予報を教えてくれますが、ここでの方法はアプリの起動なく、天気予報を教えてくれます。）

> 『注意』 
公式にはカスタマイズ方法についてガイドがあるわけではないので、NAOqi の機能を使って「うまくいった方法」を紹介しています。試した環境は NAOqi 2.4.2 です。自律モードの機能は日々進化しており、将来的にここで紹介した方法がうまく動かないことも考えられます。ご自身で行う場合は、内容をよく理解したうえで、自己責任でお願いします。

#前提（対象）

この記事は、Pepper を所有されている方で、オートノマスライフなどの基本的な Pepper の動作仕様を理解されている方を対象としています。また Dialog 機能を理解している必要があります。

#コラボラティブダイアログ

コラボラティブダイアログはオートノマスライフの会話モードの中で動く Dialog です。 Dialog を作るときに [コラボラティブダイアログとしてパッケージに追加] をチェック。　ダイアログの設定としてはこれで十分です。

<img width="1392" alt="img1.png" src="https://qiita-image-store.s3.amazonaws.com/0/81650/611a6912-2df0-5963-3af6-504bf7f14574.png">

オートノマスライフに会話を組み込むには本体にこの Dialog を含むアプリをインストールする必要があります。

インストールに先立って[プロパティ]を設定しておきます。気をつけるポイントは Japanese が対応言語に含まれていること。

<img width="1385" alt="img2.png" src="https://qiita-image-store.s3.amazonaws.com/0/81650/e2723809-4c48-06bf-606c-73734e9c7836.png">

また、タブレットランチャーにアプリを表示させる必要はないので、[ユーザーのリクエストより開始]のチェックを外しておくことです。

<img width="1386" alt="img3.png" src="https://qiita-image-store.s3.amazonaws.com/0/81650/28669448-72ba-c0e2-7763-587e9c70302d.png">

設定が一通り問題ないようであればアプリをインストールします。

<img width="395" alt="image10.png" src="https://qiita-image-store.s3.amazonaws.com/0/81650/01c8b67a-9e6d-1db6-2b00-60c3f04de702.png">

経験上、コラボラティブダイアログをインストールした後は本体を再起動したほうがいいようです。コラボラティブダイアログはオートノマスライフの中に組み込まれるため、専用の最適化処理がインストール後１度だけ行われ、その結果はが本体の中に保存されます。この最適化の処理はそれなりに時間がかかるので、インストール後は一旦再起動、その再起動処理の中で最適化処理を行わせたほうが安定しています。最適化処理のためこの再起動は通常より少し時間がかかりますが、根気強く待ちましょう。

#コラボラティブダイアログの活用例、ダイアログからサービスを呼び出す

会話シナリオでオートノマスライフとうまく連携させるのは少し試行錯誤が必要かもしれません。そんな中で今回、紹介したいのは、ダイアログからサービスを直接呼び出す方法です。前回紹介した「[Pepper の自律モード（オートノマスライフ）のカスタマイズ（１）ーカスタムサービスを常駐させる](http://qiita.com/tkawata1025/items/a036e98e16ad1dbcad2e)」と組み合わせてちょっとした独自の便利機能を自律モードに組み込むことができます。

まず独自のサービスとして次のようなサービスプログラムを作ってみました。

```py:MyCustomerPepperService.py
# -*- coding: utf-8 -*-

import qi
import sys
import json
import urllib2

class MyCustomPepperService:
  def __init__(self, session):

    self.session = session
    self.logger = self.session.service("ALLogger")

    self.logger.info("MyCustomPepperService","Starting MyCustomPepperService...")
    self.memory = self.session.service("ALMemory")
    self.rearhead_subscriber = self.memory.subscriber("RearTactilTouched")
    self.rearhead_subscriber.signal.connect(self._rearHeadCallback)

  def _rearHeadCallback(self,value):
    if int(value) > 0:
      self.logger.info("MyCustomPepperService", "RearHead touched")
      if self.memory.getData("AutonomousLife/State") == "solitary":
        self.logger.info("MyCustomPepperService", "starting autonomous Dialog...")
        al = self.session.service("ALAutonomousLife")
        al.switchFocus("mycustompepper_1/behavior_1")

  def getWeather(self, citycode):
    self.logger.info("MyCustomPepperService", "GetWeather called..")
    message = "天気情報を取得できませんでした"
    try:
      resp = json.loads(urllib2.urlopen('http://weather.livedoor.com/forecast/webservice/json/v1?city=%s'% str(citycode)).read())
      message = resp['title'].encode('utf-8') + "。\\pau=1000\\ "
      for forecast in resp['forecasts']:
        message = message + forecast['dateLabel'].encode('utf-8') + "\\pau=500\\" + forecast['telop'].encode('utf-8') + "\\pau=1000\\"
    except:
      pass

    return str(message)

if __name__ == "__main__":
    app = qi.Application(sys.argv)

    app.start()
    app.session.registerService("MyCustomPepperService", MyCustomPepperService(app.session))

    app.run()   # will exit when the connection is over

```

内容としては前回「[Pepper の自律モード（オートノマスライフ）のカスタマイズ（１）ーカスタムサービスを常駐させる](http://qiita.com/tkawata1025/items/a036e98e16ad1dbcad2e)」の中で紹介したコードに getWeather のメソッドを追加しただけです。
このメソッドは Livedoor のサービスから天気予報情報を取得しています。コードは「[python お天気apiから近日の天気を取得する](http://qiita.com/shizuma/items/ad04e08ab31ba436d34e)」を参考にしました。（今回は簡易的な方法を使いましたが、天気予報をより詳細に取得するサービスとしては [YuMake](http://www.yumake.jp/services/weather-api-main) などあります。）

サービスのインストール手順は[前回の記事](http://qiita.com/tkawata1025/items/a036e98e16ad1dbcad2e#%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92-pepper-%E6%9C%AC%E4%BD%93%E3%81%AB%E9%80%81%E3%82%8B)を参考にしてください。

サービスをダイアログから直接呼び出すことができます。書式は

> ^call( *サービス名*.*メソッド*)

サービスからの戻り値は c1: で受け取ることができます。

書いてみたQiChat は次の通り

```
topic: ~mydialog()
language: jpj

u:(マイ天気予報) \vct=135\ 天気予報をお伝えします。^call(MyCustomPepperService.getWeather(130010))
  c1:(_*) $1
```

引数に与えている 130010 は天気予報の取得地域「東京」のためのコード番号です。他の地域を指定する場合のコード番号は次を参考にしてください。
[http://weather.livedoor.com/forecast/rss/primary_area.xml](http://weather.livedoor.com/forecast/rss/primary_area.xml)

これでオートノマスライフ、会話モードの時「マイ天気予報」と言うと天気予報を答えてくれます。

#最後に

いかがでしょう。カスタムサービスとコラボラティブダイアログを組み合わせると色々な便利機能を自律モードに追加できそうです。例えば「電気消して」といって電気を消してくれる機能をアプリの中に用意するのは実際のユースケースとしてあまりぱっとしませんが、IoT 連携をして電気を消してくれるサービスをカスタムサービスとして常駐させてコラボラティブダイアログで「電気を消して」と言われたらこのサービスを呼び出するというのはいかがでしょう？
いろいろ妄想できますね！