投稿

11月, 2021の投稿を表示しています

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

イメージ
ここのところずっと Node-RED のサンプルを見ながら各ノードの使い方を確認しています。 頭出しの記事はこちら をご確認ください。今回はDelayノードを使ってみます。要はJavaScriptで言うところの「 setTimeout() 」みたいなものかと思います。 指定した時間メッセージを遅延させる 最初のサンプルは「 flows > node-red > function > delay > 01 - Delay message 」です。フローを実行すると、delayノードで遅延が発生して、時間差でログが出力されます。 Delayノードのプロパティを見ると、指定した時間(3秒)だけメッセージが遅延するようです。ここは特に解説の必要はないと思います。 msgオブジェクトのプロパティ値により遅延させる 次のサンプルは「 flows > node-red > function > delay > 02 - Delay message by message property 」です。先程と同じくDelayノードのプロパティを見てみます。ポイントは以下の2点です。 msg.delay値により遅延時間が決定される 「 時間 」の指定は無視される Injectノードでは「 msg.delay 」に遅延時間1000(ミリ秒)が設定されています。実行すると1秒遅延します。「 msg.delay 」に10000(ミリ秒)を設定すると10秒遅延します。サンプル01では遅延時間がDelayノードの設定で固定されていたのが、サンプル02ではmsg.delayの値に応じて遅延時間が変更可能になっています。 まとめ Delayノードを使うことによりフローを遅延させることができます。以下、2種類の挙動を実現できます。 Delayノードのプロパティに設定した値で遅延時間を固定する msg.delayの値に応じて遅延時間を可変にする 次回もDelayノードを見ていきます。

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

イメージ
前回 に引き続きTemplateノードを使ってみます。 JSON形式のテンプレート 最初のサンプルは「 flows > node-red > function > template > 02 - Parse result as JSON 」です。Templateノードのプロパティを見てみます。ポイントは以下の2点です。 テンプレートがJSON形式で記述されている 出力形式の設定がJSONになっている 実行結果は以下の通りで、msg.playloadにテンプレートが適用されたJSONオブジェクトが格納されていることが確認できます。 期待通りかと思うので、ここはサラッと流して次のサンプルを見てみます。 YAML形式のテンプレート 次のサンプルは「 flows > node-red > function > template > 03 - Parse result as YAML 」です。先程と同じくTemplateノードのプロパティを見てみます。ポイントは以下の2点です。 テンプレートがYAML形式で記述されている 出力形式の設定がYAMLになっている 実行結果は、先程のサンプル02と同じく、msg.payloadにテンプレートが適用されたJSONオブジェクトが設定されます。 ここで違和感があったのが「 出力形式 」の設定が違っていてもmsg.payloadに設定される結果は変わらないということです。「 出力形式 」って表現から、msg.payloadにテンプレートを適用した結果の形式がYAMLになるものだと勘違いしていましたが、どうやらそうではなく、 テンプレートを適用した結果をどういう形式で扱うか ってことみたいです。例えば、HTML形式のテンプレートを書きたい場合は、 出力形式を平文 に設定しておけばいい感じかもしれません。それにしても、ユーザに選択させる必要性がよくわかりませんでした。自動で認識してよって感じです。 まとめ まとめます。 「出力形式」はTemplateノードの出力形式を変更するものではなく、テンプレートを適用した結果をどういう形式で扱うか指定するもの 出力形式は平文、JSON、YAMLをサポートしている 利用者に出力形式を選択させる意味がよくわからない(自動で認識して欲しい)

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

イメージ
今回はTemplateノードを使ってみます。 Mustacheテンプレート 最初のサンプルは「 flows > node-red > function > template > 01 - Use mustache syntax 」です。置換したいパラメータを「 {{}} 」で括ってテンプレート上に記述するMustache形式が利用できるとのこと。 まずはInjectノードを見てみます。msg.payloadにJSONオブジェクトが、msg.topicに文字列「 Fruits 」が設定されています。 msg.payloadの内容が見づらいのでJSONエディタで開いてみると、以下のように name と price をプロパティに持つJSONオブジェクトが配列形式になっています。 続いて、templateノードを見てみます。わりと盛りだくさんですが、次の情報が読み取れます。 テンプレートが適用された文字列は「 プロパティ 」で指定した「 msg.payload 」に格納されます テンプレートエディタのハイライト(見やすいよう色付け)は「 構文 」で指定した「 mustache 」が適用されます テンプレート内の「 {{topic}} 」の部分に「 msg.topic 」の値( Fruits )が埋め込まれます 「 {{#payload}}〜{{/payload}} 」が「 JSON配列 」として評価され、テンプレート内で繰り返されます 「 {{name}} 」と「 {{price}} 」の部分に「 msg.payload 」のJSON配列の各値が埋め込まれます テンプレートは「 Mustacheテンプレート 」として評価されます 「 平文 」として出力されます 実行結果は、以下の通りです。期待通り。 templateノードの「 プロパティ 」を変えてみたらどういう結果になるでしょうか。試しに「 msg.hoge 」としてみます。 わかりやすいようにdebugノードの出力対象をmsgオブジェクト全体としてみます。 結果は以下の通りです。 msg.payload と msg.topic にはinjectノードで指定した値(それぞれJSON配列と文字列)がそのまま格納されている msg.hoge にはテンプレートが適用された文字列が格納されている まとめ

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

イメージ
引き続きサンプルフローを見ていきます。 Range ノードシリーズ2回目にして最終回です。 入力値を制限する 最初のサンプルは「 flows > node-red > function > range > 03 - Limit input value 」です。入力値を指定した範囲内になるよう制限するようです。 「 動作 」の設定は 前回 紹介したRangeノードのサンプル01と同じく「 入力値の範囲外の値を最小値/最大値とし拡大/縮小 」です。違うのは入力値の範囲と出力値の範囲のみ。 実行結果は、以下の通りです。 入力0→出力0 入力10→出力9 入力100→出力90 「 入力値の範囲を出力値の範囲にマッピングして按分計算(上下限を超えた値はサチる) 」 ってことですね。これ以上の説明は不要かと思います。 入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小 次のサンプルは「 flows > node-red > function > range > 04 - Scale and wrap input value 」です。挙動の一部はよくわからない上に、利用する場面もイマイチよくわかりませんでした。プロパティを見ていくと、「 動作 」の設定が「 入力値の範囲外の値を範囲幅で割った余りとし(「て」が抜けてる?)拡大/縮小 」となっている以外、Rangeノードサンプル03と同じです。 実行すると、以下のような結果になります。 入力0→出力0 入力10→出力10 入力100→出力10 「 入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小 」の表現をそのまま素直に読み解くと、 入力値の範囲外の値:10 (出力値の?)範囲幅:90 「入力値の範囲外の値」を「(出力値の?)範囲幅」で割った余りとし(て?)拡大/縮小:10÷90の余り:10 続いて、 入力値の範囲外の値:100 (出力値の?)範囲幅:90 「入力値の範囲外の値」を「(出力値の?)範囲幅」で割った余りとし(て?)拡大/縮小:100÷90の余り:10 計算通りになっているようです。ところで、「 入力値の範囲内 」の値を入力したらどうなるんでしょう。 入力値:5 (出力値の?)範囲幅:90 「入力値の範囲外の値」を「(出力値の?)範囲幅」で割った余りとし(て?)拡大/

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

イメージ
 引き続きサンプルフローを見ていきます。今回から Range ノードシリーズ開幕です。今回のサンプルは、挙動を見ていると理解できても、言葉で表現するのが難しかったです。 入力値の範囲を出力値の範囲にマッピングして按分計算(上下限を超えた値はサチる) 最初のサンプルは「 flows > node-red > function > range > 01 - Scale input value 」です。入力値をスケールして出力するらしいです。 「 動作 」の設定は「 入力値の範囲外の値を最小値/最大値とし拡大/縮小 」となっています。 実行するとこんな感じで、入力値が出力値の範囲の割合で按分され、出力値の範囲内の値が出るようです。 そうなると、このサンプルフローでは入力値として範囲(0〜1023)外の値を与えているわけではないので、画面の説明が不正確な気もします。意味合い的には、 「 入力値の範囲を出力値の範囲にマッピングして按分計算(上下限を超えた値はサチる) 」 みたいな感じでしょうか。文章にすると表現は難しいですが、感じ取りましょう。ちなみに、入力値の上限である1023より大きい値を与えたところ、出力は5になりました。 入力値の範囲を出力値の範囲にマッピングして按分計算(上下限を超えた値はサチらず倍率計算) 次のサンプルは「 flows > node-red > function > range > 02 - Scale input and round to integer 」です。 「 動作 」の設定は「 msg.payloadの値を拡大/縮小 」となっています。 実行すると、以下のような結果になります。 どうやら、「 入力値の範囲 」に対する「 入力値 」の倍率を出力値の範囲に倍率計算した値を出力するようです。例えば、入力値99の場合、入力値の範囲の上限9を11倍超えているので、「 出力値の範囲 」の上限128に11をかけた値「1408」が出力値となります。言葉で説明すると難しいですが、一つ前に紹介したサンプルの表現に沿うと意味合い的には 「 入力値の範囲を出力値の範囲にマッピングして按分計算(上下限を超えた値はサチらず倍率計算) 」 といったところでしょうか。 ところで、「 msg.payloadの値を拡大/縮小

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

イメージ
Change ノードの最終回です。 プロパティの削除 最初のサンプルは「 flows > node-red > function > change > 06 - Delete message property 」です。msgプロパティを削除できるようです。へー。 削除したプロパティにアクセスすると例外は発生せず「 undefined 」になります。JavaScriptだと一般的な挙動ですね。 プロパティの移動 次のサンプルは「 flows > node-red > function > change > 07 - Move message property 」です。 Injectノード では msg.topicに文字列「Hello」 を設定しています。 Changeノードでは、msg.topicの値をmsg.payloadに移動しています。 フローを実行すると、msg.payloadの値に「Hello」が設定されていることが確認できます。 ところで、移動元のmsg.topicの値はどうなったんでしょう?疑問に思ったので、以下のようにDebugノードを追加してmsg.topicの値を出力してみます。 フローを実行すると、msg.topicは「undefined」になりました。「値の移動」とは文字通り「移動」ということのようです(コピーではない)。 まとめ 以上でChangeノードのサンプル確認は終了です。今回の内容をまとめます。 プロパティの値は削除できる 削除したプロパティはundefinedになる プロパティの値は移動できる 移動元はundefinedになる 文字通り値が移動する(コピーではない) Changeノードでできる操作は、サンプルでは利用していないもの含め以下の4つのようです。 値の代入 値の置換 値の削除 値の移動

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

イメージ
前回 に引き続き Change ノードのサンプルを見ていきます。 環境変数を設定する 最初のサンプルは「 flows > node-red > function > change > 04 - Set value from env var 」です。環境変数「 HOME 」の値を msg.payload に設定しています。これ以上は説明不要ですかね。 任意のプロパティへの値設定 次のサンプルは「 flows > node-red > function > change > 05 - Set flow context 」です。フローは2つあります。 Initializeフロー のChangeノードでは flow.countに数値0を設定 しています。ここは説明不要ですね。 一方、 Count upフロー のChangeノードでは、 flow.countの値をインクリメント flow.countの値をmsg.payloadに設定 を実行しています。 前回の記事の情報を組み合わせると特に説明は不要かと思います。 まとめ 情報量は少ないですが、きりが良いので今回はこの辺でまとめておきます。 環境変数の値を参照できる フローコンテキストの値を参照できる 引き続きサンプルを見ていきます。

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

イメージ
今回から Change ノードを使ってみます。相変わらずサンプルが多くて骨が折れます。 Payloadへの値設定 最初のサンプルは「 flows > node-red > function > change > 01 - Set payload value 」です。タイトル通りchangeノードを使ってpayloadに値を設定するのに使えます。プロパティは以下のような感じで、特に説明は不要かと思います。 任意のプロパティへの値設定 次のサンプルは「 flows > node-red > function > change > 02 - Set any property value 」です。payload以外のプロパティに値を設定できます。これも説明不要ですかね。 JSONata式によるプロパティへの値設定 3つ目のサンプルは「 flows > node-red > function > change > 03 - Set value using JSONata 」です。 これを実行すると「 "Hello, World!" 」というログが出力されます。ルール「 値の代入 」が2つ、それぞれ、 msg.payloadに「 Hello 」の文字列を設定 msg.payloadに、msg.payloadの値と「 , World! 」の文字列を結合して設定 の処理を実行しています。ルールを複数設定すると上から順に実行されるということらしいです。並列実行じゃないということです。 まとめ 挙動はシンプルですが、念のためここまで確認したことをまとめておきます。 任意のmsgプロパティに値を設定できる ルールを複数登録すると上から順に実行される 引き続きサンプルを見ていきます。

コードレビュー練習会に参加してみた

最近このブログではローコードプログラミングツールのNode-REDに関する記事が多めですが、普段はコードを書く機会の多いそれなりにハイコードな生活をしています。 先日、会社で開催された「コードレビュー練習会」なるものに参加するため少しだけコードを書いてみました。 (Node.js版)1000円でチケット購入時のお釣りと硬貨の枚数を計算する関数 (Golang版)シーザー暗号化、復号化する関数 普段コードを書いているわりにレビューをする機会はないので、若手メインでいろいろな方のコードを見ることができるのはありがたかったです。今回はコードレビューとコーディングについて思うことをつらつらと書いてみます。 前提条件 最近仕事で一番使うのはPHP、次いでNode.jsとシェルスクリプトです。ちょっと前によく書いていたRuby、Java、C#はめっきり使わなくなりました。Pythonはやむを得ず読む機会は多いですが、普段書くことはありません。最近触り始めたGolangはとても使いやすいと思っています。CやC++、Fortranは20年くらい前に書いていましたが、もう忘れました。 偉そうなことを書いているようですが、自分自身、ダメなコードを書いてしまうことがよくあるのは自覚しています。時間の都合上省略したり、練りが足りなくてあとから読みづらいコードを書いてしまってごめんねー、ってなってしまったり。今回の記事に誰かを攻撃する意図はなく、理想的にはこうだったらいいなって話です。 あと、プログラミング言語自体に優劣はないと思っています。 書き慣れていない方のコードの特徴 書き慣れていない方のコードを見ていると以下の特徴があるように思います。 変数や関数の名前から意図が読み取れなない 変数名「flag」だけでは何のフラグか読み取れない 慣例やスタイルガイドラインにならっていない 定数が小文字になっている エラー発生時にreturn 0している 関数名が名詞になっている 変数名と実態がずれている 誰向けのログか意識していない アルゴリズム中にエンドユーザ向けのログを出力している 関数の利用者(他の開発者)、関数を組み込んだプログラムの利用者(エンドユーザ)どっち向けのログか意識してなさそう コメント無しでマジックナンバーを使う 「97」とか「116」とかがいきなり出てくる 行数が少ないコー

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

イメージ
前回 に引き続き Switch ノードを使ってみます。Switchノード最終回。 メッセージシーケンスの再構築 最初のサンプルは「 flows > node-red > function > switch > 07 - Recreate message sequence 」です。流れは以下の通りです。 injectノードでmsg.payloadに数値の配列を指定 splitノードで配列をmsgオブジェクトに分解 switchノードでmsg.payloadの値に応じて出力ポートを振り分け joinノードでmsgオブジェクトの値を配列に結合 ログ出力 splitノードとjoinノードの挙動確認は別の機会に譲ることにして、今回はswitchノードに着目します。msg.payloadの値を文字列の"0"と比較して出力ポートを振り分けています。数値と文字列と比較するのはサンプルとしてはあまり良くない気はしますが、結果的に期待通り動作します(もしかして意図したものかもしれませんが)。「>」の挙動は、恐らくJavaScriptの「>」演算子と同じだと思うので、厳密な挙動は 仕様 を確認しておいた方が良さそうです。素直にやるなら同じ型どうしで比較した方が良いと思います。 プロパティによる出力ポートの振り分け 次のサンプルは「 flows > node-red > function > switch > 08 - Route message based on properties 」です。 順番にプロパティを確認していきます。まずはinjectノードから。msg.payloadに数値27を、msg.topicに文字列"temperature"を指定しています。 続いてswitchノード。msg.topicの値で条件分岐しています。上のinjectノードから発行されたmsgオブジェクトはmsg.topicが"templerature"なので出力ポート1に振り分けられます。そのmsg.payloadには数値27が格納されています。 最後にdebugノード。msg.payloadを出力しています。上のフローの場合、数値27を出力します。 このサンプルからわかるのは、途中で