Xivelyとはなんぞや
Heroku には Xively という IoT Platformアドオンがあります。Xivelyは、MQTT の Message Broker を軸にして、IoTデバイスの管理やルールエンジンによるアラート機能などを持っています。標準で、Amazon KinesisやSalesforceの外部システム接続機能も持っていて、特にコードを書くことなく、カンタンに IoTを始めることができるアドオンとなっています。
そんな Xively の MQTT Message Broker は、PubSubメッセージングモデルになっていますので、プログラムからの呼出方法を理解していれば、IoTだけではなく、アプリ間の非同期メッセージ通信にも利用可能です。今回は、MQTT
を利用して、Xivelyでメッセージをやりとりする方法をまとめました。
入手・設定すべき情報
Heroku アドオンとして追加した場合も、Xivelyを単独で利用可能な状態にした場合でも、次の情報を入手する必要があります。※ 一部、Xively へログインした状態でないとアクセスできない箇所があります(Account IDやデバイス情報)。
入手の必要な情報
入手する情報 | 内容 | 入手先 |
---|---|---|
Account ID | 利用する契約主を特定する | Account details |
R1ルート証明書 | SSL接続のためのルート証明書 | GlobalSign Root Certificates |
Xively Broker URL | Xivelyのメッセージブローカーサーバーのホスト名 | broker.xively.com |
Xively Broker PORT | Xivelyブローカーサーバーの待受ポート番号 | 8883 |
ルート証明書は BASE64
形式をファイルに保管して、プログラムからアクセスできるようにしておく必要があります。
設定が必要な情報
設定すべき項目 | 内容 | 設定先 |
---|---|---|
デバイスID | IoTデバイスのID | Xively Devices |
デバイスパスワード | IoTデバイスのパスワード | Xively Devices |
チャネル | IoTデバイスが利用するチャネル | Xively Device Templates |
Xively では、Publish
する側も Subscribe
していく側も、定義された IoTデバイス毎の ID/Password と、それらを元に構成される Topic
並びに Channel
名をキーにして、メッセージのやりとりをします。デバイスは、Xively の Devices から登録をすると、デバイスごとに ID/Password が発行されます。これらのデバイスは、先にXively Device Templatesで作成されたテンプレートを元に、デバイスの情報を設定できるようになっています。チャネル情報もテンプレートに作成しておく必要があります。従って、デバイスの構成は、次のとおりとなります。
- デバイステンプレートの作成 => Xively Device Templates
- デバイスの作成 => Xively Devices
なお、チャネルは、標準では _log
だけ定義されています。
Ruby で書いてみた
実際に MQTTライブラリで、Xively へ Pub/Sub する簡易サンプルを準備してみました。必要な情報は環境変数に保管するようにしましたので、環境変数名、および設定内容は次のとおりです。Heroku のアドオンとして登録した場合には、XIVELY_BROKER_HOST
XIVELY_BROKER_PORT
XIVELY_ACCOUNT_ID
は自動的に設定されていますので、定義は不要です。
# Heroku で自動登録される部分
export XIVELY_BROKER_HOST="broker.xively.com"
export XIVELY_BROKER_PORT=8883
export XIVELY_ACCOUNT_ID="ここにXivelyの Account ID情報を入れます"
# Heroku で自動登録されない部分
export XIVELY_CA_FILE="R1ルート証明書ファイルへのパスとファイル名を指定。ex.'certs/gsroot.pem'"
export XIVELY_DEVICE_ID="対象のデバイスID"
export XIVELY_DEVICE_PASS="対象のデバイスパスワード"
export XIVELY_CHANNEL="利用するチャネル名。標準では '_log'"
次に Xively への接続と、Pub/Sub をまとめてクラス化してみました。なお、Xively は SSL接続が必須のため、ルート証明書や ssl=>true
定義が必須となります。
require 'mqtt'
class Xively
# XIVELY Message Broker : sample device #1
def initialize(id, pass, channel = '_log')
@xively_account_id = ENV['XIVELY_ACCOUNT_ID']
@xively_id = id
@xively_channel = channel
@client = MQTT::Client.connect(
host: ENV['XIVELY_BROKER_HOST'],
port: ENV['XIVELY_BROKER_PORT'],
ssl: true,
ca_file: ENV['XIVELY_CA_FILE'],
username: id,
password: pass
)
end
def PubXively(message, channel = @xively_channel)
xively_topic = "xi/blue/v1/#{@xively_account_id}/d/#{@xively_id}/#{channel}"
@client.publish(xively_topic, message)
end
def SubXively(channel = @xively_channel)
xively_topic = "xi/blue/v1/#{@xively_account_id}/d/#{@xively_id}/#{channel}"
@client.subscribe(xively_topic)
topic, message = @client.get
return [topic, message]
end
def Close()
@client.disconnect()
end
end
MQTTトピック
は、Account ID
と Device ID
と Channel名
から決定されるので、publish
/subscribe
する直前に変数を集めて定義しています。
PubXively
へ適当にメッセージを送ると、Xively の QUEUE へ登録されます。そのとき、SubXively
でメッセージの待受をしていると、1つだけ [topic, message]
の配列形式でメッセージの情報を入手します。@client.get
部分をブロック化すると、延々とメッセージを取得し続けるようになり、取得する毎にブロック内の処理を実行するようになります。
このクラスを用いて、実際に Publish/Subscribe
するサンプルが次の 2つのファイルになります。
#!/usr/bin/env ruby
require './xively.rb'
xively_id = ENV['XIVELY_DEVICE_ID']
xively_pass = ENV['XIVELY_DEVICE_PASS']
xively_channel = 'Default Channel 1'
test_message = "test #{xively_channel}"
mb = Xively.new(xively_id, xively_pass, xively_channel)
mb.PubXively(test_message)
mb.Close
#!/usr/bin/env ruby
require './xively.rb'
xively_id = ENV['XIVELY_DEVICE_ID']
xively_pass = ENV['XIVELY_DEVICE_PASS']
xively_channel = 'Default Channel 1'
mb = Xively.new(xively_id, xively_pass, xively_channel)
p mb.SubXively()
mb.Close
今回、デバイスID/Password は環境変数で一つ設定したとおりとなっていますが、インスタンスを作成する毎に別々の ID/Passwordを利用できますので、複数のデバイスも同時に利用できるはずです。たぶん。