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

スマートメーターのBルートでロギングしているデータを以前[ESP8266なガジェットで表示](http://qiita.com/yamori813/items/63c3f93961640ba29b84)してみましたが、ブラウザでも見れるようにしてみました。

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

![おうちACブラウザ.png](https://qiita-image-store.s3.amazonaws.com/0/104066/604752fa-c6e1-f300-8f7b-506f7822f02b.png)


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

![スクリーンショット（2017-04-21 8.24.21）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/394bda7c-ae4d-6c88-e7d2-d17e5688078e.png)


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

```html
<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](https://qiita-image-store.s3.amazonaws.com/0/104066/29783562-5882-072b-4dc7-1dbdb6963072.png)


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

![スクリーンショット（2017-04-21 8.25.05）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/427c2a1d-e9be-52a3-e563-7d3c1c95276c.png)

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

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

# 良いグラフ

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

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

![スクリーンショット（2017-04-28 11.49.32）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/1c726370-2da0-945a-9738-df2d9ce1ac00.png)

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

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

![スクリーンショット（2017-04-28 11.50.04）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/0f493c79-f15d-03ff-87fb-9f2a74e8ac73.png)

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

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

![スクリーンショット（2017-04-28 11.50.23）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/03fbefb5-6cb6-448a-5ca7-a96761279313.png)

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

```html
<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](https://qiita-image-store.s3.amazonaws.com/0/104066/8b415395-c893-389e-d923-7b79f117ebcb.png)

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

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

        }

```

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

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


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

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

        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](https://qiita-image-store.s3.amazonaws.com/0/104066/f7fad8c0-71cc-cc6a-68e4-ac57f82ab65c.png)

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

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

![filename-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/72e3de37-88a2-c7e9-f574-6e7d00fbb381.png)

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

![filename-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/7be6e6a1-b965-71fa-f84e-49e31c46ca3d.png)

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

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

![filename-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/7f3474f1-7fa4-c02b-29dd-86ca9fee4f3c.png)

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

![filename-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/dc5e7dca-bfc6-df54-e90d-3c383155d1f1.png)

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

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

![filename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/c00edc06-ea02-e6ba-00e2-7e9ffc6bc917.png)

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