Raspberry Pi にNode-RED MCU開発環境をシェルスクリプトでセットアップする（２）

### はじめに
以前にもシェルスクリプトを使ったセットアップの記事を作成しましたが、これは同様の作業を別パターンでおこなうものです。

https://qiita.com/mshioji/items/4084bd5fa66a99800e71

前回記事との違い
* システム起動時にNode-REDをdaemonで自動起動するようにしました。そのため、今回はNode-REDのインストールにnvmを使用していません。自動起動しなくても良いからバージョン管理にnvmを使いたい、という場合は前回記事をご覧ください。
* Moddable SDKとESP-IDFのインストールにxs-devを使用しています。
前回はgithub moddableの手順に沿っていましたが、スクリプト内でESP-IDFインストール時にバージョン指定がありました。xs-devを使ってインストールすることでModdable SDKもESP-IDFも自動的にリリース版がインストールされます。SDK単体での利用にも便利です。
* スクリプトを２つに分離しました。
Moddable SDK, ESP-IDFをインストールするスクリプトと、Node-REDをインストールしてNode-RED MCUプラグインや関連ノードをインストールするスクリプトを分けました。必要に応じて使い分けができるかと思います。

### 内容
Node-REDのフローエディタで作成したフローをESP32のような小さなマイコン(MCU)で実行できるようにするNode-RED MCUはIoTデバイスを開発するのにとても便利なのですが、実は開発環境を用意するのにステップが多くあります。

対応する環境は限定的ですが、子供たちにフロープログラミングを試してもらう機会を増やしたいなとRaspberry Piに簡単に環境を構築するシェルスクリプトを試作して使ってみた内容として紹介します。

新しいマイクロSDカードを用意して、手持ちのRaspberry Pi 4Bでやってみようかな？という方がおられたらお試しください。

:::note alert
重要なデータが入った環境には使用しないでください。
:::

それほど使い込んでいませんので、まだ不十分な点もあるかと思います。マイクロSDカードに新たにOSを書き込んだ状態で、不具合があっても消去してやり直せる環境などリスク覚悟でお願いします。改善点等あればコメント頂けると嬉しいです。

### 動作環境
Hardware : Raspberry Pi 4B　 (Pi 5は未テストです）
Operating System : Raspberry Pi OS Bookworm, Bullseye 64bit 
Target Device(MCU) : ESP32 series

### インストールステップについて
通常、マイクロSDカードにRaspberry Pi OSを書き込んだだけの状態からセットアップするには次の手順があります。これをシェルスクリプトで簡単にできるようにするのが目標です。

1. NodeJS,NPM インストール
2. xs-dev インストール
3. moddable SDK インストール
4. ESP-IDF インストール
5. Node-RED インストール
6. Node-RED settings.js の編集
7. Node-RED MCU Plugin インストール
8. MCU Nodes インストール
9. Additional Nodes インストール
10. Node-REDの自動起動を設定

* nodejsのバージョンは22をセットしています。別のバージョンにしたい場合はシェルスクリプトの内容を修正して実行してください。

* Node-REDのフローエディタのadmin authを念のため自動設定します。独自のuser/passで入りたい方はシェルスクリプトの内容を修正して実行してください。そのまま実行した場合の初期値は admin / noderedmcu です。ここに書くのもどうかな？ですが、何も設定しないよりは良いかなと思います。

### 準備
 Raspberry Piに新しいOSのはいったSDカードをセットし、起動します。インストールはネットワークからダウンロードしながら行うため、WiFiアクセスポイントに接続するなど、ネットワークが使える状態にしてください。

 ・後に説明する手順でホームディレクトリ（でも、どこでも）に次の２つのシェルスクリプトを作成して実行できるようにします。
 1. moddable-espidf_install.sh
    xs-devを使用してModdable SDKとESP32用のESP-IDFをセットアップします。 
 2. nodered-nrmcu_install.sh
    Node-REDをインストールし、Node-RED MCU pluginと関連ノードのセットアップをおこない、起動時にNode-REDが自動起動するように設定します。

#### 1. moddable-espidf_install.sh の作成
 
 　ホーム直下にmoddable-espidf_install.sh として作成する場合は次のようにします。
```
$ nano ~/moddable-espidf_install.sh
```
エディタが開きますので、次の内容をコピーしてペーストします。
```bash:moddable-espidf_install.sh
#!/bin/bash

echo "### Installing Node.js and npm..."
if command -v node &> /dev/null && command -v npm &> /dev/null; then
    echo "### Node.js and npm are already installed. Skipping installation."
else
    echo "### Installing Node.js..."
    curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
    sudo apt install nodejs -y
fi
echo "### Node.js version:"
node -v
echo "### npm version:"
npm -v

# install xs-dev
echo '### Installing xs-dev...'
sudo npm -g i xs-dev

# installing moddable SDK
echo '### Installing Moddable SDK...'
xs-dev setup

# installing ESP-IDF
echo '### Installing ESP-IDF...'
xs-dev setup --device esp32

echo '### finished.'
```
ペーストしたら、ctrl-oで保存して、ctrl-xで終了します。

#### 2. nodered-nrmcu_install.sh の作成
 
 　ホーム直下にnodered-nrmcu_install.sh として作成する場合は次のようにします。
```
$ nano ~/nodered-nrmcu_install.sh
```
エディタが開きますので、次の内容をコピーしてペーストします。
```bash:nodered-nrmcu_install.sh
#!/bin/bash

echo "### Installing Node.js and npm..."
if command -v node &> /dev/null && command -v npm &> /dev/null; then
    echo "### Node.js and npm are already installed. Skipping installation."
else
    echo "### Installing Node.js..."
    curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
    sudo apt install nodejs -y
fi
echo "### Node.js version:"
node -v
echo "### npm version:"
npm -v

# install node-red, Node-red-mcu

echo "Installing Node-RED..."
sudo npm install -g --unsafe-perm node-red

# creating Node-RED Unit file
echo "### Creating Node-RED systemd service file..."
NODE_RED_USER=$(whoami)
NODE_RED_GROUP=$(id -gn)
NODE_RED_HOME=$HOME

cat <<EOF | sudo tee /lib/systemd/system/nodered.service > /dev/null
# systemd service file to start Node-RED

[Unit]
Description=Node-RED graphical event wiring tool
Wants=network.target
Documentation=http://nodered.org/docs/hardware/raspberrypi.html

[Service]
Type=simple
# Run as the current user
User=$NODE_RED_USER
Group=$NODE_RED_GROUP
WorkingDirectory=$NODE_RED_HOME

Environment="NODE_OPTIONS=--max_old_space_size=2048"
# define an optional environment file in Node-RED's user directory to set custom variables externally
EnvironmentFile=-$NODE_RED_HOME/.node-red/environment
# uncomment and edit next line if you need an http proxy
#Environment="HTTP_PROXY=my.httpproxy.server.address"
# uncomment the next line for a more verbose log output
#Environment="NODE_RED_OPTIONS=-v"
# uncomment next line if you need to wait for time sync before starting
#ExecStartPre=/bin/bash -c '/bin/journalctl -b -u systemd-timesyncd | /bin/grep -q "systemd-timesyncd.* Synchronized to time server"'

ExecStart=/usr/bin/env node-red-pi \$NODE_OPTIONS -- \$NODE_RED_OPTIONS
#ExecStart=/usr/bin/env node \$NODE_OPTIONS red.js -- \$NODE_RED_OPTIONS
# Use SIGINT to stop
KillSignal=SIGINT
# Auto restart on crash
Restart=on-failure
RestartSec=20
# Tag things in the log
SyslogIdentifier=Node-RED
#StandardOutput=syslog

[Install]
WantedBy=multi-user.target
EOF

sudo chmod 644 /lib/systemd/system/nodered.service

# Node-RED user directory
USER_DIR="$HOME/.node-red"
if [ ! -d "$USER_DIR" ]; then
    echo "Creating Node-RED user directory at $USER_DIR..."
    mkdir -p "$USER_DIR"
fi

# log setting
LOG_FILE="$USER_DIR/node-red.log"

# first run Node-RED to create settings.js
echo "Starting Node-RED to generate settings.js..."
node-red --userDir $USER_DIR --safe > "$LOG_FILE" 2>&1 &
NODE_RED_PID=$!
sleep 5

# stop Node-RED
echo "Stopping Node-RED after settings.js generation..."
kill $NODE_RED_PID 2>/dev/null || true

# modify settings.js
SETTINGS_FILE="$USER_DIR/settings.js"
if [ -f "$SETTINGS_FILE" ]; then
    echo "Modifying settings.js..."

    # add process.env.MODDABLE
    if ! grep -q "process.env.MODDABLE" "$SETTINGS_FILE"; then
        echo "process.env.MODDABLE = '$HOME/.local/share/moddable';" >> "$SETTINGS_FILE"
        echo "Added process.env.MODDABLE setting."
    else
        echo "process.env.MODDABLE setting already exists. Skipping."
    fi

    # add adminAuth setting
    if grep -qE "^\s*adminAuth:" "$SETTINGS_FILE"; then
        echo "adminAuth setting is already enabled. Skipping."
    else
        sed -i '/module.exports = {/a \  adminAuth: { type: "credentials", users: [{ username: "admin", password: "$2y$08$g4OQQdpKaDVV6q.xUFIx.u0RZtOeENgGEJfLu9D5XvBWO.RkI4gg6", permissions: "*" }] },' "$SETTINGS_FILE"
        echo "Added new adminAuth setting."
    fi
else
    echo "Error: settings.js not found in $USER_DIR. Exiting."
    exit 1
fi


# install plugin and additional nodes
echo "### Installing plugin and additional nodes..."
cd "$USER_DIR"

echo " ## Installing node-red-mcu-plugin..."
npm i @ralphwetzel/node-red-mcu-plugin

echo " ## Installing mcu nodes..."
npm i @moddable-node-red/mcu

echo " ## Installing node-red-dashboard..."
npm i node-red-dashboard

#echo " ## Installing node-red-node-pi-gpio..."
#npm i node-red-node-pi-gpio

#echo " ## Installing node-red-contrib-ui-led..."
#npm i node-red-contrib-ui-led

#echo " ## Installing node-red-contrib-moment..."
#npm i node-red-contrib-moment

#echo " ## Installing node-red-contrib-aedes..."
#npm i node-red-contrib-aedes

# enable Node-RED service
echo "### enabling Node-RED..."
sudo systemctl daemon-reload
sudo systemctl enable nodered.service
sudo systemctl start nodered.service

echo '### finished.'
```

ペーストしたら、ctrl-oで保存して、ctrl-xで終了します。
* スクリプトの最後の方にいくつか無効化してある追加ノードのインストールがあります。Node-RED MCUと共に使うのに便利なノードですので、必要に応じて先頭の"#"を取ってスクリプトを保存してください。

#### シェルスクリプトの実行
指定した場所にファイルはできましたが、このままではシェルスクリプトとして実行できないので、２つのファイルに実行権限を付与します。
```
$ sudo chmod +x ~/moddable-espidf_install.sh nodered-nrmcu_install.sh 
```
これでシェルスクリプトとして実行可能となりました。
それでは実際に実行しましょう！
```
$ ./moddable-espidf_install.sh
```
ひとつ目のインストールが完了したらふたつ目を実行します。
```
$ ./nodered-nrmcu_install.sh
```

:::note info
たくさんインストールするので、かなり時間がかかります。こちらで試したときは40分程度かかりました。
:::

ネットワークの速度にもよりますが、時間に余裕があるときに、ゆったりお待ちください。

### セットアップが完了したら... 
Node-REDが自動で起動しているはずです。
ブラウザを立ち上げて、アドレスバーに下記を入力します。
```
localhost:1880
```
Node-RED フローエディタのログイン画面が表示されますので、先に設定したuser/passでログインしてください。

Node-RED MCUのプラグインも有効になっているはずです。

それでは、Node-REDのフロープログラミングを使ったIoTデバイス開発を楽しみましょう！