目次

統合テスト

ノード機にデータ送信機能を追加

サーバ機のAPIが準備できましたので、統合テストの前にノード機にデータの送信機能を追加します。

HTTPプロトコルでPOSTするので、net/http ライブラリを使います。今回もまずテストプログラムを作って、ライブラリの動作確認をしてみましょう。
net/http ライブラリの使い方は、Rubyの公式ドキュメント へ掲載されていますので、これをほぼそのまま試すことができます。

test-post.rb
require "net/http"
require "uri"
require "json"
 
uri = "http://192.168.1.11/cgi-bin/index.rb?ctrl=data_post"
data = {pressure: 1013.12345, temperature: 25.567}
 
res = Net::HTTP.post_form(URI.parse(uri), {"data"=>data.to_json})
puts res.body

実行結果

ruby test-post.rb 
OK

OKと表示され、サーバ機では /var/log/logger/data-日付.csv ファイルにデータが追加されます。

正しい動作が確認できたら、Workerへ組込みましょう。

worker.rb
require "al_worker"
require "al_worker_timer"
require "i2c"
require "net/http"
require "uri"
require "json"
...
POST_URI = "http://192.168.1.11/cgi-bin/index.rb?ctrl=data_post"
  ...
  def send_data( data )
    AlWorker.log( data )
 
    Net::HTTP.post_form(URI.parse(POST_URI), {"data"=>data.to_json})
  end

統合テスト

では、実行してみましょう。既にWorkerが常駐している場合は、それを終了させてから改めて実行します。

kill `cat /tmp/al_worker.pid`
ruby -I../lib worker.rb

サーバ機のデータファイルに、1分ごとにデータが追加されるのを確認します。

tail -F /var/log/logger/data-*.csv

2019-03-30 11:24:14, 1016.35, 20.1
2019-03-30 11:25:14, 1016.33, 20.1
2019-03-30 11:26:14, 1016.29, 20.1

デバッグ

うまく動作しない場合は、ノード機、サーバ機、それぞれのログファイルを確認して、何が起こっているかを把握します。

ノード機は、常駐するWorkerモジュールを使っているので、/tmp/al_worker.log です。

cat /tmp/al_worker.log

サーバ機は、apacheのcgiインタフェース経由でCGIモジュールを使っているので、/tmp/al_cgi.log です。

cat /tmp/al_cgi.log

今回のように最終的に人の手を介さないシステムでは、意図しない動作が起こった時にはログファイルがあることでトラブルシュートを圧倒的に効率的にすすめることができます。逆にログファイルが無いと、何の手がかりもなくて全くトラブルシュートができないこともあります。
Aloneでは、Rubyの例外を使って自動的にかつ効率的にログファイルを作ります。ログファイルが作られるメリットだけをとってみても、プレーンにコードを記述するよりフレームワークを使う価値はあるように思います。

自動起動の設定

すべてうまく動作している事が確認できたら、RaspberryPiの起動時に Workerも自動的に起動するように設定しておきましょう。

簡単に設定できる、昔ながらの/etc/rc.localファイルに記述する方法を使います。

/etc/rc.local
...
ruby -I /home/pi/alone/lib /home/pi/alone/bin/worker.rb
 
exit 0

最後 exit 0 の直前に起動の指示を書きます。
コマンドラインでテストしていた時は相対パスで記述していましたが、ここではここでは絶対パスで記述します。
ファイルに記述が終わったら、再起動してみてWorkerが自動起動しているか確認してみましょう。

プログラム全体

ノード機のプログラム全体を再掲しておきます。

worker.rb
require "al_worker"
require "al_worker_timer"
require "i2c"
require "net/http"
require "uri"
require "json"
 
ADRS = 0x5c          # LPS25H
NODE = "/dev/i2c-1"  # I2C device node
POST_URI = "http://192.168.1.11/cgi-bin/index.rb?ctrl=data_post"
 
def to_int16( b1, b2 )
  return (b1 << 8 | b2) - ((b1 & 0x80) << 9)
end
 
def to_uint24( b1, b2, b3 )
  return (b1 << 16) | (b2 << 8) | b3
end
 
class Worker1 < AlWorker
  def initialize2()
    @i2c = I2C.create(NODE)
    @i2c.write(ADRS, 0x20, 0x90)
 
    @timer = Timer.periodic( 60 )
    @timer.run() {
      d = get_data()
      send_data( d )
    }
  end
 
  def get_data()
    ret = {}
    buf = @i2c.read(ADRS, 5, 0xa8)
    p_cnt = to_uint24(buf.getbyte(2), buf.getbyte(1), buf.getbyte(0))
    ret[:pressure] = p_cnt.to_f / 4096
 
    t_cnt = to_int16(buf.getbyte(4), buf.getbyte(3))
    ret[:temperature] = 42.5 + t_cnt.to_f / 480
 
    return ret
  end
 
  def send_data( data )
    AlWorker.log( data )
 
    Net::HTTP.post_form(URI.parse(POST_URI), {"data"=>data.to_json})
  end
end
 
worker1 = Worker1.new()
worker1.daemon()