🔗 Node-RED Link ノードガイド

📚 目次

📖 1. 概要

Link ノードは、フロー内やフロー間で「仮想的なワイヤー」を作成するノードです。物理的なワイヤーを引かずにノード同士を接続でき、複雑なフローを整理するのに役立ちます。

📞 内線電話に例えると:Link ノードは会社の内線電話システムのようなものです。離れた部署(別のフロータブ)にいる人でも、内線番号(Link名)を使えば直接つながることができます。

💡 Link ノードを使うメリット:

🔧 2. 3種類のLinkノード

📥 Link In

Link In

役割: メッセージの受信口

特徴:

  • Link Out または Link Call からメッセージを受け取る
  • 複数の Link Out から受信可能

📤 Link Out

Link Out

役割: メッセージの送信口

特徴:

  • Link In にメッセージを送信
  • 複数の Link In に同時送信可能

📞 Link Call

Link Call

役割: サブフローを呼び出して結果を受け取る

特徴:

  • Link In を呼び出し、Link Out(return)で結果を受け取る
  • 関数呼び出しのような動作

Link Out と Link Call の違い

特徴Link Out(通常モード)Link Call
動作送りっぱなし(Fire and Forget)結果を待って受け取る
戻り値なしあり(Link Out return経由)
用途通知、ログ記録、分岐共通処理の呼び出し
接続先Link InLink In(return用Link Out必須)

⚙️ 3. 設定詳細

Link In プロパティ

プロパティ説明
名前リンクの識別名(他のLinkから参照される)

Link Out プロパティ

プロパティ説明
モード送信先の Link In を選択 / Return モード(Link Call用)
名前リンクの識別名
Links接続先の Link In ノードを選択

Link Call プロパティ

プロパティ説明
リンクの種類呼び出し方式(対象を固定で指定 / 対象を動的に指定)
Link呼び出す Link In ノードを選択(固定指定時)
タイムアウト応答待ちタイムアウト(秒)
名前ノードの識別名

🔧 4. 実用的な使用パターン

📥 サンプルフローのインポート方法:

  1. 下のサンプルフローJSONをコピー
  2. Node-REDエディタで メニュー → 読み込み を選択
  3. JSONをペーストして「読み込み」をクリック

このサンプルフローには、以下で説明するパターンの実例が含まれています。

📥 サンプルフローJSON(クリックで展開)
[ { "id": "link_sample_tab", "type": "tab", "label": "Link サンプル", "disabled": false, "info": "" }, { "id": "link_comment1", "type": "comment", "z": "link_sample_tab", "name": "━━━ 基本: Link Out → Link In ━━━", "info": "", "x": 180, "y": 40, "wires": [] }, { "id": "inject_basic", "type": "inject", "z": "link_sample_tab", "name": "送信", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Hello via Link!", "payloadType": "str", "x": 130, "y": 100, "wires": [["link_out_basic"]] }, { "id": "link_out_basic", "type": "link out", "z": "link_sample_tab", "name": "送信口", "mode": "link", "links": ["link_in_basic"], "x": 295, "y": 100, "wires": [] }, { "id": "link_in_basic", "type": "link in", "z": "link_sample_tab", "name": "受信口", "links": ["link_out_basic"], "x": 435, "y": 100, "wires": [["debug_basic"]] }, { "id": "debug_basic", "type": "debug", "z": "link_sample_tab", "name": "受信確認", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "payload", "targetType": "msg", "statusVal": "payload", "statusType": "auto", "x": 590, "y": 100, "wires": [] }, { "id": "link_comment2", "type": "comment", "z": "link_sample_tab", "name": "━━━ Link Call(サブルーチン呼び出し)━━━", "info": "", "x": 210, "y": 180, "wires": [] }, { "id": "inject_call", "type": "inject", "z": "link_sample_tab", "name": "数値入力", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "5", "payloadType": "num", "x": 140, "y": 240, "wires": [["link_call_double"]] }, { "id": "link_call_double", "type": "link call", "z": "link_sample_tab", "name": "2倍処理を呼び出し", "links": ["link_in_double"], "linkType": "static", "timeout": "30", "x": 350, "y": 240, "wires": [["debug_call_result"]] }, { "id": "debug_call_result", "type": "debug", "z": "link_sample_tab", "name": "結果: 10", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "payload", "targetType": "msg", "statusVal": "payload", "statusType": "auto", "x": 560, "y": 240, "wires": [] }, { "id": "link_comment3", "type": "comment", "z": "link_sample_tab", "name": "【共通処理】2倍にする", "info": "", "x": 160, "y": 300, "wires": [] }, { "id": "link_in_double", "type": "link in", "z": "link_sample_tab", "name": "2倍処理入口", "links": [], "x": 155, "y": 360, "wires": [["func_double"]] }, { "id": "func_double", "type": "function", "z": "link_sample_tab", "name": "×2", "func": "msg.payload = msg.payload * 2;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 310, "y": 360, "wires": [["link_out_return"]] }, { "id": "link_out_return", "type": "link out", "z": "link_sample_tab", "name": "結果を返す", "mode": "return", "links": [], "x": 455, "y": 360, "wires": [] }, { "id": "link_comment4", "type": "comment", "z": "link_sample_tab", "name": "━━━ 複数の送信先 ━━━", "info": "", "x": 160, "y": 440, "wires": [] }, { "id": "inject_multi", "type": "inject", "z": "link_sample_tab", "name": "イベント発生", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{\"event\": \"button_click\", \"time\": \"2024-01-15\"}", "payloadType": "json", "x": 150, "y": 500, "wires": [["link_out_multi"]] }, { "id": "link_out_multi", "type": "link out", "z": "link_sample_tab", "name": "複数送信", "mode": "link", "links": ["link_in_log", "link_in_notify"], "x": 315, "y": 500, "wires": [] }, { "id": "link_in_log", "type": "link in", "z": "link_sample_tab", "name": "ログ処理", "links": ["link_out_multi"], "x": 445, "y": 480, "wires": [["debug_log"]] }, { "id": "debug_log", "type": "debug", "z": "link_sample_tab", "name": "📝 ログ記録", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 590, "y": 480, "wires": [] }, { "id": "link_in_notify", "type": "link in", "z": "link_sample_tab", "name": "通知処理", "links": ["link_out_multi"], "x": 445, "y": 520, "wires": [["debug_notify"]] }, { "id": "debug_notify", "type": "debug", "z": "link_sample_tab", "name": "🔔 通知送信", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 590, "y": 520, "wires": [] } ]

使用パターン

パターン1: 基本的な Link Out → Link In

サンプルフローの「基本: Link Out → Link In」を参照してください。

Inject Link Out - - - Link In Debug

ポイント: ワイヤーの交差を避けたり、離れた場所にメッセージを送る

パターン2: Link Call(サブルーチン呼び出し)

サンプルフローの「Link Call(サブルーチン呼び出し)」を参照してください。

Inject Link Call 結果
【呼び出し先】 共通処理(3倍) 処理 Return

ポイント:

パターン3: 複数の送信先

サンプルフローの「複数の送信先」を参照してください。

Link Out - - - 受信A
- - - 受信B

ポイント: 1つの Link Out から複数の Link In に送信可能

パターン4: 共通検証処理の再利用

サンプルフローの「検証処理(共通)」「テスト呼び出し」を参照してください。

テストA 検証呼出 結果
テストB 検証呼出 結果

ポイント: 同じ検証ロジックを複数箇所から呼び出して再利用

📝 5. 演習問題

演習1: 基本的なLink接続 初級

📋 課題: Link Out と Link In を使って、ワイヤーを引かずにメッセージを送信するフローを作成してください。

✅ 成功の条件:

💡 ヒント

1. Link Out ノードの設定で、接続先の Link In を選択します

2. 名前を分かりやすくつけると管理しやすくなります

✅ 解答例フロー
[ {"id": "ex1_tab", "type": "tab", "label": "演習1"}, {"id": "ex1_inject", "type": "inject", "z": "ex1_tab", "name": "送信", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "Link経由のメッセージ", "payloadType": "str", "x": 130, "y": 100, "wires": [["ex1_link_out"]]}, {"id": "ex1_link_out", "type": "link out", "z": "ex1_tab", "name": "送信口", "mode": "link", "links": ["ex1_link_in"], "x": 275, "y": 100, "wires": []}, {"id": "ex1_link_in", "type": "link in", "z": "ex1_tab", "name": "受信口", "links": ["ex1_link_out"], "x": 435, "y": 100, "wires": [["ex1_debug"]]}, {"id": "ex1_debug", "type": "debug", "z": "ex1_tab", "name": "確認", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "payload", "targetType": "msg", "statusVal": "payload", "statusType": "auto", "x": 570, "y": 100, "wires": []} ]

演習2: 複数の受信先 初級

📋 課題: 1つの Link Out から2つの Link In にメッセージを送信するフローを作成してください。

✅ 成功の条件:

💡 ヒント

Link Out ノードの設定で、複数の Link In を選択できます。

✅ 解答例フロー
[ {"id": "ex2_tab", "type": "tab", "label": "演習2"}, {"id": "ex2_inject", "type": "inject", "z": "ex2_tab", "name": "イベント", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "共通データ", "payloadType": "str", "x": 140, "y": 140, "wires": [["ex2_link_out"]]}, {"id": "ex2_link_out", "type": "link out", "z": "ex2_tab", "name": "分岐送信", "mode": "link", "links": ["ex2_link_in1", "ex2_link_in2"], "x": 295, "y": 140, "wires": []}, {"id": "ex2_link_in1", "type": "link in", "z": "ex2_tab", "name": "処理A", "links": ["ex2_link_out"], "x": 435, "y": 100, "wires": [["ex2_debug1"]]}, {"id": "ex2_debug1", "type": "debug", "z": "ex2_tab", "name": "処理A実行", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 590, "y": 100, "wires": []}, {"id": "ex2_link_in2", "type": "link in", "z": "ex2_tab", "name": "処理B", "links": ["ex2_link_out"], "x": 435, "y": 180, "wires": [["ex2_debug2"]]}, {"id": "ex2_debug2", "type": "debug", "z": "ex2_tab", "name": "処理B実行", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 590, "y": 180, "wires": []} ]

演習3: Link Call の基本 中級

📋 課題: Link Call を使って「入力値を3倍にする」共通処理を作成し、呼び出すフローを作ってください。

✅ 成功の条件:

💡 ヒント

1. 共通処理: Link In → Function(×3) → Link Out(returnモード)

2. 呼び出し側: Inject → Link Call → Debug

3. Link Out のモードを「return」に設定することが重要です

✅ 解答例フロー
[ {"id": "ex3_tab", "type": "tab", "label": "演習3"}, {"id": "ex3_comment", "type": "comment", "z": "ex3_tab", "name": "━━━ 呼び出し側 ━━━", "info": "", "x": 140, "y": 40, "wires": []}, {"id": "ex3_inject", "type": "inject", "z": "ex3_tab", "name": "7を入力", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "7", "payloadType": "num", "x": 140, "y": 100, "wires": [["ex3_call"]]}, {"id": "ex3_call", "type": "link call", "z": "ex3_tab", "name": "3倍処理呼び出し", "links": ["ex3_link_in"], "linkType": "static", "timeout": "30", "x": 340, "y": 100, "wires": [["ex3_debug"]]}, {"id": "ex3_debug", "type": "debug", "z": "ex3_tab", "name": "結果: 21", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "payload", "targetType": "msg", "statusVal": "payload", "statusType": "auto", "x": 530, "y": 100, "wires": []}, {"id": "ex3_comment2", "type": "comment", "z": "ex3_tab", "name": "━━━ 共通処理(3倍) ━━━", "info": "", "x": 160, "y": 180, "wires": []}, {"id": "ex3_link_in", "type": "link in", "z": "ex3_tab", "name": "3倍処理", "links": [], "x": 135, "y": 240, "wires": [["ex3_func"]]}, {"id": "ex3_func", "type": "function", "z": "ex3_tab", "name": "×3", "func": "msg.payload = msg.payload * 3;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 290, "y": 240, "wires": [["ex3_return"]]}, {"id": "ex3_return", "type": "link out", "z": "ex3_tab", "name": "結果を返す", "mode": "return", "links": [], "x": 435, "y": 240, "wires": []} ]

演習4: 再利用可能な検証処理 上級

📋 課題: 「入力値が正の数かどうかを検証する」共通処理を Link Call で作成し、複数箇所から呼び出せるようにしてください。

🎯 要求仕様:

✅ 成功の条件:

💡 ヒント

Function ノードで条件分岐を行い、結果を msg に設定して返します。

✅ 解答例フロー
[ {"id": "ex4_tab", "type": "tab", "label": "演習4"}, {"id": "ex4_comment1", "type": "comment", "z": "ex4_tab", "name": "━━━ テスト呼び出し ━━━", "info": "", "x": 150, "y": 40, "wires": []}, {"id": "ex4_inject1", "type": "inject", "z": "ex4_tab", "name": "正の数: 10", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "10", "payloadType": "num", "x": 150, "y": 100, "wires": [["ex4_call"]]}, {"id": "ex4_inject2", "type": "inject", "z": "ex4_tab", "name": "負の数: -5", "props": [{"p": "payload"}], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "-5", "payloadType": "num", "x": 150, "y": 140, "wires": [["ex4_call"]]}, {"id": "ex4_call", "type": "link call", "z": "ex4_tab", "name": "正の数チェック", "links": ["ex4_validate_in"], "linkType": "static", "timeout": "30", "x": 360, "y": 120, "wires": [["ex4_debug"]]}, {"id": "ex4_debug", "type": "debug", "z": "ex4_tab", "name": "検証結果", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "true", "targetType": "full", "statusVal": "valid", "statusType": "msg", "x": 550, "y": 120, "wires": []}, {"id": "ex4_comment2", "type": "comment", "z": "ex4_tab", "name": "━━━ 検証処理(共通) ━━━", "info": "", "x": 160, "y": 220, "wires": []}, {"id": "ex4_validate_in", "type": "link in", "z": "ex4_tab", "name": "正の数検証", "links": [], "x": 145, "y": 280, "wires": [["ex4_validate_func"]]}, {"id": "ex4_validate_func", "type": "function", "z": "ex4_tab", "name": "検証", "func": "if (msg.payload > 0) {\n msg.valid = true;\n} else {\n msg.valid = false;\n msg.error = \"正の数を入力してください\";\n}\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 310, "y": 280, "wires": [["ex4_return"]]}, {"id": "ex4_return", "type": "link out", "z": "ex4_tab", "name": "結果を返す", "mode": "return", "links": [], "x": 455, "y": 280, "wires": []} ]

✅ 6. まとめ

🎯 重要ポイント:

⚠️ 注意事項:

🏭 7. 実務活用例

ケース1: ログ記録の共通化

各処理からログ記録用の Link In にメッセージを送信し、ログ処理を一元管理。

ケース2: エラーハンドリング

エラー発生時に共通のエラー処理フローへ Link で転送。

ケース3: 機能別のタブ分割

入力処理、ビジネスロジック、出力処理をタブで分けて Link で連携。

ケース4: 共通バリデーション

Link Call で入力検証を呼び出し、結果に応じて処理を分岐。

📚 Node-RED 公式ドキュメント

🏠