目次


Arduino Uno と IBM IoT Foundation を利用してクラウド対応の温度センサーを作成する

第 2 回 スケッチを作成して IBM IoT Foundation Quickstart に接続する

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: Arduino Uno と IBM IoT Foundation を利用してクラウド対応の温度センサーを作成する

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:Arduino Uno と IBM IoT Foundation を利用してクラウド対応の温度センサーを作成する

このシリーズの続きに乞うご期待。

この全 4 回からなるチュートリアル・シリーズの第 1 回では、配線用ボックス内の温度をモニターするためのプロジェクトの設計について説明し、Arduino Uno と Virtuabotix DHT11 温度センサーを使ってプロジェクトを構築しました。さらに、このプロジェクトの回路を組み立てて説明し、Arduino IDE のインストール手順と、プロジェクトの個々のコンポーネントをそれぞれに異なる Arduino サンプル・スケッチを使用してテストする方法を説明しました。現時点で、この IoT プロジェクトをクラウドに接続するためのスケッチの設計と、温度と湿度のデータをリモートからリアルタイムでモニターできるようにするためのステップについて、検討する準備が整いました。しかしその前に、IBM IoT Foundation との通信に使用するプロトコルについて説明しておかなければなりません。そのプロトコルとは、MQTT です。

MQTT の概要

MQTT (旧称 Message Queueing Telemetry Transport) は、Internet of Things のために設計された軽量で高速の通信プロトコルです。(元々は Andy Stanford-Clark 氏によって開発されて) IBM で誕生した MQTT は、その後、OASIS (Organization for the Advancement of Structured Information Standards) に提出されて、標準化が進められています。このプロトコル標準の最新バージョンは、3.1 です。「MQTT V3.1 プロトコル仕様」には、MQTT を「オープンで単純かつ軽量である上に実装が容易となるように設計された、ブローカー・ベースで軽量のパブリッシュ/サブスクライブ型メッセージング・プロトコル」にすることが、この仕様の目的であると書かれています。この仕様が発表されてから、「実装が容易」という部分は確実に達成されています。それは、MQTT クライアントを実装する各種のライブラリーが開発されていることから明らかです。Eclipse Paho プロジェクトのページに、これらのほぼすべてのライブラリーへのリンクが記載されています。

MQTT は、組み込み機器で使用するのに最適です。その理由としては、以下の点が挙げられます。

  • MQTT は非同期であり、複数の異なるレベルのサービス品質があること。これは、インターネット接続の信頼性が低い場合に重要です。
  • MQTT は短く簡潔なメッセージを送信するため、帯域幅が狭い状況でも重宝します。
  • MQTT はわずかなソフトウェアでクライアントを実装できるため、メモリー容量が限られた Arduino のような機器には理想的です。

IBM IoT Foundation QuickStart は、MQTT をプロトコルとして利用して入力を取るように作られています。

Arduino MQTT ライブラリーをダウンロードしてインストールする

このチュートリアルでは、Arduino センサーからのリアルタイムのデータをグラフにするために、IBM Internet of Things Foundation Quickstart に組み込まれた機能を利用します。

Arduino 用 MQTT のクライアント・ライブラリーをインストールするのは、第 1 回で説明した特定のハードウェア・デバイス用のライブラリーを見つけてインストールするのと同じく簡単です。このプロジェクトに使用する特定のライブラリーは、Arduino Client for MQTT Web サイトで見つかります。このサイトに、ライブラリーに関する説明、ドキュメントへのリンク、ライブラリーをダウンロードできる GitHub へのリンクが揃っています。

私のサンプル・プロジェクトで使用したのは、V1.9.1 クライアントです。GitHub リンクから ZIP ファイルまたは TAR ファイルをダウンロードして、このアーカイブに含まれている PubSubClient ディレクトリーを、Arduino IDE ディレクトリーの libraries サブディレクトリーに解凍してください。それが終わったら、Arduino IDE を再起動します。これで、メニューから「PubSubClient」 > 「mqtt_auth」「PubSubClient」 > 「mqtt_basic」「PubSubClient」 > 「mqtt_publish_in_callback」の各項目を選択できるようになります (図 1 を参照)。

図 1. 「PubSubClient」メニュー
「PubSubClient」メニューの項目のスクリーン・ショット
「PubSubClient」メニューの項目のスクリーン・ショット

ローカルで MQTT をテストする

このチュートリアルのシリーズでこれまで従ってきたプロセスは、新しいコンポーネントやテクノロジーをソリューションに導入し、そのコンポーネントが正常に機能していることを確認するために個別にテストするというものでした。MQTT クライアント・ソフトウェアをダウンロードしてインストールした後は、このソフトウェアについても同じプロセスを実行します。ただし、このクライアントをテストする場合は、もう 1 つ必要なソフトウェアがあります。

MQTT は、ブローカー・ベースのプロトコルです。つまり、クライアントはブローカーに接続し、ブローカーがクライアント同士の通信を仲介することを意味します。実のところ、これは単純なプロセスです。具体的には、一連のクライアントがそれぞれ関心対象とするトピックをブローカーに登録します。特定のトピックにクライアントがメッセージをパブリッシュすると、そのトピックを購読している他のクライントにブローカーがメッセージを転送するという仕組みです。

ローカルでのテストに使用するブローカーは、Mosquitto というオープンソースのコントリビューションです。Arduino をプログラミングする際に使用するローカル PC に Mosquitto をインストールすれば、Arduino がブローカーと通信可能であるかどうかをテストできるようになります。

Mosquitto

Mosquitto は、Mosquitto の Web サイトからダウンロードすることができます。Mosquitto は、Windows と Mac、そしてほとんどの種類の Linux 用に用意されています。Mosquitto をインストールするのは簡単で、Linuxの場合は新しいパッケージをインストールするだけのことです。Windows では、このシステムを Windows サービスまたは独立した実行可能プログラムのいずれかとしてインストールすることができますが、Windows を使用しているとしたら、サービスとしてインストールすることを選択するチェック・ボックスを必ずクリアしてください。Mosquitto を実行するには、コマンドラインを使用するほうが簡単だからです。そのほうが、ログに記録されたデバッグ情報を表示しやすくなります。

Mosquitto のインストールが完了したら、(任意のプラットフォームで) コマンドラインから以下のコマンドを実行して Mosquitto を起動します。

mosquitto -v

-v フラグは「verbose (詳細)」ロギングを行うためのものであり、確立されている接続と送受信されるメッセージに関する情報を確認できることを意味します。ロギングの結果は、ローカル・ブローカーへのメッセージ送信を開始するとすぐに表示されます。

サンプル・スケッチをダウンロードする

次のステップは、すべての構成要素を 1 つにまとめるサンプル・スケッチをダウンロードすることです (「ダウンロード」を参照)。メッセージは、MQTT プロトコルに従って MQTT ブローカーにパブリッシュされます (最初にローカル・ブローカー、次に IoT Foundation QuickStart の一部となっているブローカーにパブリッシュされます)。IoT Foundation QuickStart で最終的にセンサー・データを解析して表示するには、センサー・データを iot-2/evt/status/fmt/json という名前のトピックにパブリッシュする必要があります。同様に、データを特定の方法でフォーマット設定する必要もあります。IoT Foundation QuickStart のドキュメントで「Connect my device to QuickStart」のレシピを参照すると、データは以下の JSON (JavaScript Object Notation) フォーマットになっていなければならないことがわかります。

{
    "d": {
         "name1": "stringvalue",
         "name2": intvalue,
         ...
    }
}

サンプル・スケッチは単純なプログラムです。第 1 回で紹介した他の Arduino サンプルから、すべての Arduino プログラムは同じ構造をしていることがわかるはずです。Arduino プログラムには、setup()loop() という標準の関数セットの他、オプションの変数宣言、そして setup() 関数または loop() 関数のいずれかで使用するユーティリティー関数の宣言が組み込まれます。まずはコードの先頭から見ていき、プログラムをローカルでテストできるようにするために、変数宣言の一部にいくつかの変更を加えます。

サンプル・スケッチに変更を加える

あらゆる Arduino スケッチの例に漏れず、プログラムは、スケッチ内で使用するライブラリーの参照から始まります。

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <dht11.h>

ご覧のように、このスケッチはイーサネット・ライブラリーを使用してイーサネット・シールドを駆動し、DHT11 ライブラリーを使用して DHT11 からの読み取り値にアクセスします。ここまでは第 1 回で取り上げた例と同じですが、今回は初めて PubSubClient ライブラリーも使用しています。これらのライブラリーを使用するには、コードにいくつかの変更を加えて、ローカル・サーバーに対してコードをテストできるようにする必要があります。

// Update this to either the MAC address found on the sticker on your Ethernet shield (newer shields)
// or a different random hexadecimal value (change at least the last four bytes)
byte mac[]    = {0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
char macstr[] = "deedbafefeed";
// Note this next value is only used if you intend to test against a local MQTT server
byte localserver[] = {192, 168, 1, 98 };
// Update this value to an appropriate open IP on your local network
byte ip[]     = {192, 168, 1, 20 };

上記リストの先頭のコメントにあるように、最初に必要な変更は、イーサネット・シールドの MAC アドレスと一致するように mac 変数と macstr 変数を変更することです。比較的新しいイーサネット・シールドの場合、MAC アドレスは、カードに貼付されたステッカーに記載されています。古いカードを使用している場合は、16 進数の最後の 4 つの文字をランダムに変更して、別の有効な 16 進数にするだけで構いません。次に、ip 変数をローカル・ネットワークで空いている IP アドレスに変更します。イーサネット・ライブラリーは DHCP の使用に対応します。興味がある場合、その方法を調べることができますが、可能な限り、固定 IP アドレスを使用したほうが簡単です。続いて localserver 変数を、Mosquitto サーバーを使用しているコンピューターの IP アドレスに変更します。最後に、IBM IoT Foundation QuickStart サーバーではなくローカル MQTT サーバーに接続するようにスケッチを更新します。

コードの以下のセクションを見つけてください。

// Uncomment this next line and comment out the line after it to test against a local MQTT server
//PubSubClient client(localserver, 1883, 0, ethClient);
PubSubClient client(servername, 1883, callback, ethClient);

client(localserver で始まるコンストラクターの行のコメントを外し、その下の client(servername で始まる行をコメントアウトします。この変更を加えた後、スケッチを保存してください。

これで、必要な変更は完了したので、この単純なプログラムの残りの部分を簡単に説明しておきます。上記 2 つのスニペットの間には、以下の一連の変数宣言があります。

char servername[]="messaging.quickstart.internetofthings.ibmcloud.com";
String clientName = String("d:quickstart:arduino:") + macstr;
String topicName = String("iot-2/evt/status/fmt/json");
dht11 DHT11;
float tempF = 0.0;
float tempC = 0.0;
float humidity = 0.0;
EthernetClient ethClient;

上記のコードに示されているように、華氏の温度と摂氏の温度をそれぞれ格納する変数と、湿度を格納する変数があります。また、PubSub クライアントが使用するイーサネット・クライアントのインスタンスを格納する変数もあります。

これに続き、setup() 関数が定義されています。

void setup()

{
  // Start the Ethernet client, open up serial port for debugging, and attach the DHT11 sensor
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  DHT11.attach(3);
}

これは至って単純な関数で、まず、指定された MAC アドレスと静的 IP アドレスを持つイーサネット・クライアントを起動して、そのクライアントを実行状態にします。次に、シリアル・ポート (デバッグを行うためのシリアル・モニターとの通信用) を起動し、最後にピン 3 (~3) で DHT11 との通信を開始するだけのことです。

次に調べる関数は、loop() です。この関数は、Arduino が動作している限り、継続的に呼び出されます。

void loop()
{
  char clientStr[34];
  clientName.toCharArray(clientStr,34);
  char topicStr[26];
  topicName.toCharArray(topicStr,26);
  getData();
  if (!client.connected()) {
    Serial.print("Trying to connect to: ");
    Serial.println(clientStr);
    client.connect(clientStr);
  }
  if (client.connected() ) {
    String json = buildJson();
    char jsonStr[200];
    json.toCharArray(jsonStr,200);
    boolean pubresult = client.publish(topicStr,jsonStr);
    Serial.print("attempt to send ");
    Serial.println(jsonStr);
    Serial.print("to ");
    Serial.println(topicStr);
    if (pubresult)
      Serial.println("successfully sent");
    else
      Serial.println("unsuccessfully sent");
  }
  delay(5000);
}

ご覧のように、この関数の大部分はデバッグ用の出力を生成するためだけにありますが、注目すべき主要な要素がいくつかあります。その 1 つは、関数の先頭近くで実行される getData() 関数 (次に調べる関数) の呼び出しです。これにより、DHT11 からセンサー・データが取得されます。その後 loop() 関数では PubSubClient クライアントが接続されているかどうかをチェックし、接続されていない場合は MQTT ブローカーへの接続を試行し、接続されている場合は buildJson() を使用して JSON ストリングをフォーマット設定してから、PubSubClientpublish() メソッドを使用してその JSON ストリングを MQTT ブローカーにパブリッシュします。loop() 関数では最後に 5,000 ミリ秒間待機します。その後、Arduino ランタイムが元に戻ってこの関数を再び呼び出します。

次は、getData() 関数を調べます。

void getData() {
  int chk = DHT11.read();
  switch (chk)
  {
  case 0:
    Serial.println("Read OK");
    humidity = (float)DHT11.humidity;
    tempF = DHT11.fahrenheit();
    tempC = DHT11.temperature;
    break;
  case -1:
    Serial.println("Checksum error");
    break;
  case -2:
    Serial.println("Time out error");
    break;
  default:
    Serial.println("Unknown error");
    break;
  }
}

この関数は、DHT11 ライブラリーを利用してデータのステータスをチェックして、センサー・データを読み出せる状態になっている場合はそのデータを読み取り、そうでない場合はコンソールに通知メッセージを出力するだけのものです。

最後に、JSON 出力をフォーマット設定する関数を調べます。

String buildJson() {
  String data = "{";
  data+="\n";
  data+= "\"d\": {";
  data+="\n";
  data+="\"myName\": \"Arduino DHT11\",";
  data+="\n";
  data+="\"temperature (F)\": ";
  data+=(int)tempF;
  data+= ",";
  data+="\n";
  data+="\"temperature (C)\": ";
  data+=(int)tempC;
  data+= ",";
  data+="\n";
  data+="\"humidity\": ";
  data+=(int)humidity;
  data+="\n";
  data+="}";
  data+="\n";
  data+="}";
  return data;
}

Arduino に実装されている Processing には、ストリング処理をするための優れた機能がないという欠点があります。そのため、String クラスのインスタンスから String 型へ、あるいはその逆への奇妙な変換を行わなければ、このいずれかを要求する関数を呼び出すことができません。上記リストにこの奇妙な変換があることにお気づきのことでしょう。同様に、ストリングをフォーマット設定するための優れたライブラリーがないことから、コンソールへの出力をフォーマット設定する関数は存在するにもかかわらず、このような単純な JSON ストリングでさえも、フォーマット設定するのに苦労する場合があります。

ローカルの Mosquitto ブローカーでテストする

作業の前半部分は、あと一歩で完了です。ここで、変更を加えたスケッチを、第 1 回で説明したアップロード手順に従って Arduino にアップロードしてください。Arduino IDE のステータス行に「Done uploading (アップロード完了)」と表示されたら、早速 Ctrl-Shift-M を押して、シリアル・モニターを開きます。

出力を検証する

すべてが順調であれば、Mosquitto を起動するために使用したターミナル・ウィンドウに、以下のような出力が表示されます。

1405807697: mosquitto version 1.2.3 (build date 22/12/2013 13:36:32.54) starting
1405807697: Using default config.
1405807697: Opening ipv6 listen socket on port 1883.
1405807697: Opening ipv4 listen socket on port 1883.
1405807718: New connection from 192.168.1.20 on port 1883.
1405807718: New client connected from 192.168.1.20 as d:quickstart:arduino:deedb
afefeed (c2, k15).
1405807718: Sending CONNACK to d:quickstart:arduino:deedbafefeed (0)
1405807718: Received PUBLISH from d:quickstart:arduino:deedbafefeed (d0, q0, r0,
 m0, 'iot-2/evt/status/fmt/json', ... (100 bytes))
1405807723: Socket error on client d:quickstart:arduino:deedbafefeed, disconnect
ing.
1405807723: New connection from 192.168.1.20 on port 1883.
1405807723: New client connected from 192.168.1.20 as d:quickstart:arduino:deedb
afefeed (c2, k15).
1405807723: Sending CONNACK to d:quickstart:arduino:deedbafefeed (0)
1405807723: Received PUBLISH from d:quickstart:arduino:deedbafefeed (d0, q0, r0,
 m0, 'iot-2/evt/status/fmt/json', ... (100 bytes))
1405807729: Received PUBLISH from d:quickstart:arduino:deedbafefeed (d0, q0, r0,
 m0, 'iot-2/evt/status/fmt/json', ... (100 bytes))
1405807734: Received PUBLISH from d:quickstart:arduino:deedbafefeed (d0, q0, r0,
 m0, 'iot-2/evt/status/fmt/json', ... (100 bytes))

何も問題がないことを知るカギは、「Received PUBLISH from...」という最後の数行にあります。これは、Arduino スケッチが Mosquitto ブローカーに正常に接続していることを意味します。シリアル・モニターに目を通すと、以下のようなメッセージが見つかるはずです。

Read OK
Trying to connect to d:quickstart:arduino:deedbafefeed
attempt to send {
"d": {
"myName": "Arduino DHT11",
"temperature (F)": 71,
"temperature (C)": 22,
"humidity": 43
}
}
to iot-2/evt/status/fmt/json
successfully sent

Arduino を IoT Foundation Quickstart に接続する

ローカルではコードが正常に実行されるようになったので、IoT Foundation QuickStart で試してみる準備が整いました。ブラウザーで、IBM Internet of Things Foundation Web サイトにアクセスしてください (図 2 を参照)。

図 2. IBM IoT Foundation のホーム・ページ

「Try it out with our Quickstart (Quickstart で試す)」ボタンをクリックします。すると、図 3 に示すページが表示されます。

図 3. IBM IoT Foundation Quickstart のウェルカム・ページ

このチュートリアルでは、Arduino センサーからのリアルタイムのデータをグラフにするために、IoT Foundation Quickstart に組み込まれた機能を利用します。チュートリアルの第 3 回第 4 回では、受信したデータを使ってさらに興味深い処理を行うアプリケーションを作成します。

IoT Foundation には、他の機器用のレシピもいくつかあります。Intel Galileo や Raspberry Pi のような高度な機器を持っているとしたら、これらの機器用のレシピを試してみてください。ここではとりあえず、単純に Arduino の MAC アドレスを入力します。ただし、「Go (実行)」をクリックする前に、スケッチにもう 1 つ変更を加える必要があります。

スケッチに変更を加える

いくつか前の手順で、IoT Foundation 上の MQTT サーバーではなく、ローカルの MQTT サーバーを指すようにスケッチを変更したことを覚えていますか?現時点で、その変更を元に戻すことができます。コメントを外した行とコメントアウトした行を元に戻して、元通りのコードにしてください。

// Uncomment this next line and comment out the line after it to test against a local MQTT server
//PubSubClient client(localserver, 1883, 0, ethClient);
PubSubClient client(servername, 1883, callback, ethClient);

この変更をした後、スケッチを保存して、Arduino にアップロードします。お望みであれば、シリアル・モニターを再起動することもできますが、確かな証拠となるのは、IoT Foundation で目にする表示です。ブラウザーに戻って Mac アドレス・ページで「Go (実行)」ボタンをクリックし、しばらく待ってください。

データをグラフにする

すべてが正常に機能していれば、図 4 に示すような温度読み取り値のグラフを示すページが表示されるはずです。

図 4. グラフ化されたデータ

成功です!第 1 回で作成した機器が、グローバル IoT の一部となりました。この特定の単純なケースで必要だったのは、このグラフだけです。これで、このグラフを数時間監視して、配線用ボックス内の温度を確認することができたのですが、残念なことに、暑い日の正午でさえも温度が 73°F を上回ることはなかったので、また振り出しに戻って問題を突き止めなければなりません。しかし、IoT の利用方法を学ぶ旅は、まだ始まったばかりです。

今後の予告

このシリーズの次の 2 回 (第 3 回第 4 回) のチュートリアルでは、Arduino から送信されたデータを保持し、現行データを履歴データと比較して表示できる (IBM Bluemix 上で実行される) 独自のアプリケーションを作成します。


ダウンロード可能なリソース


関連トピック

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing, Open source
ArticleID=990415
ArticleTitle=Arduino Uno と IBM IoT Foundation を利用してクラウド対応の温度センサーを作成する: 第 2 回 スケッチを作成して IBM IoT Foundation Quickstart に接続する
publish-date=11272014