Node-REDでハマりがちな罠

  • 43
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Node-REDでハマりがちな罠をまとめます。

1. Debugの内容が途切れる

人にNode-REDを薦めると最初に言われるのがコレ。

ほとんどの場合、プロパティを絞り込んでデバッグするのでデフォルトの文字数で問題ないのですが、用途によってはどうしてもメッセージ全体を確認しないといけないような場合もあります。

その場合はDebugに表示できる文字数を増やしましょう。Debugに表示できる文字数はsettings.jsdebugMaxLengthの値を増やすだけです。

2. データ型

Debugで処理対象のデータがJSONに見えたとしても、それはObjectでなくString(文字列)かもしれません。

以下は、あるMQTTブローカをSubscribeしているflowですがDebugをよく見るとStringと表示されてます。
mqtt_node.png

これをこのままswitch nodeで条件分岐しようとすると、以下のような「プロパティがない」というエラーが表示されます。
switch_node.png

ここでは条件の対象としてpayload.d.idというプロパティを指定していますが、対象データがStringのままなので何を指定してもダメです。まずは対象のデータ型をObjectへ変換します。

JSON StringをObjectに変換するにはfunction nodeでJSON.parse()しても良いのですが同様のことはJSON nodeで可能です。

以下のようにするとMQTTブローカから取得したJSON Stringを一旦JSON Obejctへ変換してから条件分岐へ流すようにできます。
json_node.png

3. HTTPレスポンス

http in nodeでNode-REDにEndpointを作成してWebサーバとして処理を待ち受けるというようなユースケースはよくあります。

たとえば以下のように[get]/red/testというEndpointを作成してアクセスが来たらtemplate nodeに指定したWebページを表示します(Webページは「テスト」という文字だけ表示されるようになっています)
http_in_node.png

しかし実際に/red/testにアクセスしてみるとタイムアウトします(Node-REDが動作している環境によって挙動は変わります)
template_node.png

これは、先ほどのflowのhttp in nodeでHTTPリクエストを受け付けたのにHTTPレスポンスを返す処理を設定していないため、クライアント(ブラウザ)が延々とHTTPレスポンスを待ち続けている状態になっているからです。

以下のようにhttp out nodeを設定して正しくHTTP通信を実装してください。
http_out_node.png
htt_out_node.png

ちなみにhttp out nodeの位置にも気をつけましょう。flowのどこかに配置すれば一応HTTP通信が成立して動いているようには見えますが、flowで一連の処理をした後の値をクライアントへ返したいような場合は、その処理の後続としてhttp out nodeを配置するようにしましょう。

4. flowの冗長化

同じような動作をするflowを幾つも並べていませんか?以下は先ほどのWebページへアクセスするflowをNode-REDサイトだけでなくGoogleとYahooに対しても行うようにコピーしただけです。
redundancy.png

もちろんコレでも良いのですが、アクセス先が増えたりflowが複雑になってくると破綻してきます。flowの共通部分が何かを意識して差異を動的な値として1本のflowに与えていくような設計にしてみましょう。

たとえば上記flowの場合はアクセス先以外はすべて共通なので、Node-RED, Google, YahooのURLを動的なパラメータとして渡せるようにしてみます。

http request nodeのinfoを見るとアクセスするURLはmsg.urlとして動的に値を渡すことができます(他にもmethodやheaderも渡すことができると書いてます)
http_in_node_info.png

ということでアクセス先のURLを配列として保持して以下のようにloopさせることで1本の処理に動的なパラメータを渡して処理するflowになります。
loop.png

以下をインポートするとサンプルフローを再現できます。

[{"id":"1d42eedf.e2bd11","type":"http request","name":"","method":"GET","ret":"txt","url":"","x":157,"y":150,"z":"96d4a95.f692b58","wires":[["e8e419f0.171be8"]]},{"id":"a0f49389.5f0b7","type":"inject","name":"","topic":"","payload":"","payloadType":"none","repeat":"","crontab":"","once":false,"x":145,"y":88,"z":"96d4a95.f692b58","wires":[["eb81bea6.147e4"]]},{"id":"e8e419f0.171be8","type":"html","tag":"title","ret":"html","as":"single","name":"","x":318,"y":150,"z":"96d4a95.f692b58","wires":[["963ff6aa.69c008"]]},{"id":"963ff6aa.69c008","type":"debug","name":"","active":true,"console":"false","complete":"payload","x":477,"y":150,"z":"96d4a95.f692b58","wires":[]},{"id":"6c9c4de.f9363b4","type":"function","name":"","func":"msg.url = msg.payload;\nreturn msg;","outputs":1,"x":498,"y":97,"z":"96d4a95.f692b58","wires":[["1d42eedf.e2bd11"]]},{"id":"eb81bea6.147e4","type":"function","name":"for each item","func":"if( msg.i     == undefined ) msg.i = 0;\nif( msg.items == undefined ) {\n\tmsg.items = [\n\t\t\"http://nodered.org/\",\n\t\t\"http://google.com/\",\n\t\t\"http://yahoo.com/\"\n\t];\n}\n\nmsg.payload = msg.items[ msg.i ];\n\nreturn msg;","outputs":1,"x":322,"y":92,"z":"96d4a95.f692b58","wires":[["794b0123.86b5","6c9c4de.f9363b4"]]},{"id":"794b0123.86b5","type":"function","name":"++","func":"if ( (msg.i += 1) < msg.items.length ) {\n\treturn msg;\n}","outputs":1,"x":323,"y":44,"z":"96d4a95.f692b58","wires":[["eb81bea6.147e4"]]}]

もちろんアクセス先が数千とか数万箇所になってくれば、配列ではなくDBやファイルに永続化してflowからアクセス先情報を完全に分離しましょう。

また、このように後続のnodeに動的な値を渡すことがNode-RED活用のコツの一つだと思います。データベース系のnodeはSQLなどデータベース操作をするスクリプトを前段のnodeから渡すようにinfoに書かれていることがほとんどです。

5. プロパティ値の上書き

先ほどのWebアクセスのflowでhttp request nodeのURLを指定したまま外部から動的に値を渡すと以下のようなエラーが表示されます。
override.png

これはメッセージ内に表記されているリンク先( http://bit.ly/nr-override-msg-props )の通り、nodeに設定した固定の値を上書きすることで予期しない結果になる事象があるため、file系nodeやhttp系nodeでプロパティの上書きを推奨しないというものです。

6. template nodeでのプロパティアクセス

template nodeでデータをバインドしてWebページとして返したり、メールの本文として整形したりといったユースケースはよくあります。

この時のプロパティアクセスは必ず.(ドット)で辿ります。['title']などブラケットでは辿れません。

template_node.png

上記のようなObjectを流した場合はハマらないのですが、配列を流した時に慣習的に[0]と書いてしまいがちです。

以上、今後もハマり次第こちらに追加していきたいと思います。

最後に: Node-REDについてさらに知りたい

Node-RED User Group Japan へどうぞ!