Intern

スイッチのON/OFFをGrafanaで時系列表示(4・5日目)

はじめに

Easyfit SingleスイッチのON・OFFデータをNode-REDで取得し、InfluxDBでデータを格納、そのデータをGrafanaで可視化する方法を紹介する。

目次

Docker-Composeを用いた環境設定

DockerComposeとは・・・

複数のDockerコンテナを簡単に定義、管理、実行するためのツール。YAMLファイルを使用してアプリケーションのサービスを設定し、一連のコマンドでそれらのサービスを起動、停止、再構築することが可能。

※ここからの操作はDockerDesktopがインストールされていることが前提となっている


 ① DockerComposeymlファイルを作成 

  ・下記のコマンドを使用して、専用のディレクトリとymlファイルを作成。

mkdir my_docker_project
cd my_docker_project
type nul > docker-compose.yml

 ➁ 作成したymlファイルの編集 

  ・作成したプロジェクトディレクトリの中にあるymlファイルを開き、下記のコードを貼り付ける。

version: '3'
services:
  mosquitto:
    image: eclipse-mosquitto:latest
    container_name: mosquitto
    ports:
      - "1883:1883"
      - "9001:9001"
    volumes:
      - mosquitto_data:/mosquitto/data
      - mosquitto_config:/mosquitto/config
      - mosquitto_log:/mosquitto/log

  influxdb:
    image: influxdb:latest
    container_name: influxdb
    ports:
      - "8086:8086"
    volumes:
      - influxdb-storage:/var/lib/influxdb2

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana-storage:/var/lib/grafana

volumes:
  mosquitto_data:
  mosquitto_config:
  mosquitto_log:
  influxdb-storage:
  grafana-storage:

 ➂ DockerComposeの実行 

  ・下記のコマンドを使用して、DockerComposeを起動。

docker-compose up -d

Node-REDの初期設定

 ① ブラウザでhttp://localhost:1880にアクセス

 ➁「node-red-contrib-influxdb」のインストール

  1. 右上の「ハンバーガーボタン」を押す

  2. 「ノードを追加」タブを選択

  3. 検索欄から「node-red-contrib-influxdb」を追加

InfluxDBの初期設定

 ① ブラウザでhttp://localhost:8086にアクセス

 ➁ InfluxDBのセットアップ


   ・「ユーザー名」「パスワード(+確認)」「組織名」「バケット名」を設定

 ➂ 「APIToken」の作成

   ・ 左の欄にある「」マークを押し、「API TOKENS」を選択。

   ・ 「GENERATE API TOKEN」を押し、「AII Access API Token」を選択。

   ・ 必要な場合説明を記載し、「SAVE」を押す。

   ・ 作成した「API TOKEN」が表示されるので、
     コピーし、忘れないように別の場所に保存するなどして対策する。

Grafanaの初期設定

 ① ブラウザでhttp://localhost:3000にアクセス

 ➁ Grafanaログイン

   ・初回時、ユーザー名・パスワードは「admin」となっている。

   ・ログイン後、新しいパスワードを設定する。

 ➂ データソース( InfluxDB )の追加

 ・ 左側のメニューから「Connections」 > 「Data Sources (データソース)」を選択。

 ・「Add data source (データソースを追加)」をクリック。

 ・「InfluxDB」を選択。

 ➃ InfluxDBの接続情報を入力

 ・下記の通りに変更・入力する

  ① Query LanguageFluxに変更

  ➁ HTTP の URL → 「http://localhost:8086

  ➂ 「Basic auth」がオンになっているか確認

  ➃ InfluxDBで設定した「ユーザー名」を入力

  ➄ InfluxDBで設定した「パスワード」を入力

  ➅ Organization → InfluxDBで設定した「組織名」を入力

  ⑦ TokenInfluxDBで生成したAPIトークンをコピーして貼り付ける。

  ⑧ Default BucketInfluxDBで設定した「バケット名」を入力

    →「Save & Test」をクリックして接続

フロー作成

全体 

 ①「serial in」の設定

  ・「serial in」ノードをドラッグ&ドロップ

  ・ ノードをダブルクリックし、設定
    →ペンマークを押して詳細設定へ

  ・ シリアルポートを設定(デバイスマネージャーで確認)

 ➁「function」の設定

  ・「function」ノードをドラッグ&ドロップ

  ・ ノードをダブルクリックし、下記のコードを挿入

var date = new Date();
var ESP3_Packet = msg.payload;
var Header = ESP3_Packet.slice(1, 5);
var DataLength = 256 * ESP3_Packet + ESP3_Packet;
var RawData = ESP3_Packet.slice(6, 6 + DataLength);
var ERP2_Header = RawData.slice(0, 1).toString("hex");
var EEP = "RPS";
var OriginatorID = "00000000";
var Data1 = "00";
var Data4 = "00000000";
var OptionalData = ESP3_Packet.slice(6 + DataLength, 8 + DataLength);
var SubTelNum = OptionalData.slice(0, 1);
var dBm = OptionalData.slice(1, 2);

switch (ERP2_Header) {
    case "20":
        EEP = "RPS";
        OriginatorID = RawData.slice(1, 5).toString("hex");
        Data1 = RawData.slice(5, 6).toString("hex");
        break;
    case "21":
        EEP = "1BS";
        OriginatorID = RawData.slice(1, 5).toString("hex");
        Data1 = RawData.slice(5, 6).toString("hex");
        break;
    case "22":
        EEP = "4BS";
        OriginatorID = RawData.slice(1, 5).toString("hex");
        Data4 = RawData.slice(5, 9).toString("hex");
        break;
    case "61":
        EEP = "1BS teach-in";
        OriginatorID = RawData.slice(3, 7).toString("hex");
        Data1 = RawData.slice(7, 8).toString("hex");
        break;
    case "62":
        EEP = "4BS teach-in";
        OriginatorID = RawData.slice(3, 7).toString("hex");
        Data4 = RawData.slice(7, 11).toString("hex");
        break;
    default:
        break;
}

var SwitchState = global.get('buttonState_' + OriginatorID) || 0;

if (Data1 === "84" || Data1 === "88") {
    SwitchState = (SwitchState === 0) ? 1 : 0;
    global.set('buttonState_' + OriginatorID, SwitchState);
} else if (Data1 === "00") {
    return null;
}

msg.payload = {
    Time: date.toISOString(),
    OriginatorID: OriginatorID,
    SwitchState: SwitchState, // Ensure this is a number (1 or 0)
    EEP: EEP,
    Data1: Data1,
    Data4: Data4,
    SubTelNum: SubTelNum,
    dBm: dBm,
};

return msg;

 ➂「influxdb out」の設定

  ・「influxdb out」ノードをドラッグ&ドロップ

  ・ ノードをダブルクリックし、以下の内容を記入

  ・「Organization」:設定した組織名
  ・「Bucket」:設定したバケット名
  ・「Measurement」:自身で指定する

  → 「ペンマーク」を押して次の画面へ
  ・「URL」:「http://localhost:8086
  ・「Token」:作成したTokenをペースト

 ➃ それぞれのノードを繋げる(任意でデバッグノードも)

データの可視化

 ① 作成したフローの実行

  ・実行し、デバッグを確認すると押すたびに「ON/OFF (0/1)」が切り替わっているのが確認できる。

 ➁ DataExplorerで確認

  ・次に、InfluxDBのDataExplorerを用いて得られたデータをテーブルグラフで確認する

  1. 左の欄から「DataExplorer」を開く
  2. 作成・指定したバケットを選択
  3. 「Measurement」を選択
  4. 「SwitchState」フィールドを選択
  5. 右下の「AGGREGATE FUNCTION」を「CUSTOM」にし、「mean」をオフ
  6. 「SUBMIT」を押す
  7. 表示形式を「Table」にすることで値の確認も可能

 ➂ Grafanaで可視化

 ・下記のコードをクエリに挿入後、「Apply」を押すことでグラフの可視化ができる

from(bucket: "newbucket")
  |> range(start: -1h)  // 過去1時間のデータを取得
  |> filter(fn: (r) => r._measurement == "switch_state")  // switch_stateの測定値をフィルタリング
  |> filter(fn: (r) => r._field == "SwitchState")  // SwitchStateフィールドをフィルタリング