サンプルコードの動作
サンプルコード pub_demo.inoは、developerWorksで紹介されていた Arduino UNO + Ethernetシールド ベースのサンプルコードをArduino YUN向けに書きなおしたものです。
setup()とloop()
Sketchプログラムは、基本的にsetup()
とloop()
という2つの関数上にプログラムを記述します。
Arduinoに対して給電が開始されると、最初にsetup()
を1回だけ実行します。その後、loop()
を電源停止まで繰り返し実行します。
サンプルコードでは、setup()
にMQTT通信のための初期化処理を、loop()
にMQTT通信を1回実行し5秒待機する処理を記述しています。
また、setup()
やloop()
の中から呼び出す関数としてbuildJson()
とgetData()
という関数を定義しています。このように独自の関数を定義することも可能です。
シリアル操作
setup()
やloop()
の中には、「Serial」から始まる関数を呼び出している行がいくつかあります。これはシリアルポートに対する操作をおこなっています。
Arduinoを開発する場合、PCと本体をUSBケーブルで接続しますが、このときPCのシリアルポートに接続しています。シリアルポートは、プログラムのアップロードに使用しますが、プログラムの中から操作することも可能です。Arduino IDEには、シリアルモニタという機能があり、シリアルポートに対して読み書きをおこなうことができます。
Serial.print()
やSerial.println()
は、引数として与えられた文字列をシリアル出力に書き出すことができるので、サンプルコードのように動作中のログ出力として使用することができます。
setup()
内で、次のような行がありますが、シリアルモニタ画面が表示されるまでループを繰り返す処理をあらわします。
while(!Serial);
USB接続したPC上でシリアルモニタ画面を開くまで次の処理へ進まないため、ユーザの準備が整うまで一時停止する機能として使用しています。
グローバル変数
temp
やhumid
など、関数の外に定義された変数を「グローバル変数」と呼びます。グローバル変数は、プログラムのあらゆるところから参照できます。一方、関数内で宣言された変数を「ローカル変数」といいます。ローカル変数は、関数の中でのみ参照可能です。
サンプルコードでは、MQTT接続を確立するために、いくつかの項目をグローバル変数として定義しています。
MQTTブローカエンドポイントのホスト名(グローバル変数serverName)
PublisherやSubscriberが指定する通信先のホスト名として、Watson IoT Platformでは「<組織id>.messaging.internetofthings.ibmcloud.com」を指定します。
組織IDは、Watson IoT Platformへ最初にサインインした際に割り当てられる6桁の文字列です。Quickstartの組織IDは「quickstart」を指定します。
クライアントID(グローバル変数clientName)
Watson IoT Platformでは、PublisherやSubscriberといったMQTTブローカと通信をおこなう対象を「クライアント」と呼びます。クライアントIDは、クライアントに対して一意となる文字列です。
文字列の書式は決まっています。クライアントがデバイス[Publisher]である場合には「d:<組織id>:<デバイスタイプ>:<デバイスid>」、アプリケーション(Subscriber)である場合には「a:<組織id>:<アプリケーションid>」とします。
「デバイスタイプ」は、型番のようなデバイスの種類をあらわす文字列のことで、開発者側で決めることができます。サンプルコードでは「arduino」を指定しています。
「デバイスID」は、シリアルナンバーのようなデバイスを一意にあらわす文字列のことで、やはり開発者側で決めることができます。サンプルコードではデバイスのMACアドレスを指定しています。
「アプリケーションID」は、Subscriberを一意であらわす文字列のことで、これも開発者側で決めることができます。
トピック(グローバル変数topicName)
Watson IoT Platformでは、トピックについても書式が決められています。サンプルコードのように、MQTTブローカへイベントのPublishingする場合は、「iot-2/evt/<イベントid>/fmt/<フォーマット形式>」とする必要があります。
「イベントID」は、デバイス側が送信の起点となったイベントをあらわす文字列のことで、開発者側で決めることができます。サンプルコードでは「status」を指定しています。
「フォーマット形式」は、メッセージとして送信されるデータ(メッセージペイロードと呼びます)の形式をあらわす文字列のことで、開発者側で決めることができます。サンプルコードでは「json」を指定しています。
関数buildJson()
buildJson()
はloop()
内から呼び出され、メッセージペイロードとなる文字列を作成・返却する処理が実装されています。サンプルコードでは、毎回次のようなダミーデータを返却しています。
{ "d": { "myName": "Arduino YUN", "temp": 15, "humid": 40 } }
Watson IoT Platformでは、メッセージペイロードに対する形式は定められていませんが、次のような要件を満たす「IoTF JSON ペイロード仕様」を推奨しています。
- メッセージは、dおよびtsの2つのトップレベル要素のみを含む有効なJSONオブジェクト(配列ではない)でなければならない
- メッセージは、UTF-8でなければならない
- d要素には、メッセージ入れて送信されるイベント(もしくはコマンド)のすべてのデータを格納する
- d要素は必須であり、送信するデータがない場合でも必ず存在しなくてはならない
- ts要素を使用すると、イベント(もしくはコマンド)にタイムスタンプを関連付けることができる
- ts要素はオプションであり、値としてISO8601エンコードのタイムスタンプ文字列として有効なもの(例:”2014-12-30T14:47:36+00:00”)を指定する
Quickstart上のグラフを正しく表示させるには、このIoTF JSONペイロード仕様を満たす必要があります。
なお、Watson IoT Platform が受信可能なメッセージペイロードサイズは4KBとなっています。4KBを超えるメッセージを送信すると、通信が切断されます。
おわりに
センサデータをインターネット上に取り込むには、Subscriber側を実装する必要がありますが、残念ながらQuickstartでは試すことができません。Subscriber側も試してみたい方は、Quickstartとは別に用意されているWatson IoT Platformの無料プランを使ってみてください。無料プランの場合、最大20台までのデバイスに対して月100MBまでのデータ通信という制限付きですが、Watson IoT Platformのすべての機能を使うことができます。
また、Arduinoにセンサを接続して計測結果を取得する方法を知りたい方は、Sketchサンプルプログラム付きのブログ記事などをご覧ください。市販書籍も刊行されていますので、それらも参考に色々試してみてください。
IoTを始めたい方も・本格導入を検討中の方も:おすすめソリューションのご紹介
ビジネスのパフォーマンスを高めようとさまざまな業種・企業で、IoT活用を前提とするプロジェクトが動き始めています。ただし、検討を始めて最初に出てくるのは、こんな要望ではないでしょうか。
「最初は実験的にスタートしたいから、小さく簡単に素早く始めたい」
「実運用に移ったときには10万・100万単位のセンサ/デバイスに対応できるスケーラビリティも確保したい」
これにお応えできるサービス・製品がIBMにあります。ぜひ、下記の資料をご覧ください。(編集部)