前回はNode-REDから「ネットにつながっているの?」とPingで問いかけました。今回はNode-RED内のあるタブで発生したエラーをキャッチして、別なタブに「飛ばして」しまう、という技?を勉強してみます。これ自体は意味ないけど、別タブのバグが見つかりエラーをFIXっと。副作用ですな。
※「ブロックを積みながら」投稿順 index はこちら
今回試用してみるノードは、Node-REDのエディタのパレットでは、すべて「共通」なるところに置かれてます。
薄赤の背景にビックリマークが印象的な catch ノードと、灰色の link in および link out の3ノードを使用してみたいと思います。
ここまでノードを使用するときは、test というタブの中で全て完結させてきたのですが、今回初めて他のタブと連携させてみます。今回使うのは、別件で今も動作しつづけている
ATOMLiteタブ
です。M5ATOMLite上で動作しているMicroPythonスクリプトからMQTT経由で温度やら気圧やら受け取ってNode-REDダッシュボードに表示するとともにSQLデータベースに記録するもの。現在バグの叩き出しのために絶賛長時間ランニング試験中です。試用は特に走っているスクリプトやNode-REDフローなどを止めることなく、部分的なデプロイで実施です。
link in と link outノード
まず先に、フロー間を「接続する」link inノードとlink outノードについて見てみます。link outがフローからメッセージを流しだすためのノードで、link inがlink outされたメッセージを受け取るためのノードです。同じタブのフロー間でリンクを張ることも可能みたいですが、主たる目的はタブ間での接続だと思います。
link out ノードは入力を受け取るためのポートはありますが、明示的な出力ポートはありません。また、link in ノードは出力ポートのみです。しかし、フロー上にノードを配置してリンクを設定した後、該当のlinkノードを選択したときだけ、反対側に点線で接続先が現れます。link out ノードはこんな感じ。
上のようにtestタブに接続されていることが分かります。
testタブ上に配置した link in ノード選択するとこんな感じ。
タブ間では「配線」での接続ができないので、ノードのプロパティ画面から、接続先を指定します。どこのタブの何というお名前のリンクノードかチェックを入れるだけです。フロー上、リンクノードの名前はアカラサマに表示されないですが、以下を見ると識別し易い名前を付けておいた方が良さそうです。
対になる link in 側のプロパティは以下のように。
チェックを入れるだけなので、名前さえ明確であれば間違う余地は無いように思います。
catchノード
さて、ATOMLiteタブ上には、赤いキャッチノードを配置してあります。catchノードは、その名のとおりエラーをキャッチするためのノードです。同一タブ内のノードが送出するエラーが対象で、全ノード対象でも、特定ノード対象でもcatchが可能です。後で見ますがキャッチしたmsg内にエラーに関するオブジェクトが載っています。通常はこれ見てエラーへの対処するフローに接続するはず。
今回は catch したエラーをlink ノードを使って別タブに「転送」してからDebugノードに渡すような、変なことをしてます。そのようなことをしてもエラー情報はそのまま伝達されてくるみたいです。
実際には動的にフローが動作している最中で、またデバッグノードが多数生きたままになっているので、デバッグウインドウに表示される情報が多すぎました。何がなんだか分からないっと。デバッグウインドウのログのフィルタリング機能を使って、転送されてきたエラー情報のmsgのみを抽出してみてみます。フィルタの設定はこんな感じ。やはりお名前クリックなので、ノードに付けるお名前は分かり易いのが良いです。
さて、実際に送られてきたエラー情報が以下に。
まず topicに載っている “ATOMLite/Json” というのは MQTTでサブスクライブしているトピックです。このトピックを受信した後の処理でエラーが起きているみたいです。
次に parts というものに key “B” というプロパティが載ってます。これはMQTT経由で送られてきたJSONオブジェクトをsplitノードでpartsに分解した後の、Bというkey を持ったオブジェクトについてみたい。
そして最後に error オブジェクトです。Type Errorが発生しておると。具体的には undefined なものに toFixedしようとしてエラーになっているみたい。sourceを見れば、名前が logJSONobj の functionノードで起きているみたいですな。
エラーが起きているノードを選択(赤枠)してみました。フロー的にはこんな感じ。
観察するに、ここのファンクションノードで「大量に」エラーが起きている(送られてきた全てのプロパティがエラーになっていた)ために、後段にSQL文が送られず、データベースへの記録がなされていませんでした。こりゃ大変だ!
ファンクションノードの中で toFixed()しているところを調べて原因判明しました。ファンクションノードの中では、データベースにどのデバイスの何というキーのデータだいう情報を使ってSQL文を組み立てているのです。「どのデバイス」の「何というキー」の部分は、起動時にそれぞれの設定値をデータベースの該当テーブルから読み出してその後はローカルなストレージに格納して使っているのです。
その初期化が動いてなかったです。
初期化のフローは直ぐ下に Initialize FlowというInjectノードから始まるものです。以前にテストしていたときは、「開発中」ということで手動でInjectしてました。今回、Injectボタンを押すのを忘れて初期化せずいたまま、MQTT経由でデータを受け取ったためにエラーになってました。
初期化したらエラーは消えました。
きっとまたボタン押すことなど忘れます。自動でInitialize Flowが動くようにInjectノードに設定をいたしました。気づいてよかった。