ブロックを積みながら(37) Node-RED、何でもあり?Functionノード、その1

Joseph Halfmoon

前回はInjectとDebugノードでした。今回は「コア」ノードの中でも、「何でもありそうで」とても1回で覚えきれそうにないFunctionノードを使用してみたいと思います。以前から見よう見まねで使ってはいるのですが表面的。いろいろやってみたいと思うので今回は「その1」ということで。「その2」は他のノードも一巡した後でかな、何時やるんかい?

※「ブロックを積みながら」投稿順 index はこちら

何時ものことながら、Node-RED User Group Japan様の日本語ドキュメントにはお世話になっております。Functionノードについても立派なドキュメントが以下にあります。

Functionノードの書き方

これ読めば分かる、のかもしれませんが、JavaScript素人の私では、書かれていることを一つ一つ動かしてみないと身に付きませぬ。今回「その1」でやってみるのは以下のようです。

    1. 新たなメッセージオブジェクトを生成できる
    2. 独自のプロパティをメッセージに追加できる
    3. Functionノードの出力の数を変更できる。
    4. それぞれの出力に異なるメッセージを送信できる。
    5. 設定された出力数をFunctionノード内で知ることができる
    6. ノードスコープのデータを保持できる
    7. ノードスコープのデータをデプロイ時に初期化できる
    8. 入力されたメッセージオブジェクトをクローンして使用できる
第1のフロー:2つの出力、それぞれ新メッセージを送る

テスト用なのでフローは簡単、InjectノードでダミーのmsgをFunctionノードに送信。ダミーmsgは動作のトリガを引くだけで捨ててしまいます。Functionノードは何度トリガを引かれたかを数えており、Payloadにその回数を載せて2方面に出力します。その出力には出力先毎に異なる値を載せた独自プロパティも載っています。その出力オブジェクトをDebugノードで拾ってDebugウインドウに表示します。

FuncO2肝心のFunctionノードの「設定」タブからみて行きます。出力数というフィールドがあり、ここに必要な値を設定することで出力端子?が増えます。

FuncO2_FuncSetting次にノードスコープのデータ格納変数の確保と初期化です。ノードスコープのデータは context という既定のオブジェクト内に確保すれば、永続的に(デプロイしなおさない限り)使用できるようです。以下ではトリガひかれた回数を数えるための “counter” という名のプロパティに初期値0を設定しています。

FuncO2_FuncInitさて、肝心のコード部分です。まず最初の2行で、contextからトリガ回数を読み取り、更新しています。counterといいつつ、初回は0はじまりになっているので、ちょっと締まりません。トホホ。

次に空の配列を用意し、出力数(node.outputCount)だけのnewMsgオブジェクトを作って、配列に詰めていきます。出力数だけのオブジェクトの詰まった配列をreturnで返せば、接続している後続のノードに「ばらまかれる」という寸法のようです。なお、送信する新オブジェクトには payloadプロパティ以外にseqNumberという勝手プロパティを持たせています。

FuncO2_FuncCode
さて、デプロイした後、トリガを引いて動作を確認してみます。1回トリガを引けばFunctionノードで2方面にmsgが流れるので、デバッグWindowには2個づつ報告が上がってきます。こんな感じ。
FuncO2_DebugOUT

第2のフロー、入力されたメッセージをクローン

第2のフローでは、第1のフローとほとんど同じですが、Injectノードから送られてきた msg を捨てることなくクローンして使ってみます。第1のフローではmsgオブジェクトを新造しているので元のInjectノードからの情報の一部が欠落してしまっているためです(使う予定ないケド。)

こちらのInjectノードからはPayloadに「日時」(数値)を積んでいます。これをFunctionノードで2方面に分配するとともに、行き先毎に異なる seqNumberプロパティを付加するわけです。ただ、送られてきた msg オブジェクトを2方面にそのまま送ってしまうと、実体は1個なので、seqNumberプロパティに別々の値を設定することは出来ません。そこで、Node-REDの以下の関数を使って、msgオブジェクトをクローンして、中身は同じだけれど別なオブジェクトを作ってそれを書き換えます。

RED.util.cloneMessage()

フローそのものは変わり映えしません。

FuncO2dupコードも大差ないですが、Injectノードから貰ったmsgオブジェクトをクローンしてから追加プロパティに値を設定しています。

FuncO2dup_FuncCode動かしてみたのが以下です。こちらもトリガを1回引くと2個デバッグウインドウに表示が出ます。第1のフローと異なり、元々のInjectノードから送られてきている topicプロパティが空とか、の情報も失われていないことが分かります。

FuncO2dup_DebugOUT多少は理解が進んだかね。実践しなければ直ぐに忘却してしまいますが。。。

ブロックを積みながら(36) Node-RED、何気に深いInjectとDebugノード へ戻る

ブロックを積みながら(38) Node-RED、Changeノード、実は超強力 へ進む