Noodl × Node-RED × obnizを連携する

# 概要
　タイトルの通りNoodl、Node-RED、obnizの連携方法を解説します。
2019年9月27日のNode-RED UG勉強会 Vol.9にてライブコーディングを行った内容です。
[動画はこちら](https://www.youtube.com/watch?v=LalEr9vYhH4&t=3670s)

こんなデモを作りました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ハンズオンでデモが動かなかった場合のために動画撮っておきました！<br>急拵えなので、見た目は凝ってません<br>m(_ _)m<a href="https://twitter.com/hashtag/Noodl?src=hash&amp;ref_src=twsrc%5Etfw">#Noodl</a> <a href="https://twitter.com/hashtag/obniz?src=hash&amp;ref_src=twsrc%5Etfw">#obniz</a> <a href="https://t.co/Zxu2DGLt5a">pic.twitter.com/Zxu2DGLt5a</a></p>&mdash; まえぷー@Noodlもくもく会発足！ (@kmaepu) <a href="https://twitter.com/kmaepu/status/1176645371348439040?ref_src=twsrc%5Etfw">September 24, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

名称が公式サイトへのリンクになっているので、詳細はそちらをご参照ください。

[Noodl](https://tensorx.co.jp/noodl-jp/)　→　UI/UXプロトタイピングツール
[Node-RED](https://nodered.jp/)　→　フローベースビジュアルプログラミングツール
[obniz](https://obniz.io/ja/)　→　IoTデバイス

# 構成

本記事で作る構成は次のようになっています。
（MQTTブローカは[こちら](https://qiita.com/kmaepu/items/644b0bf2c3f438e71aa6)）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7b22ab90-9494-abe2-9bd3-8eec8ca470a2.png)


１．Noodlのボタンをプッシュ（MQTTパブリッシュ）
２．Node-REDで中間処理（Webhookを送信）
３．obnizでサーボモータ制御

## Noodl
NoodlのUI作成手順は次の通りです。
　1. 画像を背景にする
　2. ON/OFFボタンを作る
　3. Node-REDにコマンド送信

今回は次のようなUIを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/01e7f694-86cf-b25e-9740-674527eadfc7.png)

使用しているNoodlバージョンは、Ver1.3.1です。
 
### Noodl-1. 画像を背景にする
　Noodlで新規プロジェクトを作成すると、次のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/a04a387c-5c66-cfaa-70cf-6801cbe42d0e.png)

背景に画像を使うために、**imageノード**を追加します。
**Rectangleノード**は使用しないので削除します。
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/870f4fd6-4d35-4891-0a34-b4454e8970e7.png)

背景にしたい画像を取り込みます。
画像ファイルをNoodlのプロジェクト画面にドラッグ&ドロップで完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7774b487-eca9-a85f-2a1f-7bf128dfa08f.png)

imageノードのプロパティ**Image path**を開くと、先ほど追加した画像選択できるようようになっています。
この画像を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/4592c796-f5b2-fa37-3d68-78af6f180b5a.png)

### Noodl-2. 画像が見切れているので画面にフィットさせる
imageノードのプロパティを次のように設定します。
（画像が小さい場合も同様です。）

・ Size Mode ： Explicit
・ Fill Mode ： Aspect Fill

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/d3977772-7c6a-70ff-1c80-c25cb24a150c.png)

### Noodl-3. テキストを画面上部に移動
textノードのプロパティを次のように設定します。

・ Align Y ： Top
・ Text ： Hello Noodl（何でもいいです）
・ Color ： 視認しやすい色

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/636ca1ef-ab59-5579-20c2-5d20d4c0e06c.png)

### Noodl-4. ボタンを作る
サーボモータ制御のきっかけとなる、押しボタンを作成します。
↓のように**Groupノード**、**Circleノード**、**Textノード**を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/0fad8991-bda6-c8f0-ec9e-ad45099d239b.png)

追加した各ノードのプロパティを次のように設定します。

・**Groupノード**
- Size Mode ： Content Size
 - Align X ： Center
 - Align Y ： Center

・**Circleノード**
 - Size ： 400 px
 - Align X ： Center
 - Align Y ： Center

・**Textノード**
 - Align X ： Center
 - Align Y ： Center
 - Text ： OFF
 - Font Size ： 180

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/83bf139f-1268-b961-3940-b666584d3982.png)

### Noodl-5. ボタンを押すと文字を変える
ボタンを押したら、ボタンの文字を”ON”と”OFF”に切り替えます。
このON/OFF状態の切り替えには、**Statesノード**を利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/868021df-e7f3-48e9-42fc-96e360c5ad1c.png)
statesノードのプロパティを設定します。
プロパティ StatesにON状態とOFF状態を追加します。
プロパティ ValuesにColorとangleを追加します。
このValuesは状態が持つプロパティです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/c473535f-07fa-e7fd-70e8-c92b55789989.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/a819fa27-02e0-e708-88f3-eb512d142823.png)


次に、GroupノードとTextノード、Statesノードを次のように接続します。
この状態で、プレビュー画面のON/OFFボタンを押すと、ボタンの文字が切り替わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/3d5ebf2b-0b87-12d9-ba05-e2a4a29d0b35.png)

### Noodl-6. ボタンの色を状態ごとに変える
色の制御には**Color Blend**ノードを利用します。
このノードはプロパティ**Blend Value**の値の比率で色を出力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/6450413c-d169-4ee0-0f74-17e908ddd490.png)

Color Blendノードのプロパティを次のように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/0136f1a1-5f52-1eb0-8f10-0f504f952298.png)

Color BlendノードをGroupノードとCircleノードに接続します。
これで、状態が変わるとボタンの色も変わるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/f70e2acc-ece8-8898-23cd-e32e2ea54a41.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/21bee68f-e744-e729-5ba1-4b6ef3a170b7.png)

### Noodl-7. Node-REDと連携
NoodlにはMQTT（send/recive）ノードとRESTノードが用意されています。
今回はMQTTでNode-REDと連携します。

NoodlからMQTTでパブリッシュするには、**Send Messageノード**を利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/dc76ff71-b77b-441a-2c3f-742eba7a1d61.png)

Send Messsageノードのプロパティは次のように設定します。

- Topic(MQTTの窓口) ： /moter
- Payload(送信する箱) ： text、angle 

設定後、Send MessageノードをStatesノードに接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/33e6ae8d-9ebd-eaba-1953-c2711692da07.png)

MQTTにはブローカ（サーバ）が必要なので、利用先を設定します。Noodlエディタから**Project Settings**画面を開き、MQTTの項目を次のように設定します。
今回は外部MQTTブローカにshiftrを使用しています。
shiftrの設定については[こちら](https://qiita.com/kmaepu/items/644b0bf2c3f438e71aa6)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/25d2268e-9275-8561-2f1c-5519535e54b6.png)

ボタンをON/OFFすると、状態が切り替わり、MQTTでメッセージが送信されるようになります。

## obniz
obnizはWebhookを受けてサーボモータを制御しています。
次の手順で解説します。

1. コーディング（ほぼコピペ）
2. サーバレスイベントを作成
3. サーボモータを接続

### obniz-1.コーディング
　obnizの開発者コンソールのリポジトリから、新規プロジェクトを作成します。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/6262c80f-d0ed-be4f-faea-759dc6ccf767.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/0774ec7b-fad0-47f6-9b8d-333314b7249a.png)

今回のプロジェクト名は「demo_1」とします。

コードの9割くらいはコピペです。
obnizのドキュメントにある、

・[サーバレスイベント](https://obniz.io/ja/doc/obniz_cloud/about_event)
・Javascript SDK
　[ディスプレイ](https://obniz.io/ja/doc/sdk/doc/display)
・JSパーツライブラリ
　[サーボモータ](https://www.bing.com/profile/history?form=edgehs&fsi=1)
からコピーしてきます。

新規プロジェクトのテンプレート部分は削除します。

```javascript

obniz.onconnect = async function () {
// ここから
  var led = obniz.wired("LED", { anode:2 } );
  var uart = obniz.getFreeUart();
  uart.start({tx: 4, rx: 5, baud:9600});  

  $("#send").on("click", function(){
    uart.send($("#text").val());
  });
  uart.onreceive = function(data, text) {
    $("#recv").text(text);
  }

  $('#on').click(function () {
      led.on();
  });

  $('#off').click(function () {
      led.off();
  });
// ここまでを削除
}

```

作成したコードは次の通りです。
このコードを流用する場合、obniz IDを記述してください。


```html

<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/obniz@2.3.0/obniz.js" crossorigin="anonymous"></script>
  </head>
  <body>
    <div id="obniz-debug"></div>
    <h3>Connect From Your Browser</h3>
    <script>
      // obniz IDを追記する
      var obniz = new Obniz("OBNIZ_ID_HERE"); 

      obniz.onconnect = async function () {
        // サーバレスイベントのPOST requestを拾う
        let request = {};
        if (typeof req === "object") {
          request = req;
        }
         // 拾ったrequestのbodyから、textの文字を画面表示
        obniz.display.clear();
        obniz.display.print(request.body.text);
        // サーボモータ制御
        var servo = obniz.wired("ServoMotor", {gnd:0,vcc:1,signal:2});
        servo.angle(request.body.angle); 
      }
    </script>
  </body>
</html>

```

ディスプレイ表示とサーボモータ制御に、webhookで受け取った値を使用しています。
この部分はコーディングします。

↓ディスプレイ表示のコード

```javascript

obniz.display.print(request.body.text);
```

↓サーボモータの角度指定コード

```javascript

servo.angle(request.body.angle); 
```

### obniz-2. サーバレスイベントを登録
webhookを受けとるために、サーバレスイベントを登録します。

サーバレスイベントはobnizのライセンスによって利用可否があります。
利用不可のライセンスは**Hobby Lite**のみです。（2019/10/2現在）
注意点として、obnizのライセンスによって１日にイベント発生回数が制限されています。
Basicライセンスだと、１日120イベントで最大５個のサーバレスイベントを登録できます。

obnizの開発者画面から、イベントを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/0e18c472-49a8-9bd5-f146-f1dd66fe35d0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/5adb7e07-24c6-7b93-d3a5-595c92998252.png)

サーバレスイベントは次のように設定します。

| 名前 | 実行するApp | きっかけ | 
| --- | --- | --- |
| demo_1 | demo_1.html | Webhook |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/6e5bc747-18a1-7952-08b5-380f725f874e.png)

登録が完了するとEndpointにURLが表示されます。
このURLにアクセスするとwebhookを送信してobnizが動きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/79edf563-d3da-75d4-a86a-388e69b065fb.png)

### obniz-3. サーボモータの結線
サーボモータは次のように結線します。
使用したサーボモータは[こちら](https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=3AHX-H6MX)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/dec303a7-b4c8-d6a3-82dc-6fe434f35f16.png)

## Node-RED
Node-REDでは、NoodlからMQTTで受け取ったコマンドを、webhookにしてobnizへ送信しています。

Node-REDのフロー作成は次の手順で行います。

1. MQTTサブスクライブのフロー作成
2. Webhook送信のフロー作成
3. MQTTとWebhookを接続

今回使用しているNode-REDのバージョンは、v0.20.7です。

### Node-RED-1. MQTTサブスクライブのフロー作成
MQTTサブスクライブするには、**MQTT inノード**を利用します。
debugノードを接続すると、受け取ったデータをデバッグコンソールで確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/d52558cb-5039-acfe-fb41-f950b603573a.png)
MQTT inノードの設定をします。

サーバを新規作成して、MQTTブローカのURLを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/002bc833-61c1-e1c0-f571-aef906d13547.png)

トピックはNoodlのSend Messageノードに設定と同じにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/d03b150b-76df-9609-22ea-dcf110631d14.png)

この状態でNoodlで作成したボタンを押すと、デバッグコンソールにデータが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/828b4a2d-e40c-75f1-2d18-8c54ebf549ab.png)


### Node-RED-2. Webhook送信のフロー作成
Node-REDからWebhookを送信するために**http requestノード**を使用します。
デバッグのためにイベント発生用のinjectノードを配置します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/69f7e7a9-6573-bdbd-b122-81b35846a36d.png)

各ノードの設定は次の通りです。

・ **injectノード**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/123286d1-cda3-c0a0-7875-53dc16f4604e.png)

・ **http requestノード**
oobnizサーバレスイベントのEndpoint URLを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/a75345f2-bd19-7e1e-c7e5-38032453bfec.png)

injectノードのボタンを押すと、テキストがobnizの画面に表示され、
指定した角度にサーボモータが動きます！

### Node-RED-3. MQTTとWebhookを接続
obnizサーバレスイベントで渡すデータフォーマットはJSONです。

MQTTで受け取ったデータをJSONノードで変換して、Webhookを送信します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/1459a506-8d26-5604-65ee-a3d7303c9144.png)

以上です。

## おわりに
　Noodl×Node-RED×obnizの組み合わせで、IoTプロトタイピング爆速になりますね！！