目次
こんにちは松原です。
今回は趣味の話。
現在の自宅ではNature RemoのAPIを叩いてメトリクスを作成してGrafanaで可視化をしていた。
しかしNature RemoのAPI経由の温度情報は0.5℃単位で変動が起き、また温度が取得されるインターバルも長かったのでより詳細な情報が欲しかった。(綺麗な折れ線グラフになって欲しかった)
なので温湿度センサモジュールを購入し、そこからメトリクスを作成してGrafanaの可視化をすることにした。
センサ選び
測定精度が高めの精度のSHT35-DISを購入。
https://akizukidenshi.com/catalog/g/gK-15654/
ラズパイ接続
まずはラズパイのどこのIOピンに接続すれば良いかの確認を確認する。
IOピンの状態の表示コマンドを実行。
$ gpio readall
gpioコマンドが見つからなかったので以下のページを参考に
https://raspberrypi.stackexchange.com/questions/54116/gpio-command-not-found
$ docker run --rm --device /dev/ttyAMA0:/dev/ttyAMA0 --device /dev/mem:/dev/mem --privileged -ti python:2 /bin/sh
$ apt-get update && apt-get install git-core sudo
$ git clone https://github.com/WiringPi/WiringPi --depth 1
$ cd WiringPi/
$ ./build
$ gpio readall
IOピンの状態を確認することができた。
root@raspberry:~# gpio readall
+-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| | | 3.3v | | | 1 || 2 | | | 5v | | |
| 2 | 8 | SDA.1 | ALT0 | 1 | 3 || 4 | | | 5v | | |
| 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | |
| 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | IN | TxD | 15 | 14 |
| | | 0v | | | 9 || 10 | 1 | IN | RxD | 16 | 15 |
| 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 |
| 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | |
| 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 |
| | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 |
| 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | |
| 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 |
| 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 |
| | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 |
| 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 |
| 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | |
| 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 |
| 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | |
| 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 |
| 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 |
| | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+
以上の情報から
センサ側ピン | ピン名 | Physical |
---|---|---|
VDD | 3.3v | 1 |
SDA | SDA.1 | 3 |
SCL | SCL.1 | 5 |
ADR | 接続なし | – |
GND | 0v | 6 |
で接続を行う。
I2Cの有効化
$ sudo raspi-config
Raspberry Piの設定画面が開くので以下のように選択を行い有効化する
Interface Options > I2C > YES
最後に
Finish
で完了
I2C通信の確認を行なう。
root@raspberry:~# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- 45 -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
アドレス0x45
にマッピングされていることが確認できる。
Goでメトリクス出力
ここからはGoアプリケーションによってPrometheusのフォーマットのメトリクスを出力するために実装を行なっていく。
i2c-tools
が必要なのでまずはラズパイ側にライブラリをインストール。
$ apt-get install i2c-tools
Goの初期化とモジュール取得
適当な名前のプロジェクトを作成してモジュールをセットアップする。
$ mkdir sht35-exporter
$ cd sht35-exporter
$ go mod init sht35-exporter
Prometheusメトリクスの取得のモジュールと、ちょうど良いセンサ操作モジュールがあったので、それらを取得する。
$ go get github.com/prometheus/client_golang/prometheus
$ go get github.com/d2r2/go-i2c
$ go get github.com/d2r2/go-sht3x
センサ情報を取得してメトリクス取得用サーバーの構築を実装する。
先ほどのアドレス0x45
を設定する。
portは適当に9257
でLISTENするよう設定した。
package main
import (
"github.com/d2r2/go-i2c"
"github.com/d2r2/go-sht3x"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"log"
"net/http"
"time"
)
var temperatureGauge = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "i2c",
Name: "temperature",
})
var humidityGauge = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "i2c",
Name: "humidity",
})
func main() {
prometheus.MustRegister(temperatureGauge)
prometheus.MustRegister(humidityGauge)
go getTemperature()
http.Handle("/metrics", promhttp.Handler())
if err := http.ListenAndServe(":9257", nil); err != nil {
log.Fatal("ListenAndServe:", err)
}
}
func getTemperature() {
i2c, err := i2c.NewI2C(0x45, 1)
if err != nil {
log.Fatal(err)
}
defer i2c.Close()
sensor := sht3x.NewSHT3X()
err = sensor.Reset(i2c)
if err != nil {
log.Fatal(err)
}
for {
temp, rh, err := sensor.ReadTemperatureAndRelativeHumidity(i2c, sht3x.RepeatabilityHigh)
if err != nil {
log.Fatal(err)
}
temperatureGauge.Set(float64(temp))
humidityGauge.Set(float64(rh))
time.Sleep(10 * time.Second)
}
}
sht35-exporter
という名前でビルドを行う。
$ GOOS=linux GOARCH=arm64 go build -trimpath -o sht35-exporter .
バイナリファイルをラズパイの適当な場所に設置する。
今回は/usr/local/bin/
に配置を行なった。
あとはバイナリをを実行する。
$ /usr/local/bin/sht35-exporter &
Grafana Agent
既に設定をしていたので省略。
エージェントのセットアップは以下を参照。
https://grafana.com/blog/2021/01/26/how-to-connect-and-monitor-your-raspberry-pi-with-grafana-cloud/
スクレイピング設定に以下の設定を追加。
- job_name: integrations/i2c
static_configs:
- targets:
- localhost:9257
既にGrafana Agentを起動していたので再起動。
$ systemctl restart grafana-agent.service
結果
Grafana側で Namespace_Name の形でメトリクス名が取得できるので、今回は
温度: i2c_temperature
湿度: i2c_humidity
でメトリクス名を設定。
あとはダッシュボードをいい感じに整えて完成。