本記事は、2024年1月5日に開催した下記「Node-REDのノードを作るハンズオン」イベントの資料です。
Node-REDのコントリビュータの横井一仁です。
今回は、公式サイトに掲載されているサンプルノードをもとに、Node-REDのノードを自作する手順について説明します。
現在、Node-REDは月間15万回ダウンロードされており、急速に普及しています。また、reTerminal DMなどの産業向けRaspberry Piの標準搭載ソフトウェアにもなっています。Node-REDが普及していることの理由の1つとして、「ノードを自由に追加できる」ことによるコミュニティの力が影響していると考えます。現在、フローライブラリには、約5000個のノードが登録されており、様々な企業が自社のサービスの利用促進のためにノードを提供しています。
また、Node-REDのユーザ層は、コードが書けないユーザにも大きく拡大するポテンシャルがあります。そのため、コードを書けるエンジニアは、自身が広めたいサービスやプログラムをエンジニアでないユーザにも使ってもらうよう、ノードを開発して提供しましょう。
ノードの構成するファイル
Node-REDのノードは、JavaScriptファイルとHTMLファイルの2つで構成されています。JavaScriptファイルには、Node.jsのプログラムが書かれており、前のノードから受け取ったメッセージをもとにどの様な処理を行い、次のノードへどの様なメッセージを出力するかを記述します。HTMLファイルは、Node-REDのフローエディタで表示されるプロパティ設定画面やヘルプなどが記述されています。
※2016年6月のNode-RED Tech Talkのスライド
その他、フローライブラリに登録する際に必要なパッケージ化で用いるpackage.jsonファイル、テストケースのファイル、サンプルフローのJSONファイルを置くこともできます。
ノードの開発、公開手順
典型的なノードの開発、公開手順は以下のようになります。この記事では本手順に沿って説明をしてゆきます。
- GitHub上にリポジトリを作成
- リポジトリをローカルに取得 (git clone)
- ノードのプログラムを開発
- パッケージ化 (npm init)
- package.jsonを編集
- テストケースを作成
- tgzファイルを作成 (npm pack)
- ローカルのNode-REDにノードをインストール
- インストールしたノードの動作確認
- サンプルフローの保存
- README.mdファイルを編集
- ノードの検証
- GitHubへソースコードをアップロード (git push)
- npmのトークン発行
- GitHub Actionsの設定
- リリース
- Node-REDフローライブラリに登録
本記事では、受け取った文字列をすべて小文字に変換するオリジナルノードを例として作成します。例えば「AbCdEf」という文字列を受け取った場合は「abcdef」という文字列を出力します。
ノード開発に必要なもの
Windows PCまたはmacOSにて、次のソフトウェアのインストールとアカウント作成を行います。
- Node.js v20.x LTS https://nodejs.org
- Node-RED v3.x (Windowsの場合はnpm install -g node-red、macOSの場合はsudo npm install -g node-redのコマンドを実行してインストール)
- Git https://git-scm.com/downloads
- Visual Studio Code https://code.visualstudio.com/download
- GitHubアカウント https://github.com/signup
- npmアカウント https://www.npmjs.com/signup
GitHub上にリポジトリを作成
https://github.com/new へアクセスし、GitHubアカウントでログインします。すると以下の様な新規リポジトリ作成のページが表示されます。
# | 設定項目 | 設定内容 |
---|---|---|
1 | Repository name | ノードのモジュール名を指定します。Node-REDのモジュール名は、「node-red-contrib-<任意の名前>」をという命名ルールがあります。ここでは、「node-red-contrib-example-lower-case」という名前にしました。 |
2 | Description | リポジトリの説明を入力します。オリジナルノードの説明「A simple node that converts the message payloads into all lower-case」としました。 |
3 | リポジトリの公開設定 | 「Public」を選択します(もしフローライブラリに公開しない場合は「Private」でも構いません)。 |
4 | Add a README.md file | オリジナルノードのドキュメントを記載するREADME.mdファイルを作成するため「Add a README file」のチェックボックスは有効にします。 |
5 | Add .gitignore | Node-REDのオリジナルノードはNode.jsのプログラムであるため「Add .gitignore」は「Node」を選択します。これによってNode.js関連の一時ファイルがGitHub上にアップロードされないようになります。 |
6 | Choose a license | プルダウンメニューからライセンスを選択します。ここではNode-REDと同じApache License 2.0を選択しました。 |
最後に緑色の「Create repository」ボタンをクリックします。すると、作成されたリポジトリの画面に遷移します。
次のgit cloneコマンドで用いるため、リポジトリのURL「https://github.com/<ユーザ名>/node-red-contrib-example-lower-case.git」をクリップボードへコピーします。緑色の「Code」ボタンをクリックして「Copy url to clipboard」という吹き出しが表示されるURL右横のボタンをクリックしましょう。
リポジトリをローカルに取得 (git clone)
Windowsのメニューから「ターミナル」を開きます。
※ Windows 10ユーザの場合は、PowerShellを用いてください。
※ macOSの場合はLaunchpadから「ターミナル」を開きます。
ターミナル上で以下のコマンドを実行し、カレントディレクトリをデスクトップにします。
cd Desktop
次に、クリップボードにコピーしたパスを用いて以下のコマンドを実行し、リポジトリを取得します。
git clone https://github.com/<ユーザ名>/node-red-contrib-example-lower-case.git
デスクトップには「node-red-contrib-example-lower-case」という名前のフォルダができています。このフォルダへ移動します。
cd node-red-contrib-example-lower-case
ノードのプログラムを開発
「node-red-contrib-example-lower-case」のフォルダの中に「lower-case.js」と「lower-case.html」いう2つのファイルを作成します。最初は、Node-REDのサイトに掲載されている大文字を全て小文字に変換するノードのサンプルコードを貼り付けます。
- Visual Studio CodeでJavaScriptファイルを作成
code lower-case.js
- サンプルコードを貼り付けて、ファイル保存
module.exports = function (RED) {
function LowerCaseNode(config) {
RED.nodes.createNode(this, config);
var node = this;
node.on('input', function (msg) {
msg.payload = msg.payload.toLowerCase();
node.send(msg);
});
}
RED.nodes.registerType('lower-case', LowerCaseNode);
}
- Visual Studio CodeでHTMLファイルを作成
code lower-case.html
- サンプルコードを貼り付けて、ファイル保存
<script type="text/javascript">
RED.nodes.registerType('lower-case', {
category: 'function',
color: '#a6bbcf',
defaults: {
name: { value: '' }
},
inputs: 1,
outputs: 1,
icon: 'file.svg',
label: function () {
return this.name || 'lower-case';
}
});
</script>
<script type="text/html" data-template-name="lower-case">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="lower-case">
<p>A simple node that converts the message payloads into all lower-case characters</p>
</script>
- lsコマンドを実行し、JavaScriptファイルとHTMLファイルが作成されていることを確認
ls
これでオリジナルノードを実現する必要最小限のJavaScriptファイルとHTMLファイルを作成できました。
ノードをパッケージ化 (npm init)
オリジナルノードのパッケージを作るnpm initコマンドを実行します。
npm init
npm initコマンドでの設定項目は以下の通りです。
# | 設定項目 | 設定内容 |
---|---|---|
1 | name | ノードのモジュール名として「@<npmユーザ名>/node-red-contrib-example-lower-case」を入力します。 |
2 | version | ノードのバージョンを指定します。最初は「0.0.1」を指定します(安定するまでは0.2.x、0.3.xとベータ番号を使い、正式版から1.0.0、1.1.xという番号付けをします。その後、仕様が大幅に変わる時に2.0.0、3.0.0とメジャーバージョンアップします)。 |
3 | description | ノードの説明を記述します。ここで記述した説明は、フローライブラリやNode-REDのノードのインストール画面で表示されます。GitHubリポジトリの説明で入力した「A simple node that converts the message payloads into all lower-case」で良いでしょう。 |
4 | entry point | ノードのプログラムのファイル名を指定します。デフォルトの「lower-case.js」のままでOKです。 |
5 | test command | ノードのテストケースを実行するmochaコマンドを「mocha test/**/*_spec.js」の様に入力します。npm testコマンドを実行するとテストが行われるようになります。 |
6 | git repository | GitHubのリポジトリのURLを指定します。GitHubリポジトリのページからコピーした「https://github.com/<GitHubユーザ名>/node-red-contrib-example-lower-case.git」を入力しましょう。このURLは、最終的にNode-REDフローライブラリのオリジナルノードのページに掲載される「View on GitHub」のリンクで使われます。 |
7 | keywords | フローライブラリやNode-REDのインストール画面の検索で用いるキーワードを半角の空白区切りで指定します。ここでは「node-red lower-case」としました。フローライブラリに登録する場合はキーワード「node-red」を忘れずに入力してください。 |
8 | author | ノードの開発者名を指定します。npmアカウントと同じユーザ名を入力します。 |
9 | license | ノードのライセンスを指定します。GitHubリポジトリに設定したものと同じライセンスを入力します。ここではNode-REDと同じライセンスである「Apache-2.0」を指定しました。 |
以上の設定を入力し、最後の確認で「yes」を入力します。npm initコマンドにより、package.jsonファイルが生成されます。
ls
package.jsonを編集
package.jsonには、手動でNode-RED固有の設定を追加する必要があります。package.jsonファイルをVisual Studio Codeで開きましょう。
code package.json
以下の様に"name"や"version"と並列して"egines"と"node-red"のセクションを追加します。ここでは、動作環境としてNode.js v14.0.0以上、Node-RED v1.3.7以上をサポートするという定義を記載しました。末尾のカンマを忘れずに追加してください。
{
"name": "<@npmユーザ名>/node-red-contrib-example-lower-case",
"version": "0.0.1",
(省略)
"engines": {
"node": ">=14.0.0"
},
"node-red": {
"version": ">=1.3.7",
"nodes": {
"lower-case": "lower-case.js"
}
},
(省略)
}
Visual Studio CodeでNode-RED固有の設定を追加した様子は以下の通りです。選択部分を手動で追加しました。
テストケースを作成
Node-REDのオリジナルノードの品質を担保するには、テストケースが必須です。testフォルダの下に「_spec.js」というファイル名でテストケースを記載します。
code test/lower-case_spec.js
- 貼り付けるテストケースのコード
var helper = require("node-red-node-test-helper");
var lowerNode = require("../lower-case.js");
describe('lower-case Node', function () {
afterEach(function () {
helper.unload();
});
it('should be loaded', function (done) {
var flow = [{ id: "n1", type: "lower-case", name: "test name" }];
helper.load(lowerNode, flow, function () {
var n1 = helper.getNode("n1");
n1.should.have.property('name', 'test name');
done();
});
});
it('should make payload lower case', function (done) {
var flow = [{ id: "n1", type: "lower-case", name: "test name", wires: [["n2"]] },
{ id: "n2", type: "helper" }];
helper.load(lowerNode, flow, function () {
var n2 = helper.getNode("n2");
var n1 = helper.getNode("n1");
n2.on("input", function (msg) {
msg.should.have.property('payload', 'uppercase');
done();
});
n1.receive({ payload: "UpperCase" });
});
});
});
本ファイルには、2つのテストケースが含まれています。1つ目は「should be loaded」で、オリジナルノードが正しく読み込まれるか確認するテストです。2つ目は「should make payload lower case」で、文字列「UpperCase」をオリジナルノードの入力とした際に、出力が文字列「uppercase」となっているかをテストします。
本テストケースを実行する前に、mocha、node-red、node-red-node-test-helperのnpmモジュールをdevDependenciesとして追加します。
npm install mocha node-red node-red-node-test-helper --save-dev
最後にテストケースを実行するには、以下のコマンドを実行します。
npm test
2つのテストケースが実行され、緑色のチェックがつけばテスト成功です。
tgzファイルを作成 (npm pack)
次に以下のコマンドを実行し、オリジナルノードのファイルを固めたtgzファイルを作成します。
npm pack --pack-destination ..
一つ上の階層に対して、lsコマンドを実行するとtgzファイルが追加されていることが分かります。
ls ..
ローカルのNode-REDにノードをインストール
次にローカルのNode-RED上に、tgzファイルをアップロードして作成したオリジナルノードを追加します。タブ横の「+」ボタンをクリックして別のターミナルを開き「node-red」コマンドを入力し、Node-REDの起動しましょう。
node-red
※ もし「node-red : このシステムではスクリプトの実行が無効になっているため、ファイルC:\Users<ユーザ名>\AppData\Roaming\npm\node-red.ps1 を読み込むことができません。」というエラーが出てNode-REDが起動しない場合は「Set-ExecutionPolicy RemoteSigned」というコマンドを入力してポリシを変更してください。
EdgeまたはGoogle Chromeのブラウザから http://localhost:1880 にアクセスし、Node-REDのフローエディタを表示します。ここからtgzファイルをアップロードしてオリジナルノードをインストールします。そのためには、まず右上メニュー内の「パレットの管理」を選択して「ユーザ設定」の画面を表示します。
「ユーザ設定」の画面では「ノードを追加」タブを選択し、「モジュールのtgzファイルをアップロード」という吹き出しが表示される上矢印ボタンをクリックします。
すると、ファイル選択を行うダイアログが表示されるため、作成したtgzファイルを選択しましょう。
準備が整ったため「アップロード」ボタンをクリックします。
上手くインストールできると「ノードをパレットへ追加しました: ・lower-case」という通知ダイアログが表示されます。
ユーザ設定を閉じると、左側のパレットの機能グループの中に「lower - case」という青色のノードが登場していれば、オリジナルノードのインストール成功です。
インストールしたノードの動作確認
次にオリジナルノードの動作確認を行ってみます。以下の様にinjectノード、オリジナルノード、debugノードをつないだフローを作成します。
injectノードは、デフォルトのタイムスタンプから「AbCdEf」という文字列に変更します。タイムスタンプと書かれたノードをダブルクリックして、プロパティ設定を開きます。msg.payloadは「日時」が選択されているため、「文字列」に変更します。
その後に表示される入力欄に「AbCdEf」と入力して、完了ボタンをクリックします。
デプロイボタンを押してフローを反映させた後、右側の虫アイコンをクリックしてデバックタブを開きましょう。
injectノードの左側のボタンをクリックすると、全て小文字に変換された「abcdef」という文字列がデバックタブに表示されます。
開発したノードが他の環境でも正しく動作するか確認するため、異なるOSのNode-RED、Raspberry Pi版Node-RED、クラウド環境のNode-RED (enebularなど)にノードをインストールしてテストしてみると良いでしょう。
サンプルフローの保存
ユーザにオリジナルノードの使い方を理解してもらうには、サンプルフローを作成しておくと良いです。現在フローライブラリに登録するオリジナルノードは、サンプルフローがないと警告が出るため、作成しておく必要があります。
オリジナルノードの編集操作を行ったターミナルに戻り、以下の様に「examples」フォルダの下に「<サンプルフロー名>.json」という名前のJSONファイルを作成します。
code examples/lower-case.json
Visual Studio Codeのウィンドウはそのままにしておきます。
次にNode-REDフローエディタ上で、マウスをドラッグしてサンプルとしたいフローを選択します。
フローを選択した状態で、右上メニューから「書き出し」を選択します。
次にダイアログ上の「書き出し」ボタンをクリックして、クリップボードにフローのJSONデータをコピーします。
最後にNode-REDフローエディタ上でクリップボードに書き出したJSONデータを、Visual Studio Codeの「examples/lower-case.json」ファイルに貼り付けて保存します。
ノードをアンインストール
オリジナルノードの動作確認をした後は、一旦オリジナルノードを削除します。まずオリジナルノードを含むフローを選択して、右クリックして「選択したノードや接続を削除」を選択して全て削除します。
デプロイボタンを押してフローを反映させた後、右上メニューから「パレットの管理」を選択します。
「現在のノード」のタブの中に、インストールしたオリジナルノードが存在するため、「削除」ボタンをクリックして削除します(「使用中」と表示されている場合は、どこかのフローでオリジナルノードが使われているため、削除されているか、デプロイしてフローが反映されているかを確認します)。
本当に削除して良いかの確認ダイアログが表示されるため「削除」ボタンをクリックします。
上手くオリジナルノードが削除できたら「ノードをパレットから削除しました: ・lower-case」という通知が表示されます。
このノードの削除は、コードを更新した新しいtgzファイルをインストールする際、フローライブラリからインストールする際に必要となります。
以降はノードをフローライブラリに登録する前に行う手順になります。
README.mdファイルを編集
ノードをフローライブラリに公開するには、ノードの説明を記載したREADME.mdファイルを作成する必要があります。
code README.md
言語は日本語でも大丈夫ですが、英語の方が多くのユーザに親切です。例えば以下の内容を記載します。
- 概要説明
- 使用方法
- スクリーンショット
- 本ノードを用いたサンプルフロー
- 前提環境
- 更新履歴
ノードの検証
ノードを公開する前に、オリジナルノードの検証してくれる「Node-RED Node Developer Tools」というNode-REDプロジェクト公式ツールで必要な設定が漏れていないか確認します。本ツールは以下のコマンドでインストールできます(macOSの場合は「sudo npm install -g node-red-dev」)。
npm install -g node-red-dev
インストールした後は、オリジナルノードのファイルが格納されているフォルダ内で以下のコマンドを実行することで、検証処理が走ります。
node-red-dev validate
正常な項目はチェックマークが付きます。「lower-case」というノード名は他のノード開発者も試してフローライブラリに公開しているため「Warning: Duplicate nodename lower-case found in package」という警告が出ます。本手順では無視して良いですが、公開後にノード名の衝突を避けるため、自身で別のノードを開発した際に、この警告が出た場合はノード名を変更する必要があります。
GitHubへソースコードをアップロード (git push)
examplesとtestの2つのフォルダ、LICENSE、README.md、lower-case.html、lower-case.js、package-lock.json、package.jsonの6つのファイル、があることを確認します。
ls
次にGitHub上のリポジトリへソースコードを置きます。まずgit addコマンドを用いて、全てのファイルをコミット対象として追加します。
git add -A
変更履歴として「The first commit」というコミットメッセージをつけて、git commitコマンドを実行します。
git commit -m "The first commit"
※ もしgit commitを実行した際に、メールアドレスとユーザ名を求められた場合は、以下のコマンドを実行してください。
git config --global user.email "<メールアドレス>"
git config --global user.name "<ユーザ名>"
ソースコードをアップロードするには、以下のgit pushコマンドを実行します。
git push
※ git pushでGitHubへのログインを求められた場合は、GitHubアカウントのユーザ名とパスワードを入力してください。
正しく操作が行われると、GitHub上のリポジトリにファイルが登場します。
npmのトークン発行とGitHubへの登録
最後に、ノードをモジュールとしてnpmへ公開するために、GitHub Actionを用います。
まずnpmに公開するためのトークンを発行するため、ブラウザから https://www.npmjs.com/login にアクセスします。その後、右上のユーザアイコンをクリックしてメニューを開き、「Access Tokens」をクリックします。
するとアクセストークン一覧のページが表示されます。ここで右上にある「Generate New Token」ボタンをクリックし、その中の「Granular Access Token」を選択します。
以下の様なアクセストークンを発行する画面が表示されます。
まず「Token name」の欄を入力します。どのオリジナルノード向けのアクセストークンか後から識別できるよう、モジュール名と同じにすると分かりやすいでしょう。ここでは「node-red-contrib-example-lower-case」としました。
「Permissions」の設定では、GitHub Actionsがカスタムノードをnpmに公開できるよう「Read and write」を選択し、「Select package」では「Only select packages and scopes」を選択して、「Select packages and scopes」のプルダウンメニューから「@npmユーザ名」のスコープを選択します。最後に一番下にある「Generate token」ボタンをクリックすると、次の様な画面に遷移し、アクセストークンが表示されます。
アクセストークンの右側にあるコピーボタンを押して、クリップボードへコピーしておきます。
次に、カスタムノードを生成したGitHubリポジトリを開き、GitHub Actionsが利用する環境変数にアクセストークンを登録します。登録するには、GitHubリポジトリの上の「Settings」タブを選択し、左側の「Secrets and variables」の中の「Actions」をクリックし、次のようなページを開きます。
ここで緑色の「New repositry secret」ボタンをクリックします。すると次のような環境変数名と値を設定できる画面が表示されます。
この画面では「Name」として「npm_token」、「Secret」としてクリップボードに格納されているアクセストークンを貼り付けます。最後に下にある「Add secret」ボタンを押せば設定完了です。
GitHub Actionsの設定
次に、リリース操作の時に実行するGitHub Actionsのスクリプトを登録します。ここではGitHubに用意されている、npmへ公開するためのスクリプトを用います。まずGitHubリポジトリの「Actions」タブをクリックし、その中にある「Publish Node.js Packge」の「Configure」ボタンをクリックします。
見つからない場合は、「Search workflows」の検索欄で検索すると良いでしょう。
次の画面には、GitHub Actionsのスクリプトが表示されます。ここには、テスト実行やnpm公開のためのコマンドが既に記載されています。npmモジュールに「@」というスコープをつける場合は、npm publishコマンドに「--access=public」オプションを追加する必要があります。以下のスクリーンショットのように、31行目の「- run: npm publish」を「- run: npm publish --access=public」に変更します。
次に、右上にある緑色の「Commit Changes...」ボタンをクリックして反映させましょう。この修正によって、GitHub Releasesのページから直接npmにカスタムノードを公開できるようになりました。
ノードをリリース
さっそく公開するため、GitHubリポジトリのページの右下にある「Create a new release」ボタンをクリックします。
リリースの最初のタグを作成するには、「Choose a tag」をクリックし、「v0.0.1」と入力した後、「+ Create new tag: v0.0.1 on publish」をクリックします。
リリースのタイトルには「v0.0.1: The First Release」のようなリリースの内容が分かる文字列を入力します。
ノードのバージョンアップを行なった際は、Writeのタブの中に更新内容を書いておくと親切でしょう。
最後に、一番下にある「Publish release」ボタンを押すと「v0.0.1: The First Release」のリリースページに飛ばされます。カスタムノードの生成の進行状況を知りたい場合は、再生アイコンのある「Actions」タブからGitHub Actionsのページで処理のログを確認できます。
しばらく待つと、自分のnpmアカウントの配下に、カスタムノードが公開されます。正しく登録できると https://www.npmjs.com/package/@<npmユーザ名>/node-red-contrib-example-lower-case というURLにて公開されます。
Node-REDフローライブラリに登録
フローライブラリに登録するには、手動でフォームで申請する必要があります。 https://flows.nodered.org/add/node のページにアクセスし「3. Add your node to the Flow Library」の入力欄に、npmモジュール名「@<npmユーザ名>/node-red-contrib-example-lower-case」を入力します。
「add node」ボタンをクリックすると、フローライブラリが新規にnpmに登録されたノードをフローライブラリに登録します。
しばらくするとフローエディタ用のカタログが作成され、他の全てのNode-REDのフローエディタからノードをインストールできるようになります。
カタログの作成状況は以下のURLから参照できますので、なかなか登録されない場合は確認してみましょう。
公開したノードを削除する方法
今回作成したノードはお試し用ですので、フローライブラリから削除しておきましょう。まず、公開したnpmのページを開き、タブの一番右にある「Settings」を選択します。
一番下に「Delete package」のボタンがあるため、クリックします。
本当に削除して良いかの確認画面が表示されるため、「@<npmユーザ名>/node-red-contrib-example-lower-case」を入力します。これでnpmから削除されました。
まだフローライブラリには、カタログが残っているため、こちらも削除する必要があります。ノードの登録手順と同じ様に https://flows.nodered.org/add/node を開き「@<npmユーザ名>/node-red-contrib-example-lower-case」を入力します。
「add node」ボタンをクリックすると「TypeError: Cannot read properties of undefined (reading 'latest')」とエラーが出ますが、これで削除できています。念のため、フローライブラリからも消えているか確認しておきましょう。
最後に
Node-REDのノードが簡単に開発、公開できることを理解して頂けたと思います。既存のソフトウェアでもNode.jsのSDKがあれば簡単にノード化することができます。ぜひノードを沢山開発してフローライブラリさらに充実させましょう。
参考記事
-
Node-RED オリジナルノードの開発
この記事のもととなっているノード開発手順です。 -
Node-REDのサブフローからカスタムノードを作成する
サブフローからノンコーディングでオリジナルノードを作成する手順です。