この記事は obniz Advent Calendar 2020 11日目の記事です。
Node-RED obniz ノードの起動時の処理はノード内の初期化処理に書いたほうが良いというメモです。
気づいた流れ
このようなフローがありまして I2C のデバイスを連携しています。inject ノードで起動後 1 秒待って、接続後に該当する処理を実行するようにしています。
これが、ローカルの Node-RED だとうまく動くものの、なぜか enebular や IBM Cloud で動かすときに、このように "TypeError: Cannot read property 'clear' of undefined"
や "Error: i2c0 is not started"
といったエラーが出るようになっていました。
[{"id":"4125079.4431ff8","type":"inject","z":"12059dc8.9fee32","name":"起動時","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":"1","x":380,"y":120,"wires":[["9b489c5f.6a5c2"]]},{"id":"9b489c5f.6a5c2","type":"obniz-function","z":"12059dc8.9fee32","obniz":"b0d84422.4c91f8","name":"obniz 準備","code":"obniz.display.clear();\r\nobniz.display.print(\"Hello World\");\r\n\r\n// 黒:0番\r\nobniz.io0.output(false)\r\n// 赤:1番\r\nobniz.io1.output(true)\r\n\r\nobniz.i2c0.onerror = function(err) {\r\nconsole.error(err)\r\n}\r\n\r\n// 接続が整うまでに待ち時間が必要\r\nawait obniz.wait(100);\r\n\r\n// I2C接続\r\nobniz.i2c0.start({mode:\"master\", sda:2, scl:3, clock:400000 });","x":590,"y":120,"wires":[[]]},{"id":"b0d84422.4c91f8","type":"obniz","z":"","obnizId":"0000-0000","deviceType":"obnizboard","name":"","accessToken":"","code":""}]
検証のためフロー JSON を残しておきます。
どうも、obniz の接続が、inject ノードで起動後 1 秒待っても、準備が出てきていなくて、主要な関数が呼び出せてない。obnizのオブジェクトはなさそうという感じですね。なので I2C の宣言もコケている。なるほど。
obniz ノードの起動時の処理はノード内の初期化処理に書いたほうが良い
はい。表題の通りです。起動時の処理はノード内の初期化処理に移したら解決できました。
見た目上、全く一緒ですが、中身は変わっています。
obniz ノードが変わっています。
もともとのobniz ノードでは、obniz-functionノードのコード欄で実行して inject ノードで絡めることで Node-RED の起動後のきっかけ(1秒後)に動くようになってました。
このコードを、まるっと切り取ります。obniz-function ノード側からはなくなります。このコードを obniz ノード自体の設定に移動します。
こちらの赤枠で囲われている鉛筆マークをクリックします。
obniz ノードの各デバイスの設定画面になるので初期化処理の欄にペーストしてコードを移動します。こうすることで、正常に obniz が接続された後に初期化されるのでうまく動くようになりました。obniz repeat も初期化後に動作するので期待通りの動作になりました。
この確信が得れた段階で、CambrianRobotics 木戸さんに直接質問してみたところ、
「合ってますよー!」
とのことで、今後はこの理解でいきます!
[{"id":"4125079.4431ff8","type":"inject","z":"12059dc8.9fee32","name":"起動時","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":"1","x":380,"y":120,"wires":[["9b489c5f.6a5c2"]]},{"id":"9b489c5f.6a5c2","type":"obniz-function","z":"12059dc8.9fee32","obniz":"b0d84422.4c91f8","name":"obniz 準備","code":"","x":630,"y":120,"wires":[[]]},{"id":"b0d84422.4c91f8","type":"obniz","z":"","obnizId":"0000-0000","deviceType":"obnizboard","name":"","accessToken":"","code":"obniz.display.clear();\r\nobniz.display.print(\"Hello World\");\r\n\r\n// 黒:0番\r\nobniz.io0.output(false)\r\n// 赤:1番\r\nobniz.io1.output(true)\r\n\r\nobniz.i2c0.onerror = function(err) {\r\nconsole.error(err)\r\n}\r\n\r\n// 接続が整うまでに待ち時間が必要\r\nawait obniz.wait(100);\r\n\r\n// I2C接続\r\nobniz.i2c0.start({mode:\"master\", sda:2, scl:3, clock:400000 });"}]
うまくいったフローを残しておきます!