Pepper上にSlackBotのサービスを作成する


Pepper内でSlackBotを実行したかった。

今までSlackとPepperの連動はSlackのIncoming WebHookを使用して行っていました。
お仕事アプリからrequestモジュールを使って投稿していましたが、
Slack側からの通知を受け取れるようにしたいと思い、SlackBotのPepperへの搭載を考えました。

全お仕事アプリで横断的に使用したい。

SlackBotを使用してやりたかったこと。

  • PepperのBotを集めたチャンネルを作る。
    • Bot宛てのメッセージでPepperに各種イベントを送信する。
    • @Channel宛てのメッセージで全Pepperに各種イベントを送信する。
    • Pepperの各種センサ情報をSlackに収集する。

また、お仕事アプリによらず横断的に使用したかったため、こちら方の記事を参考にサービスとして実装してみました。
http://qiita.com/yacchin1205/items/11301d79380d08d2dbf6

開発環境

Mac OS Sierra
Python 2.7.10

SlackでBotを有効にする

環境構築

QiBuildのインストール

pip install qibuild

PythonSDKのインストール

最新版ではなく以下のバージョンを落としてきてください。
最新版(執筆時点では2.5.5)はどうやら変更点が多いようで、参考になる情報も少なかったので、2.4.3をダウンロードしました。

pynaoqi-python2.7-2.4.3.28-mac64

pathを通しておきます。
また、.bash_profileに追記しておきます。

$ export PYTHONPATH=${PYTHONPATH}:/path/to/pynaoqi-python2.7-2.4.3.28-mac64
$ export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/path/to/pynaoqi-python2.7-2.4.3.28-mac64

パスが通っていれば以下のコマンドが使用できます。

$ python

>> import qi
>> import naoqi

ワークツリーの準備

最終的に必要になる環境は以下の通りです。

SlackBotService
 qiproject.xml
 manifest.xml
 slackbotservice.py
 slackbotservice.pml
 bot_settings.py
 lib
  backports
  slackbot
  slacker
  websocket
  six.py
  plugins
   __init__.py
   mention.py
   proxy.py

プロジェクトのディレクトリと同階層で以下のコマンドを実行します。
下の階層で各種ビルド、パッケージングができるようになります。

$ pwd
/path/to/SlackBotService
$ qibuild init
$ qipy bootstrap

slackbotモジュールをインストール

$ pip install slackbot

必要なモジュールがまとめてインストールされます。
インストールされた以下のモジュールをSlackBotService/lib配下にコピーします。

$ pwd
/path/to/SlackBotService/lib
$ ls
backports/
slackbot/
slacker/
websocket/
six.py

websocket/cacert.pemをSlackBotService/lib配下にコピーします。

$ pwd
/path/to/SlackBotService/lib
$ ls
backports/
slackbot/
slacker/
websocket/
six.py
cacert.pem

SlackBotを実装する

設定を記述

SlackBotの設定を記述します。

SlackBotService/bot_settings.py
# -*- coding: utf-8 -*-

import os
from slackbot import settings

settings.API_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
settings.DEFAULT_REPLY = u"よくわかりません。"
settings.PLUGINS = [
    'plugins',
]

os.environ['WEBSOCKET_CLIENT_CA_BUNDLE'] = os.path.join('./bin', 'cacert.pem')

以下の部分は、パッケージング時にバンドルされない上述の鍵ファイルを読み込ませています。
当然警告は出ますが、Pepper本体の環境を汚したくなかったので一旦こうしました。

os.environ['WEBSOCKET_CLIENT_CA_BUNDLE'] = os.path.join('./bin', 'cacert.pem')

サービスとして起動されるメインスクリプトを実装

スクリプトの実行時にSlackBotをrunします。

SlackBotService/slackbotservice.py
# -*- coding: utf-8 -*-

from slackbot.bot import Bot
from bot_settings import *


class SlackBotService:
    def __init__(self):
        self.bot = Bot()
        self.bot.run()


def main():
    slackbotservice = SlackBotService()


if __name__ == "__main__":
    main()

SlackBotのプラグインを実装

何か話かけられたら、Pepperが発話するようにしてみます。

SlackBotService/lib/plugins/mention.py
# -*- coding: utf-8 -*-

from slackbot.bot import respond_to, listen_to
from slacker import Slacker
from plugins import proxy
from bot_settings import settings

slack = Slacker(settings.API_TOKEN)


@respond_to(u'')
def respond_any_word(message):
    """
    任意の文字を受け取る。
    :param message: 受け取ったメッセージオブジェクト
    """
    _text = message.body.get('text', '')
    _ts = message.body.get('ts', '')
    _user = message.body.get('user', '')
    _team = message.body.get('team', '')
    _type = message.body.get('type', '')
    _channel = message.body.get('channel', '')
    proxy.animated_speech(_text)
    message.reply("done")

Pepperに発話させるためのプロキシーを実装

SlackBotService/lib/plugins/proxy.py
# -*- coding: utf-8 -*-

from naoqi import ALProxy

animatedSpeechProxy = ALProxy("ALAnimatedSpeech", "127.0.0.1", 9559)


def animated_speech(text):
    _text = text if isinstance(text, str) else text.encode("utf-8")
    configuration = {"bodyLanguageMode": "contextual"}
    animatedSpeechProxy.say(_text, configuration)

アプリをパッケージングする

qiproject.xml

バンドルするモジュールを定義します。
ライブラリや、スクリプトなど必要なモジュールはもれなく定義します。

<project version="3">
    <qipython name="slackbotservice">
        <package name="backports" src="lib" />
        <package name="slackbot" src="lib" />
        <package name="slacker" src="lib" />
        <package name="websocket" src="lib" />
        <package name="plugins" src="lib" />
        <script src="lib/six.py" />
        <script src="lib/cacert.pem" />
        <script src="slackbotservice.py" />
        <script src="bot_settings.py" />
    </qipython>
</project>

manifest.xml

サービスの定義をします。
<service />タグではPepper内で認識されるサービスとしての情報を定義します。

  • name
    • サービスの物理名を定義します。ここで定義した名前で各種qicliコマンドやアプリからサービスの呼び出しが可能です。
  • autorun
    • 自動的に起動するようにtrueを指定しておきます。
  • execStart
    • サービスとして実行するスクリプトを定義します。アプリケーションにバンドルされたpythonを使用するようにします。
<package uuid="slackbotservice" version="0.1.0">
    <services>
        <service name="SlackBotService" autorun="true"
            execStart="/bin/bash ./python bin/slackbotservice.py" />
        <executableFiles>
            <file path="python" />
        </executableFiles>
    </services>
    <requirements>
        <naoqiRequirement minVersion="2.3"/>
        <robotRequirement model="JULIETTE"/>
    </requirements>
</package>

.pmlファイル

パッケージの定義を行います。

<?xml version="1.0" encoding="UTF-8" ?>
<Package name="slackbotservice" format_version="4">
    <Manifest src="manifest.xml" />
    <qipython name="slackbotservice" />
</Package>

プロジェクトのパッケージング

$ qipy install slackbotservice
$ qipkg make-package slackbotservice.pml

パッケージのデプロイ

$ qipkg deploy-package slackbotservice-0.1.0.pkg --url nao@<PepperのIP>

動作確認してみる

Slack経由でPepperに発話させることができるようになりました!

今後

各種AL系のモジュールの呼び出しがSlack経由でできるようになるので、非常に便利でした。
現時点ではサービスとしてレジストしていないので各種お仕事アプリからSlackBotを操作することはできません。
サービスとしてレジストすることでSlackBot自体の起動、停止、お仕事アプリとのメッセージのやり取りなどができるようになります。

SlackBotをうまく使えば、お仕事アプリ間の連携や、Pepper間のやり取りなんかにも使えるのではないかと思っています。