Node-RED MCU Editionを試してみた。

# はじめに

今年(2022年)も10月7日にNode-RED Con 2022が開催されました。

https://nrcon.nodered.org/

English Trackで<A HREF="https://twitter.com/phoddie">PETER HODDIE</A>さんが「Bringing Node-RED to Microcontrollers」というタイトルでNode-RED MCU Editionを紹介されていたので、さっそく試してみました。

https://www.youtube.com/watch?v=Inf37X0_xxo&t=7542s

「すべてのデバイスをプログラマブルにする」というミッションに共感しました。

(発表スライドから抜粋)

![0-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/7971308a-aafd-454b-0e84-e9617df74bba.jpeg)

今回はM5Stack Core2(ESP32)でシンプルなNode-REDフロー(injectノードとdebugノード)を動かしてみます。

(2022年10月12日追記: M5Stack Basic、M5Stack Greyでも動きました)

# 手順

GithubのREADMEが情報源になります。

https://github.com/phoddie/node-red-mcu

PCのNode-REDはNode.js(V8 JavaScriptエンジン)で動作させますが、MCU(マイクロコントローラー)はModdable SDKのXS JavaScriptエンジンで動作させます。

(発表スライドから抜粋)
![0-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/04b56af8-107b-ad88-cd19-3e2fb9f17119.jpeg)

# 環境構築

前提条件

- Intel MacBook Pro (2017)
- macOS Big Sur (バージョン 11.7)
- Xcode (バージョン 13.1)

~~※ 実機(M5Stack Core2)で動作させるためにESP-IDFを使用する必要がありますが、M1 Macはサポートされていません。~~

(2022年10月11日追記: M1 Macでも動きました。)

- M1 MacBook Air (2020)
- macOS Monterey (バージョン 12.6)
- Xcode (バージョン 13.4.1)

エラーが出る方はApple Rosetta 2をインストールしてください。

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html

## 1. Moddable SDKをインストールする

Githubの「Moddable SDK – Getting Started」が情報源になります。

https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/Moddable%20SDK%20-%20Getting%20Started.md

### 1-1. Xcodeをインストールする

App StoreからXcodeをインストールします。

※ CommandLineToolsが正しく設定されていないと、Moddable SDKのビルドでエラーになるので、メニューから「Preferences」→「Locations」でCommand Line Toolsのプルダウンメニューから設定します。

![0-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/5086bb22-0354-9606-68fd-bce51f5bdd81.jpeg)

![0-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/44b75620-03a0-c5af-3507-309a9b6f36a4.jpeg)

### 1-2. Moddableのレポジトリをダウンロードする

ホームディレクトリにダウンロード、インストールする前提で説明します。

```bash
$ git clone https://github.com/Moddable-OpenSource/moddable
```

### 1-3. 環境変数を設定する

使用しているシェル環境によって環境変数を設定するファイルが異なります。

(bashの場合) ~/.profile

(zshの場合) ~/.zshrc

以下の設定を追加します。

```bash
export MODDABLE="/Users/ユーザー名/moddable"
export PATH="${MODDABLE}/build/bin/mac/release:$PATH"
```

※ 環境変数を有効にするため、ターミナルを閉じて新しく開きます。

### 1-4. Moddable SDKをビルドする

```bash
$ cd ${MODDABLE}/build/makefiles/mac
$ make
```

### 1-5. xsbug デバッガーツールを開く

```bash
$ open ${MODDABLE}/build/bin/mac/release/xsbug.app
```

![スクリーンショット 2022-10-09 20.03.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/74b22be5-04c1-5af1-5402-88b338420f78.png)

※ デバッガーが正常に起動されることを確認したら、閉じます。

### 1-6. サンプルプログラムを実行する

サンプルプログラム(helloworld)を実行するとシミュレータ(Moddable One)とデバッガーが起動します。

```bash
$ cd ${MODDABLE}/examples/helloworld
$ mcconfig -d -m -p mac
```

mcconfigコマンドの引数(オプション)の意味は以下のとおりです。

- -d デバッグモードでビルドを行う
- -m ビルドとデバイスへの書き込みを同時に行う
- -p ビルドのプラットフォームを指定するオプション
  - macはmacOSのModdableシミュレータ
  - 実機(M5Stack(ESP32))の場合はターゲットによって値が異なります
    - M5Stack Basic、M5Stack Greyの場合はesp32/m5stack
    - M5Stack Core2の場合はesp32/m5stack_core2
    - M5Stick-Cの場合はesp32/m5stick_c

左上のメニューからシミュレータの種類を変更できます。

![スクリーンショット 2022-10-09 20.06.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/686cd30b-a41a-5425-e14a-0c7500e22a80.png)

再生ボタンを押すとhelloworldと表示されます。

![スクリーンショット 2022-10-09 20.08.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/8d0964ff-faa6-0abe-a118-53507429f961.png)

![スクリーンショット 2022-10-09 20.09.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/948a034c-3862-5f20-f911-a478323eb74d.png)

別のサンプルも試してみます。

```bash
$ cd ${MODDABLE}/examples/piu/balls
$ mcconfig -d -m -p mac
```

![スクリーンショット 2022-10-09 20.23.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ce64fd46-a10b-ce52-0cc6-9222ed561c61.png)

# 実機(M5Stack Core2、M5Stack Basic、M5Stack Grey)で動作させる

M5Stack(ESP32)で動作させるために、ESP32用のビルド環境を構築します。

## 2. ESP-IDFをインストールする

Githubの「Using the Moddable SDK with ESP32」が情報源になります。

https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/devices/esp32.md

### 2-1. ESP-IDFのレポジトリをダウンロードする

ホームディレクトリにダウンロード、インストールする前提で説明します。

```bash
$ mkdir esp32 && cd esp32
$ git clone --recursive https://github.com/espressif/esp-idf.git
$ cd esp-idf
$ git checkout v4.4.3
$ git submodule update --init --recursive
```

### 2-2. HomebrewでESP-IDFの実行に必要なツールをインストールする

```bash
$ brew update
$ brew install python cmake ninja
```

既にインストールされている場合はアップデートします。

```bash
$ brew upgrade python cmake ninja
```

### 2-3. 環境変数を設定する

使用しているシェル環境によって環境変数を設定するファイルが異なります。

(bashの場合) ~/.profile

(zshの場合) ~/.zshrc

以下の設定を追加します。

```bash
export IDF_PATH=$HOME/esp32/esp-idf
```

※ 環境変数を有効にするため、ターミナルを閉じて新しく開きます。

### 2-4. ESP-IDFをビルド、インストールする

```bash
$ cd $IDF_PATH
$ ./install.sh
```

### 2-5. ESP-IDFのビルド環境を設定する

```bash
$ source $IDF_PATH/export.sh
```

ターミナルを開く度に毎回実行するのが面倒な場合はシェルの初期化ファイル(~/.profile、または、~/.zshrc)に追加します。
手順2-3.で設定した環境変数(IDF_PATH)の後ろに追加します。

```
export IDF_PATH=$HOME/esp32/esp-idf
source $IDF_PATH/export.sh
```

### 2-6. M5Stackを接続し、シリアルポート番号を確認する

M5Stackを接続する前と後で以下のコマンドを実行して、M5Stackが認識されたシリアルポート番号を確認します。

```bash
$ ls /dev/cu.*
```

私の場合は
/dev/cu.usbserial-01F05577
として認識されました。

認識されたシリアルポート番号を環境変数(UPLOAD_PORT)に設定します。

```bash
$ export UPLOAD_PORT=/dev/cu.usbserial-01F05577
```

mcconfigコマンドを実行する時に指定することもできます。

(実行例: M5Stack Core2の場合)

```bash
$ UPLOAD_PORT=/dev/cu.usbserial-01F05577 mcconfig -d -m -p esp32/m5stack_core2
```

(実行例: M5Stack Basic、M5Stack Greyの場合)

```bash
$ UPLOAD_PORT=/dev/cu.usbserial-015F99BB mcconfig -d -m -p esp32/m5stack
```

### 2-7. サンプルプログラムを実行する

ボールのサンプルプログラムをM5Stack用にビルドし、実機へ書き込みます。

(実行例: M5Stack Core2の場合)

```bash
$ cd ${MODDABLE}/examples/piu/balls
$ UPLOAD_PORT=/dev/cu.usbserial-01F05577 mcconfig -d -m -p esp32/m5stack_core2
```

(実行例: M5Stack Basic、M5Stack Greyの場合)

```bash
$ cd ${MODDABLE}/examples/piu/balls
$ UPLOAD_PORT=/dev/cu.usbserial-015F99BB mcconfig -d -m -p esp32/m5stack
```

![FemDLI7acAEwW7j.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/75280130-c8fd-1c0d-9dd3-57e86b0d141e.jpeg)

![IMG_2215.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ca450ff0-9a22-a2a4-3fb4-6edd84ab07a9.jpeg)

![2-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/eaad0db7-83d6-b61b-ccdc-bab6bd82b6bd.jpeg)

# Node-REDフローをM5Stackで実行する

ようやく環境準備が整いました。
Node-REDフローをMCU(マイクロコントローラー)で動かす分かりやすいイメージはこちらです。

![959aa87a7f5284fb88f8673753b17c29f0cfd723.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/17b8de3b-fcf9-b2c9-4164-9c278f320007.png)

(引用元)

https://discourse.nodered.org/t/node-red-flows-on-esp8266-and-esp32/64345/7

Node-RED MCU Editionとは、Node-REDフローエディタからJSON形式でエクスポートされたフローを、Moddable SDKのXS JavaScriptエンジンで動作する形式へ変換します。

https://github.com/phoddie/node-red-mcu

Node-REDフローエディタ上でMCU用にビルド、実機へ書き込めるツール(node-red-mcu-plugin)がリリースされていますので、こちらを利用する方が楽でした。

https://github.com/ralphwetzel/node-red-mcu-plugin

まずは仕組みを理解するために、手動で変換、ビルド、書き込みを行います。

## 3. Node-RED MCU Editionを使用する

### 3-1. Node-RED MCU Editionのレポジトリをダウンロードする

```bash
$ git clone https://github.com/phoddie/node-red-mcu
```

### 3-2. Node-REDフローをJSON形式でエクスポートする

injectノードとdebugノードを接続し、injectノードは繰り返し動作に設定します。

![3-2-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/e3264c34-b67c-1854-1144-33f10710a6c9.jpeg)

![3-2-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d07644db-d85f-572b-f052-f87e376ab8d8.jpeg)

右上のメニューから「書き出し」を選択します。

![3-2-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/6c1766a2-f6dd-1c2b-ca43-3c13417543fe.jpeg)

「JSON」タブを選択します。

![3-2-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/26bc9f55-0835-1674-a190-1547d01c75e4.jpeg)

「書き出し」を選択します。

![3-2-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/cbcc3c96-c97b-ed07-c3c9-5c8486b3a6a1.jpeg)

クリップボードにNode-REDフローがJSON形式でコピーされます。

![3-2-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/411de1c5-e136-22e5-8c7b-5752e688b485.jpeg)

### 3-3. Node-REDフロー(JSON形式)をflows.jsonファイルに保存する

node-red-mcu ディレクトリに空のflows.jsonファイルがあるので、クリップボードにコピーしたNode-REDフローを書き込みます。(viコマンドでflows.jsonファイルを編集する例)

```bash
$ cd node-red-mcu
$ vi flows.json
```

(変更前)

```json:flows.json
[
]
```

(変更後)

```json:flows.json
[
    {
        "id": "8e0e0125ce64fc32",
        "type": "tab",
        "label": "フロー 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "b26f7a4723afecfe",
        "type": "inject",
        "z": "8e0e0125ce64fc32",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 230,
        "y": 140,
        "wires": [
            [
                "d6cb10fdeae23781"
            ]
        ]
    },
    {
        "id": "d6cb10fdeae23781",
        "type": "debug",
        "z": "8e0e0125ce64fc32",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 480,
        "y": 180,
        "wires": []
    }
]
```

### 3-4. Node-REDフローをMCUで実行する

(シミュレータで動かす場合)

```bash
$ mcconfig -d -m -p mac
```

![3-4-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/a670c8f7-69e4-ba96-91e5-32529790fb14.jpeg)

![3-4-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c23d8006-652d-d0e6-dafc-8479d039c9de.jpeg)

(実機(M5Stack Core2)で動かす場合)

```bash
$ UPLOAD_PORT=/dev/cu.usbserial-01F05577 mcconfig -d -m -p esp32/m5stack_core2
```

(実機(M5Stack Basic、M5Stack Grey)で動かす場合)

```bash
$ UPLOAD_PORT=/dev/cu.usbserial-015F99BB mcconfig -d -m -p esp32/m5stack
```

![3-4-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/5952b219-aa84-801a-0af3-900660367653.jpeg)

![3-4-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/0aff3967-39f3-cfd0-06b6-81323bee2b9d.jpeg)

## 4. node-red-mcu-pluginを使用する

既存のNode-REDの実行環境を壊さないために、Node-RED MCU Edition用の環境を作成する前提で手順を書きます。

(前提条件)

- Node.js (v16.14.0)

### 4-1. Node-REDをインストールする

```bash
$ mkdir node-red-mcu && cd node-red-mcu
$ npm init -y
$ npm install node-red
```

### 4-2. node-red-mcu-pluginをインストールする

```bash
$ npm install https://github.com/ralphwetzel/node-red-mcu-plugin
```

### 4-3. Node-REDを起動する

```bash
$ node node_modules/node-red/red.js -u ./
```

Node-RED起動時に以下のエラーが出力されます。

```bash
*** Error while loading node-red-mcu-plugin:
Failed to calculate correct patch path.
Please raise an issue @ our GitHub repository, stating the following information:
> require.main.path: /Users/kitazaki/node-red-mcu/node_modules/node-red
> utils.js: /Users/kitazaki/node-red-mcu/node_modules/node-red/node_modules/@node-red/registry/lib/util.js
```

node-red-mcu-pluginがパッチを適用するutils.jsが存在しないためにエラーが出力されているようです。
node_modules/node-redディレクトリで必要なモジュールをインストールします。

```bash
$ cd node_modules/node-red
$ npm install
```

もう一度、Node-REDを起動します。

```bash
$ cd ../..
$ node node_modules/node-red/red.js -u ./
```

サイドパネルに「MCU」タブが追加されます。

![4-3-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/76fa8cd9-d1cb-a726-5b11-0032afe332f8.jpeg)

### 4-4. 「MCU」タブの設定をする

いつもの通り、Node-REDフローを作成します。

![4-4-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d4208516-64fb-131b-72c1-859c46dc1073.jpeg)

「MCU」タブの「Flows to build for MCU」でチェックボックスにチェックを入れます。

![4-4-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/67b04877-4cc1-b07a-f4fb-e01a3133d87e.jpeg)

「MCU」タブの「MCU Build Configurations」で「Add config」を押します。

![4-4-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1fe5d208-b60f-18c5-3125-648a6d88be7b.jpeg)

「Add config」を2回押して、シミュレータ用と実機(M5Stack)用の設定を追加します。
実機(M5Stack Core2)用の設定についてはプルダウンメニューから「ESP32|Espressif」「esp32/m5stack_core2」を選択します。
実機(M5Stack Basic、M5Stack Grey)用の設定についてはプルダウンメニューから「ESP32|Espressif」「esp32/m5stack」を選択します。
シリアルポート番号は手順2-6.で認識された値を入力します。

![4-4-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/03986cfa-8faf-c45a-fe85-cd01512ff246.jpeg)

「Build」を押すとNode-REDフローが実行されます。
「Console Monitor」タブを押すと、ターミナル画面でビルド実行の様子を確認できます。
実機(M5Stack)の場合はビルド完了後、書き込みまで行われます。

![4-4-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ba3ae45c-0d2e-f65f-361b-6ece7d37c4ab.jpeg)

![4-4-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/7d0f255c-6e85-7935-e532-f86abdff1473.jpeg)

![4-4-6-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/0dbfa684-d638-c790-4362-86d002e3f091.jpeg)

デバッガー(xsbug)が起動し、Node-REDフローの動作を確認できます。

![4-4-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ebb1c682-80af-2f33-1bdf-5414c25993d2.jpeg)

![4-4-8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/88606a36-d1b6-f7a8-4450-ff7477dec60c.jpeg)

# さいごに

今回のNode-RED Con 2022で私は「Node-RED実行環境をいろいろ試してみた」というタイトルで登壇させていただきましたが、MCU(マイクロコントローラー)の実行環境が加わり、今後の進展が楽しみです！

![スクリーンショット 2022-10-09 23.14.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/a745428a-76ea-2780-3b31-413005ad8e22.png)

https://www.slideshare.net/kitazaki/20221007noderedcon2022kitazakiv1pdf