まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:nodered

最近、ボット関連の API や SDK をよく見るわりに、自分では使う機会が少なかったので、今更ながら1つ作ってみました。

今回作ってみたのは「シェルボット」です。名前の通り、ボットでシェルっぽいインターフェースを実現しました。何言ってるかよくわからない人はこちらの画面を参照ください:
2017060901



ボットっぽい対話型インターフェースを使って、対話しているかのようにシェルコマンドを実行します。今回はインターフェースに独自の HTML ページを用意しましたが、ぶっちゃけ LINE などでも(Messaging API を使うなどすれば)応用できると思っています。

#「チャットボット」とは違うけど「ボット」ですっ!


ソースコードを github で公開しておきました。セキュリティ的な面はまだまだ改良の余地があると思っています(rm コマンド他は実行不可にしていますが、本当は他にも実行を制御するコマンドを考慮したほうがいいと思う):
https://github.com/dotnsf/shellbot


↑このソースコードはビジュアルフローエディタである Node-RED で使う前提のものです。(IBM Bluemix などを使って)Node-RED 環境を用意し、func-exec ノードを追加した上でキャンバスに shellbot_nodes.txt の内容をインポートして、ブラウザで /shell にアクセスするだけです(詳しくは README.md 参照)。

#あー、あと今のところ Linux/Unix 系 OS に導入する前提です。


実際に Node-RED 環境上にインポートした様子のスクリーンショットがこちらです。2本のシンプルな HTTP リクエスト処理が定義されているだけのもの(うち1つは HTML 画面定義)ですが、本当にこれだけでこのシェルボットが動きます:
2017060902


実は今まで「ボット」=「チャットボット」=「コンシェルジュ」的なイメージを持っていてハードルが高かったのですが、今回のアプリを作った結果、難しく考えずに「既存アプリケーションのインターフェースを対話型にする」という実装もアリかな、と思うようになりました。


久しぶりに IBM BluemixNode-RED を使ったら、ちょっと挙動というか、使い始めるまでのステップが変わっていたことに気付きました。クラウド環境なので今後も UI 含め色々な変更があるかもしれませんが、このブログエントリを書いている2017年4月18日時点での「Bluemix 環境下での Node-RED の使い方」をまとめてみることにしました。

既に Bluemix や Node-RED を使っている方にとっては復習の部分も多く含まれていると思いますが、ユーザー名やパスワードの設定など比較的最近になって変わった部分もあるので参考にしてください。


まず PC のウェブブラウザ(FireFox, Chrome 推奨)で Bluemix 環境にログインします。アカウントをお持ちでない方は無料体験版のアカウントを申し込むなどしてアカウントをご用意の上でログインしてください。


では早速 Node-RED 環境を用意します。ログイン後のダッシュボード画面で「アプリの作成」をクリックします:
2017041801


Bluemix の Node-RED は「ボイラープレート」の「Node-RED Starter」として簡単に環境が用意できるテンプレートが用意されています。こちらを選択します:
2017041802


これから作成する Node-RED 環境の名称(URL の一部)を入力します。例えばここで test という名称を付けると、デフォルト状態では(カスタムドメインを使わなければ)Node-RED 環境のホスト名は test.mybluemix.net となります。URL の一部になる名称のため、簡単すぎる名前だと既に使われている可能性があり、その場合は利用できません(先に進めません)。例えば (自分の名前)-(日付) など、他と被らないような名称を指定してください(以下の例では dotnsf-nodered-20170418 という名称を指定しています。この場合のホスト名は dotnsf-nodered-20170418.mybluemix.net となります)。指定し終わったら最後に「作成」ボタンをクリックしてこの環境を作成します:
2017041803


(おまけ)
なお、上記画面をよく見ると分かるのですが、この Node-RED Starter ボイラープレートを使って Node-RED 環境を構築すると、Node.js ランタイム(アプリケーションサーバー)と Cloudant NoSQL データベースが1インスタンスずつ作成されます:
2017041804


Node.js ランタイムは Node-RED の実行前提環境として必要なサーバーなのですが、Cloudant の使いみちについて補足しておきます。通常の(Bluemix 環境ではない、オープンソース版の)Node-RED も Node.js サーバー上で動くウェブアプリケーションですが、そのままでは1つのサーバーインスタンス上で稼働する前提の挙動がいくつかあります。具体的にはフロー図の情報などはファイルシステムとして保存しています:
2017041801


そのため、例えばクラウド環境で使う場合のインスタンス数を2つや3つなどに増やした場合、最新の保存情報は複数あるインスタンスのどれかのファイルシステムに保存されている、ということが発生してしまい、インスタンスによって定義されているフローが異なる、という事態が発生してしまいます。そのため負荷が高くなったからといって単純にスケールアウトさせるわけにはいかなくなります:
2017041802



一方、Bluemix 環境ではこの辺りが拡張されており、フロー情報などは全て Cloudant のデータベース内に格納されます(これらのファイルを書き換えるイベントをフックして、ファイルではなくDBを書き換えるような拡張が加えられています)。全てのインスタンスは同データベースにバインドされており、インスタンスの増減があっても常に(論理的に)1つのデータベースに対してこれらの情報を読み書きするため、スケールメリットの大きなクラウド環境においても Node-RED が安心して利用できる環境となっています。ここも Bluemix で Node-RED を利用する上でのメリットだと思っています:
2017041803


(おまけおわり)


話を戻します。Node-RED ボイラープレートから「作成」ボタンを押すと一瞬画面が暗転して・・・
2017041804


しばらくするとこの環境(Node.js + Cloudant NoSQL の2つのサーバー)を作成中のステータスに変わります。しばらくお待ち下さい:
2017041805


しばらくするとステータスが「実行中」に変わります。この段階では Node-RED が利用できるようになっているので、横のホスト名部分をクリックして、Node-RED にアクセスします(ここまでは今までの Node-RED と同じです):
2017041806


最新の Bluemix の Node-RED はここからが少し変わりました。以前はここから早速フローエディタが使えるようになっていましたが、現在はもう1段階の簡易設定を行う画面に移行します。まずは Next をクリック:
2017041807


Node-RED のフローエディタにアクセスできる人を制限する設定画面が表示されます。上の "Secure your editor as only authenticated users can access it" にチェックを入れると、その下に指定するユーザー名/パスワードを入力できた人だけが編集できるようになります。なお、更にその下の "Allow anyone to view the editor, but not make any changes" にチェックすると、「誰でもフローエディタを見ることはできるが、変更はできない」というモードになります(下図ではチェックしていません):
20170418075


一方、下のように "Not recommended: Allow anyone to access the editor and make changes" にチェックを入れると(これまで同様に)URL を知っている誰もがフローエディタにアクセスし、変更できるようになります。このいずれかをチェックした上で "Next" をクリックします:
2017041808


後で詳しく説明しますが、標準の Node-RED には含まれていない拡張機能を後から追加することもできるようになっています。そのような拡張機能の代表的なものが紹介されています:
2017041809


例えば node-red-dashboard という箇所をクリックすると、ダッシュボード機能を追加する拡張モジュールの説明が表示され、内容を確認できます。このモジュールの追加方法については後述します:
20170418095


最後に設定内容の確認を行います。なお、ここで行った設定については実行環境の環境変数でも挙動を指定/変更することが可能です。最後に "Finish" をクリックします:
2017041810


すると一瞬このような画面になってから・・・
2017041811


改めて Bluemix 環境での Node-RED のスタート画面が表示されます。ここでは "Go to your Node-RED flow editor" ボタンをクリックしてフローエディタ画面に移動します:
2017041812


先程の画面でパスワードによる認証が設定されていると、ここでユーザー名とパスワードを入力する画面になります:
2017041813


設定時に自分で指定したユーザー名/パスワードを入力して「ログイン」します:
2017041814


正しい情報が入力されていると、Node-RED フローエディタ画面に移動します。これで Bluemix 環境下の Node-RED が利用できるようになりました:
2017041815



さて、比較的最近のアップデートで Node-RED 環境に GUI 操作でカスタムノードモジュールを追加できるようになりました(今まではソースコードの package.json を編集する必要があったので、それを意識せずに環境を構築できる Bluemix ではこの作業のためにソースコードを用意する必要があったりして不便に感じていました)。最後にその方法を紹介しながら、先程参照したダッシュボード機能のモジュールを追加してみます。Node-RED 画面右上のハンバーガーメニューから「処理ノードの追加削除」を選択します:
2017041801


すると画面左に「処理ノードの追加削除」というペインが現れ、ここで現在利用中のノードモジュールの一覧を参照したり、追加/削除といったカスタマイズが可能になります:
2017041802


ここで「処理ノードを追加」タブを選び、検索フィールドに dashboard と入力すると、検索結果一覧の中に "node-red-dashboard" が出て来るはずです(似た名前もあるので注意)。これを選んで「処理ノードを追加」ボタンをクリックします:
2017041807


ノードを追加インストールする確認メッセージが表示されます。ここでは "Install" を選択:
2017041803


しばらくするとノードが追加され、成功を示すメッセージが(一瞬)表示されます:
2017041804


この状態でノード一覧を下の方にスクロールすると、"dashboard" カテゴリの中にいくつもの node-red-dashboard ノードが追加されたことが確認できるはずです。またこの dashboard ノードが利用するための "dashboard" タブが右ペインにも追加されているはずです:
2017041806


動的なノード追加も簡単にできるようになっていることが確認できました!








 

ビジュアルデータフローエディタの Node-RED は、IoT を始めとするデータの取り込みや加工、書き出しを視覚的に行う便利なツールです。更に IBM Bluemix 環境であれば、「ボイラープレート」と呼ばれるテンプレート機能を使うことで、サーバー管理とかミドルウェアインストールとかを意識することなく、簡単に Node-RED 環境を構築して、すぐに使い始めることができます。


が、簡単すぎるが故の課題もあります。典型的な例の1つが「バージョンアップ」です。まあクラウドの宿命といえなくもないのですが、ミドルウェアやアプリケーションのバージョン管理をどうするか、という課題です。クラウド環境の場合、バージョン管理含めてクラウド業者に手放したい人もいれば、バージョン管理は自分でやりたいという人もいるので、1つの正解というものが存在しない、難しい問題ではあります。Bluemix では新規にサーバーを作る際のミドルウェア/アプリケーションバージョンは原則最新のものが用意されますが、一度作ったサーバーのミドルウェア/アプリケーションバージョンが勝手に変更されることはありません。つまり使い続ける間は利用者が管理する必要があります。 

・・・と、ここまではいいのですが、問題は「最初の一歩が簡単すぎる&中で何がどう動いているか分からなくても使い始めることができる故、バージョンアップがやけに難しく感じる」ことです(苦笑)。

一応難しく(というか、ややこしく)なっている理由を解説すると、Bluemix 環境では Node.js サーバーがランタイムとして用意されます。そしてその上に Node-RED アプリケーションが導入されて動いているわけですが、このアプリケーション部分である Node-RED のバージョンアップをする必要があるわけです。この Node-RED のバージョンアップの際に、前提となる Node.js のバージョンも合わせて上げる必要が生じるケースもあります。また Node.js では npm というパッケージ管理の仕組みが使われていて、npm の作法でバージョンを管理する必要があります。 普通の Node.js 環境の場合、自分で npm を管理したり、npm に指示を出すような設定ファイルを用意したりするのですが、Bluemix はその辺りを全く知らなくても(事前に何も用意しなくても)インターネット上に Node-RED 環境が作れてしまうのです。で、バージョンアップの段階になってこれらの用意がないことが話をややこしくする要素になるのでした。


という背景の説明はここまでにして、以下は実際に(数ヶ月前のバージョンが古かった頃から動いているような)Bluemix 上の Node-RED をバージョンアップする方法を紹介します。

まずは Node-RED 環境にアクセスし、画面右上のハンバーガーメニューから Node-RED のバージョンを確認します。この図では "0.13.1" というバージョンになっていることが確認できます。2017/Feb/09 時点での Node-RED の最新バージョンは "0.16.2" なので、この環境はバージョンアップが可能な状態にある、ということになります:
2017020801


(Node.js や)Node-RED のバージョンアップのためには Node-RED のスターターコードと呼ばれるファイル一式か、IBM DevOps サービス等を使ったソースコード一式が必要になります。バージョンアップの対象となる Node-RED 環境を作った際にこれらの環境ごと用意されているのであれば、そのソースコードを用意してください。 以下はスターターコードも IBM DevOps サービスも使わず、ソースコードが手元にない状態からの入手方法になります。

改めて IBM Bluemix にログインし、対象の Node-RED ランタイムのプロジェクトを選択します。そして「開始」タブを開くと、Node-RED のカスタマイズの節内に "DOWNLOAD STARTER CODE" と書かれたボタンがあります(バージョンによって微妙に表現が異なるかもしれません)。ここをクリックしてスターターコードの zip ファイルをダウンロードします:
2017020802


ダウンロードした zip ファイルを展開します。この中に package.json というファイルがあるので、これをテキストファイルで開きます。もともとスターターコードをダウンロード済みであったり、IBM DevOps サービス等でソースコードを管理済みだった場合もお手元のコードの package.json を開いてください:
2017020803


package.json ファイルの中身を確認してみます:
2017020901


この中で利用する各コンポーネントモジュールとそのバージョンを管理しています。まず Node-RED 自体は
      :
  "node-red": "0.x"
      :

と指定されていました。これは「0.ナントカの中で最新のもの」を使うよう指定されていることになり、この指定であれば現時点での最新版 Node-RED である 0.16.2 が使われることになります。もしこのような指定になっていなかった場合はこのように変更してください。

次に Node.js のバージョンを確認します。Node-RED v0.16.0 からは Node.js のバージョンが 4.0 以上のみをサポートしており、Node.js のバージョンが古いと最新版の Node-RED は動きません。そこで Node.js のバージョンも合わせておく必要があります。こちらについては
      :
  "node": "4.x"
      :

と指定されている必要があります。もしこのような指定になっていなかった場合はこのように変更してください。


ここまでの変更・確認の上で(必要であれば他のモジュールや public フォルダ以下に静的ファイルを追加した上で)、cf コマンドでプッシュするか、IBM DevOps サービスを使って Deploy してください。

再デプロイ後に改めて Node-RED のバージョンを確認します:
2017020805


↑最新版になっていることが確認できれば成功です。

 

Node-REDnode-red-node-twitter ノードを使って、ツイッターのリアルタイム検索を行い、その結果を表示するウェブアプリケーションを作ってみました。Node-RED 環境に node-red-node-twitter ノードを追加することで以下の作業が可能になります。或いは IBM Bluemix から Node-RED スターターを使って作成した環境であれば、はじめから同ノードが組み込まれているため利用可能です。

まずは Node-RED のキャンバス内に以下のようにノードを配置します:
balloon_nodered


Twitter のノードにはリアルタイム検索を行うキーワードを指定しておきます。以下の例では "iPhone" というキーワードで Twitter 内をストリーム検索するように指定しています:
2017020501


そして WebSocket 出力ノードでは出力先を /ws/tweets に指定しています。ここは任意の文字列でもいいのですが、後述の HTMLテンプレートの内容が "/ws/tweets" の WebSocket を監視するような内容になっているので、これらの内容を一致させる必要があります:
2017020502


また HTTP 入力ノードでは GET の /tweets を指定しています。つまりウェブブラウザで /tweets というページを参照した時にここで定義するページ内容が表示されるようにしています:
2017020503


その際のページ内容をこちらのテンプレートノードで定義しています。以下のように HTML が指定されており、それがそのまま出力されます:
2017020504


このテンプレートノードの中身は、こちらの template ファイルの内容をそのままコピー&ペーストしてお使いください:
https://github.com/dotnsf/balloon_tweets


※なお、上記で紹介したのとまったく同じノード構成をこちらに用意しておきました。自分でノードを構成しなくても(単に動かしたいという目的だけであれば)この JSON ファイルの内容を Node-RED にインポートして使っていただいてもかまいません:
http://dotnsf.blog.jp/balloon_tweets.json


ノード構成の準備ができたら、Node-RED 画面右上のボタンでデプロイします:
2017020505


デプロイが成功するとここで定義したノードが動き出し、指定したキーワード(今回の場合は "iPhone")で Twitter のリアルタイムツイート検索が行われます。該当するツイートは画面右の debug タブ内に次々と表示されていきます:
2017020506


この様子をもう少し見やすくしたのが HTML テンプレートです。Node-RED と同じホストを指定して、http://(Node-RED のホスト)/tweets をウェブブラウザで開くと、検索されたツイートが画面内に次々と吹き出しを伴って表示されていく様子を確認できます:
2017020500


実際にツイートが次々と追加されていく様子はこちらの動画を御覧ください。"iPhone" くらいに頻度の高いワードで検索すると、こんな感じのスピードでツイートされている、というのが分かる動画になっています:




IBM Bluemix からも提供しているビジュアルフローエディタ Node-RED の最新バージョン v0.16 がリリースされました(2017/Jan/17 時点での最新版は v0.16.1):
https://libraries.io/npm/node-red/


新機能などの情報についてはこちらの公式ブログエントリや、
http://nodered.org/blog/2017/01/11/version-0-16-released

こちらのリリースノートを参照ください:
https://github.com/node-red/node-red/releases/tag/0.16.0


さて、上記ブログエントリにも書かれているのですが、この v0.16 より Node.js の v0.10 および v0.12 がサポート外になりました。Node.js も v4 以上のものを用意する必要があります。

これで問題になるのが CentOS/RHEL 6.x を使っている場合です。現在、CentOS/RHEL 6.x で(epel リポジトリなどを使って)普通に Node.js を導入すると v0.10.48 が導入されます:
# node -v
v0.10.48

IBM からも IBM SDK for Node.js として IBM 版の Node.js がリリースされていますが、こちらも CentOS/RHEL 6.x は v0.12 までしか用意されておらず、Node.js v4 以上を使おうとすると CentOS/RHEL であれば 7.x を使う必要があります:
https://developer.ibm.com/node/sdk/

2017011702


ちなみに Node.js v0.10.x が導入された状況下で深く考えずに npm を使って Node-RED を導入すると、最新バージョン(今であれば v0.16.1)が導入されてしまいます。その結果起動時にエラーが発生し、ユーザー画面にもエラーメッセージが表示されてしまいます:
# npm install node-red -g  (このコマンドは成功する)

# node-red
  :
  :
Welcome to Node-RED
===================

17 Jan 10:10:33 - [info] Node-RED version: v0.16.1
17 Jan 10:10:33 - [info] Node.js  version: v0.10.48
17 Jan 10:10:33 - [error] *****************************************************************
17 Jan 10:10:33 - [error] * Unsupported version of Node.js. Requires: >=4 Found: v0.10.48 *
17 Jan 10:10:33 - [error] *****************************************************************
17 Jan 10:10:33 - [info] Linux 2.6.32-642.11.1.el6.x86_64 x64 LE
17 Jan 10:10:33 - [info] Loading palette nodes

/usr/lib/node_modules/node-red/node_modules/mqtt/lib/connect/index.js:100
    const isSecure = ['mqtts', 'wss'].indexOf(opts.protocol) !== -1
    ^^^^^
17 Jan 10:10:35 - [warn] ------------------------------------------------------
17 Jan 10:10:35 - [warn] [rpi-gpio] Info : Ignoring Raspberry Pi specific node
17 Jan 10:10:35 - [warn] [mqtt] SyntaxError: Use of const in strict mode.
17 Jan 10:10:35 - [warn] ------------------------------------------------------
17 Jan 10:10:35 - [info] Settings file  : /root/.node-red/settings.js
17 Jan 10:10:35 - [info] User directory : /root/.node-red
17 Jan 10:10:35 - [info] Flows file     : /root/.node-red/flows_xxxxxxxx.xxxxx.xxx.json
17 Jan 10:10:35 - [info] Creating new flow file
17 Jan 10:10:35 - [info] Server now running at http://127.0.0.1:1880/
17 Jan 10:10:35 - [info] Starting flows
17 Jan 10:10:35 - [info] Started flows

↑起動が成功したように見えるが、バージョン非互換のエラーが発生している

2017011701


では改めて CentOS/RHEL 6.x のバージョンアップをせずにどうやって Node-RED を導入すればよいでしょうか? Node-RED の最新版を動かすために工夫する、というのも1つの方法ですが、Node-RED が最新版でなくてもよい場合であれば Node-RED v0.14.x を使う、という方法もあります。このバージョンであれば CentOS/RHEL 6.x でも動作します。

その場合の手順を紹介します。まず上記のコマンドを実行してしまって Node-RED v0.16.x を導入してしまった場合はアンインストールします:
# npm uninstall node-red -g

リリースサイトを見ると、v0.14.x の最新バージョンは v0.14.6 のようです(2017/Jan/17 時点)。というわけで、改めてこのバージョンを指定して npm でインストールします:
# npm install node-red@0.14.6 -g

こうしてインストールした Node-RED を起動すればエラーは発生しません:
# node-red
  :
  :
Welcome to Node-RED
===================

17 Jan 10:15:55 - [info] Node-RED version: v0.14.6
17 Jan 10:15:55 - [info] Node.js  version: v0.10.48
17 Jan 10:15:55 - [info] Linux 2.6.32-642.11.1.el6.x86_64 x64 LE
17 Jan 10:15:55 - [info] Loading palette nodes
17 Jan 10:15:58 - [warn] ------------------------------------------------------
17 Jan 10:15:58 - [warn] [rpi-gpio] Info : Ignoring Raspberry Pi specific node
17 Jan 10:15:58 - [warn] ------------------------------------------------------
17 Jan 10:15:58 - [warn] Missing node modules:
17 Jan 10:15:58 - [warn]  - node-red: yaml
17 Jan 10:15:58 - [info] Removing modules from config
17 Jan 10:15:58 - [info] Settings file  : /root/.node-red/settings.js
17 Jan 10:15:58 - [info] User directory : /root/.node-red
17 Jan 10:15:58 - [info] Flows file     : /root/.node-red/flows_xxxxxxxx.xxxxx.xxx.json
17 Jan 10:15:58 - [info] Creating new flow file
17 Jan 10:15:58 - [info] Starting flows
17 Jan 10:15:58 - [info] Started flows
17 Jan 10:15:58 - [info] Server now running at http://127.0.0.1:1880/

↑起動成功

というわけで、現時点で比較的簡単に CentOS/RHEL 6.x で Node-RED を動かす場合はこの方法になるのかな、と思ってます:
2017011703


なお、CentOS/RHEL 6.x に Node.js v4.x を導入してから Node-RED v0.16.x を入れる、という方法もあります。CentOS/RHEL 6.x に Node.js v4.x を入れる方法についてはこちらに詳しく書かれていました:
CentOS 6.xにLTS(4.3.0)のnode.jsをインストールする

このページのトップヘ