BME280とCCS811を使って、部屋の環境データを取得してる。

取得したデータはPrometheusに集積して、グラフにして見たりしてる。

台風がきた時のグラフ

しかし、ページを開かないと見れない。

気圧が下がってきている時は頭痛に気をつけたり、 部屋のCO2濃度が上がってきたら換気をするようにしたいが、 ページを見ていないと気がつかない。

そこで、これを常に表示するダッシュボードを作ろうと思った。 常に表示するなら電子ペーパーがいい。

デバイスとして買うならM5 Paperがいいと思ったんだが、 M5 Paperは品薄で買えない。 そこで、画面が小さいけど電子ペーパーをもってるM5Stack CoreInkを買った。

これは200x200の解像度の電子ペーパーと、ESP32を搭載してる。

最初はPrometheusからデータをダウンロードして画面に表示するプログラムをC++で書いて、ESP32で動かそうと考えたが、 考えただけで面倒になった。

他の方法として、Prometheusを動かしているサーバーで、画像を生成して、それをCoreInkでダウンロードして表示する方法を考えた。

CoreInk側

探すと先人がいたので、参考にさせてもらった。

M5Stack CoreInkをWeb経由で取得して表示するやつ作った記録

この記事のCoreInk側のコードを参考にした、 ただし、この記事では、独自の画像フォーマットに変換した物を送っている。 それだとデバッグが大変だし、サイズも大きそうなので、 普通の2値BMPを読む用に変えた。

2値BMPを読むのは、

  • 10-13バイト目にあるヘッダサイズ分を読み飛ばす。
  • 各行のデータは4の倍数バイトでなければならない
    • 200ピクセルは25バイトなので、3バイト余白があって1行28バイトになる。
  • Y軸が下から上なので反転する必要がある

という点に気をつければ、ESP32でもBMPファイルを読める。

サーバー

サーバー側は、

M5Paperでウェブサイトを表示する node.js 版

を参考にした。

これはchromeのヘッドレスモードを使って、用意したHTMLのスクリーンショットを作る。 HTMLだと自由度が高くUIが簡単に定義できそうでいい。 元コードはPNGでそのまま吐いているが、今回はBMPで吐きたい。

そこで、jimpというモジュールを使って、 PNGをBMPに変換しようとしたが、jimpは2値bmpは生成できなかった。

そこで、単純にimagemagicで変換した。

        await spawn("convert", [
          input,
          "-colors","2",
          "+dither",
          "-type","bilevel",
          output ,
        ]);

HTML

最後にダッシュボードになるHTMLを書いた。

PrometheusのAPIで データは習得できる。

取得したデータは、chart.jsでグラフを書いた。

冷蔵庫に貼っておいて離れて見るので、 数字は大きめに書いた。

できあがり