Go
WebAPI
vue.js
chart.js
IoT

IoT機器のデータをWeb API経由でDBに保存したり時系列でChart表示したりしてみた

More than 1 year has passed since last update.

まえがき

こんにちは!KemoKemoです!٩( 'ω' )و

前回・前々回と2つの記事で、以下を実践して「温度センサー現在値」が扱えるようになりました。

  • Raspberry PiとArduinoを使った温度センサーデータのWeb API化
  • 温度センサーデータの描画

詳しくは以下をご覧ください。

概要

chart.png

今回は、上図のように「温度を時系列でチャート表示するっ!」システムを構築してみます。以下3つのサービスを実装します。

  1. センサー情報収集サービス
  2. チャートデータ用DBのWeb APIサービス
  3. チャート描画サービス

センサー情報収集サービス (Collector Service)

collecting.png

やること

  • 定期的に温度センサーの情報を取得して、現在時刻情報を付与する(この情報をDataSetとします)
  • DataSetをチャートデータ用DB APIにPOSTする
  • 収集する時間間隔を外部設定ファイル(*.yml など)で設定する

作ってみた

今回もgithubにソースコードあります٩( 'ω' )و

KemoKemo/IoT-DB-Sample/collector

APIサービスのURIや収集時間の間隔はcollector.ymlを書き換えて調整します。

collector.yml
# The unit of this parameter is minute
duration: 5

# The address of the sensor API
sensor: http://192.168.111.135:5000/api/v1/sensors

# The address of the DB API
db: http://localhost:9000/sensors

デプロイ

Ubuntu ServerでSystemdを使ってサービス稼働するときの例です。

  • collectorという名前でビルド
  • /usr/local/bin/tempcolディレクトリにcollector.ymlと共に配置
  • /usr/local/bin/tempcol/collectorに実行権限を付与
  • 以下の内容をtempcol.serviceとして/lib/systemd/system/に配置
  • sudo systemctl enable tempcol.serviceして再起動
tempcol.service
[Unit]
Description=a collector service for the temperature

[Service]
Type=simple
WorkingDirectory=/usr/local/bin/tempcol
ExecStart=/usr/local/bin/tempcol/collector
ExecStop=/bin/kill -SIGTERM $MAINPID

[Install]
WantedBy=multi-user.target

チャートデータ用DB API (DB API)

MongoDBをGo言語のAPIサービスでラップして、Web API経由でデータの保存や取り出しができるサービスにしてみました。

DBaaSみたいな構図も最初考えたのですが、マイクロサービスアーキテクチャ的には以下のような理由から現在の構成の方が良いだろうと考えました。

  • DBが別途マイクロサービスで起動してればいい
  • データの保存も取得もWeb API経由で簡単に済ませたい
  • DBの種類によって利用者側のコードに依存があったら嫌だ

また、今回のように「API経由で渡されたJSONデータを保存」「ざっくり貯めてざっくり見る」という用途にはドキュメント型DBのMongoDBがもってこいだと判断しました。

やること

  • 日付情報付きのセンサー情報(DataSet)がPOSTで渡されたらDBに保存
  • GETで要求されたら指定時間区間のDataSet配列(ChartDataとよぶ)を返す

作ってみた

KemoKemo/IoT-DB-Sample/db-api

DB接続を伴うWeb APIの実装には、デコレーターパターンを用います。

  • mgoライブラリを使ってMongoDBに接続してセッションを取得
  • これをデコレーターパターンで修飾したハンドラーに渡す
    • withVars(withData(s, epGetSensors))など
s, err := mgo.Dial(*dbaddr)
if err != nil {
  log.Println("Failed to dial to db", err)
  return exitCodeFailed
}
defer s.Close()

r := gin.Default()
r.Use(cors.Default())
r.GET("/sensors", withVars(withData(s, epGetSensors)))
r.POST("/sensors", withVars(withData(s, epPostSensors)))
err = r.Run(*addr)

詳しくは、以下の書籍の「6章 REST形式でデータや機能を公開する」を参照してください。

Go言語によるWebアプリケーション開発

チャート描画サービス (Chart Service)

chart_service.png

やること

チャート描画のためのデータはWeb APIで取得可能になっているので、以下のようにすれば良さそうです。

  • axiosを使って情報取得
  • vue-chartjsを使ってチャート表示
    • 素のChart.jsを使う手もあるが、vue.jsのリアクティブ性を使いたかった

作ってみた

KemoKemo/IoT-Chart-Sample

以下の素晴らしい記事を参照しながら進めました。この場をお借りしてお礼申し上げますm( _ _ )m

まとめ

  • 温度の変化を時系列で確認できるようになった
  • DBサービスをWeb APIで実現することにより、利用者側のサービスにDBアクセスコードが一切不要になった
  • データ変換と収集を行うマイクロサービスを追加することで、既設のIoT機器側のAPIを一切変更することなく新たなサービスを追加することができた