Reekohサービスプラグイン(Node.js)を作ってみる

#Reekohとは
[Reekoh](https://reekoh.com/)とは、IoTデータをNode-REDのようにハードウェアデバイス/APIをオンラインサービスに接続したり、独自のダッシュボードを構築することができるクラウドサービスです。
ただ、フリーサービスではないので、Reekoh社及び代理店からの提供されるエンタープライズ向けツールです。 
Node-REDのNodeのようにReekohプラットフォームはPluginをパイプします。このPluginを自ら開発することも可能です。

#はじめてのReekoh Plugin開発
Reekohは、プラグインを作成してプラットフォームの機能を操作するためのオープンソースのフレームワーク/ APIを提供しています。(Node.js環境は事前に設定しておいてください）

##Reekohパッケージのインストール
下記コマンドラインにより、Reekohパッケージをインストールします。

```
cd /path/to/your/project-folder　<-適当なプロジェクトフォルダ
npm install reekoh --save
```
これにより、これから開発するReekoh Pluginで下記のようにインポートすればReekohパッケージを使用することができます。

```
const reekoh = require('reekoh')
```
#Node.js Service Pluginプロジェクト
Reekoh Service Pluginプロジェクトの雛形を作る。その前に

##Pluginプロジェクト雛形のジェネレータをインストール
SDKとは別に、ReekohからYeomanを使用して新しいプラグインプロジェクト雛形を作成するためのプロジェクト作成ツールを提供されています。このツールは、Node.js Plugin SDKを使用してプラグインを作成するために必要なファイルとフォルダを自動的に作成します。
下記コマンドでプロジェクト作成ツールをインストールできます。

```
npm install yo generator-reekoh-node -g
```
##ジェネレータを使って雛形を作る
下記コマンドで作成できます

```
cd path/to/your/project-folder
yo reekoh-node:service
```
yo reekoh-nodeのパラメータを変更すると、Service Plugin以外の下記その他Pluginを生成できます。

- Channel
- Connector
- Exception Logger
- Gateway
- Inventory Sync
- Logger
- Service
- Storage
- Stream

作成されたPlugin雛形は下図のような構成になっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/172313/30a30458-3190-8066-048d-d96d87c91923.png)

リリースノートやテスト、公開時のイメージファイルなどを編集することも必要ですが、Pluginの基本は**app.js**となります。

```app.js
'use strict'

let reekoh = require('reekoh')
let plugin = new reekoh.plugins.Service()

plugin.on('data', (data) => {
  console.log(data)
})
```
ここで`plugin`がReekoh Service Pluginを開発する上でのプロパティ、メソッド、イベントをもつ基本となるインスタンスです。
plugin.on('data' (data))ですが、'data'というのは、デバイスやセンサーデータを受信した時に立つイベントです。ここで、実際に受信したときの処理を記述するわけですが、理解しやすいように単純な外部サービスとの連携を例にサービスプラグインを作ってみます。

##国土地理院の標高APIと連携するReekoh Service Pluginを作る
とにかく何か位置情報を送信するようなIoTデバイスを考えてみます。そのIoTデバイス（GPSデバイス）がある位置の標高を求めるようなAPIと連携してみます。
[緯度経度から標高を返してくれるAPIを国土地理院が試験サービス](https://maps.gsi.go.jp/development/api.html )しているので、こちらを使います。
`http://cyberjapandata2.gsi.go.jp/general/dem/scripts/getelevation.php?<パラメータ>`にパラメータとして`lat`、`lon`を渡してあげればJSON形式で`elevation`を返してくれるサービスです。

```修正したapp.js
plugin.on('data', (data) => {
  let lat = get(data, plugin.config.latKey) || get(data, 'lat')

  if (lat) {
    searchUrl = 'lat=' + lat
  } else {
    missingParam = {message: 'Field (lat) Latitude is missing in the data and required for the request.', missingField: 'lat'}
  }

  let lon = get(data, plugin.config.lngKey) || get(data, 'lng')

  if (lon) {
    searchUrl = searchUrl + '&lon=' + lon
  } else {
    missingParam = {message: 'Field (lon) Longitude is missing in the data and required for the request.', missingField: 'lon'}
  }

  url = 'http://cyberjapandata2.gsi.go.jp/general/dem/scripts/getelevation.php?' + searchUrl

  if (missingParam) {
    plugin.logException(new Error(JSON.stringify(missingParam)))
  } else {
    request.get({
      url: url,
      json: true
    }, (err, response, body) => {
      if (err) {
        return plugin.logException(err)
      } else {
        if (response.statusCode === 200) {
          plugin.pipe(data, body)
            .then(() => {
              plugin.log(JSON.stringify({
                title: 'Open Weather Map Service Result',
                data: data,
                result: body
              }))
            })
            .catch((error) => {
              plugin.logException(error)
            })
        } else {
          plugin.logException(new Error(JSON.stringify(body)))
        }
      }
    })
  }
})
```
これにより、デバイスから取得した`data.lat`と`data.lng`を標高APIに渡し、その結果のJSONを次に渡すService Pluginができます。

つまり、あるIoTデバイスから緯度35.641468、経度139.741785というGPS位置情報をReekohプラットフォームで受信し、その緯度経度を
`http://cyberjapandata2.gsi.go.jp/general/dem/scripts/getelevation.php?lat=35.641468&lon=139.741785&outtype=JSON`
で国土地理院の標高APIに渡し、応答のあったJSON（標高は4.5mだったのね）
`{"elevation":4.5,"hsrc":"5m\uff08\u30ec\u30fc\u30b6\uff09"}`
を次の何かサービスにパイプするということができるわけです。

このPluginをPiplelineに登録することにおり、下図のように、Sigfox対応GPS端末のデータをSigfoxクラウドからCallbackで受け、その緯度経度を国土地理院の標高APIに渡し、結果として得られた標高データをストレージに蓄積したら、他のアプリケーションサービスにWebhookするというようなことが簡単に作成できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172313/9b67eaac-2999-fce2-e994-37a838d4d3d3.png)


Reekoh Plugin SDK: https://gitlab.com/reekoh/reekoh-node
npm repository: https://www.npmjs.com/package/reekoh