📈

複数ソースからの温度・湿度情報をGrafanaで表示する

2024/06/25に公開

今年も暑い

“今日も暑ーい1日になりそうです” ほら言ってる わっ超あおられる ♪

ほんとテレビのニュースをみると暑いって話ばかり。なので家で安全に過ごしたい。外に出る場合も温度や温度を把握しておきたい。

参考にした記事

次のデバイス or APIから温度あるいは湿度の情報を得て

次の記事で InfluxDBv2 に格納し Grafana で可視化することができる。

https://qiita.com/yoroyasu/items/56e687df4e8970c5e49a

https://zenn.dev/tanny/articles/a5c0fa5c2230a7

https://qiita.com/hkato/items/173e1008cbec8054787b

やりたいこと

私は SwitchBot Hub2TEMPer も所有してるので、OpenWeather 含め、これらの温湿度情報まとめて表示したい。

Grafana から InfluxDB の Flux Query

Fluxを良くわかってないので間違っているかもしれません。とりあえずユニオンすれば良いかなぁとやって出来たので…他に良い方法があるのかもしれませんが…。

SwitchBotの記事の様に単一の情報元なら次の様なクエリーでGrafanaに表示できる。

from(bucket: "switchbot")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
    r._measurement == "MeterPlus" and
    r._field == "humidity"
  )

じゃあ複数をまとめるには?

fromで取得したデータはstreamという様なので、各情報を一旦streamに入れる。

OpenWeatherMap

上記のOpenWeatherの参考記事の様にTelegrafのOpenWeatherMap PlugIn で取得しているのでCPU, MEMなどの情報も入っている。ここから私はraspiという名前のバケットに格納した。_measurementweatherに天気情報が入っているがcpu, memなども入っているのでweatherでフィルタし、温度の場合はtemperatureでフィルタする。他のAPI or デバイスの_fieldtemperatureなので適当に名前を変えてあげた(家族がわかりやすい様にインターネット情報とした)

openweathermap = 
from(bucket: "raspi")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "weather")
  |> filter(fn: (r) => r["_field"] == "temperature")
  |> set(key: "_field", value: "インターネット情報")

SwitchBot

上記のSwitchBotの参考記事のやり方で行い、switchbotバケットに入れているのと、私は SwitchBot Hub2 からとりあえず温湿度情報を取得している(追加で温湿度計を購入予定)。なので_measurementdevice_idでフィルタし、こちらも_fieldをわかりやすいユニークな名前に変えてあげる。こちらも家族がわかりやす様に設置場所とした。

hub2 =
from(bucket: "switchbot")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "Hub 2")
  |> filter(fn: (r) => r["device_id"] == "_my_device_id__")
  |> filter(fn: (r) => r["_field"] == "temperature")
  |> set(key: "_field", value: "リビングのキャビネット上")

TEMPer

こちらも同様

temper = 
from(bucket: "temper")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "TEMPer")
  |> filter(fn: (r) => r["_field"] == "temperature")
  |> set(key: "_field", value: "リビングの時計下")

まとめる

unionでまとめて必要なカラムだけ残す。

union(tables: [openweathermap, hub2, temper])
  |> keep(columns: ["_field", "_time", "_value"])

結果

openweathermap = 
from(bucket: "raspi")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "weather")
  |> filter(fn: (r) => r["_field"] == "temperature")
  |> set(key: "_field", value: "インターネット情報")

hub2 =
from(bucket: "switchbot")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "Hub 2")
  |> filter(fn: (r) => r["device_id"] == "_your_device_id__")
  |> filter(fn: (r) => r["_field"] == "temperature")
  |> set(key: "_field", value: "リビングのキャビネット上")

temper = 
from(bucket: "temper")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "TEMPer")
  |> filter(fn: (r) => r["_field"] == "temperature")
  |> set(key: "_field", value: "リビングの時計下")

union(tables: [openweathermap, hub2, temper])
  |> keep(columns: ["_field", "_time", "_value"])

同様に湿度はhumidityでフィルタ。

できたグラフ

QNAPでGradana+InfluxDBを動かしReverse Proxyで公開してるので外からスマフォ画面で。

もろもろ

  • Flux Queryがこれで良いのかどうか不明なので勉強する
  • 温湿度センサーを追加購入して寝室も測りたい
  • 夏に負けない

Discussion