0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ラズパイで取得した温湿度気圧(BME680)データをInfluxDBへAPI経由で格納

Posted at

概要

RaspberryPi4と温湿度気圧計(BME680)をつなぎ、データを取得します。同ラズパイ上にInfluxDBを起動し、API経由で、取得したデータを格納します。

BME680をつなぐ

BME680をRaspberry Pi 4で使ってみる #RaspberryPi - Qiita 前の記事を参考に接続し、BME680から値を取得できることを確認します。

InfluxDBを起動

dockerで起動します。

起動&接続確認

docker-composeファイルを作成します

compose.yaml
services:
  influxdb:
    image: influxdb:2.7.6
    container_name: influxdb-local
    volumes:
      - ./docker/influxdb2/data/:/var/lib/influxdb2/
      - ./docker/influxdb2/config/:/etc/influxdb2/
    ports:
      - 8086:8086
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=my_secret_password
      - DOCKER_INFLUXDB_INIT_ORG=MyOrganization
      - DOCKER_INFLUXDB_INIT_BUCKET=MyBucket
docker compose up -d

起動できたらInfluxDBのWebクライアントに接続します http://localhost:8086/ 。初期アカウントはcompose.yamlのenvに指定しているadmin/my_secret_passwordとなります。接続できることを確認します。

APIを使ってみる

API Token発行

APIで格納するためにAPI認証するためのTokenを発行します。

  • 左メニューの「Load Data」 > API TOKENS > 「GENERATE API TOKEN」を押下 > とりあえず「Custom Access API Token」を作成
    • Descriptionに適当にわかり易い名前をつける
    • Resources > Buckets > とりあえず「All Buckets」の「Read」と「Write」にチェックを入れる
    • 「GENERATE」押下で作成

BME680のデータを投入

pythonであれば、ライブラリinfluxdb_clientがあるので、pythonを使いました。温湿度気圧を取得し、APIに格納します。

post_sample.py
import datetime
from dataclasses import dataclass

from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS

TOKEN = "xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxx==" # 先程生成したTOKENを設定
ORGANIZATION = "MyOrganization"
BUCKET = "MyBucket"
URL = f"http://localhost:8086"
MEASUREMENT = "sample"

BME680_ADDRESS = "0077"
BME680_DIR = f"/sys/bus/i2c/devices/1-{BME680_ADDRESS}/iio:device0"


@dataclass
class Bme680Data:
    """Bme680から取得した温湿度気圧データ"""

    humidity: float
    """相対湿度[%]"""

    pressure: float
    """気圧[hPa]"""

    resistance: int
    """抵抗値"""

    milli_temperature: int
    """気温 [ミリ℃]"""

    def get_temperature(self) -> float:
        """単位はミリ℃で格納されているようなので1000で割る(例: 27820℃ -> 27.820℃)"""
        return self.milli_temperature / 1000.0


class Bme680Reader(object):
    """Bme680のデータを取得します"""

    def __init__(self, bme680_dir: str):
        super().__init__()
        self.bme680_dir = bme680_dir

    def fetch(self):
        """Bme680から温湿度気圧データを取得します"""

        with open(
            f"{BME680_DIR}/in_humidityrelative_input", "r", encoding="utf-8"
        ) as humidity_reader, open(
            f"{BME680_DIR}/in_pressure_input", "r", encoding="utf-8"
        ) as pressure_reader, open(
            f"{BME680_DIR}/in_resistance_input", "r", encoding="utf-8"
        ) as resistance_reader, open(
            f"{BME680_DIR}/in_temp_input", "r", encoding="utf-8"
        ) as temp_reader:
            # blackにフォーマット任せたらこうなったけど、なんか奇妙↑

            humidity = float(humidity_reader.readline())
            pressure = float(pressure_reader.readline())
            resistance = int(resistance_reader.readline())
            milli_temp = int(temp_reader.readline())
            humidity_reader.close()
            pressure_reader.close()
            resistance_reader.close()
            temp_reader.close()
            return Bme680Data(humidity, pressure, resistance, milli_temp)

    def __str__(self):
        return self.bme680_dir


def main():
    """ラズパイ上でBME680の温湿度気圧データを取得してInfluxDBへ投入します"""

    write_client = InfluxDBClient(url=URL, token=TOKEN, org=ORGANIZATION)
    write_api = write_client.write_api(write_options=SYNCHRONOUS)

    bme680_reader = Bme680Reader(BME680_DIR)
    bme680_data = bme680_reader.fetch()

    # timezoneをしっかり設定しないと投入される時刻がおかしくなる。
    # JST環境では+9時間後の時刻で投入された・・・
    localTimeZone = datetime.datetime.now().astimezone().tzinfo
    timestamp = datetime.datetime.now(localTimeZone)

    point = (
        Point(MEASUREMENT)
        .tag("sensor", "bme680")  # tagは追加できます
        .field("temperature", bme680_data.get_temperature())
        .field("humidity", bme680_data.humidity)
        .field("pressure", bme680_data.pressure)
        .field("resistance", bme680_data.resistance)
        .time(timestamp)
    )
    write_api.write(bucket=BUCKET, org=ORGANIZATION, record=point)
    print(f"Point: {str(point)}")


if __name__ == "__main__":
    main()

下記のようにスクリプトを起動しデータを投入します。

# InfluxDBのライブラリをインストール
pip3 install influxdb-client --break-system-packages

# 実行
python3 post_sample.py

break-system-packagesしたくない場合は、下記のように仮想環境を作ってから実行します。

# 新しい仮想環境を作成
python3 -m venv .venv
source .venv/bin/activate

pip3 install influxdb-client
python3 post_sample.py

# 仮想環境終了
deactivate

データの確認

  • InfluxDBのWebクライアントに接続します http://localhost:8086/
  • 左メニュー「Data Explorer」 > 「FROM」にバケット一覧が表示されているので「MyBucket」を選択 > Filter/_measurementで「sample」を選択 > Filter/_fieldで「temperature」等を選択 > 「SUBMIT」ボタンを押下
  • グラフが表示されることを確認
    • 表示されない場合はグラフの表示期間(「SUBMIT」ボタンの2つほど左のプルダウン)で表示を広げてみる。

cronに指定

毎分実行するようにします。

crontab -e

下記のようなcron設定を記述します。

LANG=ja_JP.UTF-8
SHELL=/bin/bash

* * * * * python3 path/to/post_sample.py &>>cronrun.log

# 仮想環境の場合
# * * * * * cd "path/to/post_sample_dir" && source .venv/bin/activate && python3 post_sample.py &>>cronrun.log

おまけ

curlでデータ投入するサンプル

サクッとInfluxDBへ投入したいときはこちらが使えます。

TOKEN="xxxxx"
ORGANIZATION="MyOrganization"
BUCKET="MyBucket"
API_URL="http://localhost:8086/api/v2/write?org=${ORGANIZATION}&bucket=${BUCKET}&precision=ns"
MEASUREMENT="sample"

curl -fv \
  -H "Authorization: Token $TOKEN" \
  -H "Content-Type: text/plain; charset=utf-8" \
  -H "Accept: application/json" \
  -d @- \
  -X POST "$API_URL" <<EOS
{{{ここにLineProtocolフォーマットで、改行区切りでバルクインサートできるっぽいがうまくいかなかった}}}
EOS

下記に具体例を示します。

curl -fv \
  -H "Authorization: Token $TOKEN" \
  -H "Content-Type: text/plain; charset=utf-8" \
  -H "Accept: application/json" \
  -d @- \
  -X POST "$API_URL" <<EOS
${MEASUREMENT},sensor=bme680 humidity=61.613,pressure=1006.88,resistance=16422i,temperature=31.59 1719757981665187000
EOS

エポック秒・ミリ秒・マイクロ秒・ナノ秒 早見表

日時 エポック 単位 指数表記
2024年6月30日 23:16:11 1719756971 10
2024年6月30日 23:16:11.629 1719756971629 ミリ秒 13 10^-3
2024年6月30日 23:16:11.629074 1719756971629074 マイクロ秒 16 10^-6
2024年6月30日 23:16:11.629074000 1719756971629074000 ナノ秒 19 10^-9
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?