AmbientのNode-REDノードを作り、Node-RED Libraryに登録したので、一連の流れを忘備録として共有します。Ambientノードの使い方は「Node-REDでAmbientにデーター送信して可視化する」をご覧ください。

作業はMac OS上でおこないましたので、コマンドなどはMac OSのものです。

Ambientノードの設計

Node-REDのAmbientノードを作る上で、次のように要件を整理しました。

  • ノードは他の人も簡単に利用できるよう、Node-RED Libraryに登録する
  • Ambientはデーターを受信し、蓄積して可視化(グラフ化)するサービスなので、ノード化する際は入力:1、出力:0のノードとする
  • Ambientにデーターを送信する時は、「チャネルId」と「ライトキー」を指定して送信するので、「チャネルId」と「ライトキー」をノード・プロパティーとして設定することとする
  • ノードのカテゴリーはGoogle Chartと同じ「advanced」とする

Node-RED Libraryはnode.jsのパッケージマネージャー「npm」を使って実現されています。Node-RED Libraryに登録するためには、モジュールをGithubに登録し、npmに登録する(と自動的にNode-RED Libraryに登録される)という流れになります。

ファイル構造

Node-RED公式ドキュメントの「パッケージング」を参考に、次のようなファイルを用意しました。

    - node-red-contrib-ambient
      - package.json
      - ambient.js
      - ambient.html
      - README.md
      - .gitignore

ディレクトリー名(node-red-contrib-ambient)がGithubのリポジトリー名になり、npmのパッケージ名になり、Node-REDのノード名になります。「パッケージング」によれば、サードパーティー提供のノードは「node-red-contrib-」というプレフィクスを使うことが推奨されているので、「node-red-contrib-ambient」という名前にしました。

ノード動作の記述 .js

ノードの動作はjavascriptで記述します。フレームワークは公式ドキュメントの「Node作成」「JavaScriptファイル」をご覧ください。

    module.exports = function(RED) {
        var request = require('request');
        var hostname = 'http://ambidata.io';

        function ambient(n) {
            RED.nodes.createNode(this,n);
            this.channelId = n.channelId;
            this.writeKey = n.writeKey;
            var node = this;

            this.on('input', function(msg) {
                var payload = msg.payload;
                payload.writeKey = node.writeKey;
                options = { // HTTPパケットの組み立て
                    url: hostname + '/api/v2/channels/' + node.channelId + '/data',
                    headers: {'Content-Type': 'application/json'},
                    body: payload,
                    json: true
                };

                request.post(options, function(err, res, body) { // HTTP POST
                    if (err) {
                        node.error(err);
                        node.status({fill:"red", shape:"ring", text:"ambient send failed"});
                    } else {
                        node.status({});
                    }
                });
            });
        }
        RED.nodes.registerType("Ambient",ambient);
    }

Ambientノードは上流のノードからメッセージを受信したら、HTTPパケットを組み立てて、Ambientサーバーに送信(POST)します。HTTP POSTするために、requestというパッケージを使います。

データー送信に必要な「チャネルId」と「ライトキー」はノード・プロパティーとして設定されるので、それを次のように受け取ります。

    function ambient(n) {
        RED.nodes.createNode(this,n);
        this.channelId = n.channelId;
        this.writeKey = n.writeKey;
        ...
    }

ノードの定義 .html

ノードの定義はhtmlで記述します。定義はノードの全体定義、編集テンプレートの定義、Infoの記述の三つに分かれます。

ノードの全体定義

    <script type="text/javascript">
        RED.nodes.registerType('Ambient',{
            category: 'advanced',
            color: '#a6bbcf',
            defaults: {
                name: {value:""},
                channelId: {value:"",required:true},
                writeKey: {value:"",required:true},
            },
            inputs:1,
            outputs:0,
            icon: "arrow-in.png",
            align: "right",
            label: function() {
                return this.name||"Ambient";
            }
        });
    </script>

ノードの全体定義ではノードの名称、パレット上のカテゴリー、プロパティー、入出力数、アイコンなどを定義します。要件に書いたように、カテゴリーは「advanced」、入力数:1、出力数:0としました。またフローの右端に置かれるノードなので、align: “right”を指定しています。
プロパティーは”defaults”で定義します。名前(name)の他にチャネルId(channelId)とライトキー(writeKey)を定義し、必須(required:true)に設定しました。こうすると、これらのプロパティーが未定義の時はノードに赤い三角が表示され、必須のプロパティーが未定義であることが分かります。

fig2-1

編集テンプレートの定義

    <script type="text/x-red" data-template-name="Ambient">
        <div class="form-row">
            <label for="node-input-name"><i class="icon-tag"></i> Name</label>
            <input type="text" id="node-input-name" placeholder="Name">
        </div>
        <div class="form-row">
            <label for="node-input-channelId"><i class="icon-tag"></i> ChannelId</label>
            <input type="text" id="node-input-channelId" placeholder="ChannelId">
        </div>
        <div class="form-row">
            <label for="node-input-writeKey"><i class="icon-tag"></i> WriteKey</label>
            <input type="text" id="node-input-writeKey" placeholder="WriteKey">
        </div>
    </script>

ノードの編集テンプレートを記述しています。入力するプロパティーごとに<div>要素を定義し、<label>タグと<input>タグを記述します。Ambientノードには名前、チャネルId、ライトキーの三つのプロパティーがあるので、それぞれに対応した三つの<div>要素を記述しています。<input>タグの中のid属性をnode-input-プロパティー名とすると、ノードの動作を記述するjavascriptで次のように参照できるようになります。

    function ambient(n) {
        RED.nodes.createNode(this,n);
        this.channelId = n.channelId;
        this.writeKey = n.writeKey;
        ...
    }

Infoの記述

    <script type="text/x-red" data-help-name="Ambient">
        <p>Ambientにデーターを送信して可視化する</p>
        <p>
            AmbientはIoTクラウドサービスで、センサーデーターを受信し、蓄積し、可視化(グラフ化)します。
            Ambientの詳細、使い方は<a href="https://ambidata.io">こちら</a>をご覧ください。
        </p>
        <p>
            ワークスペース上のAmbientノードで、AmbientのチャネルIDとライトキーを設定します。
        </p>
        <p>
            データーは<pre>{"d1":データー1, "d2":データー2, ...}</pre>という形式で渡します。
        </p>
        <p>
            チャートは<a href="https://ambidata.io">Ambientサイト</a>で見ることができます。
        </p>
    </script>

ワークスペース上のノードをクリックした時に、右側に現れるInfoの内容を記述します。1行目はパレット上のノードにマウスオーバーした時にポップアップする説明文としても使われます。

fig2-2

README.md

Githubに登録した時にリポジトリーページの説明文に使われ、そのままnpmの説明文とNode-RED Libraryの説明文に反映されます。
機能概要、インストール方法、データーの送信方法などを記述しました。

package.json

適当な場所でnode-red-contrib-ambientディレクトリーを作り、npm initでpackage.jsonのひな形を作り、git initします。

$ mkdir node-red-contrib-ambient
$ cd node-red-contrib-ambient
$ npm init
$ git init

package.jsonはnpmのパッケージ情報ファイルです。Node-REDのノード用には”node-red”というエントリーでノード名とjavascriptファイルの場所を記述します。

    {
        "name": "node-red-contrib-ambient",
        "version": "0.0.4",
        "description": "Ambient Node to send data to Ambient. Ambient is a cloud service for IoT, Internet of Things. It receives sensor data, stores them and visualize them.",
        "repository": {
            "type": "git",
            "url": "git+https://github.com/TakehikoShimojima/node-red-contrib-ambient.git"
        },
        "keywords": [
            "node-red",
            "Ambient"
        ],
        "node-red": {
            "nodes": {
                "Ambient": "ambient.js"
            }
        },
        "author": "Takehiko Shimojima",
        "license": "MIT",
        "dependencies": {
            "request": "^2.74.0"
        }
    }

開発とデバッグ

node-red-contrib-ambientディレクトリーで.jsファイルと.htmlファイル、README.mdファイルを作っていきます。

javascriptが使うモジュールはnpm installでインストールします。この時、–saveオプションをつけることで、必要なモジュールがpackage.jsonに反映されるようにします。
開発中のノードをNode-RED環境に追加する時もnpmコマンドが使えるようです。開発中のディレクトリーが”どこか/node-red-contrib-ambient”だとすると、次のようにnpm installすると、開発中のノードがNode-REDエディターのパレットに現れ、扱えるようになります。

$ cd $HOME/.node-red
$ npm install どこか/node-red-contrib-ambient

npm installでノードをNode-REDエディターに取り込み、動作を確認し、必要があればファイルを修正するというループを繰り返してノードを完成させます。

登録

ノードを記述する.jsファイルと.htmlファイル、README.mdファイルが出来上がったら、まずGithubに登録します。

Githubへの登録

Githubへのアカウント登録は終わっているものとして、まずGithubで「node-red-contrib-ambient」という名前のリポジトリーを作ります。
開発したファイルを次のようにローカルリポジトリーにcommitし、さらにリモートリポジトリーに反映させます。

$ git add .
$ git commit -m “Initial submission"
$ git remote add origin https://github.com/TakehikoShimojima/node-red-contrib-ambient.git
$ git push -u origin master

これでGithubにモジュールが登録できました。実際に登録したモジュールはこちらをご覧ください。

npmへの登録

npm adduser でユーザー登録した後に、次のようにモジュールを登録します。

$ npm publish

これでnpmに登録できました。実際に登録したモジュールはこちらをご覧ください。

Node-RED Libraryにも反映されます。

fig2-4

これでAmbientノードも他のライブラリーと同様に使えるようになりました。

$ cd $HOME/.node-red
$ npm install node-red-contrib-ambient