2016年10月13日木曜日

TinkerMODE の MQTT を ruby から直接使ってみた

概要

TinkerMODE の MQTT エンドポイントを ruby から使ってみました
イベントとコマンド用のトピックに対して pub/sub を実行してみました

環境

  • Mac OS X 10.11.6
  • Ruby 2.2.3p173
  • Gem 2.4.5.1
  • TinkerMODE (2016/10/12 時点)

前提知識

TinkerMODE では MQTT のエンドポイントを公開しています

  • mqtt.tinkermode.com:1883

SecurePort で 8883 も公開しているので証明書を使えば SSL を使うこともできます (今回は 1883 ポートを使います)

利用者側では pub/sub できるトピックが限定されています
Publish できるトピックは「/devices/DEVICE_ID/event」で Subscribe できるトピックは「/devices/DEVICE_ID/command」になります
公式でも以下のような見解を述べています

  • A device can only PUBLISH to the topic /devices/<device Id>/event
  • A device can only SUBSCRIBE the topic /devices/<device Id>/command

要するにイベントは Publish のみでコマンドは Subscribe のみ提供しています
ではイベントに対する Subscribe とコマンドに対する Publish はどうするかというと「コンパネ」と「REST API」が用意されています

図にすると以下のような感じです
tinkermode_mqtt_fig.png

ということで実際に挙動を確認していきます

ライブラリ準備

  • bundle init
  • vim Gemfile
source "https://rubygems.org"

gem "mqtt"
  • bundle install

イベントへの Publish

まずはイベントの挙動を確認します
Ruby スクリプトは Publish するスクリプトになります

  • vim pub_event.rb
require 'mqtt'
require 'json'

MQTT::Client.connect(
  :host => 'mqtt.tinkermode.com',
  :port => 1883,
  :version => '3.1.1',
  :clean_session => true,
  :username => 'nnn',
  :password => 'v1.ZHw4MDh8MA==.xxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') do |c|

  payload = {
    'eventType' => 'test-event',
    'eventData' => {
      'value': 1
    }
  }.to_json
  c.publish('/devices/nnn/event', payload)
end

「username」に TinkerMODE 上で作成したデバイスの Device ID を「password」には API Key を設定してください

:version => '3.1.1' の記述がないと「Failed to read byte from socket (MQTT::ProtocolException)」が発生するので注意してください

記載できたら実行しましょう

  • bundle exec ruby pub_event.rb

これで TinkerMODE の MQTT を使ってイベントを送信することができます
送信できたらコンパネでイベントが送信されているか確認してみましょう
tinkermode_mqtt_receive_event.png

こんな感じでコンパネ側で Subscribe できているのがわかります

イベントの Publish と大きく絡む機能は SmartModule という機能です
今回 eventType に「test-event」という値を設定して Publish しました
SmartModule でもイベントをSubscribe しており、この eventType ごとに実行すると SmartModule を振り分けることができます

例えば「test-event」が Publish されたときはサイト A に Webhook を送る、「test-event2」が Publish されたらサイト B に Webhook を送るみたいなことができるようになります

これは所謂イベントパイプラインと呼ばれる仕組みで、あるイベントの発生に応じて次に実行する処理を振り分けることができます
TinkerMODE の SmartModule ではそのような機能を提供しています

コマンドの Subscribe

次のコマンドの挙動を確認します
Ruby スクリプトは Subscribe するスクリプトになります

  • vim sub_command.rb
require 'mqtt'

MQTT::Client.connect(
  :host => 'mqtt.tinkermode.com',
  :port => 1883,
  :version => '3.1.1',
  :clean_session => true,
  :username => 'nnn',
  :password => 'v1.ZHw4MDh8MA==.xxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') do |c|

  c.get('/devices/nnn/command') do |topic,message|
    puts "#{topic}: #{message}"
  end
end

username, password には同様に Device ID と API Key を設定してください
また、Subscribe するトピックにも Device ID が必要になるので記載してください
記載できたら実行しましょう

  • bundle exec ruby sub_command.rb

エラーにならなければ Subscribe が始まります

ではコマンドを送信してみます
アプリシミュレータから REST 経由のコマンド送信できるのでアプリシミュレータを使います
起動してコマンド情報を入力し送信してみましょう
tinkermode_mqtt_send_command.png

すると以下のような感じで ruby スクリプト側でコマンドを Subscribe できると思います

/devices/808/command: {"action":"taction","parameters":{"key":1}}

最後に

TinkerMODE の MQTT エンドポイントを試してみました
当初はイベントとコマンドはどちらも pub/sub できると思っていたのですが、それぞれで pub/sub に制限があるということがわかりました

用途としてイベントはスマートモジュールと絡めて使うのがメインで、コマンドはデバイスのリアルタイムな遠隔操作 (メッセージの送信) に使うのがユースケースかなと感じました

参考サイト

0 件のコメント:

コメントを投稿