Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

スマートメーターの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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away