1. 記事一覧 >
  2. ブログ記事
category logo

BME280で取得した温湿度気圧をWeb画面に表示する(python,wiringpi,apache)

(更新) (公開)

はじめに

ラズベリーパイとセンサーを組み合わせて温度、湿度、気圧のデータを取得し Web 画面にグラフを表示するシステムを構築しました。いわゆる IoT です。python,wiringpi,apache を使用して、python プログラム(GitHub/wiringpi-python-bme280)でデータを取り出して記録 →Web 画面にグラフを表示までやっていきます。
BME280 で取得した温湿度気圧を Web 画面に表示する(wiringpi-php8 使用)」の Python 版になります。
Raspberry Pi 4 に温湿度気圧センサ BME280 を取り付けてデータを LCD 1602A に表示する」は、センサーと LCD の取り付け、単体動作確認を行っています。今回、こちらの作業の続きになります。

【 wiringpi 】

wiringpi(ワイヤリングパイ)とは、GPIOを操作するライブラリです。C言語、Python用に有ります。

※php7,8に対応したものが無かったため、作成し、githubに公開しています。

php8対応版:wiringpi-php8

php7対応版:wiringpi-php7


環境構築 - apache2、mod_wsgi インストール
環境構築 - pip インストール
bme280.py でデータロギング
Web 画面にグラフを表示
複数の観測ノードに対応


今回の検証環境は、

LABISTS Raspberry Pi 4 STARTER KIT

Raspbian GNU/Linux 10 (buster)

Python 3.7.3

温湿度気圧センサBME280

LCD 1602A

Apache 2.4.38

wiringpi 2.60.1

Flask 1.0.2

になります。

画面の画像は、「BME280で取得した温湿度気圧をWeb画面に表示する(wiringpi-php8使用)」と同じものは使いまわしています。


環境構築 - apache2、mod_wsgi インストール

ラズパイ本体に Web サーバー apache2 をインストールします。まずは、以下の状況を目指します。

$ sudo passwd root
$ su
# apt update
# apt install apache2

以降、sudoを省略し、root権限でコマンドを入力しているものとします。apt installには-yを付けて、? [Y/n]のような確認は省略します。


/var/www/html/index.html が自動的に作成されますので、
http://[ラズパイのIPアドレス]/
にアクセスします。


⇒Apache2 Debian Default Page が表示されればOKです。


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

# apt install -y libapache2-mod-wsgi-py3

【 mod_wsgi 】

mod_wsgiとは、WSGI (Web Server Gateway Interface) インターフェースに準拠した PythonのプログラムをApache HTTP Serverで動作させるためのモジュールです。

【 WSGI 】

Web Server Gateway Interface (WSGI; ウィスキー) は、WebサーバとWebアプリケーションを接続するための、標準化されたインタフェース定義です。

WSGIで動くプログラムは、WebサーバーがWSGIに対応していれば、無改修で動くという理屈になります。


環境構築 - pip インストール

wiringpi インストール

wiringpi を pip でインストールします。今回 Python3 で動かしたいため、pip3 でインストールします。

# pip3 install wiringpi

Flask

Flask を pip でインストールします。※検証環境では、最初からインストールされていました。

# pip3 install Flask

【 Flask 】

Flask(フラスコ/フラスク)はPythonのWebアプリケーションフレームワークです。標準で提供する機能を最小限に保っているため、小規模なアプリに向いています。


bme280.py でデータロギング

wiringpi-python-bme280opt/bme280.pyを使って、データロギングを行います。
opt/bme280.pyは、温湿度気圧センサ BME280 からデータを取得し、LCD 1602A に表示すると同時に、/var/log/bme280log/YYYYMMDD.log にデータを記録し続けるプログラムです。

wiringpi-python-bme280からwiringpi-python-bme280-main.zipをダウンロードして、/home/pi に置かれているものとします。

# cd /home/pi
# unzip wiringpi-python-bme280-main.zip
# cd /home/pi/wiringpi-python-bme280-main/opt
# chmod 755 bme280.py
# ./bme280.py

⇒/var/log/bme280log/YYYYMMDD.log に

# tail /var/log/bme280log/20210627.log
date    time    temp    humid   press
2021/06/27      17:05:00        26.15   47.05   999.00
2021/06/27      17:10:00        25.79   42.96   998.98
2021/06/27      17:15:00        25.91   46.81   999.21
2021/06/27      17:20:00        26.13   50.05   999.40

のように記録されていれば、bme280.pyと温湿度気圧センサ BME280 の動作は、OKです。※5分間隔で記録します。起動して5分後に初めて YYYYMMDD.log に出力されます。


のように LCD に表示されていれば、bme280.py と LCD 1602A の動作は、OKです。


ここまでで確認した内容を図示すると、以下になります。


止めるときは、以下のコマンドになります。

# cd /home/pi/wiringpi-python-bme280-main/opt
# ./bme280.py stop

再起動時の自動起動は、以下の設定になります。

# cd /home/pi/wiringpi-python-bme280-main/opt
# cp -p bme280.py bme280_inc.py lcd1602_inc.py /opt/
# vi /etc/rc.local

exit 0の前に/opt/bme280.pyを追加します。

/opt/bme280.py
exit 0

Web 画面にグラフを表示

グラフ表示用にプログラムを配置します。

# cd /home/pi/wiringpi-python-bme280-main
# cp html/bme280.html /var/www/html/
# cp -r js /var/www/html/
# mkdir /var/www/flask
# cp py/app.wsgi /var/www/flask/
# cp py/app.py /var/www/flask/
# cp py/getlogdata.py /var/www/flask/
# chown -R www-data:www-data /var/www/html /var/www/flask /var/log/bme280log

ここまでで以下の配置になるはずです。
# find /var/www/html /var/www/flask -type f
/var/www/html/js/jquery.flot.crosshair.min.js
/var/www/html/js/jquery-1.8.3.min.js
/var/www/html/js/jquery.flot.min.js
/var/www/html/js/excanvas.min.js
/var/www/html/js/jquery.flot.tooltip.min.js
/var/www/html/bme280.html
/var/www/html/index.html
/var/www/flask/getlogdata.py
/var/www/flask/app.py
/var/www/flask/app.wsgi

apache の設定を作成します。
mod_wsgi を使うため、以下の設定にします。

# vi /etc/apache2/sites-available/flask_wsgi.conf
<VirtualHost *:80>
    ServerName xxx.example.com
    ServerAdmin xxx@example.com

    DocumentRoot /var/www/html

    WSGIDaemonProcess app user=www-data group=www-data threads=5
    WSGIScriptAlias /flask /var/www/flask/app.wsgi
    WSGIChunkedRequest On

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Directory /var/www/flask/>
        WSGIProcessGroup app
        WSGIScriptReloading On
        Require all granted
        Options FollowSymLinks
        AllowOverride All
    </Directory>
</VirtualHost>

設定を反映して、apache を再起動します。

# a2ensite flask_wsgi
# a2dissite 000-default
# systemctl restart apache2

a2ensite flask_wsgi:/etc/apache2/sites-enabled/flask_wsgi.conf が作成されて、flask_wsgi.confが有効になります。これは、/etc/apache2/sites-enabled/flask_wsgi.conf -> ../sites-available/flask_wsgi.confとシンボリックリンクになっています。※手動でシンボリックリンクを作成しても有効にできます。

a2dissite 000-default:000-defaultはapacheのデフォルトの設定で、flask_wsgi.confだけ有効にしたいため、これを無効にしています。こちらは、逆にシンボリックリンクを削除しています。


以下のような流れで、グラフを表示します。

http://[ラズパイのIPアドレス]/bme280.html をブラウザで表示

jQuery の ajax で
http://[ラズパイのIPアドレス]/flask/getlogdata にアクセス

WSGIScriptAlias /flask /var/www/flask/app.wsgiの設定により、/var/www/flask/app.wsgi起動

app.wsgiapp.py の以下のルーティング設定により、getlogdata.py の getlogdata()呼び出し

#!/usr/bin/ python3
# -*- coding: utf-8 -*-

from flask import Flask
import getlogdata
import secrets

app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False

secret = secrets.token_urlsafe(32)
app.secret_key = secret


@app.route("/getlogdata", methods=["GET", "POST"])
def get():
    return getlogdata.getlogdata()


if __name__ == "__main__":
    app.run()


/var/www/flask/getlogdata.py が /var/log/bme280log/YYYYMMDD.log を読み取って、json を返す。

ブラウザに json データが返ってきて、/js/jquery.flot.min.js でグラフ描画
グラフ上にマウスホバーすると、/js/jquery.flot.tooltip.min.js で値を表示

構成を図示すると、以下です。


http://[ラズパイのIPアドレス]/bme280.html にアクセスしてみます。


表示されました!


複数の観測ノードに対応

以下の構成にして複数のノード(ラズパイ+センサ)の結果を一画面に表示します。


観測ノード(ラズパイ+センサ)インストール

観測ノード(ラズパイ+センサ)を作成します。(今回は2台)
以下の構成にしてデータ収集と応答だけに特化します。

上述の手順の通り、 wiringpi、apache、mod_wsgi、Flask をインストールして、wiringpi-python-bme280 からwiringpi-python-bme280-main.zipをダウンロードして、/home/pi に置かれているものとします。

データのロギングを開始します。

# cd /home/pi
# unzip wiringpi-python-bme280-main.zip
# cd /home/pi/wiringpi-python-bme280-main/opt
# chmod 755 bme280.py
# ./bme280.py

ログデータ取得 API の設定をします。(bme280.html、js は必須ではありません。)

# cd /home/pi/wiringpi-python-bme280-main
# cp html/bme280.html /var/www/html/
# cp -r js /var/www/html/
# mkdir /var/www/flask
# cp py/app.wsgi /var/www/flask/
# cp py/app.py /var/www/flask/
# cp py/getlogdata.py /var/www/flask/
# chown -R www-data:www-data /var/www/html /var/www/flask /var/log/bme280log
# vi /etc/apache2/sites-available/flask_wsgi.conf
<VirtualHost *:80>
    ServerName xxx.example.com
    ServerAdmin xxx@example.com

    DocumentRoot /var/www/html

    WSGIDaemonProcess app user=www-data group=www-data threads=5
    WSGIScriptAlias /flask /var/www/flask/app.wsgi
    WSGIChunkedRequest On

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Directory /var/www/flask/>
        WSGIProcessGroup app
        WSGIScriptReloading On
        Require all granted
        Options FollowSymLinks
        AllowOverride All
    </Directory>
</VirtualHost>
# a2ensite flask_wsgi
# a2dissite 000-default
# systemctl restart apache2

curl コマンドで getlogdata.py の確認を確認します。

# curl -X POST --data "TYPE=CURRENT" http://localhost/flask/getlogdata
{"datetime":"2021/06/27 18:37:13","humid":"49.15","press":"999.71","temp":"26.14"}

のように現在値が返ればOKです。


インストール - 画面兼中継サーバー

以下の構成にして画面表示とデータ中継を担います。

上述の手順の通り、apache、mod_wsgi、Flask がインストール済みとします。(wiringpi は不要です。)

中継サーバーは、curl の機能を使うため、pycurl が必要です。

pycurl を pip でインストールします。

# apt install libcurl4-openssl-dev libssl-dev
# pip3 install pycurl

【 pycurlについて 】

libcurlをpython3のプログラムで利用できるものです。今回、先に開発したphp版(itc-lab/wiringpi-php-bme280)がcurlライブラリを使っていたため、pycurl使用縛りとしました。


wiringpi-python-bme280 から wiringpi-python-bme280-main.zip をダウンロードして、/home/piに置かれているものとします。
# cd /home/pi
# unzip wiringpi-python-bme280-main.zip
# cd wiringpi-python-bme280-main
# cp html_relay/bme280s.html html_relay/rooms.json /var/www/html/
# cp -r js /var/www/html/
# mkdir /var/www/flask
# cp py_relay/app_relay.wsgi /var/www/flask/
# cp py_relay/app_relay.py /var/www/flask/
# cp py_relay/proxyproc.py /var/www/flask/
# chown -R www-data:www-data /var/www/html /var/www/flask
# vi /var/www/html/rooms.json

この例のように、ノード(ラズパイ+センサ)の台数分の IP アドレスを設定します。 今回は、
192.168.2.32
192.168.2.38
2台とします。※192.168.2.33、192.168.2.34 はコメントアウトされています。

[
  { "url": "http://192.168.2.38/", "name": "居間" },
  { "url": "http://192.168.2.32/", "name": "洋室1" },
  { "//url": "http://192.168.2.33/", "name": "洋室2" },
  { "//url": "http://192.168.2.34/", "name": "洋室3" },
  {}
]

apache の設定を作成します。
mod_wsgi を使うため、以下の設定にします。

# vi /etc/apache2/sites-available/flask_wsgi.conf
<VirtualHost *:80>
    ServerName xxx.example.com
    ServerAdmin xxx@example.com

    DocumentRoot /var/www/html

    WSGIDaemonProcess app_relay user=www-data group=www-data threads=5
    WSGIScriptAlias /flask /var/www/flask/app_relay.wsgi
    WSGIChunkedRequest On

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Directory /var/www/flask/>
        WSGIProcessGroup app_relay
        WSGIApplicationGroup %{GLOBAL}
        WSGIScriptReloading On
        Require all granted
        Options FollowSymLinks
        AllowOverride All
    </Directory>
</VirtualHost>

WSGIApplicationGroup %{GLOBAL}proxyproc.pyで stdoutをBytesストリームに切り替え(io.BytesIO())→元に戻す という処理があるのですが、アクセスが交錯すると、戻っていない状態で処理が走ることがありました。この設定をすると、正しく動作しました。https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIApplicationGroup.html記載の"sub interpreter"ではなく、"first interpreter"で動作させないといけないパターンだったと思われます。※interpreterとはインタープリタの事で、Python言語を解する実行体、同時通訳者のような意味です。

# a2ensite flask_wsgi
# a2dissite 000-default
# systemctl restart apache2

Web 画面にグラフを表示

以下の仕組みにより、まとめてグラフを表示します。

http://[画面兼中継サーバー]/bme280s.html にアクセスします。



できました!


loading...