独自ALMemoryイベントの作成


## はじめに

* 自分で書いておいてなんですが、まだふわふわとした理解なため、タイトルはこれで大丈夫だろうか？と不安です。
* 取り急ぎ、ALMemoryのイベントに関して、試してみた内容を記録してみます。

## 各ツールのバージョン

| ツール                     | バージョン                  |
|:--------------------------|:--------------------------|
| C++ SDK                   | naoqi-sdk-2.0.5.3         |
| Python SDK                | pynaoqi-python2.7-2.0.5.3 |
| Choregraphe               | 2.1.2.17                  |

## 独自ALMemoryイベントの作成

### モジュールの作成

```bash
$ qisrc create HelloEventModule
```

### コードの修正

#### helloevent.h

```helloevent.h
#ifndef HELLO_EVENT_H
#define HELLO_EVENT_H

#define BOOST_SIGNALS_NO_DEPRECATION_WARNING

#include <boost/shared_ptr.hpp>
#include <alcommon/almodule.h>
#include <alproxies/almemoryproxy.h>

namespace AL
{
  class ALBroker;
}

class HelloEvent : public AL::ALModule
{
 public:
  HelloEvent(boost::shared_ptr<AL::ALBroker> broker, const std::string& name);
  virtual ~HelloEvent();

  virtual void init();

  void callback(const std::string &key, const AL::ALValue &value, const AL::ALValue &msg);

 private:
  AL::ALMemoryProxy fMemoryProxy;
};

#endif // HELLO_EVENT_H
```

#### helloevent.cpp

```helloevent.cpp
#include "helloevent.h"

#include <alvalue/alvalue.h>
#include <alcommon/alproxy.h>
#include <alcommon/albroker.h>
#include <qi/log.hpp>

HelloEvent::HelloEvent(boost::shared_ptr<AL::ALBroker> broker, const std::string& name):
  AL::ALModule(broker, name), fMemoryProxy(getParentBroker())
{
  setModuleDescription("");

  functionName("callback", getName(), "callback");
  BIND_METHOD(HelloEvent::callback);
}

HelloEvent::~HelloEvent()
{
  fMemoryProxy.unsubscribeToEvent("HelloEvent", "HelloEvent");
  fMemoryProxy.unsubscribeToMicroEvent("HelloMicroEvent", "HelloEvent");
}

void HelloEvent::init()
{
  fMemoryProxy.subscribeToEvent("HelloEvent", "HelloEventModule", "callback");
  fMemoryProxy.subscribeToMicroEvent("HelloMicroEvent", "HelloEventModule", "subscribe message", "callback");
}

void HelloEvent::callback(const std::string &key, const AL::ALValue &value, const AL::ALValue &msg)
{
  qiLogInfo("HelloEvent") << "Callback:" << key << std::endl;
  qiLogInfo("HelloEvent") << "Value   :" << value << std::endl;
  qiLogInfo("HelloEvent") << "Msg     :" << msg << std::endl;
}
```

#### main.cpp

```main.cpp
#include "helloevent.h"
#include <boost/shared_ptr.hpp>
#include <alcommon/albroker.h>
#include <alcommon/almodule.h>
#include <alcommon/albrokermanager.h>

extern "C"
{
  int _createModule(boost::shared_ptr<AL::ALBroker> pBroker)
  {
    AL::ALBrokerManager::setInstance(pBroker->fBrokerManager.lock());
    AL::ALBrokerManager::getInstance()->addBroker(pBroker);

    AL::ALModule::createModule<HelloEvent>(pBroker, "HelloEventModule");

    return 0;
  }

  int _closeModule()
  {
    return 0;
  }
}
```

```CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(HelloEventModule)

find_package(qibuild)

set(CMAKE_CXX_FLAGS "-stdlib=libstdc++")

set(_srcs
  main.cpp
  helloevent.h
  helloevent.cpp
)

qi_create_lib(HelloEventModule SHARED ${_srcs} SUBFOLDER naoqi)

qi_use_lib(HelloEventModule ALCOMMON ALPROXIES)
```

### configure & make

```bash
$ qibuild configure -c mytoolchain
$ qibuild make -c mytoolchain
```

### モジュールのインストール

```bash
$ export NAOQI_RUNTIME=/path/to/Choregraphe.app/Contents/Resources
```

```bash
$ vi $NAOQI_RUNTIME/etc/naoqi/autoload.ini
$ tail $NAOQI_RUNTIME/etc/naoqi/autoload.ini
alvisualcompass
allocalization
alpanoramacompass

autonomouslife

dialog

HelloEventModule
```

```bash
$ cp -p build-mytoolchain/sdk/lib/naoqi/libHelloEventModule.dylib $NAOQI_RUNTIME/lib/naoqi/
```

### 動作確認

#### Choregraphe でイベントを受ける部分を作成

まずはダイヤグラムのボックスを作成します。

![2015011201.png](https://qiita-image-store.s3.amazonaws.com/0/20418/9493af98-6bd9-6e03-1eca-81e033840a38.png "2015011201.png")

ボックス内に入り、「ALMemoryからのイベントの追加」を押下し、「HelloEvent」「HelloMicroEvent」をチェックして追加します。

![2015011202.png](https://qiita-image-store.s3.amazonaws.com/0/20418/b875823c-c3b8-f227-928a-955031ecaf9d.png "2015011202.png")

Log ボックスを配置し、追加したイベントから接続します。

![2015011203.png](https://qiita-image-store.s3.amazonaws.com/0/20418/ddca6f2f-8ce8-b3ba-54df-1ddad2887e00.png "2015011203.png")

#### Python からイベント発行

```bash
$ /usr/bin/python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

>>> from naoqi import ALProxy

>>> m = ALProxy("ALMemory", "localhost", 59350)
[I] 3343 qi.eventloop: Creating event loop while no qi::Application() is running
[I] 3343 qimessaging.session: Session listener created on tcp://0.0.0.0:0
[I] 3343 qimessaging.transportserver: TransportServer will listen on: tcp://192.168.1.6:59389
[I] 3343 qimessaging.transportserver: TransportServer will listen on: tcp://127.0.0.1:59389

>>> m.raiseEvent("HelloEvent", "test")
>>> m.raiseEvent("HelloMicroEvent", "test2")
```

#### 結果確認

モジュール内から出しているログと、log ボックスからのログがログビューアに表示されました。

![2015011206.png](https://qiita-image-store.s3.amazonaws.com/0/20418/011aa23e-2037-7a1b-dd8d-93aa01dbedbe.png "2015011206.png")

## 感想

* 長々と書きましたが、やっていることは「Subscribe to Event」「Raise Event」ボックスを組み合わせてできる内容かと思います。
* Event と MicroEvent の違いがよくわかっていません。