この記事は データ可視化 Advent Calendar 2020の参加記事です。
前回は@kabu10さんの1年間人生の軌跡を記録してみた話でした。記録した後の可視化って楽しいのわかります。Googleデータポータルも便利ですよね。
homeenvdashプロジェクトの紹介
この記事はhomeenvdashというプロジェクトを紹介します。名前の通り家の環境をダッシュボードで見れるように作ったダッシュボードアプリです。
主にPlotlyのDashを使っています。ソースコードはGitHubに公開済みですが今のところはとりあえず動くものです。
動作させるためには2つのシステムが必要でセンサーノードとダッシュボードをそれぞれ用意します。
この記事ではダッシュボード側の概要を紹介します。センサーノードの部分をざっくりいうと、Raspberry Piと温度/湿度/気圧を計測できるBME280をつないでGoogleスプレッドシートに記録しています。センサーノード側は次の記事で紹介します。
そもそもなんでやろうとしたのか
部屋の環境をスマートホーム的にしたくてそういう分野にちょっとした憧れとか夢を感じてます。元々データの可視化インフラが好きなのもあります。センシング機器も好きといえば好きで最近だとCOVI19の件もあってCO2センサーも使ってみたいです。
もう1つは、実家の祖母が今年で98歳となりまして、元気ではありますが目が離せないのもあり見守り用途にも考えています。高齢者にとっては温度湿度はなかなか感じづらいもので、介助者側はいつでも部屋の状況を見れた方がいいためです。
システム全体図
こんな感じの組み合わせです。
特徴を上げると
- センサーノードを作りセンサーをつないで記録する。温度湿度気圧センサーのBME280をラズベリーパイに接続しています。
- ダッシュボード本体はdashがベース
- DBは(用意が面倒だったので)Google Sheet APIでスプレッドシートに入れてます。
- Google Sheet APIの認証はGoogleサービスアカウント認証。内部的に人が介在していないのでIoTの認証に向く。(といってもGoogle Cloud Consoleを使う必要があるのでちょっと面倒)
どうしてdashを使ったのか
ダッシュボード系のサービスだと、外部のサービスではAmbient、Mackerel、Machinist、BIツール系などなど。
ローカルネットワークでインストールして使えるものとしたらGrafanaとかKibanaあたりかなと思ってます。これらでももちろんいいのですが、見た目があんまりシンプルではないのがあって今回は取りやめました。
それならそれと単独のアプリを考えるのですが、たとえばWebならHTML/CSS, Webアプリ向けのフレームワークにDBといった(最近のSSR/SSGベースのシステム構成もありますが)一般的なアプリを作るにはそれなりの時間がかかります。
もちろん時間をかけてもいいのですが、早めに作れて見れるほうがいいですよね。
そこで最近知ったDashを使うことにしました。DashとはReact + Flask + Plotly(グラフを扱うPlotly.jsのPythonバインディング)が入ったアプリ作成フレームワークです。
Dash Documentation & User Guide | Plotly
はんなりPythonの会のDashハンズオンでこのフレームワークを知ったのですが、少ないコードの量から簡単にアプリ化できるので、いずれ使いたいなと思ってました。いいチャンスが巡ってきました。
Dashの特徴としては
- NumPy、Pandas等のデータ分析界隈のライブラリを使える
- 基本的にPythonを書くだけ。htmlタグをラップしたコンポーネントと、Plotlyやブラウザ内イベントの扱いを簡単に呼び出せるコアコンポーネントを組み合わせて作る
- コールバック機能を使って動的な処理もできる。ただし癖があるのである程度習う必要がある
- プラグインシステム
- Jupyter上でも稼働できる(今回は単独アプリとして動かしたいのでJupyterは使っていません
データを取り扱う環境がそろっているなかで、すぐにアプリ化できる点でDashはほかのツールよりは抜きに出ていると思います。
現在の進捗
homeenvdashの特徴は、センサーノードで取得した最新の値を左側に表示して、右側に各センサーのグラフを表示しています。
日付は1日と1週間です。スマホで見ることを想定しているので1週間ぐらいがちょうどいいと思います。
個人的に気圧効果に弱い体質で、気圧の変動が見れてとても助かってます。
Dashで使ってみた機能
自動でインターバル更新
センサー情報は一定の時間ごとに記録しているので、Dash側で常に最新の情報を表示したくなります。Dashは自動でサイトのリロードを行う機能があります。
Live Updates | Dash for Python Documentation | Plotly
間隔はミリ秒らしいので、適当に計算して分単位等で更新するといいと思います。
# intervalの使い方について、詳しくは上のドキュメントにて
# homeenvdashのコードから抜粋しています。実際の動作するコードではありません
# layoutのchild引数のリスト内に書いておいて
dcc.Interval(
id="interval-component",
interval=10 * 60 * 1000, # in milliseconds
n_intervals=0,
),
# 中略
# Input("interval-component", "n_intervals")でdcc.intervalの要素でのタイミングを入力(フック)しています
@app.callback(
[
Output("latest_view", "children"),
Output("graph_tabs", "children"),
],
[
Input("interval-component", "n_intervals"),
Input("date-range-dd", "value"),
Input("location-dd", "value"),
],
)
def update_contents(n, date_dd_value, location_dd_value):
# Output向けのコンポーネントレイアウトを更新したりします
dash-bootstrap-components: Bootstrap 4が使えるhtmlコンポーネント
DashはHTMLの構造はPythonで構築できますが、デザインについてはCSSを読み込むことが通常の方法らしいです。
# Dashのドキュメントでよく見るCSSファイル
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
なのでオリジナルのCSSを指定してDashのコンポーネントにidやClassを設定して、独自のデザインを作ることもできます。ただ今回は手っ取り早く作りたかったので、Bootstrap 4を内蔵したプラグインを使ってみました。
dashコンポーネントをラップしている感じで、同じ感覚で使うことができます。
# homeenvdashのコードから抜粋しています。実際の動作するコードではありません
import dash_bootstrap_components as dbc
# 中略
# bootstrap4のgridを表してる。 md4とかはグリッドの12列の4列のこと。
dbc.Container(
[
dcc.Location(id="url", refresh=False),
html.H2(config.TITLE),
html.Hr(),
dbc.Row(
[
dbc.Col(
[dbc.Label("場所: "), location_dd, latest_view],
md=4,
id="sidebar",
),
dbc.Col(main_view, md=8),
],
),
dcc.Interval(
id="interval-component",
interval=10 * 60 * 1000, # in milliseconds
n_intervals=0,
),
],
)
まとめ
Dashを使ってセンサー情報をダッシュボード化したhomeenvdashプロジェクトの紹介でした。
ダッシュボードのアプリはLinuxサーバーにインストールして、センサーは各部屋にラズパイ+環境センサーをつないで動かしています。見る分には今のところ快適です。
まだ作ったばかりでだれしも使える形にはなっていません。ここからさらに便利にしたくて、今後はwishlistに書いてあるものを進めていきたいです。
- まだデザインがアレなので最近のデザインを学びつつシンプルな見栄えを目指したい
- ラズパイで全部動かすことを考えたけど、dashの依存になってるnumpyのインストールに悩む(raspi用のwheelがあるのですが、x86向けとどうやってパッケージ管理すればいいかわからん)
- DB周りが悩みどころで、家の環境を外部のサービスに預けるのが嫌なこともあるので、センサーノード側はprometheusっぽくプル型にして、ダッシュボード側で情報をため込むような仕組みに変えたい
- センサーノードをたくさん作るときに、よくあるセンサーをつないで設定するだけで動作できるようにしたい
- ラズパイ以外のIoTデバイス(ESP32等)の対応
- PyPiへ公開できるようにしたい
最後に、家の環境を見れるとめっちゃ便利なので、センサー買ってダッシュボードを作ろう!
参考
- Dash for Python Documentation | Plotly
- Dash Bootstrap Components
- Plotly/Dashによるインタラクティブ・データ可視化ハンズオン - connpass
Dashは今年になって入門向けの書籍が発売されています。近々レビューを公開します(遅くて申し訳)が、日本語情報が少ないDashの書籍として貴重なものなのでおススメです!
Python インタラクティブ・データビジュアライゼーション入門 ―Plotly/Dashによるデータ可視化とWebアプリ構築― | |
ASIN : 4254122586 こちらはAmazonアソシエイトプログラム参加リンクです |