Node-RED MQTTブローカー経由でNefryBT+フルカラーテープLEDを動かすメモ

NefryBTでフルカラーテープLEDを動かすことができたので、Node-RED MQTTブローカー経由でNefryBT+フルカラーテープLEDを動かしたメモです。

今回の仕組み

image

ノートPCインストールされたNode-REDにMQTTブローカーノードを立てて中継し、NefryBTとフルカラーテープLEDを動かす仕組みです。

image

さらに、タブレットからノートPCのIPで表示したNode-REDを閲覧して直接操作します。

Node-REDのフローの準備

image

Node-REDのフローはMQTTブローカーで中継の仕組みを作る部分の上部と、MQTT パブリッシュを行ってノートPC側からNefryBT側に通信する下部に分かれます。

MQTTブローカー

MQTTブローカーは、Node-REDが中継してPepperとMilkcocoa(NefryV2)が連携したときのMQTTブローカー実装を参考に設定します。

image

MQTTブローカーノード( node-red-contrib-mqtt-broker )をインストールして、debugノードをつなげます。

image

image

MQTTブローカーノードのプロパティは、一回開いて完了ボタンを押して設定します。

MQTT パブリッシュ

つづいて、MQTT パブリッシュの設定です。

image

injectノードから点灯状態を伝えるJSONデータ

{"led":1} 

or

{"led":0} 

を送り、MQTT outノードを使って、NefryBTが接続されているトピックへデータを送る流れになっています。

injectノード

image

injectノードの設定です。

image

MQTT outノード

image

MQTT outノードの設定です。

image

トピックは、後述するNefry BT内のArduinoでしているトピックと合わせます。サーバーはNode-REDと同一の場所なので、127.0.01:1883に指定します。

Node-REDフロー

今回のNode-REDのフローデータを置いておきます。

[
    {
        "id": "a85796d5.f13b78",
        "type": "mosca in",
        "z": "ab3a5f76.c7464",
        "mqtt_port": 1883,
        "mqtt_ws_port": 8080,
        "name": "",
        "username": "",
        "password": "",
        "dburl": "",
        "x": 131,
        "y": 720,
        "wires": [
            [
                "c71bac71.51431"
            ]
        ]
    },
    {
        "id": "d37d0f9a.14b3c",
        "type": "comment",
        "z": "ab3a5f76.c7464",
        "name": "MQTTブローカー",
        "info": "",
        "x": 121,
        "y": 680,
        "wires": []
    },
    {
        "id": "c71bac71.51431",
        "type": "debug",
        "z": "ab3a5f76.c7464",
        "name": "",
        "active": false,
        "console": "false",
        "complete": "payload",
        "x": 373,
        "y": 719,
        "wires": []
    },
    {
        "id": "a670d5df.1f7978",
        "type": "mqtt out",
        "z": "ab3a5f76.c7464",
        "name": "/sub/NefryBT/SAMPLE",
        "topic": "/sub/NefryBT/SAMPLE",
        "qos": "",
        "retain": "",
        "broker": "32a2c535.945fea",
        "x": 374,
        "y": 817,
        "wires": []
    },
    {
        "id": "a3322e0f.8fc5e",
        "type": "inject",
        "z": "ab3a5f76.c7464",
        "name": "",
        "topic": "",
        "payload": "{\"led\":1}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "x": 116,
        "y": 792,
        "wires": [
            [
                "a670d5df.1f7978"
            ]
        ]
    },
    {
        "id": "cd0132a3.b849",
        "type": "inject",
        "z": "ab3a5f76.c7464",
        "name": "",
        "topic": "",
        "payload": "{\"led\":0}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "x": 118,
        "y": 877,
        "wires": [
            [
                "a670d5df.1f7978"
            ]
        ]
    },
    {
        "id": "32a2c535.945fea",
        "type": "mqtt-broker",
        "z": "",
        "broker": "127.0.0.1",
        "port": "1883",
        "clientid": "",
        "usetls": false,
        "compatmode": true,
        "keepalive": "60",
        "cleansession": true,
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": ""
    }
]

NefryのArduinoソースコード

AWS IoTをNefryBTで使うメモ でMQTT通信を利用した PubSubClient でMQTTの送受信をさせて、MQTT outノードから送られてきたJSONデータは、ArduinoでJSONを扱う「ArduinoJSON」の参考にして、ArduinoJsonを利用してled = 1 or led = 0で判定できるようにしてます。

#include <Nefry.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.h>

IPAddress endpoint;
const int port = 1883;

const char *pubTopic;
const char *subTopic;
const char *deviceName;

WiFiClient httpsClient;
PubSubClient mqttClient(httpsClient);

int INPUT_PIN = A0;  // 今回センサーがつながったピン番号 A0
int OUTPUT_PIN = D2;  // 出力ピン D2

// 入力の状態記録
int sensorValueState = LOW;

// 光らせるLEDの数
#define NUMPIXELS      59  // 100cmで60個

// NeoPixel設定
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, OUTPUT_PIN, NEO_GRB + NEO_KHZ800);
 
void setup() {

  //// NefryBT設定画面まわり ////////////////////////////////////////
  
  // NefryBT
  pubTopic = "/pub/NefryBT/SAMPLE";
  subTopic = "/sub/NefryBT/SAMPLE";
  deviceName = "NefryBT_SAMPLE";  // 複数台で利用する場合は必ずかぶらないように変更する
  // IPAddress型に収納。配列っぽく入れる。
  endpoint[0] = 192;
  endpoint[1] = 168;
  endpoint[2] = 1;
  endpoint[3] = 50;

  //// 以下通常処理 ////////////////////////////////////////
  
  Serial.begin(115200);
  
  mqttClient.setServer(endpoint, port);
  mqttClient.setCallback(mqttCallback);

  pinMode(INPUT_PIN,INPUT);
  
  pixels.begin();
  
  connectMQTT();
}
 
void connectMQTT() {
    Serial.println("connectMQTT");
    Serial.println(deviceName);
    while (!mqttClient.connected()) {
      Serial.print(".");
        if (mqttClient.connect(deviceName)) {
            Serial.println("Connected.");
            int qos = 0;
            mqttClient.subscribe(subTopic, qos);
            Serial.println("Subscribed.");
        } else {
            Serial.print("Failed. Error state=");
            Serial.print(mqttClient.state());
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}
 
char pubMessage[128];
 
void mqttCallback (char* topic, byte* payload, unsigned int length) {

    String str = "";
    Serial.print("Received. topic=");
    Serial.println(topic);
    for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
        str += (char)payload[i];
    }
    Serial.print("\n");

    StaticJsonBuffer<200> jsonBuffer;
    
    JsonObject& root = jsonBuffer.parseObject(str);
  
    // パースが成功したか確認。できなきゃ終了
    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }

    const char* message = root["message"];
    int led = root["led"];

    Serial.print("led = ");
    Serial.println(led);

    if( led == 1 ){
      // 点灯
      Serial.println("led on");
      pixels.setBrightness(128);
      for(int i=0;i<NUMPIXELS;i++){
        pixels.setPixelColor(i, pixels.Color(0,255,0));
        pixels.show();
        delay(50);
      }
    } else {
      // 消灯
      Serial.println("led off");
      pixels.setBrightness(0);
      for(int i=0;i<NUMPIXELS;i++){
        pixels.setPixelColor(i, pixels.Color(0,0,0));
        pixels.show();
        delay(50);
      }
    }

    Nefry.ndelay(1000);
    
}
 
void mqttLoop() {
    if (!mqttClient.connected()) {
        connectMQTT();
    }
    mqttClient.loop();
}
 
void loop() {
  mqttLoop();

  // センサー反応ON
  int sensorValueCurrent = digitalRead(INPUT_PIN);
  if ( sensorValueCurrent != sensorValueState ) {
    if( sensorValueCurrent == HIGH ){
      Serial.println("sensor ON");
      mqttClient.publish(pubTopic, "{\"flag\":1}");
    } else {
      Serial.println("sensor OFF");
      mqttClient.publish(pubTopic, "{\"flag\":0}");
    }
  }
  // 入力の状態を次のループまで記憶
  sensorValueState = sensorValueCurrent;
}

動かしてみる

ここまで設定できたら、実際に動かしてみましょう。タブレットからノートPCのIPで表示したNode-REDを閲覧して直接操作しています。

無事操作できています!

Raspberry Pi内のバージョン情報

基本的なバージョン情報は以下に記載しております。

2017年後半のRaspberry Pi関連の設定情報をまとめておくメモ – 1ft-seabass.jp.MEMO

まとめ

ということで、NefryBTでNode-RED MQTTブローカー経由でフルカラーテープLEDを動かすことができました。今回は、単純な点灯ですが、MQTTでのデータのやり取りと、NefryBTでの点灯をうまく合わせれば、もっと細かい操作も可能ですね。

また、今回の動画はHoloLensで撮影したのですが、デモしやすいですね!

それでは、よき IoT & Node-RED Lifeを!