Node-RED2.1の新機能: フローおよびグループに対する環境変数の定義

# Node-RED2.1の新機能: フローおよびグループに対する環境変数の定義

株式会社日立製作所 
サービスコンピューティング研究部
西山博泰

## はじめに

 プログラミングの手間を劇的に削減しアプリケーション開発者の裾野を広げるNo CodeやLow Codeといったキーワードが注目を集めています。
[Node-RED](https://nodered.org/)はコーディングレスでプログラムを作成できるLow Codeプログラミングツールであり、IoT分野を筆頭に様々な分野で活用されています。

 Node-REDでは、ノードと呼ばれる機能ブロックをつなぎ合わせることで、とても簡単にプログラムを作成することができます。こういったノードには、乱数生成など簡単なユーティリティノードから、SNSからの情報収集、今流行りの機械学習を行うためのノードなど様々なノードが存在し、それらはOSSノードとして[多数公開](https://flows.nodered.org/)されています。

 2021年10月、Node-REDの最新版であるバージョン2.1がリリースされました。Node-RED 2.1では、アプリケーションの開発を容易化するさまざまな機能が新しく導入されました。一連の記事でNode-RED 2.1の新機能を紹介したいと思います。

 この記事では、そのうち筆者が開発に参画したフローおよびグループに対する環境変数の定義機能について紹介します。

## Node-REDにおける環境変数

 2019年にリリースされたNode-RED 0.20で、Node-REDのサブフロー(ノードを組み合わせたフローで再利用可能なノード風部品を定義する仕組み)に対して「**環境変数**」(environment variable)、もしくは、「**サブフロー・インスタンス・プロパティ**」(Subflow Instance Property)と呼ばれる機能が導入されました。
 Node-REDにおける環境変数とは、ノード内で参照可能な変数であり、フローのデプロイ時にその値が定義され変更することはできません。以下にサブフローに対する環境変数定義の例を示します。この例では、変数「`VAR`」の値を「`Hello, World!`」と定義しています。
![env-var-list-0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/569b21ec-5c31-8e66-7b53-98254305b9d6.png)
 定義した環境変数は各ノードの設定などで参照できます。次の例では、changeノードで`msg.payload`に環境変数`VAR`の値を設定しています。
![change-node.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/63bbca0a-3a81-0924-0ab4-ee4475d155f8.png)
 この例では、環境変数を入力フィールドの種別(`$`)として指定していますが、「＄{*変数名*}」という形式を利用すると、入力フィールドの文字列の一部を環境変数の値で置き換えることができます。例えば、環境変数`VAR`の値が`X`の場合、「`VARの値は「${VAR}」です`」という文字列は、「VARの値はXです」という文字列に置き換えられます。
参照した環境変数がサブフローで定義されていない場合、OSで同名の環境変数が定義されていれば、その値が使われます。

 Node-RED 1.0では、さらに環境変数の定義で変数の設定UIを定義できるようになりました。環境変数定義と参照機能を使うと、サブフローの動作を指定した環境変数の値によって簡単にカスタマイズでき、再利用性の高いサブフローを定義できます。

## グループおよびタブへの環境変数指定

 Node-REDのフローはタブという単位で管理されます。これに対し、Node-RED 1.1からは複数のノードをグループという単位でまとめる機能が導入されました。下の例ではswitchと2つのchangeノードから構成されるグループを定義しています。グループはネスト可能であり、ラベルをつけたり色を変更したりすることができます。こういった機能を使うと、フローの一部を理解しやすく構成することができます。
![group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/8c4a8c8d-e077-88a4-f090-7da76c995500.png)
 Node-RED 2.1で導入されたグループへの環境変数設定では、グループの設定パネルで環境変数の値を定義できます。この値は、グループ内のノードで参照できます。
![group-env-var.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/69dc2598-0d4b-179f-72a3-fbb6fdb2da97.png)
 同様に、タブへの環境変数指定では、以下の設定パネルで環境変数の値を定義でき、タブ内のノードで参照可能です。
![tab-env-var.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/f244e9a7-5c92-96bb-a145-e64f9e983d89.png)

## 再利用性の高いフローの作成

 グループに対する環境変数定義を用いることで、同一のノード群を複製し、複製毎に環境変数に別の値を設定することで、個別に動作をカスタマイズすることができます。
 より再利用性の高いサブフローを作成する場合、グループおよびタブへの環境変数指定機能を利用し、次のような手順で作成を行うと作成が容易にできます。

1. サブフロー化したいノード群を含むフローを作成
2. 作成したフローを環境変数を用いてカスタマイズ可能とする  
3. タブ、または、グループへの環境変数指定機能を用いてフローをテスト  
4. テストが完了したら、対象部分をサブフロー化  
5. サブフローの環境変数設定UIを定義  

上に示したフローの例をサブフロー化し、環境変数の入力インターフェイスを定義した例を示します。
![subflow-UI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/1d8ddae0-7c84-83c8-ecfa-c7accb4dd49e.png)
サブフローの環境変数入力UIは以下のように、変数名、デフォルト値、アイコン、ラベル、入力形式などにより定義します。
![UI-def.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/c74db422-b18f-aeb0-bde4-bbcf20903dc7.png)

## ネストしたグループ、サブフローにおける環境変数の扱い

 サブフロー、グループなどで環境変数が定義されていない場合、より上位の定義が検索されます。具体的には、以下の図に示すように、サブフロー、グループ、タブ、OSなど、参照を行う階層にを遡って、最初に見つかった定義が利用されます。
![lookup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546217/6375d099-ab01-6e79-c91d-7aea2dc1dbda.png)

## おわりに

 Node-RED 2.1で実装された環境変数の機能拡張を紹介しました。この機能により再利用可能なノードの作成と再利用の手間を大きく低下できます。また、Node-RED 1.3では、サブフローをノード化する機能がサポートされました。今回紹介した機能と組み合わせると、再利用可能なノードを簡単に実現できます。これについては別記事 [Node-RED1.3の新機能: サブフローのノード化 - Qiita](https://qiita.com/HiroyasuNishiyama/items/7e80dc9faf5518233568) で紹介していますので、合わせてご覧ください。

## Node-RED 2.1の新機能紹介

- Node-RED 2.1の新機能: フローおよびグループに対する環境変数の定義(本記事)
- [Node-RED 2.1の新機能: HTTP Requestノードのログ機能強化](https://qiita.com/k-toumura/items/294aa189c59333e2dd18)
- [Node-RED 2.1の新機能: ツアー機能](https://qiita.com/kazuhitoyokoi/items/cbb01abeedc353423d94)

*Node-RED: Node-REDは，OpenJS Foundationの米国およびその他の国における登録商標または商標である。*
*JavaScript: JavaScriptは、Oracleの米国およびその他の国における登録商標または商標である。*