Node-REDのサブフローからカスタムノードを作成する

この記事では、サブフローからNode-REDのノードを開発する方法を紹介します。サブフローは、一般的なプログラミング言語の「関数」と同じ様にフローを再利用できる機能です。このサブフローを使用すると、Node-REDユーザは、フロー開発の知識のみを使用してカスタムノードを作成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/fdb3417e-b0e6-710b-a4ea-0dfae717d5ce.png)

この手順では、サブフローの作成が最初のステップです。 サブフローをJSONファイルとしてローカルPCにダウンロードした後、JSONファイルをGitHubリポジトリに配置します。 その後、アップロードされたJSONファイルはGitHub Actionsによってカスタムノードを含むtgzファイルに変換されます。 最後に、生成されたtgzファイルをローカルPCにダウンロードし、それをNode-RED環境にインストールして、カスタムノードをテストします。

# 前提条件
- GitHubアカウント
  GitHubアカウントをお持ちでない場合は、次のWebサイトでアカウントを登録してください。
     https://github.com/signup

- Node-RED環境
  ローカルPCまたはクラウド上のNode-RED環境が利用可能な場合は、すぐにサブフローの作成を開始できます。 一方、Node-RED環境がない場合は、次のGitpod環境を使うと便利です。
  https://gitpod.io/#github.com/node-red/node-red

  GitHubアカウントでGitpodにログインすると、Node-REDの構築プロセスが自動的に開始されます。約1分後、Gitpod UIの右下に次のような通知ダイアログが表示されます。
![gitpod.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/e0feb88a-ca4a-33a2-59df-6ab84f4a28c0.png)
  「Open Browser」ボタンをクリックすると、新しく開いたタブ内のページで一時的にNode-RED環境を使用できます。Node-REDのプロセスが終了してしまうため、Gitpodが開いているタブは閉じないようにしてください。

# 1. いつも通りフローを作成
最初に、フローを最初から作成する必要があります。 フローエディタのワークスペースにfunctionノードを配置した後、「コード」タブ内のテキスト領域に次のコードを貼り付けます。

```JavaScript
msg.payload = cowsay2.say(String(msg.payload));
return msg;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/237bb3d2-c5c5-edaa-5e75-1f7c5d10fe1a.png)

`cowsay2`モジュールを読み込むには、functionノードの「設定」タブを開き、左下の「+追加」ボタンをクリックした後、モジュール名の入力欄に`cowsay2`を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/d9f46c09-7994-fbc7-65ae-e511cf889ff0.png)

functionノードの前後に、injectノード(フローでは「タイムスタンプ」という名前)とdebugノードを接続してフローを完成させます。 フローを実行する前に、右上のデプロイボタンをクリックして、フローをバックエンドにデプロイします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/3cf343a6-5ed5-5cf2-3bd8-00072c662bf3.png)

右側の虫アイコンが付いているデバッグタブを表示させた後、「タイムスタンプ」と書かれたinjectノードの左側のボタンをクリックすると、デバッグタブに牛のASCIIアートが表示されます。

# 2. フローをサブフローに変換

 次に、定義されたフローから新しいサブフローを作成しましょう。サブフローに変換するfunctionノードを選択した後、右上にある三本線の「メニュー」->「サブフロー」->「選択部分をサブフロー化」を選択します（今回の場合、対象のフローはfunctionノードのみです。そのため、functionノードのみを選択しました。もちろん、3つ以上のノードを対象とする場合は、サブフローにする必要がある複数のノードを選択する必要があります。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/156a66ad-3a2f-7c2a-9c97-8c9be0581deb.png)

この操作をすると、選択したfunctionノードがサブフローに変更されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/e13fb850-e5a0-d02f-4f1f-b113e1d74f3d.png)

ダブルクリックしてサブフローを開くと、サブフローのノードプロパティが表示されます。 このノードプロパティには、「サブフローのテンプレートを編集」ボタンがあり、内部のフローを参照して、カスタムノードに関連するいくつかの設定を入力できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/231356dd-576f-9783-ddae-212078a3e94c.png)

厳密には、前の「選択部分をサブフロー化」の操作では、functionノードがサブフロー内に移動されています。 そのため「サブフローのテンプレートを編集」ボタンをクリックすると、元のfunctionノードが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/fb304294-f195-d408-0695-b9578f0727d5.png)

次の手順として、フローエディタの左上にある「プロパティを編集」のボタンをクリックします。

# 3. ノードモジュールの情報を入力
「名前」フィールドに、サブフロー名として使用する「cowsay」を入力します。この名前は、最終的に、生成されたカスタムノードの名前として使用されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/599edbf8-a221-6032-cf00-23bb2fda84b3.png)

ノードモジュール情報を設定するには、中止ボタンと完了ボタンの下にある立方体アイコンをクリックします。 立方体アイコンをクリックして開いた「モジュールプロパティ」タブで、カスタムノードの情報を指定します。これらの情報は、カスタムノードの[package.jsonファイル](https://docs.npmjs.com/cli/v8/configuring-npm/package-json)で使用されます。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/dbe142f2-6cd5-c985-c06d-94b7c4bab4e6.png)

カスタムノードのポリシーのため、「モジュール」は、他のユーザが開発したカスタムノードとは異なる名前で、「node-red-contrib-」で始まる一意の名前にする必要があります。 したがって、たとえば競合を避けるために、「node-red-contrib-cowsay\<誕生日\>」と入力します。 この命名規則に加えて、「キーワード」にもルールがあります。 カスタムノードをNode-REDフローライブラリで公開する場合は、カンマで区切られたキーワードに「node-red」を追加する必要があります。

次の表は、入力の例です。

| フィールド   | 入力値                                           |
| ----------- | ------------------------------------------------ |
| モジュール   | node-red-contrib-cowsay\<誕生日\>         |
| ノードの型   | cowsay                                           |
| バージョン   | 0.0.1                                            |
| 説明         | A node to generate ascii art using cowsay module |
| ライセンス   | Apache-2.0                                       |
| 作者         | Kazuhito Yokoi \<kazuhitoyokoi@example.com\>     |
| キーワード   | node-red,cowsay                                  |

# 4. サブフローをJSONファイルとして書き出し

サブフローデータをローカルPCにダウンロードするには、まず中央のワークスペースでサブフローを選択します。 次に、フローエディタのメニューから「書き出し」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/26ec3b50-2441-dca1-767e-a1c53933b838.png)

次に、「フローを書き出し」ダイアログにある「ダウンロード」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/17b4b6dd-637e-1ff6-33fd-57e75b531503.png)

ボタンを押すと、ブラウザは自動的に「flows.json」ファイルを「Downloads」フォルダにダウンロードします。

# 5. GitHubリポジトリにテンプレートを読み込み

 このステップでは、「flows.json」ファイルを保存するためのGitHubリポジトリを準備します。 GitHubのURL（ https://github.com/new/import ）にアクセスすると、既存のリポジトリをインポートするための次のページが表示されます。

|![importing_repository.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/8bc8fa60-ea9b-16e7-45d9-c63f7cd436be.png)|
|:-:|

「Your old repository’s clone URL」のフィールドに、「 https://github.com/kazuhitoyokoi/node-red-contrib-template.git 」と入力します。このリポジトリには、サブフローからカスタムノードを自動的に構築するためのGitHub Actionsスクリプトが含まれています。「Repository Name」の欄に、リポジトリ名としてノードモジュール名を入力します。これは、サブフローのノードプロパティで指定したモジュール名と同じ(今回は「node-red-contrib-cowsay\<誕生日\>」)である必要があります。 最後に「Begin import」ボタンをクリックして、インポート処理を実行します。

インポート処理が成功すると、次のメッセージが表示されます。

|![imported_repository.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/924004a0-1983-9c6b-30aa-fd4e48d6d127.png)|
|:-:|

上記のスクリーンショットの例では、「kazuhitoyokoi/node-red-contrib-cowsay0912」のリンクから作成したGitHubリポジトリに移動できます。

# 6. JSONファイルをGitHubリポジトリにアップロード
インポートしたリポジトリでは、ブラウザの操作でflows.jsonファイルをアップロードできます。次のスクリーンショットに示すように、最初に「Add file」ボタンをクリックしてから、プルダウンメニューで「Upload files」を選択します。

|![upload_subflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/89aedf81-3a7e-77a6-a88b-b5a2fb19a00b.png)|
|:-:|

次の画面で、flows.jsonファイルを中央の領域にドラッグするか、「choose your files」のリンクからファイルをアップロードします。 flows.jsonファイルをアップロードした後、「Commit changes」ボタンをクリックして、アップロードされたファイルをバージョン管理システムに記録します。

|![upload_subflow2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/b91411ea-6a9c-c245-d3c5-b856d9a1504d.png)|
|:-:|

これらの操作の後は、アップロードされたflows.jsonファイルが、「.github/workflows」ディレクトリおよび「README.md」ファイルとともにGitHubリポジトリに表示されます。

# 7. リポジトリ設定を変更
インポートしたリポジトリでは、GitHub Actionsはデフォルトで無効になっています。したがって、GitHub Actionsを有効にして、権限も変更する必要があります。設定を変更するには、歯車のアイコンが付いた「Settings」をクリックします。Settingsのページに移動すると、最初にGeneral設定が表示されます。 GitHub Actionの構成に移動するには、左側のメニューに再生ボタンがある「Actions」を開き、「General」を選択します。

|![allow_actions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/a8e07fa8-0d72-bcfe-145e-a12b83e8a1ed.png)|
|:-:|

上記は設定変更後のスクリーンショットです。このスクリーンショットからわかるように、権限設定を変更する必要があります。まず、「Actions permissions」セクションにある「Disable Actions」を「Allow all actions and reusable workflows (すべてのアクションと再利用可能なワークフローを許可する)」にラジオボタンを切り替えます。

その他、GitHub ActionsのActions permissionsの設定変更に加えて、Workflow permissionsの設定変更も必要です。

Read repository contents and packages permissions
↓
Read and write permissions

![Screenshot 2024-02-26 at 23.40.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/e292b6de-796c-2ecf-e34b-93e1dae80f0a.png)

その後、「Save」ボタンをクリックして変更を適用します。

# 8. カスタムノードの生成

次のステップでは、GitHub Releasesの機能を使用してカスタムノードをリリースします。左側にある「Code」メニューからGitHubリポジトリのトップページに移動します。

|![link4release.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/bebcb4f4-b8aa-40af-3adb-3f6369794432.png)|
|:-:|

トップページの右下の「Releases」エリアに「Create a new release」というリンクがあります。このリンクをクリックすると、リポジトリのリリースページに移動できます。

|![create_tag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/6f4ab591-c3c7-74be-1362-3aeacf998836.png)|
|:-:|

リリースの最初のタグを作成するには、「Choose a tag」をクリックし、「v0.0.1」と入力した後、「+ Create new tag: v0.0.1 on publish」をクリックします。この「v0.0.1」は、最初のリリースであることを意味します。

|![first_release.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/c91a370a-fa1a-5a82-8745-0be46cf34d32.png)|
|:-:|

リリースのタイトルには、たとえば「v0.0.1: The First Release」のような説明を入力します。 最後に、「Publish release」ボタンを押します。

リリース手順の後、ブラウザに次のページが表示されます。 リリース直後は、Assetsのファイルリストには最初にzipとtar.gzの2つのソースコードファイルしかありません。 しかし、しばらくすると1分以内にカスタムノードを含むtgzファイル「node-red-contrib-cowsay0912-0.0.1.tgz」が追加されます。 カスタムノードの生成の進行状況を知りたい場合は、再生アイコンのある「Actions」ボタンからGitHub Actionsのページで処理のログを確認できます。

|![released_assets.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/08dbeb91-ce48-c59b-7d11-68dcd40a2241.png)|
|:-:|

tgzファイルをローカルPCにダウンロードするには、「node-red-contrib-cowsay0912-0.0.1.tgz」のリンクをクリックします。

# 9. カスタムノードをNode-REDにインポート
生成したカスタムノードをテストするために、tgzファイルをNode-REDフローエディタにインストールします。まず、右上のメニューの「パレットの管理」の項目を選択します。次に、ユーザ設定の画面で、「パレット」タブの中にある「ノードを追加」のタブをクリックします。このタブ内には「並べ替え」の左隣に、tgzファイルをNode-REDフローエディタにアップロードするためのボタンがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/d923252b-0f31-68c1-6a38-0d3ecb141832.png)

ファイルをNode-REDフローエディタにアップロードした後、矢印アイコンの付いた新しいcowsayノードがパレットの機能カテゴリに表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/d9fd53ee-c8a1-9340-136f-3c7e5cd4d85a.png)

もちろん、生成されたノードは元のサブフローと同じように動作します。フローを作成してみましょう。

# 最後に
この記事では、サブフローからカスタムノードを生成する方法を紹介しました。この開発方法は、Node-REDのカスタムノードを作成する最も簡単な方法です。さらに、GitHub Actionsを使用すると、ユーザはローカルPCで開発環境をセットアップする必要もありません。

カスタムノードを作成するときに、この効率的な開発スタイルを使用していただければ幸いです。

# おまけ
本記事のコミュニティに認められ、世界最大のOSSイベントで講演する機会を頂けました✌️

https://youtu.be/HIEZyUJHpsM

これからも頑張ります💪