Mesubluは複数のトランポートプロトコルに対応しています。REST APIでPOSTしたメッセージをMQTTでsubscribeして受信することができます。クラウド上のDockerホストにMeshbluコンテナを起動したあと、localhostでメッセージングとデータ保存のテストをしてみます。
Meshbluのインストール
MeshbluとRedis、MongoDB、OpenResty、CLIツールなど一式をDocker Composeで起動します。リポジトリはこちらです。
$ sudo apt-get update && sudo apt-get install -y git $ mkdir ~/iot_apps && cd ~/iot_apps $ git clone https://github.com/IDCFChannel/meshblu-compose $ cd meshblu-compose
|
インストールスプリクトを実行するとMeshbluのコンテナが起動します。
$ ./bootstrap.sh ... Name Command State Ports ------------------------------------------------------------------------- meshblucompose_m npm start Up 0.0.0.0:1883->18 eshblu_1 83/tcp, 80/tcp meshblucompose_m /entrypoint.sh Up 27017/tcp ongo_1 mongod meshblucompose_o nginx -c /etc/ng Up 0.0.0.0:443->443 penresty_1 inx/nginx.conf /tcp, 0.0.0.0:80 ->80/tcp meshblucompose_r /entrypoint.sh Up 6379/tcp edis_1 redis-server
|
curlとMosquitto
RESTはcurlを使い、MQTTはMosquittoをクライアントに使ってテストをします。
$ sudo apt-get install curl mosquitto-clients
|
デバイスの準備
MeshbluではREST APIやMQTTを使ってメッセージをpubsubするクライアントを「デバイス」として管理します。
デバイスの登録
インストール直後はデバイスは登録されていません。最初にdocker-compose.ymlに付属しているCLIを使いプリセットのデバイスを登録します。
$ cd ~/iot_apps/meshblu-compose $ docker-compose run --rm iotutil register
> iotutil@0.0.1 start /app > node app.js "register"
┌─────────┬────────────────────┬──────────────────────────────────────┐ │ keyword │ meshblu_auth_token │ meshblu_auth_uuid │ ├─────────┼────────────────────┼──────────────────────────────────────┤ │ owner │ 8ec3992b │ ed311cd7-dc09-459b-9aaf-7d1c08186bdd │ └─────────┴────────────────────┴──────────────────────────────────────┘
|
コマンドを実行すると、trigger-[1-5]
とaction-[1-5]
とownerをあわせて合計11個のデバイスが登録されます。標準出力されるownerのデバイスは作成した11個のデバイスすべてにメッセージを送信することができます。デフォルトでは、trigger-[1-5]
からaction-[1-5]
へ末尾が同じ数字の組み合わせのメッセージ送信を許可しています。
デバイスの一覧
登録したデバイスは以下のコマンドで確認することができます。uuidとtokenはMeshbluのブローカーに接続するための認証情報としても利用します。
$ docker-compose run --rm iotutil list
> iotutil@0.0.1 start /app > node app.js "list"
┌───────────┬──────────┬──────────────────────────────────────┐ │ keyword │ token │ uuid │ ├───────────┼──────────┼──────────────────────────────────────┤ │ trigger-1 │ 6e8e63fe │ 71a24381-02e2-47f3-bfa6-8174545f2261 │ ├───────────┼──────────┼──────────────────────────────────────┤ │ trigger-2 │ 85a97be4 │ 561bc67b-0c0c-4ad4-a6ec-f1a6163f02b0 │ ├───────────┼──────────┼──────────────────────────────────────┤ │ trigger-3 │ ede956b8 │ 6a21c6b7-2a1c-40e3-a26c-96b52f48c586 │ ├───────────┼──────────┼──────────────────────────────────────┤ │ trigger-4 │ 4e120995 │ 9f109642-efa9-4973-9bb4-4bc48987e5ec │ ├───────────┼──────────┼──────────────────────────────────────┤ │ trigger-5 │ 190ade78 │ 12cdc02d-f1ac-43ef-936a-a44565a58f2f │ ├───────────┼──────────┼──────────────────────────────────────┤ │ action-1 │ a02222d2 │ 4dbe71d3-ad32-45e5-99fc-88c225bf11b8 │ ├───────────┼──────────┼──────────────────────────────────────┤ │ action-2 │ 4cb06821 │ 6244ee9c-203c-478a-992b-5fe1c5f782cb │ ├───────────┼──────────┼──────────────────────────────────────┤ │ action-3 │ 54c454e5 │ b3b4cee4-2f19-4c05-904e-1fa139f531bc │ ├───────────┼──────────┼──────────────────────────────────────┤ │ action-4 │ 6b80470a │ c2986c27-e751-47d1-b655-d1750e3ecb71 │ ├───────────┼──────────┼──────────────────────────────────────┤ │ action-5 │ 3aefc667 │ fd9f1a40-fa99-44f4-a405-49f360c175aa │ └───────────┴──────────┴──────────────────────────────────────┘
|
Mesubluの状態確認
APIの仕様
MeshbluのREST APIやMQTTの使い方はDocumentationのサイトに詳しく書いてあります。
SSL通信のinsecureフラグについて
Docker ComposeでMeshbuを起動するとフロントのリバースプロキシとしてOpenRestyが起動しています。Dockerホストの80と443にマップされています。
$ docker-compose ps openresty Name Command State Ports ------------------------------------------------------------------------- meshblucompose_o nginx -c /etc/ng Up 0.0.0.0:443->443 penresty_1 inx/nginx.conf /tcp, 0.0.0.0:80 ->80/tcp
|
http(80)はすべてhttps(443)にリダイレクトしています。./bootstrap.sh
を実行するときに自己署名のSSL証明書を作成しているので、curlコマンドからHTTPSを使う場合は--insecure
オプションが必要です。
~/iot_apps/meshblu-compose/nginx/conf/nginx.confhttp { server { listen 80; server_name localhost; underscores_in_headers on; return 301 https://$host$request_uri; }
|
GET /status
curlからMeshbluが起動しているかstatus
を確認します。
$ curl -X GET \ "https://localhost/status" \ --insecure \ --header "meshblu_auth_uuid: ed311cd7-dc09-459b-9aaf-7d1c08186bdd" \ --header "meshblu_auth_token: 8ec3992b"
|
結果
メッセージを送信して、すぐに受信する
MQTTブローカーを使った一番基本的なメッセージングから試してみます。テスト用のデバイスとしてtrigger-1
とaction-1
を使います。
- メッセージ送信: trigger-1
- メッセージ受信: action-1
メッセージを送信するデバイスはtrigger-1です。tokenとuuidを確認します。
$ docker-compose run --rm iotutil show -- -k trigger-1
> iotutil@0.0.1 start /app > node app.js "show" "-k" "trigger-1"
┌───────────┬──────────┬──────────────────────────────────────┐ │ keyword │ token │ uuid │ ├───────────┼──────────┼──────────────────────────────────────┤ │ trigger-1 │ 6e8e63fe │ 71a24381-02e2-47f3-bfa6-8174545f2261 │ └───────────┴──────────┴──────────────────────────────────────┘
|
メッセージを受信するデバイスはaction-1です。tokenとuuidを確認します。
$ docker-compose run --rm iotutil show -- -k action-1
> iotutil@0.0.1 start /app > node app.js "show" "-k" "action-1"
┌──────────┬──────────┬──────────────────────────────────────┐ │ keyword │ token │ uuid │ ├──────────┼──────────┼──────────────────────────────────────┤ │ action-1 │ a02222d2 │ 4dbe71d3-ad32-45e5-99fc-88c225bf11b8 │ └──────────┴──────────┴──────────────────────────────────────┘
|
MQTT subscribe uuid
最初にmosquitto_subコマンドを使い、action-1がMQTTのメッセージをsubscribeします。Meshbluではメッセージをsubscribeするトピック名はメッセージを受信するデバイスのuuidになります。またusernameとpasswordも必須項目です。それぞれuuidとtokenを指定します。
$ mosquitto_sub \ -h localhost \ -p 1883 \ -t 4dbe71d3-ad32-45e5-99fc-88c225bf11b8 \ -u 4dbe71d3-ad32-45e5-99fc-88c225bf11b8 \ -P a02222d2 \ -d
|
MQTT publish message
trigger-1からaction-1にメッセージを送信します。mosquitto_subと同様にusernameとpasswordはtrigger-1のuuidとtokenを指定します。トピック名はmessage
が固定なので注意が必要です。送信先はJSON形式のメッセージの中にdevices
キーの値として指定します。action-1にメッセージを送信するので、action-1のuuidの4dbe71d3-ad32-45e5-99fc-88c225bf11b8
を記述します。メッセージの本文はpayload
キーに指定します。この例ではJSON形式で記述していますが、文字列も使えます。またpayload
キーと値がなくても空でメッセージを送信することもできます。
新しいシェルを開き、mosquitto_pubコマンドからpublishします。
$ mosquitto_pub \ -h localhost \ -p 1883 \ -t message \ -m '{"devices": ["4dbe71d3-ad32-45e5-99fc-88c225bf11b8"], "payload": {"led":"on"}}' \ -u 71a24381-02e2-47f3-bfa6-8174545f2261 \ -P 6e8e63fe \ -d
|
mosquitto_subコマンドを実行しているシェルにメッセージが届きました。
HTTP POST /messages
MQTTのsubscriberにREST APIからメッセージをPOSTしてみます。RESTのクライアントはcurlコマンドを使います。MQTTのpublishと同様にURLは/messages
が固定です。トピック名と違いURLの方は/messages
と複数形になっています。メッセージはJSON形式なのでContent-Type: application/json
が必要です。また、trigger-1のuuidとtokenは認証情報としてHTTPヘッダに記述します。
先ほどのmosquitto_subコマンドが起動している状態で、新しいシェルを開きcurlコマンドからメッセージをPOSTします。
$ curl -X POST \ "https://localhost/messages" \ --insecure \ -H "Content-Type: application/json" \ -d '{"devices": "4dbe71d3-ad32-45e5-99fc-88c225bf11b8", "payload": {"led":"on"}}' \ --header "meshblu_auth_uuid: 71a24381-02e2-47f3-bfa6-8174545f2261" \ --header "meshblu_auth_token: 6e8e63fe"
|
メッセージのPOSTに成功すると以下のメッセージが表示されます。
{"devices":"4dbe71d3-ad32-45e5-99fc-88c225bf11b8","payload":{"led":"on"}}
|
mosquitto_subコマンドを実行しているシェルにメッセージが届きました。
データを保存して、あとで取り出す
Raspberry Piと環境センサーが計測した湿度が70%を超えたときなど、特定の閾値をデータとして送信したい場合があります。
データの送信先がMQTTやWebSocketでsubscribeしている場合は、上記で確認したようにMQTT publishやHTTP POST /messagesからメッセージとして送信できます。ただし、データの送信先がHTTPの場合はメッセージを同期で受信するのが困難になります。
MQTTの場合はdata
トピックに、HTTPの場合は/data/uuid
に送信して一度MongoDBにデータを保存します。データの送信先はMongoDBにレンジクエリのAPIを使い保存されているデータをポーリングして取り出しします。
MQTT publish data
trigger-1から閾値越えのデータをdata
トピックに送信してみます。特定のデバイスにメッセージを送信したときのmessage
トピックとは異なり、データを保存する場合はdata
トピックを固定で使います。devices
キーは、データを保存するuuidなのでtrigger-1自身のuuidになるので注意が必要です。
$ mosquitto_pub \ -h localhost \ -p 1883 \ -t data \ -m '{"devices": ["71a24381-02e2-47f3-bfa6-8174545f2261"], "payload": "trigger on"}' \ -u 71a24381-02e2-47f3-bfa6-8174545f2261 \ -P 6e8e63fe \ -d
|
MongoDBのデータ
MondoDBコンテナに入り保存されたデータを確認します。MondoDBのデータベース名はskynet
です。
$ cd ~/iot_apps/meshblu_compose $ docker exec -it meshblucompose_mongo_1 mongo skynet
trigger-1がmosquitto_pubしたデータを確認します。
```bash > db.data.find().sort({ $natural: -1 }).limit(1); { "_id" : ObjectId("55b212f5ac81f6100042b353"), "devices" : [ "71a24381-02e2-47f3-bfa6-8174545f2261" ], "payload" : "trigger on", "fromUuid" : "71a24381-02e2-47f3-bfa6-8174545f2261", "uuid" : "71a24381-02e2-47f3-bfa6-8174545f2261", "timestamp" : "2015-07-24T10:27:01.766Z" }
|
HTTP GET /data/uuid
このレンジクエリを実行するデバイスのuuidとtokenはすべてのデバイスにアクセスができるownerデバイスのuuidとtokenを認証情報に使います。
$ docker-compose run --rm iotutil owner
> iotutil@0.0.1 start /app > node app.js "owner"
┌─────────┬────────────────────┬──────────────────────────────────────┐ │ keyword │ meshblu_auth_token │ meshblu_auth_uuid │ ├─────────┼────────────────────┼──────────────────────────────────────┤ │ owner │ 8ec3992b │ ed311cd7-dc09-459b-9aaf-7d1c08186bdd │ └─────────┴────────────────────┴──────────────────────────────────────┘
|
一定間隔でレンジクエリのstartとfinishをインクリメントして、MongoDBに閾値越えのデータが保存されているか確認します。レコードタイムスタンプが2015-07-24T10:27:01.766Z
です。テストのためstart
とfinish
でタイムスタンプをはさむようにクエリします。
$ curl -X GET \ "https://localhost/data/71a24381-02e2-47f3-bfa6-8174545f2261?start=2015-07-24T10:25:01.766Z&finish=2015-07-24T10:40:01.766Z&limit=1" \ --insecure \ --header "meshblu_auth_uuid: ed311cd7-dc09-459b-9aaf-7d1c08186bdd" \ --header "meshblu_auth_token: 8ec3992b"
|
以下のようにtrigger-1がmosquitto_pubから保存したデータを取り出すことができました。
{"data":[{"devices":["71a24381-02e2-47f3-bfa6-8174545f2261"],"payload":"trigger on","fromUuid":"71a24381-02e2-47f3-bfa6-8174545f2261","uuid":"71a24381-02e2-47f3-bfa6-8174545f2261","timestamp":"2015-07-24T10:27:01.766Z"}]}
|