mrubyも少しずつ知られてきていて、WindowsやLinux、MacOSX等マルチプラットフォームで色々遊んでいる人が多いことでしょう。そうなってくると、しばらく弄ってみた後はやっぱりマルチプラットフォームで同じようにHTTPで通信してみたいと思いませんか?
例えば、
- mrubyでHTTPのGETとかPOSTとかしてみたり
- mrubyを組み込んだデバイスからTwitterに呟いてみたり
- 各種デバイスからZabbixをつついてみたり
- エアコンを監視してるRaspberry PiからGrowthForecastにデータを送ってグラフ化してみたり
- 組み込みデバイスや低レイヤーなソフトウェアからfluentdにデータを送って解析してみたり
ということで、今回はそういうことをするためにはmruby側でどういう準備をして、どう実装すればいいかの導入部分を説明したいと思います。
HTTP関連のmrbgemsを導入
mrubyは基本的に全ての機能をスタティックにリンクするので、まずは以下のようなHTTPで色々遊ぶためのmrbgemsをリンクする設定をbuild_config.rbに書きましょう。
toolchain :gcc
conf.gembox 'default'
conf.gem :git => 'https://github.com/iij/mruby-pack.git'
conf.gem :git => 'https://github.com/iij/mruby-digest.git'
conf.gem :git => 'https://github.com/mattn/mruby-json.git'
conf.gem :git => 'https://github.com/mattn/mruby-uv.git'
conf.gem :git => 'https://github.com/mattn/mruby-http.git'
conf.gem :git => 'https://github.com/matsumoto-r/mruby-simplehttp.git'
conf.gem :git => 'https://github.com/matsumoto-r/mruby-httprequest.git'
conf.gem :git => 'https://github.com/matsumoto-r/mruby-oauth.git'
conf.gem :git => 'https://github.com/matsumoto-r/mruby-sleep.git'
conf.gem :git => 'https://github.com/matsumoto-r/mruby-zabbix.git'
conf.gem :git => 'https://github.com/matsumoto-r/mruby-growthforecast.git'
conf.gem :git => 'https://github.com/y-ken/fluent-logger-mruby'
end
続いて、マルチプラットフォームでのTCP通信の核となるlibuvが必要になりますので、これをgithubからダウンロードして最新のものをビルドしておきましょう。最近のgithubのlibuvはconfigureスクリプトも用意されてきているので、./configure make make installで基本的にOKなはずです。
そして、上記のようにlibuvをインストール後、build_config.rbにmrbgemの設定を記述した状態で、rakeあるいはmakeすればビルドが完了するはずです。
HTTP通信を色々してみる
では早速、rakeによって生成されたバイナリbin/mrubyを使って、HTTP通信してみましょう。上記のmrbgemを組み込んだmrubyバイナリやlibmruby.aをリンクさせたバイナリは、以下のようなRubyコードを実行することができます。
例えば、任意のURLに対して、普通にGETしたりPOSTするには以下のように書きましょう。
- GETする場合
p h.get("http://blog.matsumoto-r.jp/")
これでHTTPのGETができてしまいます。
で実行してやると良いでしょう。以下、同様に./bin/mrubyで実行できます。
- POSTする場合
h.post("http://127.0.0.1:5125/http/master/access", {
:number => 7,
:color => "#333399",
:mode => "count",
},{
'User-Agent' => "mruby-growthforecast",
})
とかしてやれば、HTTPのPOSTができます。
Twitterに呟いたりTL眺めたりしてみる
次にTwitterに呟いてみたいときは、以下のように書くと良いでしょう。
CONSUMER_SECRET = ''
ACCESS_TOKEN = ''
ACCESS_TOKEN_SECRET = ''
API_URL = 'http://api.twitter.com/1.1/statuses/update.json'
tweet = "happy new year from mruby-oauth"
ex_headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
twitter = OAuth.new(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
response = twitter.post(API_URL, {:status => tweet}, ex_headers)
if response.code.to_i == 200
puts "tweet success: #{tweet}"
else
puts "tweet failed: #{tweet}: bellow response"
p response
end
これて、ツイートできるはずです。
単純にストリームAPIを使わずにタイムラインをmrubyで眺める場合など、以下のように書くと良いでしょう。
CONSUMER_SECRET = ""
ACCESS_TOKEN = ""
ACCESS_TOKEN_SECRET = ""
GET_API_URL = 'http://api.twitter.com/1.1/statuses/home_timeline.json?count='
tweet_num = 10
interval = 60
twitter = OAuth.new(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
new_id = 0
old_id = 0
while
response = twitter.get(GET_API_URL + tweet_num.to_s)
if response.code.to_i == 200
data = JSON::parse(response.body)
if old_id == 0 ¦¦ old_id != data[0]["id"].to_i
new_id = data[0]["id"].to_i
data.reverse.each do ¦d¦
if old_id < d["id"].to_i
puts "[¥e[33m#{d["created_at"]}¥e[m] ¥e[36m#{d["user"]["screen_name"]}¥e[m: #{d["text"]}"
end
end
old_id = new_id
end
else
p response
raise "Request failed: " + response.code.to_s
end
sleep interval
end
これを./bin/mruby timeline.rbとかして実行すると、タイムラインが表示されます。
ZabbixのAPIをつついてみる
ZabbixのAPIのをつつきたい場合は、以下のように書くと良いでしょう。
:url => "http://127.0.0.1/zabbix/api_jsonrpc.php",
:ua => "mruby-zabbix",
:user => "api-admin",
:pass => "api-admin",
}
z = Zabbix::Client.new(config)
data = {
:method => "get",
:object => "host",
:params => {
:output => "extend",
:filter => {
:host => "example.com",
},
},
}
puts "request: #{JSON::stringify(data)}"
puts "response: #{z.post(data)["body"]}"
paramsシンボルにAPIの仕様にのっとったJSONをハッシュ形式で与えてやれば、Zabbixにmrubyを組み込んだ各種デバイスから指示が出せます。
GrowthForecastにデータを送ってみる
エアコンを監視していたり、様々なセンサーデータをRaspberry Piで集めていて、C/C++アプリからグラフ化したいデータをGrowthForecastに送りたい場合は、以下のように書くと良いでしょう。
config = {
:service => "apache",
:section => "scoreboard",
:graph => "worker",
}
data = {
:number => 7,
:color => "#333399",
:mode => "count",
}
p g.post(config, data)
これで、エアコンを監視しているRaspberry Piから、GrowthForecastにデータを送って良い感じに宅内情報をグラフ化する事ができます。
Fluentdにデータを送ってみる
組み込みデバイスにmrubyを組み込んでいたり、低レイヤーなアプリから定期的にログを直接fluentdに投げたい場合は、以下のように書くと良いでしょう。
log.post('myapp.access', {"agent"=>"foo"})
これで簡単にmrubyを組み込んだデバイスや低レイヤーなソフトウェアの内部情報をfluentdに投げて解析する事ができます。
C/C++アプリへの組み込み方
基本はここに書かれているような感じです。これを参考にすると良いでしょう。分からない事があったら、Twitterでmrubyというキーワードを入れて質問すると、誰かが反応してくれると思います。
基本は、
- rakeで生成されたbuild/host/lib/libmruby.aをCアプリにリンクさせる
- リンクさせる際にはbuild/host/lib/libmruby.flags.makから必要なincludeファイルやライブラリを得る
です。libmruby.flags.makから得たcflagsとldflagsとlibsをgccのオプションに渡して、libmruby.aをリンクさせる、という手順です。
例えばmod_mrubyでは以下のようなMakefileを使って、動的に読み込むようにしています。
MRUBY_MAK_FILE := $(MRUBY_ROOT)/build/host/lib/libmruby.flags.mak
ifeq ($(wildcard $(MRUBY_MAK_FILE)),)
MRUBY_CFLAGS =
MRUBY_LDFLAGS =
MRUBY_LIBS =
else
include $(MRUBY_MAK_FILE)
endif
APXS_LDFLAGS=-Wl,-lcrypto,-lm,
CFLAGS=$(INC)
LDFLAGS=$(MRUBY_LDFLAGS)
LIBS=$(LIB) $(MRUBY_LIBS)
これによって生成されたC/C++アプリから上記のRubyコードにデータをC側から渡しつつ実行することで、C/C++アプリから簡単にmruby経由でのHTTP通信が可能になります。
最後に
どうでしょう。このように、mrubyをちょっと弄ってみたら、HTTP通信をしたくなるのはエンジニアの性だと思いますので、上記のサンプルを参考に色々とC/C++アプリやデバイス等から簡単にHTTP通信を楽しんでみて下さい。最近はmrubyで色々なデバイスを動かしている事例を見かけますので、そこからHTTP通信でデータを送受信したりすると面白い事が沢山できるかもしれませんね!
何か良い感じのmrbgemができる事を楽しみにしています。
0 Comments.