PythonとOPCUA、Grafanaを使ってデータをリアルタイムで可視化

FA

FlaskでWebで表示できるようになったが、Webアプリ側を開発しないとリッチなUI表示ができなくなっているので、簡単にリッチなUIができるGrafanaを使用して可視化をできるようにする。

アプリケーション全体像

Flaskとの違いとしては、OPC‐UA serverから直接データベースのmysqlに書き込むようになり、フロントエンドのWebAppは独立したコンテナとした。

Docker Composeの設定

まず、Docker Composeを使って複数のコンテナを設定します。1つは温度データを取得するためのコンテナ(temperature-sensor)、もう1つはデータベースのためのコンテナ(mysql)、そしてGrafanaを使用してデータを可視化するコンテナ(grafana)です。

version: '3'
services:
  temperature-sensor:
    build:
      context: .
      dockerfile: sensor.Dockerfile
    networks:
      - tempnet
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: temperature_db
    networks:
      - tempnet
    volumes:
      - mysql_data:/var/lib/mysql
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    networks:
      - tempnet
    volumes:
      - grafana_data:/var/lib/grafana

volumes:
  mysql_data:
  grafana_data:

networks:
  tempnet:

温度データ取得コンテナの設定

temperature-sensorコンテナは、ダミーの温度データを生成し、MySQLデータベースに保存します。

Dockerfile (sensor.Dockerfile)

FROM python:3.9-slim

RUN pip install opcua pymysql

COPY sensor.py /app/sensor.py

CMD ["python", "/app/sensor.py"]

温度センサースクリプト (sensor.py)

from opcua import Server
import pymysql
import random
import time

server = Server()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
namespace = server.register_namespace("TemperatureSensorNamespace")

objects = server.get_objects_node()
temperature_obj = objects.add_object(namespace, "TemperatureSensor")
temperature = temperature_obj.add_variable(namespace, "Temperature", 0)

temperature.set_writable()

db = pymysql.connect(host="mysql", user="root", password="example", database="temperature_db")

server.start()
print("OPCUA Server Started")

try:
    while True:
        temp = random.uniform(20.0, 25.0)
        print(f"New Temperature: {temp}")
        temperature.set_value(temp)

        cursor = db.cursor()
        cursor.execute("INSERT INTO temperatures (value) VALUES (%s)", (temp,))
        db.commit()

        time.sleep(2)
except KeyboardInterrupt:
    print("Server Stopped")
finally:
    server.stop()
    db.close()

テーブルの作成

MySQLデータベース内に必要なテーブルを作成します。

MySQLコンテナに接続し、テーブルを作成

docker-compose up -d mysql

docker exec -it <mysql_container_id> mysql -u root -p

MySQLシェルで以下のコマンドを実行します:

USE temperature_db;

CREATE TABLE temperatures (
    id INT AUTO_INCREMENT PRIMARY KEY,
    value FLOAT NOT NULL,
    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Grafanaの設定

GrafanaのWebインターフェースにアクセスします。ブラウザでhttp://localhost:3000のURLを開きます

初期設定のユーザー名とパスワードは admin/admin です。ログイン後にパスワード変更を求められます。

データソースを追加します。Grafanaの左サイドバーから「設定 (Configuration)」 > 「データソース (Data Sources)」を選択し、「データソースを追加 (Add data source)」ボタンをクリックします。

「MySQL」を選択し、以下の情報を入力します:

  • Host: mysql:3306
  • Database: temperature_db
  • User: root
  • Password: example

「Save & Test」ボタンをクリックして、接続が成功することを確認します。

ダッシュボードの作成

Grafanaのトップページに戻り、「+」アイコンをクリックし、「Dashboard」 > 「新しいパネル (New panel)」を選択します。

クエリセクションで、データソースとして先ほど追加したMySQLデータソースを選択し、以下のクエリを入力します

SELECT
  timestamp AS "time",
  value
FROM temperatures

画面右上にあるTime SeriesStatに変更することで時系列的変化と最新データを表示できるようにする

ダッシュボードを変更してみると数値データと時系列データを分離することもできます。

結論

これで、PythonとOPCUA、Grafanaを使用して温度データをリアルタイムに可視化する環境が整いました。各アプリケーションをコンテナにすることで、可用性、保守性が増えました。Grafanaを使用することで、リッチなUIが簡単に作成することができました。

今回は温度データの可視化のみでしたが、他にも閾値を設けることでアラートも出すことができるようになったりするので、今後はやってみたいと思います。

他にも、一日あたりの生産量と進捗率を組み合わせて、スケジュールの変更の助けにもなるかもしれません。

コメント

タイトルとURLをコピーしました