ども、ハゲましておめでとうございます。cloudpackかっぱ (@inokara) です。

はじめに

改めて Raspberry Pi を使って室内の温度を可視化してみたいと思います。
前回は USB の温度計を利用していましたが、今回は「ハック ラズベリーパイ Raspberry Pi 電子工作入門キット。」に付属している温度センサーを利用して温度を収集してみたいと思います。

尚、温度センサーの組み立てに関しては以下の記事を参考にさせて頂きました。

上記の記事を参考にブレッドボードに温度センサー、コンデンサをつないでいきましょう。ハンダ付け不要が嬉しすぎて涙目です。
Raspberry Pi + Datadog + Librato を使って室温を可視化する: ブレッドボードを使って配線

ブレッドボードに繋いで、さらに Raspberry Pi に繋いだ状態です。中央に見える(ジャンパーワイヤの影に隠れて見難いですが…)IC チップは A/D コンバータでアナログの温度センサーがが検知した温度をデジタルデータに変換してくれるようです。

早速…

温度を測ってみるよ

こちらの記事を参考に一秒毎に計測した温度を標準出力に出力するスクリプト。

#!/usr/bin/env ruby

require 'pi_piper'

loop do
  value = 0
  PiPiper::Spi.begin do |spi|
    raw = spi.write [0b01101000,0]
    value = ((raw[0]<<8) + raw[1]) & 0x03FF
  end
  volt = (value * 3300.0)/1024.0
  degree = (volt - 500.0)/10.0
  puts degree
  sleep(1)
end

この冬でも程よく温かい部屋で計測した場合には以下のようにちょっと暑い位の 25 度前後です。

$ sudo ruby ./temperature.rb
24.765625
24.765625
24.765625
25.087890625
24.765625
24.765625

温度を datadog で可視化

では、早速ではありますが収集している温度を datadog と Ruby を使って可視化してみたいと思います。Ruby で datadog にメトリクスを飛ばす場合にはdogapiを利用することでとても簡単にメトリクスを飛ばすことが出来ます。

以下のように dogapi をインストールします。

sudo gem install dogapi --no-ri --no-rdoc -V

インストール後に datadog のダッシュボードから API キーを取得して先ほどのスクリプトを以下のように修正します。

#!/usr/bin/env ruby

require 'rubygems'
require 'pi_piper'
require 'dogapi'

api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
dog = Dogapi::Client.new(api_key)

loop do
  value = 0
  PiPiper::Spi.begin do |spi|
    raw = spi.write [0b01101000,0]
    value = ((raw[0]<<8) + raw[1]) & 0x03FF
  end
  volt = (value * 3300.0)/1024.0
  degree = (volt - 500.0)/10.0
  t =  Time.now.to_i
  dog.emit_point('room.temperature', degree, :host => "raspi.inokara.internal")
  sleep(1)
end

このスクリプトを実行して暫くすると…datadog のダッシュボードに Custom Metrics として以下のように表示されます。
Raspberry Pi + Datadog + Librato を使って室温を可視化する: Datadogのダッシュボードで表示確認
簡単ですね。しかも、美しい。

更に Librato でも可視化

Libratoという可視化サービスにも飛ばしてみたいと思います。datadog と同様に Ruby で Librato にメトリクスを飛ばす場合にはlibrato-metricsという gem を使えば簡単に飛ばすことが出来ます。

以下のようにlibrato-metricsをインストールします。

sudo gem install librato-metrics --no-ri --no-rdoc -V

インストール後に先ほどのスクリプトを以下のように修正します。

#!/usr/bin/env ruby

require 'rubygems'
require 'pi_piper'
require 'dogapi'
require 'librato/metrics'

api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
dog = Dogapi::Client.new(api_key)
Librato::Metrics.authenticate 'xxx@xxxx.com', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
queue = Librato::Metrics::Queue.new

loop do
  value = 0
  PiPiper::Spi.begin do |spi|
    raw = spi.write [0b01101000,0]
    value = ((raw[0]<<8) + raw[1]) & 0x03FF
  end
  volt = (value * 3300.0)/1024.0
  degree = (volt - 500.0)/10.0
  t =  Time.now.to_i
  #puts sprintf( "%10i,%10.1f",t,degree)
  # datadog にデータを投げる
  dog.emit_point('room.temperature', degree, :host => "raspi.inokara.internal")
  # Librato にデータを投げる(但し、一旦キューに突っ込んでから)
  queue.add :temperature => {:measure_time => t, :value => degree, :source => 'room'}
  queue.submit
  sleep(1)
end

スクリプトを修正後、スクリプトを実行して暫くすると Librato のダッシュボードには以下のように表示されます。
Raspberry Pi + Datadog + Librato を使って室温を可視化する: Libratoのダッシュボードで表示確認
おお、datadog の白いページとは異なりますが、これもまたカッコイイ。

尚、librato-metrics を利用してメトリクスを飛ばす場合には以下のように submit メソッドを利用するようですが…

Librato::Metrics.submit :my_metric => {:type => :counter, :value => 1002, :source => 'myapp'}

頻繁にデータ送信を行うような場合にはリクエストの送信量を減らすためにキューを利用することが推奨されているようです。

are sending very many measurements or sending them very often, it will be much higher performance to bundle them up together to reduce your request volume. Use Queue for this.

以下のように書くことでキューを使ったデータ送信が可能になります。

queue = Librato::Metrics::Queue.new
queue.add :temperature => {:measure_time => t, :value => degree, :source => 'room'}

datadog と Librato それぞれ見た目や操作は異なりますが、API やライブラリが用意されているので簡単に可視化することが可能ですな。

fluentd にも温度データを…

fluentd にもスクリプトから温度データを送りたいと思いますので、以下のようにfluent-logger-rubyをインストールします。

sudo gem install fluent-logger --no-ri --no-rdoc -V

インストール後に先ほどのスクリプトを以下のように修正します。

#!/usr/bin/env ruby

require 'rubygems'
require 'dogapi'
require 'librato/metrics'
require 'pi_piper'
require 'fluent-logger'

api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
dog = Dogapi::Client.new(api_key)
Librato::Metrics.authenticate 'xxx@xxxx.com', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
queue = Librato::Metrics::Queue.new
log = Fluent::Logger::FluentLogger.new(nil, :host=>'localhost', :port=>24224)

loop do
  value = 0
  PiPiper::Spi.begin do |spi|
    raw = spi.write [0b01101000,0]
    value = ((raw[0]<<8) + raw[1]) & 0x03FF
  end
  volt = (value * 3300.0)/1024.0
  degree = (volt - 500.0)/10.0
  t =  Time.now.to_i
  #puts sprintf( "%10i,%10.1f",t,degree)
  log.post("room.temperature", {"temperature"=> degree})
  dog.emit_point('room.temperature', degree, :host => "raspi.inokara.internal")
  queue.add :temperature => {:measure_time => t, :value => degree, :source => 'room'}
  queue.submit
  sleep(1)
end

また、fluentd は以下のように設定しておきます。


  type stdout

スクリプトを修正後、スクリプトを実行すると fluentd のログに以下のようなログが記録されます。

2015-01-02 00:54:42 +0900 room.temperature: {"temperature":22.509765625}
2015-01-02 00:54:46 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:54:49 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:54:53 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:54:56 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:54:59 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:55:03 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:55:07 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:55:10 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:55:13 +0900 room.temperature: {"temperature":22.83203125}
2015-01-02 00:55:17 +0900 room.temperature: {"temperature":22.83203125}

一度 fluentd に放り込んでしまうことで、datadog や Librato のような可視化ツールに対してアウトプットするプラグイン(以下のような)があるのでそちらを利用するのもいいかなー。

ということで…

Raspberry Pi と電子工作キットで簡単な温度計測環境を作ることは出来ますし、datadog や Librato を利用すればさくっとその計測結果を可視化することが出来ました。また fluent-logger で fluentd に送ることで各種プラグインで処理することも出来るので fluentd に送るのも面白いことが出来そうです。

元記事はこちらです。
Raspberry Pi で室内の温度を可視化するよー 2015(Datadog と Librato を使って可視化するよー)