投稿

Switchノードを使う(その2)

イメージ
前回 に引き続き Switch ノードを使ってみます。 入力値の型による出力ポートの振り分け 最初のサンプルは「 flows > node-red > function > switch > 04 - Select output port by type 」です。 ノードのプロパティを見ると「 is of type 」を使って「 文字列 」と「 数値 」で条件分岐しています。これで入力値が数値の128と文字列の"128"で出力ポートの振り分けを行っています。JavaScriptで言うところの typeof ですかね。 JSONata式のルールによる振り分け 次のサンプルは「 flows > node-red > function > switch > 05 - Use JSONata for switch rule 」です。 プロパティを確認すると、JSONata式としてpayloadを2で割った余りが0か1かで条件分岐をしています。要は偶数と奇数で分岐しているということですね。 JSONata式は以前見てきました が、いろいろなクエリが書けるので、switchノードだけでかなり複雑な判定ができそうです。 JSONata式の結果による振り分け 一つ前のサンプルと比較すると挙動がわかりやすいのが次のサンプル「 flows > node-red > function > switch > 06 -  Use JSONata for switch value 」です。違いはSwitchノードのプロパティ側にJSONata式を指定してtrue/falseで条件分岐をしている点です。今回の場合、サンプル05と06で結果に違いはありませんが、柔軟に条件分岐の設定ができることを意味しています。 とりあえずまとめ Switchノードはあと少しです。

Switchノードを使う(その1)

イメージ
 今回は Switch ノードを使ってみます。 JavaScriptのswitch文 に相当します。機能的にはシンプルな気はしますが、サンプルが多いのが意外でした。今回も少々時間はかかりますが、一個ずつ見ていきたいと思います。 入力値による出力ポートの振り分け 最初のサンプルは「 flows > node-red > function > switch > 01 - Select output port 」です。 ノードのプロパティを見るとまんまswitch文のcase句が実装されているイメージです。合致した条件に応じて出力ポート1〜3に振り分けられます。条件を増やしていくと出力ポートが増えるようです。 全ルールのチェック 次のサンプルは「 flows > node-red > function > switch > 02 - Check all rules 」です。switchノードには2つの出力ポートがあります。 プロパティを確認すると、条件分岐2つの下に「 全ての条件を適用 」と設定されています。 各フローを実行すると、以下のようなログが出力されます。 -10選択時 "<10" 0選択時 "<10" ">-10" 10選択時 ">-10" つまり、ある条件に合致してもそこで判定処理は終わらず、他の条件にも合致するか確認するということですね。JavaScriptのswitch文で言うところのcase句の中にbreakがない状態みたいなイメージでしょうか。 最初に合致した条件で判定処理を終える 一つ前のサンプルと比較すると挙動がわかりやすいのが次のサンプル「 flows > node-red > function > switch > 03 - Stop after first match 」です。違いはSwitchノードプロパティの条件適用の設定のみで、こちらは「 最初に合致した条件で終了 」となっています。 各フローを実行すると、以下のようなログが出力されます。 -10選択時 "<10" 0選択時 "<10" 10選択時 "...

Functionノードを使う(その5)

イメージ
前回 まででFunctionノードのサンプルをひと通り見て満足していたのですが、そういえば、1箇所だけ触っていない設定があったことを思い出しました。設定プロパティの「 モジュール 」です。 Functionノードの ドキュメント によると、 functionExternalModules オプションを使うとsettings.js上でいちいちrequire()しなくても外部モジュールが使えるとのこと。settings.jsを確認したところデフォルトで有効化されていました。それを先に言えよ。 /** Allow the Function node to load additional npm modules directly */ functionExternalModules: true, というわけで、早速動作確認します。 その3の記事 で使ったaxiosで試してみます。前提条件として「 npm install axios 」コマンドでaxiosをインストールしておきます。続いて設定タブでモジュールにaxiosを追加します。 この設定は「 const axios = require("axios") 」みたいなことをやってくれているということなのだと思います。続いて、コードタブに以下のように書きます。いきなりaxios.get()を呼び出せるのがポイントです。 フローを実行するとresponseが出力されます。 まとめ 今回利用した方法だと特定のFunctionノードでのみ外部モジュールが利用可能になりますが、 その3の記事 で確認したsettings.jsファイルの functionGlobalContext でrequire()する方法だと全Functionノードで外部モジュールが利用可能になるということなのでしょう。状況によって使い分けすれば良さそうです。Functionノードについてはこんなもんですかね。  

Functionノードを使う(その4)

イメージ
今回も、 前回 に引き続きFunctionノードのサンプルフローを見つつざっとその機能を把握してみます。第四回目です。 初期化処理と終了処理 最初のサンプルは「 09 - Setup and close 」です。Functionノードはフロー実行時だけでなく、Node-RED起動時と終了時にもコードを実行できます。いつも通りFunctionノードのプロパティを見ていきます。 初期化処理タブではglobalコンテキストの変数を0で初期化しています。 続いてコードタブではglobalコンテキストの変数値をインクリメントしてmsg.playloadに格納しています。 最後に終了処理タブではglobalコンテキストの変数値をコンソールに出力しています。 このフローを何度か実行すると、インクリメントされた値がログに出力されます。この出力はコードタブに記載した内容の実行結果です。 終了処理が実行されることを確認するため、コンソール上でNode-REDを停止すると、以下のように最新のglobalコンテキスト内の変数値が出力されます。通常、この手の機能はログ出力が目的ではなく、リソースの解放処理のような後始末をするのに利用するのが一般的だと思います。 28 Oct 22:33:19 - [info] フローを開始します 28 Oct 22:33:19 - [info] フローを開始しました ^C28 Oct 22:34:57 - [info] フローを停止します count: 4 28 Oct 22:34:57 - [info] フローを停止しましたつ さらに再びNode-REDを起動してフローを実行すると、出力される値がリセットされて1、2、3、、、と増えていくのが確認できると思います。初期化処理タブに記載した内容がNode-RED起動時に実行されて変数値がリセットされたんですね。 というわけで、初期化処理と終了処理の動作が確認できました。パッと使いどころは思いつきませんが、フロー実行のたびに実行するにはコストの高い処理をNode-RED起動時に実行して、終了時に止める、みたいな感じでしょうか。ありがちなパターンかと思います。 非同期初期化 ラストのサンプルは「 10 - Asyncronous setup 」です。デプロイすると1秒後にログが出力されます。初期化処理でも非同...

Functionノードを使う(その3)

イメージ
今回も、 前回 に引き続きFunctionノードのサンプルフローを見つつざっとその機能を把握してみます。第三回です。 コンテキストにデータを保存 最初のサンプルは「 06 - Storing data in context 」です。コンテキストにデータを保存するらしいです。この時点でだいたい予想はついたので中身は見なくてもいいかと思いましたが、さすがに雑だと思ったので一応見ますです。Functionノードのプロパティはこんな感じ。 何回か実行すると、ログ上で数値がインクリメントされて出力されます。context上の'count'という名前の変数を使って、実行のたびに値を読み出し、インクリメント、値を保存しています。通常、フローは一回実行したら実行結果は消えてしまいますが、contextに保存して次回実行時に参照しているということですね。ステートフルな作りになってしまうので、バグの温床になりかねませんが、きっと必要な場面もあるはずです。コンテキストについてのドキュメントは こちら 。コンテキストはデフォルトでメモリ上に保存されるので、Node-REDを再起動したら消えるってことですね。 ステータスの表示 次のサンプルは「 07 - Showing status information 」です。フローはこんな感じ。 injectノードではmsg.playloadに「 red 」という文字列を設定しています。 Functionノードではmsg.payloadの値でswitchして、node.status()関数でステータスを更新しているようです。あとは この辺 読んで感じ取れってことですね。 外部モジュールの利用 次のサンプルは「 08 - Using external modules 」です。このままフローを実行してもエラーが出て動きません。commentノードの詳細を見ろとあるので確認してみます。 setting.jsに以下のように書いて「os」モジュールを読み込めば良いようです。 functionGlobalContext: { os: require("os"), } ~/.node-red/settings.jsを確認するとちょうどこれと同じ記述がコメントアウトされているので、コメント部分を外して有効化します。Node...

Functionノードを使う(その2)

イメージ
前回 に引き続きFunctionノードのサンプルフローを見つつざっとその機能を把握してみます。 非同期メッセージの送信 最初のサンプルは「 03 - Send message asynchronously 」です。Functionノードのプロパティはこんな感じです。 実行すると、2秒遅れてログが出力されます。setTimeout()で遅延を発生させて、node.send(msg)することで次のノードにメッセージを送信しているようです。普通に非同期処理がかけるってことですね。なるほど。 ログ出力とログレベル 次のサンプルは「 04 - Logging events 」です。Functionノードからデバッグウィンドウにログ出力ができます。 ログ出力関数 は、log()、warn()、error()と3種類あって、出力時に色分けされるようです。これは、見やすいですね。 エラーハンドリング 次のサンプルは「 05 - Handling errors 」です。 実行すると 、catchノードの先に繋がっているdebugノードがログを1件出力します。 Functionノードのコードはこんな感じでnode.error()関数を呼び出しています。こうすると、それ以上先にフローは進まず、catchノードで例外をキャッチできるようです。 第二引数にmsgを設定しているのが興味深かったので、試しにnullを渡してみたところ、node.error()の実行エラーになりました。よくわかりませんが、msgを渡すことに意味があるようです。 とりあえずまとめ いろいろできるようです。続く。

Functionノードを使う(その1)

イメージ
今回は Function ノードを使ってみます。ローコードプログラミング環境のNode-REDをハイコード化する本末転倒感が漂っていますが、JavaScriptを書ける人であればむしろこっちの方が学習コストが低くて使い勝手が良いのではないかと思います。何でもできる分、奥が深くてサンプルもたくさん提供されています。少々時間はかかりますが、一個ずつ見ていきたいと思います。 msgの加工 最初のサンプルは「 flows > node-red > function > function > 01 - Send message to output port 」です。 functionノードのプロパティは以下のような感じです。 暗黙的に入力値としてmsgオブジェクトを受け取っている msg.payloadの値を加工している returnしたmsgオブジェクトが次のノードに渡される 複数msgの出力 次のサンプルは「 flows > node-red > function > function > 02 - Send multiple messages 」です。functionノードから出力が2つ出ています。 プロパティを確認すると、配列がネストしており、それぞれがpayloadプロパティをもっています。 出力数の指定は「 設定 」タブでできるようです。 デプロイして実行するとログが4件出力されます。「 〜out of output 1 」は1つ目の出力から出た内容です。debugノードが受け取ったmsg1〜msg3を含む配列内のmsg.payloadを出力しているということでしょうか。ログが2件で前者が配列で出力されるのであれば直感的に理解できそうですが、ちょっと謎な動きです。 とりあえずまとめ まだまだサンプルはたくさんあるので続きます。