LoginSignup
104
110

More than 1 year has passed since last update.

Node-REDでハマりがちな罠

Last updated at Posted at 2015-08-31

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でプロパティの上書きを推奨しないというものです。

特にfunction nodeで以下のように msg を返すような書き方が散見されますが、これは msg オブジェクトの他のプロパティを無意識に消滅させてしまいます。Node-REDのnodeは msg オブジェクトの受け渡しを前提に動作している場合が多いので以下の書き方をしてしまうと思わぬハマりに遭遇してしまいます。

retuen msg = {
  payload: "hoge"
};

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

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

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

template_node.png

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

7. あるnodeの状態によって後続のflowを実行したい

例えば、以下のようにメール送信するflowがあったとします。ただ、email nodeの後続に端子がないので後続のflowを作りたくても作れません。

スクリーンショット 2018-08-03 11.58.12.png

こういう場合は、以下のようにstatus nodeを置いてemail nodeの状態を監視します。

スクリーンショット 2018-08-03 11.59.17.png

こうすることでメール送信してみると、以下のようにメール送信時とメール送信完了時の2回、email nodeの状態がdebug nodeに通知されますので、あとはswitch nodeなどで status.text の内容で後続の処理を分岐するような流れになります(ステータスメッセージはnodeの作り次第になりますのでemail nodeの送信完了時のように何もメッセージがないというような場合も往々にしてあります...)

スクリーンショット 2018-08-03 12.01.09.png

8. 日本語のプロパティにアクセスする方法

template node や change node で日本語のプロパティにアクセスする場合は以下のようにします。

template node

スクリーンショット 2023-03-07 17.38.32.png

change node

スクリーンショット 2023-03-07 17.39.29.png

9. template node で文字化けする

以下の画像のURLのところですが {{ だと文字参照として表示されてしまいます。

スクリーンショット 2023-03-07 17.54.16.png

<img src="https:&#x2F;&#x2F;d1d7kfcb5oumx0.cloudfront.net&#x2F;articles&#x2F;images&#x2F;5b30b3cee08d441789edad89&#x2F;thumb_0.jpg" />
<ul>
    <li>タイトル: 生後9ヶ月メス1匹</li>
    <li>都道府県: 東京</li>
    <li>所在地: 中野区 新中野駅 猫</li>
    <li>本文: 先住の犬と相性が悪くて泣く泣く里親に出すことにしました メス白黒のパンダがいます !早急にお願いします ワクチン 去勢はしてないです</li>
</ul>
<hr />

以下の画像のように {{{ で囲むと文字参照として表示されません。

スクリーンショット 2023-03-07 17.55.29.png

<img src="https://d1d7kfcb5oumx0.cloudfront.net/articles/images/5b30b3cee08d441789edad89/thumb_0.jpg" />
<ul>
    <li>タイトル: 生後9ヶ月メス1匹</li>
    <li>都道府県: 東京</li>
    <li>所在地: 中野区 新中野駅 猫</li>
    <li>本文: 先住の犬と相性が悪くて泣く泣く里親に出すことにしました メス白黒のパンダがいます !早急にお願いします ワクチン 去勢はしてないです</li>
</ul>
<hr />

10. 動的なキーでオブジェクトにアクセスしたい

javascriptで書くと以下のようなアクセスのことです。

let obj = {
  a: "田中",
  b: "山田",
}

const key = "a";

console.log(obj[key]); // => 田中

change node でも以下のように書けます。

スクリーンショット 2023-03-07 17.59.22.png

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

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

Node-RED User Group Japan へどうぞ!

104
110
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
104
110