Inkbirdの温湿度計のデータをRaspberry Piで取得しPrometheusとGrafanaで可視化する

# はじめに
Inkbirdの温湿度計IBS-TH1やIBS-TH2は、専用のスマホアプリを使ってBluetooth経由で取得したデータを参照することができます。
スマホアプリだとグラフの読み込みに時間がかかることやアプリをインストールした端末からしかデータを参照できない不便さがあるので、PrometheusとGrafanaを使ってWebブラウザで参照できるように設定してみました。

スマホアプリだと、こんな感じ。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/b617a0b9-9f05-425f-1c25-5594e4f57f13.png" width="50%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/f4c2cb54-a859-bf54-8abc-a5c3ccd2dbdd.png" width="50%">



# 参考情報

複数のIBS-THシリーズからBluetooth経由でデータを取得するコードは、@c60evaporatorさんの記事 [家の中のセンサデータをRaspberryPiで取得しまくり、スーパーIoTハウスを実現](https://qiita.com/c60evaporator/items/283d0569eba58830f86e) をもとにしています。元記事にはない IBS-TH2やPrometheus exporterの処理を追加し、今回使用しないセンサー向けの処理は省きました。

- [家の中のセンサデータをRaspberryPiで取得しまくり、スーパーIoTハウスを実現](https://qiita.com/c60evaporator/items/283d0569eba58830f86e)
- [インフラ・サービス監視ツールの新顔「Prometheus」入門](https://knowledge.sakura.ad.jp/11633/)
- [PrometheusとGrafanaを組み合わせて監視用ダッシュボードを作る](https://knowledge.sakura.ad.jp/12058/)
- [独自メトリクス取るなら Textfile Collector 独自メトリクス取るなら Textfile Collector](https://qiita.com/sugitak/items/25007e6bbb18ead107af)
- [Inkbird IBS-TH1 のログをbluetoothで取得してAmbientに送信し可視化する](https://qiita.com/junara/items/f396c1c4c15c78cde89f)
- [Inkbird IBS-TH1の値をRaspberryPiでロギング](https://qiita.com/c60evaporator/items/fcc16ac9ab582a25c376)
- [PythonでバイナリをあつかうためのTips](https://qiita.com/pashango2/items/5075cb2d9248c7d3b5d4)
- [Prometheusのストレージのドキュメントをさらっと読んでみて、retentionの設定もしてみる](https://kazuhira-r.hatenablog.com/entry/2019/05/02/232813)
- [Prometheus -> InfluxDB -> Grafana](https://qiita.com/Boccochan/items/ad98a38dc5ec8a0523e9)
- [【Prometheus】弱点を克服。Prometheusのデータを長期保管出来るようにする方法](https://qiita.com/MetricFire/items/40ebab3b70dc1d74b963)
- [Raspberry Piでセンサー情報グラフ化～その１ InfluxDBとGrafanaをインストール](https://www.mikan-tech.net/entry/influxdb-grafana-install)

# 準備するもの
センサーはIBS-TH1かIBS-TH2のいずれかがあれば今回の記事の内容を試すことができます。同じセンサーが複数個あっても設定可能です。

- [Raspberry Pi4 Model B](https://www.amazon.co.jp/dp/B081YD3VL5)
- [Inkbird IBS-TH2 Bluetooth温度計 湿度計](https://www.amazon.co.jp/gp/product/B08WWPSTRS)
    - 同じ型番で温度計のみのものがあります。購入間違いに注意。(私は間違って温度計のみのものを購入したため、改めて購入しなおしました。)
- [Inkbird IBS-TH1 温湿度計 外部プローブ付き](https://www.amazon.co.jp/gp/product/B0774BGBHS)

# ゴール
スマホアプリで見ている情報を、Grafanaで見られるようにします。

<!-- スマホアプリとGrafanaのスクリーンショット -->
3台のセンサーをそれぞれ以下の場所に設置し、データを取得しています。
IBS-TH1 : 外部プローブをワインセラー庫内に入れて温湿度を計測
IBS-TH2 (温湿度計) : ワインセラーを置いている収納スペースの温湿度を計測
IBS-TH2 (温度計のみ) : 書斎の室温を計測

![grafana-20210513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/975826cd-74ab-70b2-333d-7a766bcc4ef4.png)


<!-- # アーキテクチャ -->
<!-- 図を挿入する -->


# 環境構築

## 前提条件
Raspbian OSを使用。

```script:/etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
```

Pythonのコードを実行するディレクトリは、`/home/pi/raspberry-inkbird_ibsth/`
(別のディレクトリにコードや設定ファイルを配置する場合は、後述のcronや設定内のパスも変更が必要です。)


最終的にはこのようなディレクトリ構成となります。
Sensorディレクトリ以下のファイルやディレクトリは、Pythonスクリプトにより自動生成されます。

```console
$ tree /home/pi/raspberry-inkbird_ibsth/
/home/pi/raspberry-inkbird_ibsth/
├── config.ini
├── Data
│   ├── inkbird-ibs-th.prom
│   └── Sensor
│       ├── Inkbird_IBSTH1_1
│       │   └── 2021
│       │       └── Inkbird_IBSTH1_1_202105.csv
│       ├── Inkbird_IBSTH2_1
│       │   └── 2021
│       │       └── Inkbird_IBSTH2_1_202105.csv
│       └── Inkbird_IBSTH2_2
│           └── 2021
│               └── Inkbird_IBSTH2_2_202105.csv
├── DeviceList.csv
├── inkbird_ibsth1.py
├── Log
│   ├── inkbird-ibs-th1.prom
│   └── Sensor
│       ├── sensorlog_210501.log
│       ├── sensorlog_210502.log
│       └── sensorlog_210503.log
└── sensors_to_prometheus.py
``` 

## Python3や必要なライブラリのインストール

```console
$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install python3-dev python3-pip libglib2.0-dev bluez libatlas-base-dev
$ pip3 install bluepy pandas prometheus-client
``` 

## crontabの有効化
Raspberry Pi 4ではcrontabがデフォルトでは有効になっていないため、設定を変更します。

```diff:/etc/rsyslog.conf
- #cron.*            /var/log/cron.log
+ cron.*             /var/log/cron.log
```

設定を変更後、rsyslogを再起動します。

```console
$ sudo /etc/init.d/rsyslog restart
```

```diff:/etc/default/cron
- #EXTRA_OPTS=''
+ EXTRA_OPTS='-L 15'
```

設定を変更後、cronを再起動します。

```
$ sudo /etc/init.d/cron restart
$ sudo /bin/systemctl enable cron.service
```


# Pythonスクリプトの設置

* @c60evaporatorさんの記事 [家の中のセンサデータをRaspberryPiで取得しまくり、スーパーIoTハウスを実現](https://qiita.com/c60evaporator/items/283d0569eba58830f86e) をもとに、IBS-TH2の処理やPrometheus exporterの処理を追加しました。

## ディレクトリの作成

```
$ cd /home/pi
$ mkdir -p ./raspberry-inkbird_ibsth/{Data/Sensor,Log/Sensor}
```


## 設定ファイル

* DeviceList.csv

センサーごとの情報を記載します。ここでは3台のセンサーを設定しています。

```script:/home/pi/raspberry-inkbird_ibsth/DeviceList.csv
DeviceName,SensorType,MacAddress,Timeout,Retry,Offset_Temp,Offset_Humid,API_URL,Token
Inkbird_IBSTH1_1,Inkbird_IBSTH1,10:08:xx:xx:xx:xx,0,2,0,0,,
Inkbird_IBSTH2_1,Inkbird_IBSTH2,49:42:xx:xx:xx:xx,0,2,0,0,,
Inkbird_IBSTH2_2,Inkbird_IBSTH2,49:42:xx:xx:xx:xx,0,2,0,0,,
```

カラムの仕様は、[家の中のセンサデータをRaspberryPiで取得しまくり、スーパーIoTハウスを実現](https://qiita.com/c60evaporator/items/283d0569eba58830f86e) の [設定ファイル](https://qiita.com/c60evaporator/items/283d0569eba58830f86e#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)の項目を参照。

> DeviceName：デバイス名を管理、同種類のセンサが複数あるときの識別用
> SensorType：センサの種類。この値に応じ実行するセンサデータ取得クラスを分ける
> MacAddress：センサのMACアドレス
> Timeout：スキャン時のタイムアウト値（ブロードキャストモードのセンサのみ、推奨値5前後）
> Retry：最大再実行回数（詳細、推奨値2～3）
> Offset_Temp：温度オフセット値（現状未使用）
> Offset_Humid：湿度オフセット値（現状未使用）
> API_URL：APIのURL（Nature Remoのみ使用）
> Token：アクセストークン（Nature Remoのみ使用）

センサーのMACアドレスは、[Inkbird IBS-TH1の値をRaspberryPiでロギング](https://qiita.com/c60evaporator/items/fcc16ac9ab582a25c376)の解説もしくは、Inkbirdのスマホアプリから確認できます。

---

* config.ini

ログやCSVの出力先を記載します。CSVデータは今回の記事内では使用しませんが、取得したデータのログとして残しています。

```script:/home/pi/raspberry-inkbird_ibsth/config.ini
[Path]
CSVOutput  = /home/pi/raspberry-inkbird_ibsth/Data/Sensor
LogOutput  = /home/pi/raspberry-inkbird_ibsth/Log/Sensor
PromOutPut = /home/pi/raspberry-inkbird_ibsth/Data/inkbird-ibs-th.prom
```

CSVOutput : センサーごとに取得したデータをCSVで記録したもの
LogOutput : Pythonスクリプトの動作ログ
PromOutPut : Prometheus node exporterの出力先



## Pythonスクリプト本体　

* characteristicの1~2byteが温度、3~4byteが湿度、それ以降が不明。(バッテリー残量が取得できると思われるが、それらしき値がとれず。[AWS Amplify で自宅の温度や湿度を可視化する IoT アプリ開発にチャレンジしてみよう !](https://aws.amazon.com/jp/builders-flash/202006/amplify-hygrothermograph/?awsf.filter-name=*all) の記事ではnode.jsでバッテリー残量が取得できているのでPythonでなにか方法はありそうな気がします。)

```python:/home/pi/raspberry-inkbird_ibsth/inkbird_ibsth1.py
# coding=UTF-8

from bluepy import btle
import struct

#Inkbird IBS-TH1データ取得クラス
class GetIBSTH1Data():
    def get_ibsth1_data(self, macaddr, sensortype):
        #デバイスに接続
        peripheral = btle.Peripheral(macaddr)
        #IBS-TH2のとき
        if sensortype == 'Inkbird_IBSTH2':
            characteristic = peripheral.readCharacteristic(0x24)
            return self._decodeSensorData_th2(characteristic)
        #IBS-TH1のとき
        elif sensortype == 'Inkbird_IBSTH1':
            characteristic = peripheral.readCharacteristic(0x28)
            return self._decodeSensorData_th1(characteristic)
        else:
            return None

    #IBS-TH2
    def _decodeSensorData_th2(self, valueBinary):
        (temp, humid, unknown1, unknown2, unknown3) = struct.unpack('<hhBBB', valueBinary)
        sensorValue = {
                'SensorType': 'Inkbird_IBSTH2',
                'Temperature': float(temp) / 100,
                'Humidity': float(humid) / 100,
                'unknown1': unknown1,
                'unknown2': unknown2,
                'unknown3': unknown3,
            }
        return sensorValue

    #IBS-TH1
    def _decodeSensorData_th1(self, valueBinary):
        (temp, humid, unknown1, unknown2, unknown3) = struct.unpack('<hhBBB', valueBinary)
        sensorValue = {
                'SensorType': 'Inkbird_IBSTH1',
                'Temperature': temp / 100,
                'Humidity': humid / 100,
                'unknown1': unknown1,
                'unknown2': unknown2,
                'unknown3': unknown3,
            }
        return sensorValue
```

* sensors_to_prometheus.py

```python:/home/pi/raspberry-inkbird_ibsth/sensors_to_prometheus.py
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from bluepy import btle
from inkbird_ibsth1 import GetIBSTH1Data
from datetime import datetime, timedelta
from prometheus_client import Counter, Gauge, write_to_textfile, REGISTRY
import os
import csv
import configparser
import pandas as pd
import requests
import logging
import subprocess
import time

#グローバル変数
global masterdate

######Inkbird IBS-TH1のデータ取得######
def getdata_ibsth1(device):
    #値が得られないとき、最大device.Retry回スキャンを繰り返す
    for i in range(device.Retry):
        try:
            sensorValue = GetIBSTH1Data().get_ibsth1_data(device.MacAddress, device.SensorType)
        #エラー出たらログ出力
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}]')
            sensorValue = None
            continue
        else:
            break

    if sensorValue is not None:
        #POSTするデータ
        data = {
            'DeviceName': device.DeviceName,
            'Date_Master': str(masterdate),
            'Date': str(datetime.today()),
            'Temperature': str(sensorValue['Temperature']),
            'Humidity': str(sensorValue['Humidity']),
        }
        return data
    #値取得できていなかったら、ログ出力してBluetoothアダプタ再起動
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}]')
        restart_hci0(device.DeviceName)
        return None


######データのCSV出力######
def output_csv(data, csvpath):
    dvname = data['DeviceName']
    monthstr = masterdate.strftime('%Y%m')
    #出力先フォルダ名
    outdir = f'{csvpath}/{dvname}/{masterdate.year}'
    #出力先フォルダが存在しないとき、新規作成
    os.makedirs(outdir, exist_ok=True)
    #出力ファイルのパス
    outpath = f'{outdir}/{dvname}_{monthstr}.csv'

    if not os.path.exists(outpath):
        with open(outpath, 'w') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writeheader()
            writer.writerow(data)
    #出力ファイル存在するとき、1行追加
    else:
        with open(outpath, 'a') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writerow(data)

######温度と湿度データを.promファイルに出力######
def output_prometheus_collector(data):
    # メトリック名を指定
    g_temp  = Gauge(data['DeviceName'] + '_temp', 'Gauge')
    g_humid = Gauge(data['DeviceName'] + '_humid','Gauge')

    while True:
        g_temp.set(data['Temperature'])
        g_humid.set(data['Humidity'])

        # promファイルに出力
        write_to_textfile(cfg['Path']['PromOutPut'], REGISTRY)
        break


######Bluetoothアダプタ再起動######
def restart_hci0(devicename):
    passwd = 'RaspberryPiパスワードを入力'
    subprocess.run(('sudo','-S','hciconfig','hci0','down'), input=passwd, check=True)
    subprocess.run(('sudo','-S','hciconfig','hci0','up'), input=passwd, check=True)
    logging.error(f'restart bluetooth adapter [date{str(masterdate)}, device{devicename}]')


######メイン######
if __name__ == '__main__':
    #開始時刻を取得
    startdate = datetime.today()
    #開始時刻を分単位で丸める
    masterdate = startdate.replace(second=0, microsecond=0)
    if startdate.second >= 30:
        masterdate += timedelta(minutes=1)

    #設定ファイルとデバイスリスト読込
    cfg = configparser.ConfigParser()
    cfg.read('./config.ini', encoding='utf-8')
    df_devicelist = pd.read_csv('./DeviceList.csv')
    #全センサ数とデータ取得成功数
    sensor_num = len(df_devicelist)
    success_num = 0

    #ログの初期化
    logname = f"/sensorlog_{str(masterdate.strftime('%y%m%d'))}.log"
    logging.basicConfig(filename=cfg['Path']['LogOutput'] + logname, level=logging.INFO)


    ######デバイスごとにデータ取得######
    for device in df_devicelist.itertuples():
        #Inkbird IBS-TH1
        if device.SensorType in ['Inkbird_IBSTH2','Inkbird_IBSTH1']:
            data = getdata_ibsth1(device)
        #上記以外
        else:
            data = None

        #データが存在するとき、CSV､Prometheusに出力
        if data is not None:
            # Inkbird
            if device.SensorType in ['Inkbird_IBSTH2','Inkbird_IBSTH1']:
                # Prometheus textfile collector出力
                output_prometheus_collector(data)

            #CSV出力
            output_csv(data, cfg['Path']['CSVOutput'])
            #成功数プラス
            success_num+=1


    #処理終了をログ出力
    logging.info(f'[masterdate{str(masterdate)} startdate{str(startdate)} enddate{str(datetime.today())} success{str(success_num)}/{str(sensor_num)}]')
```

# crontabの設定
piユーザーのcrontabに以下の設定を追加します。
毎分スクリプトを実行し、config.iniに指定したファイルにログなどを出力します。
正常に動作しない場合、/var/log/syslogを確認します。


```console
* * * * * cd /home/pi/raspberry-inkbird_ibsth;  /usr/bin/python3 /home/pi/raspberry-inkbird_ibsth/sensors_to_prometheus.py >/dev/null 2>&1
```

# Prometheusのインストールと設定
PrometheusはOSのパッケージマネージャ経由でインストールします。

## node_exporterのインストールと設定
Node ExporterにTextfile Collectorを設定し、指定したディレクトリにある.promファイル内の値をPrometheusが取得できるようにします。

prometheus-node-exporterをインストール。

```console
$ sudo apt-get install prometheus-node-exporter
```

node_exporterを実行するprometheusユーザーを追加。

```console
$ sudo useradd -U -s /sbin/nologin -M -d / prometheus
```

prometheus-node-exporterの起動を確認。

```console
$ systemctl status prometheus-node-exporter
● prometheus-node-exporter.service - node_exporter for Prometheus
   Loaded: loaded (/etc/systemd/system/prometheus-node-exporter.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2021-04-03 22:55:06 JST; 4 weeks 2 days ago
 Main PID: 5305 (prometheus-node)
    Tasks: 16 (limit: 4915)
   CGroup: /system.slice/prometheus-node-exporter.service
```

systemd経由でnode_exporterを管理できるよう、`/etc/systemd/system/prometheus-node-exporter.service`として以下の内容のファイルを作成します。ここで、prometheus-node-exporterの起動オプションとして --collector.textfile.directory の値に前述の前提条件に記載した実行ディレクトリを指定しています。

```script:/etc/systemd/system/prometheus-node-exporter.service
[Unit]
Description=node_exporter for Prometheus

[Service]
Restart=always
User=prometheus
ExecStart=/usr/bin/prometheus-node-exporter --collector.textfile.directory /home/pi/raspberry-inkbird_ibsth/Data
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
SendSIGKILL=no

[Install]
WantedBy=multi-user.target
```

systemdの設定を再読み込みする。

```
$ sudo systemctl daemon-reload
```

## Prometheus Serverのインストールと設定

Prometheusをインストールします。

```console
$ sudo apt-get install prometheus
```

node_exporter同様にsystemdでprometheusを管理できるよう`/etc/systemd/system/prometheus.service`として以下の内容のファイルを作成します。
`--storage.tsdb.retention.time=1y` 取得したデータの保持期間を設定しています。デフォルトは15d(15日間)です。データ容量とディスクサイズ、必要な保持期間とのバランスで設定します。
後述の時系列データベース InfluxDB にデータを保存するため、ここでは15日に設定します。

```script:/etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus - Monitoring system and time series database

[Service]
Restart=always
User=prometheus
ExecStart=/usr/bin/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/var/lib/prometheus/metrics --storage.tsdb.retention.time=15d
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
SendSIGKILL=no

[Install]
WantedBy=multi-user.target
```

収集したデータを格納するディレクトリを--storage.tsdb.pathで指定しています。このディレクトリを作成します。

```console
$ sudo mkdir -p /var/lib/prometheus
$ sudo chown prometheus:prometheus /var/lib/prometheus
```

systemdの設定を再読み込みする。

```
$ sudo systemctl daemon-reload
```

Prometheus Serverの設定はprometheus.ymlに定義します。ここでは、Prometheusがexporterに対しデータを取りに行く間隔`scrape_interval`を1m(1分)に設定しています。

```script:/etc/prometheus/prometheus.yml
global:
  scrape_interval:     1m
  evaluation_interval: 1m


# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093']

scrape_configs:
  - job_name: 'prometheus'

    static_configs:
      - targets: ['localhost:9090']

  - job_name: node
    static_configs:
      - targets: ['localhost:9100']
```

OS起動時にPrometheus Serverが自動起動するようにします。

```console
sudo systemctl enable prometheus.service
```

Prometheus Serverを起動します。

```console
sudo systemctl start prometheus.service
```

## WebブラウザからPrometheusコンソールにアクセスする

Prometheus Serverを起動後、Webブラウザで http://(Raspberry Pi4のIPアドレス):9090/ にアクセスすると、コンソールが表示されます。

<!-- コンソールのスクリーンショット -->
![Prometheus01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/98e104d5-afc4-31c0-2233-e655b6189e51.png)

inkbird-ibs-th.promにPrometheus exporterのデータが正しく出力されていれば、`-insert metric at cursor-`のプルダウンメニューにDeviceList.csvで設定したデバイス名が表示されます。

![Prometheus02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/f750f080-3e68-c189-a222-5df029b4f573.png)

どれかひとつを選択し`Execute`をクリック->`Graph`タブをクリックすると、センサーから取得した値をもとにグラフが描画されます。
![Prometheus03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/e9e07109-b195-52e1-7aad-d9323f28cdb0.png)

# Grafanaのインストールと設定

## Grafanaのインストール
Grafanaは、公式サイトの[Install on Debian or Ubuntu](https://grafana.com/docs/grafana/latest/installation/debian/#install-on-debian-or-ubuntu)に従ってインストールします。

```console
$ curl https://packages.grafana.com/gpg.key | sudo apt-key add -
$ echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
$ sudo apt-get install apt-transport-https
$ sudo apt-get update
$ sudo apt-get install grafana
```

systemdの設定を再読み込みする。

```console
$ sudo /bin/systemctl daemon-reload
```

OS起動時にGrafanaが自動起動するようにします。

```console
$ sudo /bin/systemctl enable grafana-server
```

$ Grafanaを起動します。

```console
$ sudo /bin/systemctl start grafana-server
```

## WebブラウザからGrafanaコンソールにアクセスする
Grafanaを起動後、Webブラウザで http://(Raspberry Pi4のIPアドレス):3000/ にアクセスすると、コンソールが表示されます。
初回は、Username, Passwordとも`admin`でログインできます。ログイン後、パスワードを変更します。

![Grafana01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/bf2ca33a-bcad-399c-043a-d0eac2f2e9b5.png)

## Grafanaの設定

### データソースを指定
PrometheusのデータをGrafanaで読み込むためのデータソースを指定します。
左サイドバーの歯車アイコンから`Data Sources`をクリックします。

![Grafana02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/a73dae0a-91bf-beb6-a16d-166a30a43504.png)

Data Sourcesのタブ内にある`Add data source`をクリックし、表示された時系列データベース一覧から`Prometheus`をクリックします。

![Grafana03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/a5548238-9534-3464-8a24-801c2d68cb71.png)

Nameに適当なデータソース名を入力します。URLは、PrometheusのWebコンソールにアクセスした際のURLを入力します。その他の項目はデフォルトのままとし、画面下部の`Save & Test`をクリックします。`Data source is working`と表示されれば成功です。

![Grafana04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/f82af7e7-2d29-c019-bc61-50b6746168e8.png)

### ダッシュボードを作成
様々なグラフを管理するダッシュボードを追加します。
左サイドバーの＋アイコンから`Dashboard`をクリックします。

![Grafana05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/fb6aabe4-8c90-1722-6ce9-c08289085a72.png)

Queryタブの`Metrics`プルダウンから`Inkbird`を選択し、展開された一覧からパネルに表示するデータを選択します。
![Grafana06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/afac5f76-1d0b-253b-4211-f369b25ba73e.png)

グラフの見た目や追加表示する項目、凡例などは右側の`Panel`タブ内の項目で設定可能です。
今回は、温度と湿度のデータを取得したので、グラフのY軸に設定する単位は`Axes`の`Left Y`にある`Unit`で設定します。

単位に温度を設定する場合。
![Grafana12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/26b3c32a-532e-5c70-0616-cd13e4cc3fdf.png)

単位に湿度を設定する場合
![Grafana13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/5f673006-4115-5e8d-5d7e-4f18f6bc70d3.png)

それぞれのグラフをダッシュボードに追加すると、以下のようになります。
![Grafana14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/222ed934-6436-7c0e-c328-1c9d2cb91fd8.png)

### グラフの設定
`Panel`タブ内の設定です。

![Grafana07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/84eee970-6093-e38a-79aa-938e1377bdce.png)
![Grafana08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/c657e0a2-10f3-dca0-ea4b-d4b0ee5362a5.png)
![Grafana09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/77e12090-cf5a-6ba6-7ed7-404bb6ce4e71.png)
![Grafana10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/dc692a36-a3d1-4911-1a2d-5623c56c722e.png)
![Grafana11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/f467652b-6e21-f14c-d018-dc2b2396e31e.png)


# InfluxDBのインストールと設定

センサーから取得したデータを長期保存するためデータをリモートストレージへ転送し、Grafanaはリモートストレージをデータストアとして使用するように設定を変更します。


## InfluxDBのインストール

InfluxDBのリポジトリを登録します。

```console
$ wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -
$ echo "deb https://repos.influxdata.com/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
```

InfluxDBをインストールします。

```console
$ sudo apt update && sudo apt install -y influxdb
```

OS起動時にサービスが自動起動するように設定します。

```console
$ sudo systemctl unmask influxdb.service
$ sudo systemctl start influxdb
$ sudo systemctl enable influxdb.service
```

## IncludDBの設定

センサーのデータを投入するデータベースを作成します。

```console
$ influx
Connected to http://localhost:8086 version 1.8.6
InfluxDB shell version: 1.8.6
> CREATE DATABASE prometheus
```

データベースが作成されたことが確認できます。

```console
> show databases;
name: databases
name
----
_internal
prometheus
```

prometheus.ymlをに `remote_read`と`remote_write`を追記します。

```script:/etc/prometheus/prometheus.yml
global:
  scrape_interval:     1m
  evaluation_interval: 1m


# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093']

scrape_configs:
  - job_name: 'prometheus'

    static_configs:
      - targets: ['localhost:9090']

  - job_name: node
    static_configs:
      - targets: ['localhost:9100']

remote_write:
  - url: "http://localhost:8086/api/v1/prom/write?db=prometheus"

remote_read:
  - url: "http://localhost:8086/api/v1/prom/read?db=prometheus"
```

サービスを再起動します。

```console
$ sudo systemctl daemon-reload
$ sudo systemctl reload prometheus.service
```

## データベースを確認

```console
 $ influx
Connected to http://localhost:8086 version 1.8.6
InfluxDB shell version: 1.8.6
> use prometheus
Using database prometheus
> show MEASUREMENTS
name: measurements
name
----
Inkbird_IBSTH1_1_humid
Inkbird_IBSTH1_1_temp
Inkbird_IBSTH2_1_humid
Inkbird_IBSTH2_1_temp
Inkbird_IBSTH2_2_humid
Inkbird_IBSTH2_2_temp
(後略)
```
毎分データが登録されているので、Prometheusを再起動した数分後にはこのようなデータが確認できます。

```console
> select * from Inkbird_IBSTH1_1_humid limit 5;
name: Inkbird_IBSTH1_1_humid
time                __name__               instance       job  value
----                --------               --------       ---  -----
1622648491459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 62.87
1622648551459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 62.68
1622648611459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 62.28
1622648671459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 61.98
1622648731459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 61.58
```


## Grafanaの設定 

### データソースを指定

GrafanaのデータソースにInfluxDBを追加します。

![influxdb01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/8acf2b05-aec9-6c3e-86bf-adae929145af.png)

Nameに適当なデータソース名を入力します。　URLは`http://localhost:8086`を指定します。
![influxdb02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/82de5868-8f3b-0f23-8edc-f5efb0d2c108.png)

Databaseは、先ほど作成した `prometheus`　を指定します。 画面下部のSave & Testをクリックします。Data source is workingと表示されれば成功です。
![influxdb03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/7af299d5-50cf-5b1d-e67f-7af69d21dd13.png)

新たにダッシュボードを作成しパネルを追加、もしくは、Prometheusをデータソースとして作成したダッシュボードのパネルを編集します。

QueryタブのデーターソースプルダウンからInfluxDBを選択し、FROMプルダウンからパネルに表示させるデータを選択します。1分毎のデータなので、GROUP BYにはtime(1m)を選択します。

![influxdb04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/3bbd206c-a426-461f-8326-b3597a88a251.png)