Arduino YUN Mini でIoT その3 MQTT(1)

センサからのデータをクラウドに

 計測したセンサ・データは、従来SDメモリのようなローカルなストレージに保管しました。センサの設置数が増えてくると、それらを集めて集計するのは大変になります。低価格な無線モジュールが使えるようになったので、データを保存するために、インターネット上にあるクラウドを利用できるようになりました。

 電子工作の実験で使えるのは無線LANのWi-Fiです。Wi-FiはTCP/IPプロトコルを実装しているので、ハードのリソースが大きくなりやすいです。

 クラウドでは、たんにデータを中継・保存するだけではなく、統計処理や設定したスレッショルドを超えたらアラートを出すなどのアプリケーションを組める環境が用意されています。数千から数万のセンサのデータを集めることができるクラウドが多いですが、多くは有料です。

MQTTとは

 日本で商用のインターネット利用が始まった1992年、使われているのはほとんどがFTPというプロトコルでした。どこかに利用価値のあるソフトウェアが置いてあるからダウンロードして利用する、という使い方です。

 1991年HTML(httpプロトコル)が発明されました。いずれも、人がコンピュータの前に座って利用していました。コンピュータとコンピュータが自動的に解読してデータのやり取りができるようにとXMLが発明されました(1998年)。

 センサ類にを扱うマイコンはメモリも少ないので、JSONというコンパクトな記述方法でデータを送受信するMQTTの利用が始まっています。利用するのはTCP/IPです。

 IoTの用途ではMQTT以外に、https、AMQPなどプロトコルも使われます。

 MQTTは三つから構成されています。

(1) データを送るパブリッシャ

(2) データを受け取り送信するMQTTブローカというサーバ(クラウド上にある)

(3) データを受け取るサブスクライバ

 三つは非同期で動作します。同じtopicによって正しくデータのやり取りができます。データはメッセージと呼ばれます。パブリッシャがデータを送ったら、すぐにサブスクライバが受信しなければならないわけではありません。

MQTTの通信を確認する環境の用意

 ラズパイには、node-REDというGUIでソフトウェアを開発ツールが入っています。この中にMQTTがすぐに利用できるノードと呼ばれるモジュールが用意されています。手軽にセットアップができます。MQTTブローカ(mosquitto)も動きます。

 ラズパイのメニューからnode-REDを起動します。

 PCのWebブラウザを起動し、URLにラズパイのIPアドレス(http://192.168.111.50:1880/)を入れると、次の画面が出ます。1880はポート番号です。画面左のノード・パレットの一番上にあるinjectノードをドラッグ&ドロップで中央のエリアに持ってきます。続いて、outputにあるmqttノードをドラッグ&ドロップし、結びます。

 mqttノードをダブルクリックして設定画面を出します。Serverの項目の右にある鉛筆のアイコンをクリックします。ラズパイのIPアドレス(192.168.111.50)を入れ、Done(update)をクリックし、Doneをクリックするとパブリッシャ側の設定は完了です。右肩のDeployをクリックします。mqttノードの下にconnectedと表示が出ます。

 画面左のノード・パレットのinputからmqttノードを、outputにあるdebugノードをドラッグ&ドロップし、結びます。

 mqttノードをダブルクリックして、Serverのところに、ラズパイのIPアドレス(http://192.168.111.50:1883/)が入っているのを確認します。

 右肩のDeployを押すと、本当によいかというアラートが出ます。Confirm deployをクリックします。サブスクライバ側ではtopicの欄が空白だとconectedになりません。サブスクライバ側のmqttノードをダブルクリックして設定画面を出し、Topic欄に「ondo」と入れます。

 パブリッシャ側のmqttノードも同じくTopicの欄に「ondo」と入れます。Deployをクリックします。二つのmqttのはどちらもconnectedになります。

 パブリッシャ側のtimestampノードの左のあるボタンをマウスでクリックします。すると、画面右のdebugエリアに数字が出ます。これは、サブスクライバ側のmqttノードがメッセージを受け取って、デバッグ情報として出力したものです。

 これで、LAN経由で、メッセージが送受信できることを確認できました。ラズパイ1台で、mqttに必要な三つの機能を実装しました。

 timestamp(inject)ノードをダブルクリックし、Payloadをstringに変更します。その欄に、「温度は20℃です。」と入力し、Doneを押します。

 Deployを押してプログラムを更新します。


 tiomestanpノードの左のボタンをクリックすると、debugエリアに「温度は20℃です。」と表示されます。

 ラズパイのMQTTブローカによってメッセージが伝わっていることが確認できました。

Arduino YUN Miniのソフトウェア

 Arduino IDEは1.6.13を使っています。メニューのファイル-スケッチの例-MQTT-ArduinoYun_MQTTClientを参考にしながら、

https://github.com/knolleary/pubsubclient/blob/master/examples/mqtt_esp8266/mqtt_esp8266.ino
  Copyright (c) 2008-2015 Nicholas O'Leary

をベースに修正しました。

 メニューのスケッチからライブラリをインクルード->ライブラリを管理でライブラリマネージャを出します。pubsubで検索し、PubSubClinetをインストールします。

 パブリッシュとサブクライブの両方が動いています。実行の様子はシリアルモニタから行います。mqttブローカはラズパイを利用しています。ラズパイのdebug欄にもYUN Miniからのメッセージが表示されるのを確認できます。

/*
Basic ESP8266 MQTT example

This sketch demonstrates the capabilities of the pubsub library in combination
with the ESP8266 board/library.

It connects to an MQTT server then:
- publishes "hello world" to the topic "outTopic" every two seconds
- subscribes to the topic "inTopic", printing out any messages
it receives. NB - it assumes the received payloads are strings not binary
- If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
else switch it off

It will reconnect to the server if the connection is lost using a blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
achieve the same result without blocking the main loop.

To install the ESP8266 board, (using Arduino 1.6.4+):
- Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
- Select your ESP8266 in "Tools -> Board"

PubSubClient ライブラリ
Copyright (c) 2008-2015 Nicholas O'Leary
*/
#include <Bridge.h>
#include <BridgeClient.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.

/*const char* mqtt_server = "broker.mqttdashboard.com";
*/
const char* mqtt_server = "192.168.111.50";
BridgeClient c;
PubSubClient client(c);

char Topic[] = "ondo";
long lastMsg = 0;
char msg[50];
char msgR[50];
int value = 0;

void setup() {
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  Bridge.begin();
  Console.begin();
// while (!Console);
// Console.println();
// Console.println(*mqtt_server + "! Start !");
}


void callback(char* topic, byte* payload, unsigned int length) {
  Console.println();
  Console.print("Message arrived [");
  Console.print(topic);
  Console.print("] ");
  for (int i = 0; i < length; i++) {
    Console.print((char)payload[i]);
  }
  Console.println();
}

void reconnect() {
  client.connect("--YUN--");
  // Loop until we're reconnected
/*
  while (!client.connected()) {
  Serial.print("Attempting MQTT connection... ");
  // Attempt to connect
  if (client.connect("ESP8266Client")) {
  Serial.println("connected");
  Console.println("re---connect");
  client.publish(Topic, " Arduino YUN Mini----reconnect");
  // ... and resubscribe
  //client.subscribe("vol001");
  } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Console.print(client.state());
    Serial.println(" try again in 5 seconds");
    Console.println(" try again in 5 seconds");
   // Wait 5 seconds before retrying
  delay(1000);
  }
}
*/
}
void loop() {
  delay(2000);
  if (Console.available() > 0) {
    Console.println("-!- ");
    if (!client.connected()) {
      reconnect();
    }
    client.loop();

    long now = millis();
    if (now - lastMsg > 100) {
        lastMsg = now;
        ++value;
        snprintf (msg, 75, "Published YUN Mini- #%ld", value);
        Console.println(msg);
        client.publish(Topic, msg);
    }
  }
  Console.print(" Received " + client.subscribe(Topic));

}

Bridgeライブラリ

 YUN Miniは、8ビット・マイコンATmega32U4とWi-Fiモジュール側にあるAR9331のLinuxシステムとが双方向で会話ができます。そのクラス・ライブラリです。

 このBridgeライブラリにはhttpサーバやメールなども扱えるたくさんのクラスを含んでいます。これらはこちらを参照ください。

 Serial.printはCOMポートにつないだとき、Console.printはWi-Fiでつないだときにシリアルモニタに文字を出します。

BridgeClientライブラリ

 イーサネットのライブラリです。いろいろなサンプルに登場するYunClientは現在BridgeClientに置き換わっています。

PubSubClient ライブラリ

 MQTTの送受信ライブラリです。MQTTではMQTTブローカと呼ばれる中継点にデータを送るのがPublisher、MQTTブローカからデータを受け取るのがSubscriberです。その両方がおこなえるライブラリです。

 MQTTブローカは、家庭内LANに存在する場合、インターネット上に存在する場合がありますが、区別なく利用できます。こちらのライブラリを利用します。

  Arduino Client for MQTT

 GitHubからダウンロードしたファイルは解凍して、Arduinoー>librariesにフォルダごと保存しました。

 MQTTのライブラリは、こちらにもあります。

MQTTブローカ

 ラズパイにはmosquittoというMQTTブローカがインストールされています。データを中継するMQTTブローカのテストには最適です。

 利用条件は調べていませんが、インターネットにある次のサイトのMQTTブローカが使えるようです。

iot.eclipse.org

broker.hivemq.com

実験開始!

 Arduino IDE 1.6.13にはYUN-Miniボードは存在しないので、コンパチブルのYUNを選択します。ポートは、192.168.111.108が見えているのでこれを選択します。

 コンパイルしてアップロードし、シリアルモニタを開きます。何も起こらないので、送信ボタンをクリックすると表示が始まります。

 Arduinoのスケッチは、ラズパイのMQTTブローカに「Published YUN Mini-xxxx」というメッセージをパブリッシュします。同時にMQTTブローカからサブクライブします。サブクライブするとき、topicが同じメッセージを受信します。ラズパイからのメッセージが文字化けしています。

 ラズパイのほうでパブリッシュとサブクライブしている様子です。

 PCのWebブラウザChromeにはMQTTLensという拡張機能を追加できます。ラズパイで動いているMQTTブローカに接続してメッセージを見ている様子です。

コラム 屋外で利用する

 日本のどこでもつながるのが3G、LTEなどの携帯電話の通信です。電子工作でも利用できるモジュールがありますが、3万円前後と高価です。MQTTを使うような用途では送信するデータ量は1回あたり数十バイトです。そういう通信に特化した契約があります。日本では実験が始まったところです。また、1台だけ契約できるようなサービスは少ないです。

  • さくらのIoT Platform
  • SORACOM