スズハドットコム

IT関連や3Dプリンタの記事、たまに生活のメモを書いていきます。

スマートメーターから消費電力データを取得してグラフ化する ③influxdb&telegrafでデータ取り込み編

こちらの続きです。 suzu-ha.com

作業全体の説明はこちらです。 suzu-ha.com

前回は、スマートメーターから消費電力データを取得してログファイルに出力する部分を作りました。
今回は、このログファイルをデータベースに取り込む部分を作ります。

もくじ


環境

  • Radxa ROCK 4C+
  • Debian bullseye (Radxa公式イメージの rock-4c-plus_debian_bullseye_kde_b60.img)
  • influxdb 2.7.5-1
  • telegraf 1.29.2-1

influxdbのインストール

influxdbのドキュメントには、aptを使ってinfluxdataのリポジトリからインストールする方法は載っていません。
しかし、telegrafのドキュメントには載っています。
telegrafのドキュメントを参考にしてリポジトリを登録し、influxdbをaptでインストールします。

radxa@rock-4c-plus:~$ cd /var/tmp/
radxa@rock-4c-plus:/var/tmp$ curl -s https://repos.influxdata.com/influxdata-archive_compat.key > influxdata-archive_compat.key
radxa@rock-4c-plus:/var/tmp$ echo '393e8779c89ac8d958f81f942f9ad7fb82a25e133faddaf92e15b16e6ac9ce4c influxdata-archive_compat.key' | sha256sum -c && cat influxdata-archive_compat.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg > /dev/null
radxa@rock-4c-plus:/var/tmp$ echo 'deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main' | sudo tee /etc/apt/sources.list.d/influxdata.list
radxa@rock-4c-plus:/var/tmp$ sudo apt update
radxa@rock-4c-plus:/var/tmp$ sudo apt install influxdb2

influxdbを起動します。また、OS起動時に自動起動するようにします。

radxa@rock-4c-plus:/var/tmp$ sudo systemctl enable influxdb
radxa@rock-4c-plus:/var/tmp$ sudo systemctl start influxdb

influxdbの設定

初期設定

http://ROCK 4C+のIPアドレス:8086 を開きます。

ユーザ名、パスワード、Organization名、Bucket名を設定します。

用語集によると、OrganizationとBucketの意味は以下のとおりです。

organization
A workspace for a group of users. All dashboards, tasks, buckets, members, and so on, belong to an organization.

bucket
A bucket is a named location where time series data is stored. All buckets have a retention period. A bucket belongs to an organization.

Organizationはスキーマ、Bucketはデータベースみたいなイメージでしょうか。

APIトークンが表示されます。
後で使用しますが、二度と確認できないらしいのでしっかり保管しておきましょう。

データ保持期間の設定

CONFIGURE LATERボタンをクリックすると、influxdbのトップ画面に戻ります。
左側メニューから Load Data -> Buckets をクリックします。
初期設定画面で作成したバケットの SETTINGS ボタンをクリックします。

Delete Data のところで OLDER THAN をクリックします。
その下のプルダウンで保存期間を設定します。
今回は「1年前の電力と比較出来たらいいなぁ」という思いで13か月にしています。
SAVE CHANGES をクリックして保存します。

この辺りはディスク使用率をみながら追い追い調整していきます。

telegrafのインストール

influxdbインストールのために設定したaptリポジトリからインストールできます。
さっそくインストールします。

radxa@rock-4c-plus:/var/tmp$ sudo apt install telegraf

インストールされたことを確認します。

radxa@rock-4c-plus:/var/tmp$ telegraf --version
Telegraf 1.29.2 (git: HEAD@d92d7073)

telegrafの設定

telegraf configコマンドでコンフィグファイルのテンプレートを出力します。
ログファイルから入力してinfluxdbに出力するので --input-filter file --output-filter influxdb_v2 を指定します。
残りの--aggregator-filter、--processor-filter、--secretstore-filterは使わないので hoge にしています。(ヒットしない文字列なら何でも良いと思われます。)

radxa@rock-4c-plus:~$ cd /var/tmp/
radxa@rock-4c-plus:/var/tmp$ telegraf config --input-filter file --output-filter influxdb_v2 --aggregator-filter hoge --processor-filter hoge --secretstore-filter hoge > telegraf.conf

これをベースに telegraf.conf を作成していきます。
まず inputs.file の部分ですが、以下の定義しかありません。

[[inputs.file]]
  ## Files to parse each interval.  Accept standard unix glob matching rules,
  ## as well as ** to match recursive files and directories.
  files = ["/tmp/metrics.out"]

  ## Character encoding to use when interpreting the file contents.  Invalid
  ## characters are replaced using the unicode replacement character.  When set
  ## to the empty string the data is not decoded to text.
  ##   ex: character_encoding = "utf-8"
  ##       character_encoding = "utf-16le"
  ##       character_encoding = "utf-16be"
  ##       character_encoding = ""
  # character_encoding = ""

  ## Data format to consume.
  ## Each data format has its own unique set of configuration options, read
  ## more about them here:
  ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
  data_format = "influx"


  ## Name a tag containing the name of the file the data was parsed from.  Leave empty
  ## to disable. Cautious when file name variation is high, this can increase the cardinality
  ## significantly. Read more about cardinality here:
  ## https://docs.influxdata.com/influxdb/cloud/reference/glossary/#series-cardinality
  # file_tag = ""

keilogが出力するログはCSVなので、元の設定ファイルの以下の部分を削除して…

  ## Data format to consume.
  ## Each data format has its own unique set of configuration options, read
  ## more about them here:
  ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
  data_format = "influx"

CSV Parser PluginのREADMEにあるConfigurationの内容で置き換えます。

  ## Data format to consume.
  ## Each data format has its own unique set of configuration options, read
  ## more about them here:
  ##   https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
  data_format = "csv"

  ## Indicates how many rows to treat as a header. By default, the parser assumes
  ## there is no header and will parse the first row as data. If set to anything more
  ## than 1, column names will be concatenated with the name listed in the next header row.
  ## If `csv_column_names` is specified, the column names in header will be overridden.
  csv_header_row_count = 0

  ## For assigning custom names to columns
  ## If this is specified, all columns should have a name
  ## Unnamed columns will be ignored by the parser.
  ## If `csv_header_row_count` is set to 0, this config must be used
  csv_column_names = []

  ## For assigning explicit data types to columns.
  ## Supported types: "int", "float", "bool", "string".
  ## Specify types in order by column (e.g. `["string", "int", "float"]`)
  ## If this is not specified, type conversion will be done on the types above.
  csv_column_types = []

  ## Indicates the number of rows to skip before looking for metadata and header information.
  csv_skip_rows = 0

  ## Indicates the number of rows to parse as metadata before looking for header information.
  ## By default, the parser assumes there are no metadata rows to parse.
  ## If set, the parser would use the provided separators in the csv_metadata_separators to look for metadata.
  ## Please note that by default, the (key, value) pairs will be added as tags.
  ## If fields are required, use the converter processor.
  csv_metadata_rows = 0

  ## A list of metadata separators. If csv_metadata_rows is set,
  ## csv_metadata_separators must contain at least one separator.
  ## Please note that separators are case sensitive and the sequence of the separators are respected.
  csv_metadata_separators = [":", "="]

  ## A set of metadata trim characters.
  ## If csv_metadata_trim_set is not set, no trimming is performed.
  ## Please note that the trim cutset is case sensitive.
  csv_metadata_trim_set = ""

  ## Indicates the number of columns to skip before looking for data to parse.
  ## These columns will be skipped in the header as well.
  csv_skip_columns = 0

  ## The separator between csv fields
  ## By default, the parser assumes a comma (",")
  ## Please note that if you use invalid delimiters (e.g. "\u0000"), commas
  ## will be changed to "\ufffd", the invalid delimiters changed to a comma
  ## during parsing, and afterwards the invalid characters and commas are
  ## returned to their original values.
  csv_delimiter = ","

  ## The character reserved for marking a row as a comment row
  ## Commented rows are skipped and not parsed
  csv_comment = ""

  ## If set to true, the parser will remove leading whitespace from fields
  ## By default, this is false
  csv_trim_space = false

  ## Columns listed here will be added as tags. Any other columns
  ## will be added as fields.
  csv_tag_columns = []

  ## Set to true to let the column tags overwrite the metadata and default tags.
  csv_tag_overwrite = false

  ## The column to extract the name of the metric from. Will not be
  ## included as field in metric.
  csv_measurement_column = ""

  ## The column to extract time information for the metric
  ## `csv_timestamp_format` must be specified if this is used.
  ## Will not be included as field in metric.
  csv_timestamp_column = ""

  ## The format of time data extracted from `csv_timestamp_column`
  ## this must be specified if `csv_timestamp_column` is specified
  csv_timestamp_format = ""

  ## The timezone of time data extracted from `csv_timestamp_column`
  ## in case of there is no timezone information.
  ## It follows the  IANA Time Zone database.
  csv_timezone = ""

  ## Indicates values to skip, such as an empty string value "".
  ## The field will be skipped entirely where it matches any values inserted here.
  csv_skip_values = []

  ## If set to true, the parser will skip csv lines that cannot be parsed.
  ## By default, this is false
  csv_skip_errors = false

  ## Reset the parser on given conditions.
  ## This option can be used to reset the parser's state e.g. when always reading a
  ## full CSV structure including header etc. Available modes are
  ##    "none"   -- do not reset the parser (default)
  ##    "always" -- reset the parser with each call (ignored in line-wise parsing)
  ##                Helpful when e.g. reading whole files in each gather-cycle.
  # csv_reset_mode = "none"

その後、全体を編集していきます。
主な編集ポイントは以下のとおりです。

metric_buffer_limit = 100000

動作させたところMetric buffer overflow を起こしたので、metric_buffer_limitを50000から100000に変更しています。
(とりあえず2倍にしてみたもので、数字に根拠はありません。)

token = "xxxxxxxxx"
organization = "org1"
bucket = "bucket1"

influxdbのセットアップ時に発行されたAPIトークン、指定したOrganization名とBucket名を記入します。

[[inputs.file]]
name_override = "BRoute"

measurement名(テーブル名のようなもの)は、デフォルトでinput名になります。
この例の場合は「file」となります。
ちょっとわかりづらいので、「BRoute」という名前にしています。(赤字部分を追加)

files = ["/script/keilog/????????-smartmeter-log.txt"]

読み込み対象のログファイル=keilogのログファイルを指定します。
ファイル名に日付が入る部分は「?」で指定しました。「*」で指定するよりは範囲が狭く誤ヒットの可能性が小さいだろうという判断です。

csv_column_names = ["date","unitid","epc","edt","dataid"]
csv_column_types = ["string","string","string","float","string"]

CSVのカラム名とデータ型を指定します。

csv_timestamp_column = "date"
csv_timestamp_format = "2006/01/02 15:04:05"
csv_timezone = "Asia/Tokyo"

タイムスタンプが記録されるカラムと、タイムスタンプのフォーマット、タイムゾーンを指定します。
タイムスタンプのフォーマットはyyyy/MM/ddなどではなく、特定の日付「Mon Jan 2 15:04:05 MST 2006」を使って表現しなければいけません。Go言語のお作法らしいです。

編集が終わったら、/var/tmp内で編集していたtelegraf設定ファイルを本来のディレクトリ /etc/telegraf にコピーします。

radxa@rock-4c-plus:/var/tmp$ sudo cp telegraf.conf /etc/telegraf/

telegrafを起動します。また、自動起動するようにします。

radxa@rock-4c-plus:/var/tmp$ sudo systemctl enable telegraf
radxa@rock-4c-plus:/var/tmp$ sudo systemctl start telegraf

設定ファイルの不備でエラーが出ていないか確認しましょう。

radxa@rock-4c-plus:/var/tmp$ sudo systemctl status telegraf

取り込み結果の確認

telegrafが正常に起動し、取り込み対象であるkeilogのログファイルが存在していれば、influxdbにデータが取り込まれているはずです。
確認してみます。

influxdbのWeb画面 http://ROCK 4C+のIPアドレス:8086 を開き、ログインします。
左側メニューから Data Explorer を選択します。
下側のFROM欄とFilterは画像のように選択します。
左上の表示方法を選択するプルダウンは、Tableを選択します。

influxdbはデフォルトで一定時間ごとの測定値を集計して表示します。これではkeilogのログファイルの数値と一致せず正しく取り込めているのか分からないので、集計を止めます。
画面右下のAGGREGATE FUNCTIONを CUSTOM にして、その下のチェックをすべて外せばOKです。

これで測定値が表で表示されるはずです。(表示されない場合はSUBMITボタンを押してみてください。)
keilogのログファイルと見比べて、正しく取り込まれていることを確認しましょう。

(参考)不要データの削除

telegrafの設定ミスで変なデータを取り込んでしまったとか、データの取り込みを一からやり直したいという場合は、以下の手順で既存データを削除できます。

influx-cliの設定

データの削除はGUIでは出来なさそうなので、コマンドラインツールのinflux-cliを使用します。
influx-cliはinfluxdbと同時にインストールされます。

まず、influx config createコマンドでinfludbに接続するためのコンフィグを作成します

radxa@rock-4c-plus:/var/tmp$ influx config create --config-name default --host-url http://localhost:8086 --org org1 --token xxxxxxxxx --active
Active  Name    URL                     Org
*       default http://localhost:8086   org1

--config-name は自分で分かる名前であれば何でも良いです。--org にはinfluxdbのセットアップ時に指定したOrganization名、--token にはAPIトークンを指定します。

なお、コンフィグを削除したい場合は、influx config rmコマンドで消せます

(必要に応じて)telegrafの停止
radxa@rock-4c-plus:/var/tmp$ sudo systemctl stop telegraf
データ削除

influx delete コマンドでデータを削除します

influx delete --bucket bucket1 --start 2024-01-01T00:00:00Z --stop 2024-01-31T00:00:00Z

--start から--stop の間のデータが削除されます。