OpenBlocks BX1とAWS IoTをつなげてAmazon S3にメッセージをなげてみる

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

こんにちは、せーのです。 AWS IoTが発表されてクラメソのブログでも色々と各機能の紹介をしています。触ってみた方は大体の感じがつかめてきたかと思います。 ここで実際のIoTデバイスからAWS IoTへ繋いで、データを送ってみたいと思います。使うデバイスはいつものBX1です。

ステップを確認する

Developers.IOをはじめ、大体のブログがAWS CLIを使ってコマンドラインで書かれているものが多いので、今回はマネージメントコンソールを使ってわかりやすくやってみましょう。 マネージメントコンソールで必要なステップは

1. Thingsを登録する
2. Rulesに必要なリソースとRulesを登録する
3. Certificateを登録する
4. Policyを登録する
5. CertificateにPolicyとThingsを紐付ける

この5つです。一方クライアント側となるデバイスで必要なことは

1. 証明書と鍵、ルートCA証明書を用意する
2. MQTTでpublishできるクライアントを用意する
3. (必要であれば)エンドポイントを確認する

この3つです。2の「MQTTでpublishできるクライアント」はいくつか種類があるのですが、AWS IoTとつなげることを考えると

- オープンソースの[Mosquito]
- AWS IoT Device SDK

の2つが候補となるかと思います。Mosquitoの場合はエンドポイントの指定が必要ですが、AWS IoT Device SDKはそこらへんをいい感じにやってくれるので指定する必要はありません。 ということで今回はAWS IoT Device SDKを使ってみたいと思います。

やってみる

それではやってみましょう。まずはマネージメントコンソール側です。

bx1_awsiot1

Thingsを登録する

まずはThingsを登録します。[Create a resource]ボタンでCreate Panelを開き、[Create a Thing]ボタンを押します。

bx1_awsiot2

あとは名前を入れてCreateすればOKです。

Rulesに必要なリソースとRulesを登録する

つぎにRuleを登録していきます。今回は簡単にS3にメッセージを入れてみましょう。ということでS3のバケットを作成します。

bx1_awsiot9

AWS IoTに戻ってCreate Panelから[Create a Rule]ボタンを押します。

bx1_awsiot3

RuleはSQLライクにメッセージの処理方法を決めるコンポーネントです。今回は[bx1test]というtopicにメッセージが入ってきたらその全てのメッセージをS3に投げる、というRuleを作ります。 フィルタリングを決めたら次にアクションをつけていきます。

bx1_awsiot4

S3の場合は対象となるバケット名とIAM Roleを作ります。IoTRuleがS3を操作できるようにS3のPutObjectの権限をこのRuleにつけるわけです。

bx1_awsiot5

これでRuleの作成はOKです。Createしてみましょう。

bx1_awsiot6

Certificateを登録する

次はCertificate, 証明書を登録していきます。証明書は自分で作ったcsrを登録する方法と全てをAWSで作る方法の2つがあります。

bx1_awsiot7

今回は全てをAWSで作ってみます。これはなんとボタンを押すだけで出来てしまいます。Create Panelから[Create Certificate]ボタンを押し、[1-Click Certificate Create]ボタンを選択します。

bx1_awsiot8

これでPublic Key, Private Key, Certificateの3つがダウンロードできるリンクが表示されます。Certificateは後からでもダウンロードできますがPublic Key, Private Keyはこのワンチャンスを逃すとダウンロードできなくなるのでここで必ずダウンロードするようにして下さい。

Policyを登録する

さて、次はPolicyを登録します。これは後ほど証明書に紐付けるためのもので、このポリシーで設定した権限を、このPolicyを紐付ける証明書を使ってConnectしたデバイスが使える、ということです。 Create Panelから[Create a Policy]を選択します。今回はConnectとPublishが出来ればいいのですが、シンプルにiot系全てを全てのデバイスから動かせるPolicyを作成します。

bx1_awsiot10

CertificateにPolicyとThingsを紐付ける

最後は作成したCertificateにPolicyとThingsを紐付けます。作ったCertificateを選択して[Attach Policy][Attach Thing]をActionから選択します。

bx1_awsiot11

あとはそれぞれ表示された小窓からPolicy, Thingを登録すればOKです。

bx1_awsiot12

bx1_awsiot13

これでAWS側の設定はOKです。

デバイス(BX1)側の設定

ここからはBX1側の設定をしていきます。まずは各モジュールをインストールするためにnodeとnpmをインストールします。 /etc/apt/sources.listを開いて、コメントアウトされている行のコメントを外します。

vi /etc/apt/sources.list

deb http://ftp.plathome.co.jp/pub/debian wheezy main
deb-src http://ftp.plathome.co.jp/pub/debian wheezy main

deb http://ftp.plathome.co.jp/pub/debian-security wheezy/updates main
deb-src http://ftp.plathome.co.jp/pub/debian-security wheezy/updates main

#deb http://ftp.plathome.co.jp/pub/debian wheezy-backports main contrib non-free ←ここと
#deb-src http://ftp.plathome.co.jp/pub/debian wheezy-backports main contrib non--
free ←ここのコメントを外す

deb http://ftp.plathome.co.jp/pub/BX1/debian/wheezy ./

コメントを外したらnodeを入れていきます。元々のパッケージには入っていないのでholdします。

apt-get update
apt-get install nodejs
apt-get install nodejs-legasy
echo nodejs hold | dpkg --set-selections
echo nodejs-legacy hold | dpkg --set-selections

コメントを元にもどして再びパッケージをupdateし、npmを入れていきます。

apt-get update
curl -L https://npmjs.org/install.sh | sh

nodeとnpmが入っているかどうかバージョンで確認します。

node -v
npm -v

次にAWS IoT Device SDKをインストールします。インストールができたらAWS IoT Device SDKに必要なモジュールをnpmでインストールします。

apt-get install git
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 blessed-contrib
npm install minimist

デバイスのデフォルトとなるファイル名をヘルプコマンドで確認します。

nodejs 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
  -F, --configuration-file=FILE    use FILE (JSON format) for configuration
  -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                      private.pem.key
  client-certificate               certificate.pem.crt
  ca-certificate                   root-CA.crt
  reconnect-period-ms              3000ms
  delay-ms                         4000ms
  test-mode                        1
  

マネージメントコンソールからダウンロードしたCertificateのうちCertificate, Private Keyの証明書をそれぞれ[certificate.pem.crt][private.pem.key]に変更し、macならCyberduck, WindowsならWinSCPなどを使ってまっさらなフォルダに転送します。今回はルートフォルダ直下に[certs]というフォルダを作りました。

cd ~
mkdir certs

ここにroot CA証明書を入れます。なおcurlコマンドはBX1には初期では入っていないためインストールします。

apt-get install curl
cd ~/certs/
curl -o root-CA.pem  https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem

それぞれのアクセス権限をルートCA証明書: 644, 鍵,証明書: 600で設定し、入っている内容を確認します。

chmod 644 ~/certs/root-CA.crt
chmod 600 ~/certs/certificate.pem.crt
chmod 600 ~/certs/private.pem.key

ls -la ~/certs/
total 20
drwxr-xr-x  2 root root 4096 Nov  1 23:47 .
drwxr-xr-x 10 root root 4096 Nov  1 18:19 ..
-rw-r-----  1 root root 1220 Nov  2 02:02 certificate.pem.crt
-rw-r-----  1 root root 1679 Nov  2 02:02 private.pem.key
-rw-r--r--  1 root root 1758 Nov  2 02:02 root-CA.crt

BX1はiptablesで必要以外のポートが閉じられているため、AWS IoTで必要な8883ポートを空けます。

/sbin/iptables -A INPUT -p tcp --dport 8883 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport 8883 -j ACCEPT

さあ、これで準備は完了です。exampleからMQTTSでメッセージを送るとRulesにてそのメッセージをSubscribeしてS3に送られます。 ただ、exampleは[topic_1][topic_2]となっているので、ここを[bx1test]に変更します。今回はtestModeという変数を1にて送るのでtestMode===1のところだけでOKです。

vi examples/device-example.js
...
device
  .on('connect', function() {
    const minimumDelay=250;
    console.log('connect');
    if (args.testMode === 1)
    {
        device.subscribe('bx1test');
    }
...
   timeout = setInterval( function() {
        count++;

        if (args.testMode === 1)
        {
            device.publish('bx1test', JSON.stringify({
            mode_1_process: count }));
        }
        else
......

コードを読んで頂ければわかるように最初にtopicをsubscribeしてその後にsetIntervalで定期的にtopicに向けてカウントアップした数値をpublishしているだけです。 それでは実際に実行してみましょう。exampleのRegionはus-west-1なので東京リージョンであるap-northeast-1を指定します。

nodejs examples/device-example.js -f ~/certs/ -g ap-northeast-1
connect
message bx1test {"mode_1_process":1}
message bx1test {"mode_1_process":2}
message bx1test {"mode_1_process":3}
message bx1test {"mode_1_process":4}
message bx1test {"mode_1_process":5}

publishは成功です!ではsubscribeはどうでしょうか。S3のバケットの中身を見てみます。

bx1_awsiot14

入ってますね!中身を見ると

{"mode_1_process":5}

publishされたjsonがそのまま入っていますね。うまく行きました。

まとめ

いかがでしたでしょうか。今回ご紹介したようにAWS側は非常にシンプルです。後はデバイス側の実装だけですが、それもAWS IoT Device SDKを使うととてもシンプルに実装できます。 とりあえず色々なデバイスに実装してみるところから初めてみましょう。