AWS IoT Device SDK for JavaScriptのサンプルでAWS IoTプログラミングを理解する #reinvent

2015.10.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
AWSのカンファレンスイベント、re:Invent 2015で発表&ベータがローンチされたAWS IoT、皆さん触ってますか?

AWS IoTはメッセージブローカーを基盤とするIoTデバイスとAWSサービスを連携させるサービスです。今回ご紹介するAWS IoT Device SDKは、AWS IoTのMQTT APIと通信するためのラッパーライブラリです。現在、以下3つのプログラミング言語/プラットフォームの対応版が公開されています。

いずれも現時点でできることはさほど大きく変わりません。今回はJavaScript版を試してみたいと思います。

IoT Device SDKでできること

上述の通り、MQTTのマネージドサービスであるAWS IoTメッセージブローカーを介するPub/Subを実装します。AWS IoTでは純粋なPub/Subに加えて、デバイス(Thing)の属性情報をAWS IoT側で保持するRegistryとデバイスの状態情報をAWS IoT側で管理するThing Shadowsという機能がありますが、RegistryはREST APIのみで提供されるためDevice SDKでアクセスできるのはPub/SubとThing Shadowsのみです。

一方で、Thing Shadowsは前回のエントリーでご紹介した通り特定トピックへのPub/Subが実際には行われるのですが、トピックの階層を理解した上で複数トピックを組み合わせなければならないなど、プログラミングにおいて煩雑な要素が多いと見ることもできます。Device SDKは、Thing Shadowsに関するPub/Sub処理を抽象化することで見通しの良いコーディングをサポートするとともに、MQTTやPub/Subの知識があまり無いプログラマに対してはそれらの実装を隠蔽するはたらきを持ちます。

また、Device SDKと名付けられてはいますがハードウェアとしての制約は無いので、管理アプリケーションなどデバイス以外のマシンで利用することもできます。試してはいないですが、Lambdaでも動くかもしれません。

IoT Device SDK for JavaScriptのセットアップ

  • 検証環境 : Vagrant/VirtualBox仮想マシン debian/wheezy
  • aws-iot-device-sdkのバージョン : 1.0.2

まずは、以下のブログを参考に、Debian WheezyにNode.jsをインストールします。

$ sudo vi /etc/apt/sources.list # 以下を追加
deb http://ftp.jp.debian.org/debian/ wheezy-backports main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ wheezy-backports main contrib non-free
$ sudo apt-get update
  :(略)
$ sudo apt-get install nodejs nodejs-legacy
  :(略)
$ curl -L https://npmjs.org/install.sh | sudo sh
  :(略)
$

Node.jsのセットアップはこれでOKです。続いて、IoT Device SDKをインストールします。GitHubのREADME.mdにはnpmでのインストールコマンドが書かれていますが、/index.jsrequire文がイマイチでnpm環境では動きませんでした。git cloneで持ってきて、依存パッケージをインストールします。

$ sudo apt-get install g++ git # g++は依存パッケージのインストールのために必要
  :(略)
$ git clone https://github.com/aws/aws-iot-device-sdk-js.git
  :(略)
$ cd aws-iot-device-sdk-js/
$ npm install mqtt
$ npm install blessed
$ npm install blessed-contrib
$ npm install minimist

これで準備OKです。

サンプルプログラムの使い方

GitHubのREADME.mdにかなり詳しく関われていますので、詳細はそちらを参照して下さい。サンプルはexamples/以下にいくつかあります。いずれのスクリプトも-hオプションでヘルプが見られるので、実行する前に確認しましょう。MQTT APIにアクセスするためには、こちらのエントリーにあるクライアント証明書一式が必要です。Thing Shadowsを試すサンプルの場合はこちらのエントリーにあるようにThingを作成しておきましょう。

サンプルは以下があります。

  • device-example.js : 端末を二つ用意し、-tオプションの1と2でお互いにPub/Subを繰り返します
  • echo-example.js : -Tオプションで指定するThingの更新内容(delta)を表示するシンプルなサンプル
  • temperature-control.js : 端末を二つ用意し、温度管理についてのデバイスと管理アプリケーションのやり取りをシミュレーションします
  • thing-example.js : 端末を二つ用意し、表示色についてのデバイスと管理アプリケーションのやり取りをシミュレーションします

ひとまず、device-example.jsを試してみましょう。まずはヘルプを確認します。

$ node examples/device-example.js -h
Usage: device-example.js [OPTION...]

device-example.js: connect to the AWS IoT service and publish/subscribe to topics using MQTT, test modes 1-2

 Options

  -g, --aws-region=REGION          AWS IoT region
  -i, --client-id=ID               use ID as client ID
  -k, --private-key=FILE           use FILE as private key
  -c, --client-certificate=FILE    use FILE as client certificate
  -a, --ca-certificate=FILE        use FILE as CA certificate
  -f, --certificate-dir=DIR        look in DIR for certificates
  -r, --reconnect-period-ms=VALUE  use VALUE as the reconnect period (ms)
  -t, --test-mode=[1-n]            set test mode for multi-process tests
  -T, --thing-name=THINGNAME       access thing shadow named THINGNAME
  -d, --delay-ms=VALUE             delay in milliseconds before publishing

 Default values

  aws-region                       us-east-1
  client-id                        $USER<random-integer>
  private-key                      ./privkey.pem
  client-certificate               ./cert.pem
  ca-certificate                   ./aws-iot-rootCA.crt
  reconnect-period-ms              3000ms
  delay-ms                         4000ms
  test-mode                        1

今回は東京リージョンのエンドポイントを利用したいので-gオプション、証明書は-k/-c/-aオプションでそれぞれ設定できますが、証明書一式をデフォルトのファイル名で用意し、-fオプションで指定するのが楽でしょう。

【1つ目の端末】

$ node examples/device-example.js -f /vagrant -g ap-northeast-1 -t 1
connect
message topic_1 {"mode_2_process":1}
  :

【2つ目の端末】

$ node examples/device-example.js -f /vagrant -g ap-northeast-1 -t 2
connect
message topic_2 {"mode_1_process":17}
  :

1つ目の端末はtopic_2にメッセージをPublishしつつtopic_1をSubcribeし、2つ目の端末は逆にtopic_2をSubscribeしつつtopic_1にメッセージをPublishしていることがわかりますね。ではソースを見てみましょう。

21行目でDevice SDKのdeviceモジュールを読み込み、33〜40行目でモジュールで定義されるDeviceクラスからインスタンスを生成しています。

examples/device-example.js(抜粋)

      : 
    21	const deviceModule   = require('../device');
     :
    33	const device = deviceModule({
    34	  keyPath: args.privateKey,
    35	  certPath: args.clientCert,
    36	  caPath: args.caCert,
    37	  clientId: args.clientId,
    38	  region: args.region,
    39	  reconnectPeriod: args.reconnectPeriod,
    40	});
     :

生成したdeviceインスタンスはMQTTの処理をラップし、対応するトピックのパスや実行するタイミングをイベントリスナーとして定義します。50行目以降はひたすらリスナーを定義しているのがわかります。

    50	device
    51	  .on('connect', function() {
     :      :
    80	    });
    81	device
    82	  .on('close', function() {
    83	    console.log('close');
    84	    clearInterval( timeout );
    85	    count=0;
    86	  });
     :

Deviceクラスはmqtt.Clientクラスを薄くラップしただけでイベントは全てmqtt.Clientクラスと共通です。一方、Thing Shadowsを扱うためのThingShadowクラスのインスタンスは以下のイベントリスナーを定義しつつ、メソッドをコールしてThingおよびThing Shadowの操作を行います。

  • deltaイベント : ThingとThing Shadowの差分ができた時に発生する。デバイス側で実装し、差分に合わせた処理を実行し、Thingの状態を更新する
  • statusイベント : Thing/Thing Shadowの変更リクエストが受理された時に発生する
  • timeoutイベント : Thing/Thing Shadowの変更リクエストがタイムアウトした時に発生する

この辺りの実装例としてはthing-example.jsが参考になるでしょう。

実際に作成するときは

Device SDKとしては、MQTTブローカーへのPub/Subのみ利用する場合とPub/SubとThing Shadowsを併用する2パターンが考えられます。デバイスからクラウドに一方向にデータを送信するようなシンプルなセンサーネットワークであればPub/Subのみで十分なこともあると思います。一方、Thing Shadowsを利用することで管理アプリケーションからのデバイス操作に関するメッセージングが可能にあるため、HEMS用途やデバイスの遠隔操作などに利用することができるでしょう。

まとめ

AWS IoT Device SDKのサンプルをご紹介しました。AWS IoTを利用するIoTシステムでのプログラミングの雰囲気が少しでも伝われば嬉しいです。

参考URL