LoginSignup
3
1

More than 3 years have passed since last update.

Chart.jsでスマートメーターのデータを表示

Last updated at Posted at 2017-04-19

スマートメーターのBルートでロギングしているデータを以前ESP8266なガジェットで表示してみましたが、ブラウザでも見れるようにしてみました。

グラフの画像を作るライブラリなども探してみたのですが、ホストがMIPSで複雑なクロスコンパイルは面倒な事と、ストレージも小さいため、Javascriptで作られたChart.js(2.5.0)を使う事にしてみました。

おうちACブラウザ.png

処理はESP8266の時と同じように生データをcrontabに設定したmrubyスクリプトで処理して、jsonなデータを吐いておくようにしました。

スクリーンショット(2017-04-21 8.24.21).png

こちらのコードはこんな感じです。

<html>
<head>
</head>
<body>
<script src="Chart.min.js"></script>
<script src="jquery.min.js"></script>
<canvas id="myChart" width="200" height="100"></canvas>
<script>
var ctx = document.getElementById("myChart");
var clab = [];
var cdat = [];
var bg = [];
var bd = [];
$(function() {
  if(!window.CanvasRenderingContext2D){
    return;
  }
  $.getJSON("last.json" , function(data) {
    var
      len = data.length;

    for(var i = 0; i < len; i++) {
      clab.push(data[i].day);
      cdat.push(data[i].power);
      bg.push('rgba(54, 162, 235, 0.6)');
      bd.push('rgba(54, 162, 235, 1)');
    }

    var myChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: clab,
            datasets: [{
                label: 'Power',
                data: cdat,
                borderWidth: 1,
            backgroundColor: bg,
            borderColor: bd
            }]
        },
        options: {
          tooltips: {
            callbacks: {
              label: function (tooltipItem, data) {
                return data.datasets[0].data[tooltipItem.index]
                  + " kWh";
              }
            }
          }
        }
    });
  });
});
</script>
</body>
</html>

1日の時間毎のグラフも作ってみました。

スクリーンショット(2017-04-21 8.24.46).png

活動による消費と定常な消費を区別するために就寝時の0時らから5時までの消費電力を4倍(一日分)にして、一日の合計から引いてグラフにしてみました。橙色が活動による消費で、青が定常的な消費です。

スクリーンショット(2017-04-21 8.25.05).png

定常的に消費している電気製品(ほとんどがおそらく冷蔵庫)が大きいような感じがします。

実はロギングが170日くらいので止まってしまい、GPIOでの制御をスリープをやめてリセットに作り替えたついでに作ってみました。数字だけよりも良い感じです。

良いグラフ

日々の違いを知る事で節電への意識が高まると考えています。

最初のグラフは壊れていたデータが含まれていて、数日たって正しいデータのグラフを見てみました。

スクリーンショット(2017-04-28 11.49.32).png

Chart.jsがy軸の設定を自動で行ってくれるのですが、4/22がゼロかと勘違いしてしまい良くないですね。

ためしにbeginAtZero:trueで作ってみました。

スクリーンショット(2017-04-28 11.50.04).png

これだと日々の差が見えにくいですね。

とりあえずロジックでこんな風にしてみました。

スクリーンショット(2017-04-28 11.50.23).png

最低値が0の時は0始まり、最低値が3.0など小数点以下が無い場合はそれよりも1小さい値、それ以外は最低値の小数点以下切り捨ての値で開始。コードはこんな感じです。

<html>
<head>
</head>
<body>
<script src="Chart.min.js"></script>
<script src="jquery.min.js"></script>
<canvas id="myChart" width="200" height="100"></canvas>
<script>
var ctx = document.getElementById("myChart");
var clab = [];
var cdat = [];
var bg = [];
var bd = [];
$(function() {
  if(!window.CanvasRenderingContext2D){
    return;
  }
  $.getJSON("last.json" , function(data) {
    var
      len = data.length;
    var min = 999;

    for(var i = 0; i < len; i++) {
      clab.push(data[i].day);
      cdat.push(data[i].power);
      if(data[i].power < min) {
        min = data[i].power;
      }
      bg.push('rgba(54, 162, 235, 0.6)');
      bd.push('rgba(54, 162, 235, 1)');
    }
    if(min == 0) {
      min = 0;
    } else if(min * 10 % 10 == 0) {
      min = min - 1;
    } else {
      min = Math.floor(min);
    }

    var myChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: clab,
            datasets: [{
                label: 'Power',
                data: cdat,
                borderWidth: 1,
            backgroundColor: bg,
            borderColor: bd
            }]
        },
        options: {
          scales: {
              yAxes: [{
                  ticks: {
                      min:min
                  }
              }]
          },
          tooltips: {
            callbacks: {
              label: function (tooltipItem, data) {
                return data.datasets[0].data[tooltipItem.index]
                  + " kWh";
              }
            }
          }
        }
    });
  });
});
</script>
</body>
</html>

一日のグラフに合計値を入れてみました。

スクリーンショット(2017-05-07 1.42.11).png

CSSで文字を入れているサンプルがありかっこよかったのですが、CSSはよくわからないのでChart.jsのdata:datasets:labelで入れてみました。マウスオーバーの表示がlabelを含んでしまうのでoptionsで調整しました。

        options: {
          tooltips: {
            callbacks: {
              label: function (tooltipItem, data) {
                return data.datasets[0].data[tooltipItem.index]
                  + " kWh";
              }
            }
          }

        }

逆にlabelはいじらずに、凡例をいじる方法もあるようです。

        options: {
          legend: {
            labels: {
              generateLabels: function(chart) {
                labels = Chart.defaults.global.legend.labels.generateLabels(chart);
                labels[0].text = String(sum) + ' kWh';
                return labels;
              }
            }
          }
        }

イメージ保存用にリンクを追加してみました。HTMLとJavascriptに以下を追加します。

<a hidden='true' id='link' download='filename.png'>Save as Image</a>

        options: {
          bezierCurve : false,
          animation: {
            onComplete: done
          },


function done(){
  var url_base64 = document.getElementById('myChart').toDataURL('image/png');
  link.href = url_base64;
  link.hidden = false;
}

スクリーンショット(2017-11-17 12.55.10).png

活動による消費と定常な消費のグラフがイマイチピンとこなないので、いろいろ考えてみました。

こんな日があったとします。

filename-36.png

6時間ごとのグラフを作って見ました。

filename-32.png

傾向はわかりますが、これもイマイチです。

1時間当たりの消費電力の時間数をグラフにしてみました。

filename-33.png

JavaScriptで連想配列をそのまま書いてるので順番がぐちゃぐちゃになるのでsortしてみました。

filename-34.png

数字が大きい方はアクティブに使っていて、少ない方は定常的に使われていると考えられるのではないでしょうか。

合計値も入れてみました。

filename.png

うちは消費が少ないので、こんなグラフになりますが、消費が多い場合にはばらつくので、幅をもたせた集計にするのが良いような気もします。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1