大阪近郊で活動するフリーランスエンジニアのブログです 技術情報とか趣味など

*

Raspberry Pi2で室温、水温を計測してグラフ表示する その2

   

前回でRaspberry PiからさくらVPSへ計測したデータを飛ばして登録できるようになった
今回は登録したデータをグラフ表示して可視化する

室温のグラフ描画

グラフ描画にあたって何かいいのがないか探してみるとMetricsGraphics.jsというのがホットらしいので使ってみる
複数の折れ線グラフを表示したいのでマルチラインチャートの例を参考に作成する
しかしこのサンプルがスーパー不親切なので色々とハマる 詳しくは後述

PHPからJSONデータを出力

フロント側でグラフ表示をする前にサーバーのDBからデータを引っ張りだしてやる必要があるのでPHPで実装する
とりあえず最新50件でいいか的な意識低いphpソース

<?php
require_once('./db_conf.php');
$pdo = getPDO();

$ret = array();
$sql_ret = $pdo->query("select *  from stat order by assay desc limit 50")->fetchAll(PDO::FETCH_ASSOC);

$room = array();
$cpu = array();
$water = array();

foreach ($sql_ret as $v) {
        $row = array('date' => $v['assay'], 'value' => $v['room_temp']);
    $room[] = $row;

        $row = array('date' => $v['assay'], 'value' => $v['cpu_temp']);
    $cpu[] = $row;

        $row = array('date' => $v['assay'], 'value' => $v['water_temp']);
    $water[] = $row;
}

$ret[] = $water;
$ret[] = $room;
$ret[] = $cpu;

$pdo = null;

header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
echo json_encode($ret, JSON_PRETTY_PRINT);

MetricsGraphics.js

サーバー側の準備ができたんでjs側の実装
jQuery d3 cssが必要らしいので読み込んでおく

<link rel="stylesheet" href="css/metricsgraphics.css" type="text/css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src='js/d3.js' charset="utf-8"></script>
<script src='js/metricsgraphics.js'></script>

ひとまず何も考えずサンプルをコピる

<div id="stat"></div>
<script>
d3.json('phpの場所', function(data) {
    for (var i = 0; i < data.length; i++) {
        data[i] = MG.convert.date(data[i], 'date');
    }

    MG.data_graphic({
        title: "Multi-Line Chart",
        description: "This line chart contains multiple lines.",
        data: data,
        width: 600,
        height: 200,
        right: 40,
        target: '#stat',
        legend: ['Line 1','Line 2','Line 3'],
        legend_target: '.legend'
    });
});
</script>

動かないので何でやとJSコンソールを覗いてみると大量の謎エラーが吐出されてる
xxxx

調べたらMG.convert.date()という関数が日付変換で年月日までしか対応してないようだ
第2引数にフォーマット文字列でも渡せるのかと思いきやそうでもないらしい ふぁっきん
仕方ないのでMG.convert.dateをコピってMG.convert.datetimeを作る意識低いマン

    MG.convert.date = function(data, accessor, time_format) {
        time_format = (typeof time_format === "undefined") ? '%Y-%m-%d' : time_format;
        data = data.map(function(d) {
            var fff = d3.time.format(time_format);
            d[accessor] = fff.parse(d[accessor]);
            return d;
        });

        return data;
    };
    // コピって追加する
    MG.convert.datetime = function(data, accessor, time_format) {
        time_format = (typeof time_format === "undefined") ? '%Y-%m-%d %H:%M:%S' : time_format;
        data = data.map(function(d) {
            var fff = d3.time.format(time_format);
            d[accessor] = fff.parse(d[accessor]);
            return d;
        });

        return data;
    };

で、グラフ表示は出来たんだけど日付周りが全てアメリカ表記になっている
33333

どっかロケールを1箇所変更すればいいのかとソースを覗いたらゴリゴリのハードコーディングになっていた マジかよ・・・

        this.rolloverOn = function(args) {
            var svg = mg_get_svg_child_of(args.target);
            var fmt;
            switch(args.processed.x_time_frame) {
                case 'seconds':
                    fmt = d3.time.format('%b %e, %Y  %H:%M:%S');
                    break;
                case 'less-than-a-day':
                    fmt = d3.time.format('%b %e, %Y  %I:%M%p');
                    break;
                case 'four-days':
                    fmt = d3.time.format('%b %e, %Y  %I:%M%p');
                    break;
                default:
                    fmt = d3.time.format('%b %e, %Y');
            }
        if (args.time_series && (args.show_years || args.show_secondary_x_label)) {
            var secondary_marks,
                secondary_function, yformat;

            var time_frame = args.processed.x_time_frame;

            switch(time_frame) {
                case 'seconds':
                    secondary_function = d3.time.days;
                    yformat = d3.time.format('%I %p');
                    break;
                case 'less-than-a-day':
                    secondary_function = d3.time.days;
                    yformat = d3.time.format('%b %d');
                    break;
                case 'four-days':
                    secondary_function = d3.time.days;
                    yformat = d3.time.format('%b %d');
                    break;
                default:
                    secondary_function = d3.time.years;
                    yformat = d3.time.format('%Y');
            }

何かキレイに直す方法はないものかと思ったけど面倒になったので直接ハックする意識低いマン

        this.rolloverOn = function(args) {
            var svg = mg_get_svg_child_of(args.target);
            var fmt;
            switch(args.processed.x_time_frame) {
                case 'seconds':
                    fmt = d3.time.format('%Y/%m/%d %H:%M:%S');
                    break;
                case 'less-than-a-day':
                    fmt = d3.time.format('%Y/%m/%d %H:%M');
                    break;
                case 'four-days':
                    fmt = d3.time.format('%Y/%m/%d %H:%M');
                    break;
                default:
                    fmt = d3.time.format('%Y/%m/%d');
            }
        if (args.time_series && (args.show_years || args.show_secondary_x_label)) {
            var secondary_marks,
                secondary_function, yformat;

            var time_frame = args.processed.x_time_frame;

            switch(time_frame) {
                case 'seconds':
                    secondary_function = d3.time.days;
                    yformat = d3.time.format('%I %p');
                    break;
                case 'less-than-a-day':
                    secondary_function = d3.time.days;
                    yformat = d3.time.format('%m/%d');
                    break;
                case 'four-days':
                    secondary_function = d3.time.days;
                    yformat = d3.time.format('%m/%d');
                    break;
                default:
                    secondary_function = d3.time.years;
                    yformat = d3.time.format('%Y');
            }

あとはワードプレスに組み込んで完成
mmmm

完成品は金魚水槽のページから見れます

MetricsGraphics.jsを使ってみましたが、サンプルがdateとかdataとか羅列さてまくってて分かり難い上に色々と不親切でかゆい所に手が届かない印象
他のグラフ描画するjsライブレリと比べ、わざわざ使うメリットは見い出せなかったのが正直なところ

 - JavaScript, php, Raspberry Pi, 金魚 , , ,

  • このエントリーをはてなブックマークに追加
  • にほんブログ村 観賞魚ブログ 金魚へ

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

  関連記事

WordPressでモバイルの時はサイドウィジェットを非表示にしたい

私のブログ重すぎ・・・!? 外出先でモバイルから自分のブログ見るとサイドに置いて …

Raspberry Pi ZEROでGW-450D2(無線LANドングル)を使う

ZERO買っちゃった Pimoroniで入荷しているのを見たのでRaspberr …

Raspberry Pi ZERO + L-03D + IIJmioを使ってネットに接続する

野外のソーラーパネル&ラズパイからネットに繋ぎたい ソーラーパネルで給 …

45cm水槽を修理してみた

大昔に使ってた45cm水槽が出てきたので洗って使おうと思ったんですが水漏れしてま …

Raspberry Pi2で外部から水槽のLEDを点灯する その2

前回でひとまずさくらVPS上のPHPから自宅水槽のLED照明をONにできるように …

エサやりボタンを撤去しました

寒い! 寒くなってきましね。 水温を10度を切り始めたので、プラ舟ページに配置し …

Raspberry Pi2で室温、水温を計測してグラフ表示する

Raspberry Pi2に水温計と温度計を取り付け、10分ごとに室温と水温を計 …

寿恵廣錦を購入しました

また水槽が増えた 寝室に60cm水槽を1つ立ち上げたので何を入れようか考えていた …

みんなのラズパイコンテストにて受賞しました

ラズパイマガジンと日経Linux、日経ソフトウエア様の みんなのラズパイコンテス …

Raspberry Pi2で水槽のLEDを自動点灯/消灯する

先日Raspberry Pi2を購入し、自宅からのストリーミング配信する為あれこ …