LoginSignup
50
52

More than 5 years have passed since last update.

AWS IoTとRuby製MQTTクライアントでPub/Subしてみた

Last updated at Posted at 2015-10-14

この文書について

先日ベータ版が公開されたAWS IoT(AWS上でサーバーインスタンスを自分で用意する事なくMQTTブローカー(+α)のサービスを利用できる)をRubyクライアント(ruby-mqtt)から試してみた個人的なメモです。

本家のクイックスタートを見つつ、AWS IoT Message BrokerのMQTTでpub/subをやってみたも参考にさせて頂きつつやってた覚書ですが、現時点(2015/10/14)でAWS IoTはベータ版であり、今後サービスの仕様が変わる可能性があるため、できるだけ本家のドキュメントを参照される事をおすすめします。

AWS IoTではクライアント側のSDKも提供されているようですが、今回はオープンソースで公開されているMQTTクライアントを使ってPub/Subを試してみます。

AWS IoTの概念についてはLearn how AWS IoT works with this interactive tutorialで図解入りでわかりやすく説明されているので、こちらを参照。以下は同ページのスクリーンショット。RGBのスイッチの状態がMQTTブローカーを通して別のデバイスやストレージ、AWS上の別のサービスと連携する様子が示されています。

スクリーンショット 2015-10-14 11.09.11.png

AWS CLIの準備

すでに最新のAWS CLIをインストール済みの場合は、この項目は飛ばしてかまいません。

$ sudo pip install awscli --upgrade

なお、AWS CLIの詳細なインストール方法に関してはGetting Set Up with the AWS Command Line Interfaceを参照のこと。

Thingを登録する

MQTTクライアントからMQTTブローカーに接続するには Thing を登録する必要があるとのこと。以下のようにして sample_things という名前で登録しました。

$ aws iot create-thing --thing-name "sample_things"

現在登録されているThingのリストは以下のコマンドで確認できます。

$ $ aws iot list-things

{
    "things": [
        {
            "attributes": {}, 
            "thingName": "sample_things"
        }, 
        {
            "attributes": {}, 
            "thingName": "my_things"
        }
    ]
}

先ほど登録した sample_things の他に以前私が登録した my_things も表示されています。

AWS IoTとThing間でのセキュアな通信のための準備

証明書の用意

先ほど登録した ThingAWS IoT 間のセキュアな通信のために、X.509証明書を作成します。

以下のコマンドで、証明書とキーペアを cert.json というファイルに書き出します。

$ aws iot create-keys-and-certificate --set-as-active > cert.json

cert.json の中身はJSONフォーマットですので、ファイルから秘密鍵と公開鍵をそれぞれ thing-public-key.pemprivate-key.pem というファイルに書き出します。
(なお、ローカルに jq コマンドがインストールされていない場合は $ brew install jq すること)

$ cat cert.json | jq .keyPair.PublicKey -r > thing-public-key.pem
$ cat cert.json | jq .keyPair.PrivateKey -r > private-key.pem

証明書を cert.pem という名前のファイルとして書き出します。

$ aws iot​ describe-certificate --certificate-id "<here-is-your-certificate-id>" --output text --query certificateDescription.certificatePem > cert.pem

'<here-is-your-certificate-id>' の部分に先ほどの cert.json の最終行付近にある "certificateId" として与えられた文字列を入れて実行します。

AWS IoTポリシーを作成して証明書に紐付ける

以下のような内容で policy.json というファイルを新規に作成します。

policy.json
{
    "Version": "2012-10-17", 
    "Statement": [{
        "Effect": "Allow",
        "Action":["iot:*"],
        "Resource": ["*"]
    }]
}

作成したファイルへのパスをコマンド引数に渡して PubSubToAnyTopic という名前のポリシーを作成します。

$ aws iot create-policy --policy-name "PubSubToAnyTopic" --policy-document file://policy.json

作成した証明書とポリシーを紐付けます。

$ aws iot attach-principal-policy --principal "<certificate-arn>" --policy-name "PubSubToAnyTopic"

'<certificate-arn>' のところには、先ほどの cert.json 中で "certificateArn" として渡された文字列( "arn:aws:iot:ap-northeast-1::..." ) を入れます。

証明書をThingに紐付ける

さて、最後に証明書とThingを紐付けます。

$ aws iot attach-thing-principal --thing-name "<thing-name>" --principal "<certificate-arn>"

<thing-name> のところには最初に登録したThingの名前が入ります。今回で言えば sample_things になりますね。

<certificate-arn> のところには、先ほどと同じく cert.json の中で、"certificateArn" として与えられた文字列( "arn:aws:iot:ap-northeast-1::..." )が入ります。

お疲れ様でした、これでAWS IoTを使ってPub/Subする準備が整いました。

Ruby ClientでPub/Subしてみる

MQTT クライアントライブラリのインストール

AWSのクイックスタートではMosquittoのPub/Subクライアントを使ってテストしていますが、私はRubyプログラマなのでRubyを使ってやってみます。

MQTTのRubyクライアントとしてはgithub.com/njh/ruby-mqttがあります。

インストールはgemで

$ gem install mqtt

ルート証明書のダウンロード

また、ルート証明書を rootCA.pem というファイル名でカレントディレクトリに落としておきます。

$ wget https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem -O rootCA.pem

MQTTブローカーエンドポイントの確認

それと、MQTTブローカーのエンドポイントはAWSのアカウントごとに用意されています。自分のアカウントのエンドポイントを確認するには、以下のようにします。

$ aws iot describe-endpoint
{
    "endpointAddress": "AAAAAAAAAAA.iot.ap-northeast-1.amazonaws.com"
}

この場合は AAAAAAAAAAA.iot.ap-northeast-1.amazonaws.com が自分のアカウントのエンドポイントということになります。

ポートは共通で 8883 です。

Ruby製Subscriberの用意

データを待機するSubscrberは以下のように書きました。

sub.rb
require "mqtt"

MQTT::Client.connect(host: "AAAAAAAAAAA.iot.ap-northeast-1.amazonaws.com",
                     port: 8883,
                     ssl: true,
                     cert_file: "cert.pem",
                     key_file: "thing-private-key.pem",
                     ca_file: "rootCA.pem") do |client|

  client.subscribe("topic/test")
  topic,message = client.get #ここでブロックする
  p [topic, message]
end

Ruby製Publisherの用意

データを送信するPublisherは以下のように

pub.rb
require "mqtt"

MQTT::Client.connect(host: "AAAAAAAAAAA.iot.ap-northeast-1.amazonaws.com",
                     port: 8883,
                     ssl: true,
                     cert_file: "cert.pem",
                     key_file: "thing-private-key.pem",
                     ca_file: "rootCA.pem") do |client|

  client.publish("topic/test", "From Ruby!")
end

実際にPub/Subしてみる

まずは sub.rb を実行。

$ ruby sub.rb

この時点でSubscriberがデータを待機してブロックします。


続いて pub.rb を実行。

$ ruby pub.rb 

pub.rb はデータをパブリッシュしたらすぐに終了します。直後にブロックしていた sub.rb 側で以下のように受信したデータを表示します。

$ ruby sub.rb
["topic/test", "From Ruby!"]

料金

AWS IoTの課金体系については、この文書を書いている段階で以下のように公表されています。

  • US East (N. Virginia): $5 per million messages
  • US West (Oregon): $5 per million messages
  • EU (Ireland): $5 per million messages
  • Asia Pacific (Tokyo): $8 per million messages

東京リージョンだけ、ちょっとお高いですね。ただ実装するアプリケーションがリアルタイム性を重視するなら、やはり日本国内では東京リージョンを使うことになるでしょう。

感想など

最初の手順が若干必要ですが、順を追って一つづつやっていけば簡単にMQTTブローカーを利用できるようになります。EC2で自分でサーバーインスタンスを立ち上げる必要もなく、またサーバーインスタンスの保守・運用についても考慮することなくセキュリティを考慮されたMQTTブローカーが使用できるというのは、これからMQTTを使ったアプリケーション開発を始める人にとってはとっても楽チンで、とりあえずMQTTを使って端末間の通信を実現したい場合には第一候補になるサービスと感じました。

ただ、本当にシビアな、多数のクライアントから多数のメッセージが送られてくるような場合は、どこかで自前のサーバーを用意したほうが安くつく分岐点があるのだろうと予想しますが、その分岐点がどこになるかは今の私にはわかりません。

AWS IoTは純粋なMQTTブローカーとしても使用できますが、やはりAWSでMQTTする場合の最大の魅力は、AWSの他のサービスとの連携だと思います。次回以降でそのあたりも色々やってみたいと思います。それと Shadow という機能も気になりますね。こっちも色々やってみます。

50
52
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
52