放射線量可視化(3):JSONによるデータ転送

注: この作業によって作成した可視化グラフはhttp://FromTo.Cc/rad/で、結果の定期ツイートは@xckbradで公開されています。

自宅サーバから公開サーバへのデータ転送法検討

さて、現在自宅サーバのPostgreSQL上に所得した放射線のデータが置かれており、 公開サーバにはApacheのサーバが動いているわけですが、 この間のデータ転送法を考えます。大きく分けて、

  • 公開サーバ側から自宅サーバのPostgreSQLにアクセスしてデータを取得する
  • 自宅サーバ側から公開サーバ上に何らかの方法でデータをコピーする

の2つが考えられると思います。しかし前者は、 どちらかといえば不安定な自宅サーバの状態に依存してしまい、 自宅サーバが落ちている場合や、 (動的IPしか今は持っていないので)DDNSのタイムラグなどでアクセスが途絶えた場合などに公開サーバ上でもデータが参照できなくなります。

そのため、今回は後者を採用しました。 前回採用を決定したHighcharts JSは、 JSON形式でのデータ取得が可能であるため、自宅サーバ上でJSONデータを生成し、 それをssh(ssh-agentを利用した都度パスワードなしscp)で転送することにしました。

JSON化のためのデータを準備

cronで毎分起動されるスクリプトexportjsonが、 JSONデータを生成し、公開サーバに転送しています。

JSONデータはPerlのJSONクラスで生成します。 とりあえず初期化はこんな感じ。 cronで起動された時に、他のcronジョブとタイミングをずらすために、20秒冒頭でsleepしてます。

#!/usr/bin/perl
use strict;
use DateTime;
use DateTime::Format::Pg;
use DBI qw(:sql_types);
use DBD::Pg qw(:pg_types);
use JSON;

sleep 20;

my $json_file = "/パス/doserae2-1day.json";
my $dest_json_file = "公開サーバホスト名:/パス/doserae2-1day.json";

my $db = DBI->connect
    ("dbi:Pg:dbname=doserae2", 'getrae', '****パスワード****',
     { RaiseError => 1,
       PrintError => 0,
       AutoCommit => 1, });

if (not $db) {
    die "connecting database failed";
}

データベースから最新1日分のデータを取り出し、 時刻をJavaScript形式(Unix Epoch Timeの1000倍)に直し、 その時点のμSv/hの値を組にして配列のリファレンスにします。 そしてこのリファレンスを@resultという配列に突っ込みます。 念のためμSv/hの値に0.0を足したりして、 数値データであることをしつこく強制しています (時刻は既に1000を掛け算しているので問題ない)。

my @result = ();

eval {
    my $sth = $db->prepare(<<EOT);
SELECT tstamp, usv FROM radiation
WHERE tstamp > CURRENT_TIMESTAMP - INTERVAL '1 day'
ORDER BY id
EOT
    $sth->execute();
    while (my @data = $sth->fetchrow_array()) {
        my $tstamp = $data[0];
        my $usv = $data[1] + 0.0;
        my $dt = DateTime::Format::Pg->parse_datetime($tstamp);
        $dt->set(nanosecond => 0);
        $dt->set(second => 0);
        $dt->set(minute => ($dt->minute - $dt->minute % 5));
        my $jstime = $dt->epoch() * 1000;
        push @result, [$jstime, $usv];
    }
};

if ($@) {
    die "DB Error: $@\n";
}

データのJSON化と転送

そしてJSONオブジェクトを作って@resultをJSONエンコードします。 こいつを一時ファイルにセーブして、 scpを起動してファイルをコピーします (ssh-agentを用いてscpでパスワードなしコピーが出来る準備は別途やっておく)。

my $json = JSON->new->allow_nonref;
my $json_text = $json->encode(\@result);

open my $jsonf, ">:utf8", $json_file or die "cannot open $json_file";
print $jsonf $json_text;
close $jsonf;

system "/usr/bin/scp $json_file $dest_json_file";

これは5分平均を24時間分、288ポイント分のデータを転送しているわけですが、 同様に2時間平均を12日分、1日平均を144日分、同様にJSONファイルを作成します。

あとは、この転送されたJSONのデータを、Highcharts JSでグラフ化するわけです。

続く