工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

データからグラフへ:FlaskとSQLiteを使用したWebジャーニー

実際のデータをキャプチャし(RPi / DHT22)、データベースに保存し(SQLite)、グラフを作成し(Matplotlib)、Webページに表示します(Flask)。

はじめに:データからグラフへ。 FlaskとSQLiteを使用したWebジャーニー

以前のチュートリアルである、FlaskとRaspberryPiを使用したPythonWebServerでは、Flaskで構築されたWebフロントエンドページを介して、物理的な世界と対話する方法を学びました。したがって、次の自然なステップは、現実の世界からデータを収集し、それらをWebページで利用できるようにすることです。とてもシンプル!しかし、たとえば前日の状況を知りたい場合はどうなるでしょうか。または、それらのデータを使用して何らかの分析を行いますか?そのような場合は、データもデータベースに保存する必要があります。

つまり、この新しいチュートリアルでは、次のことを行います。

実際のデータをキャプチャする (気温と相対湿度)DHT22センサーを使用して、それらのデータを読み込みます ローカルのデータベース SQLite; で構築 グラフィックを作成する 履歴データ Matplotlib; を使用する データを表示 JustGage; で作成されたアニメーションの「ゲージ」を使用 Python で作成されたローカルウェブサーバーを介してすべてをオンラインで利用できるようにします および Flask;

ブロック図は、プロジェクト全体のアイデアを示しています。

ステップ1:BoM –部品表

ステップ2:SQLiteのインストール

OK、一般的な考え方は、センサーからデータを収集してデータベースに保存することです。

しかし、どのデータベース「エンジン」を使用する必要がありますか?

市場には多くのオプションがあり、おそらくRaspberryPiとセンサーで最もよく使用される2つはMySQLとSQLiteです。 MySQLは非常によく知られていますが、単純なRaspberryベースのプロジェクトで使用するには少し「重い」ものです(Oracleが所有していることを除けば)。 SQLiteがおそらく最も適切な選択です。サーバーレス、軽量、オープンソースであり、ほとんどのSQLコードをサポートしているため(ライセンスは「パブリックドメイン」です)。もう1つの便利な点は、SQLiteがデータを1つのファイルに保存し、どこにでも保存できることです。

しかし、SQLiteとは何ですか?

SQLiteは、Cプログラミングライブラリに含まれるリレーショナルデータベース管理システムです。他の多くのデータベース管理システムとは対照的に、SQLiteはクライアントサーバーデータベースエンジンではありません。むしろ、それはエンドプログラムに埋め込まれています。

SQLiteは人気のあるパブリックドメインです Webブラウザなどのアプリケーションソフトウェアのローカル/クライアントストレージ用の組み込みデータベースソフトウェアとしての選択。これは、今日、いくつかの広範なブラウザ、オペレーティングシステム、および組み込みシステム(携帯電話など)などで使用されているため、間違いなく最も広く展開されているデータベースエンジンです。 SQLiteには、プロジェクトで使用されているPythonなどの多くのプログラミング言語へのバインディングがあります。

(ウィキペディアの詳細)

ここではあまり多くの詳細を入力しませんが、SQLiteの完全なドキュメントは次のリンクにあります:https://www.sqlite.org/docs.html

だから、それでいい! PiにSQLiteをインストールしましょう

インストール:

以下の手順に従ってデータベースを作成します。

1.次のコマンドを使用してSQLiteをRaspberryPiにインストールします:

  sudo apt-get install sqlite3  

2.プロジェクトを開発するためのディレクトリを作成します:

  mkdir Sensors_Database  

3.次のディレクトリに移動します:

  cd mkdir Sensors_Database /  

3.名前を付けて、 databaseName.db のようなデータベースを作成します (私の場合は「sensorsData.db」):

  sqlite3ensorsData.db  

SQLiteコマンドで入力できる「シェル」が表示されます。後で戻ります。

  sqlite>  

コマンドは、「。help」、「。quit」などの「。」で始まります。

4.シェルを終了してターミナルに戻ります:

  sqlite> .quit  

上記のターミナルの印刷画面は、説明内容を示しています。

上記の「sqlite>」は、SQLiteシェルがどのように表示されるかを示すためだけのものです。入力する必要はありません。自動的に表示されます。

ステップ3:テーブルの作成と作成

DHTセンサーの測定データをデータベースに記録するには、テーブルを作成する必要があります。 (データベースには複数のテーブルを含めることができます)。テーブルの名前は「DHT_data」で、3つの列があり、収集したデータをログに記録します:日付と時間(列名:タイムスタンプ )、温度(列名: temp )、および湿度(列名: hum

テーブルの作成:

テーブルを作成するには、次のようにします。

1.シェルの使用:

最後の手順で作成したデータベースを開きます:

  sqlite3ensorsData.db  

そしてSQLステートメントで入力する:

  sqlite> BEGIN; sqlite> CREATE TABLE DHT_data(timestamp DATETIME、temp NUMERIC、hum NUMERIC); sqlite> COMMIT;  

すべてのSQLステートメントは「;」で終わる必要があります。また、通常、これらのステートメントは大文字を使用して記述されます。必須ではありませんが、良い習慣です。

2.Pythonの使用

  import sqlite3 as liteimport syscon =lite.connect( 'sensorsData.db')with con:cur =con.cursor()cur.execute( "DROP TABLE IF EXISTS DHT_data ")cur.execute(" CREATE TABLE DHT_data(timestamp DATETIME、temp NUMERIC、hum NUMERIC) ") 

GitHubから上記のコードを開きます:createTableDHT.py

ターミナルで実行します:

  python3 createTableDHT.py  

使用する方法がどこであっても、テーブルを作成する必要があります。 「.table」コマンドを使用して、SQLiteシェルで確認できます。データベースシェルを開きます:

  sqlite3> SensorsData.db  

シェルで、 .table を使用すると コマンドを実行すると、作成されたテーブル名が表示されます(この場合、「DHT_table」は1つだけです。その後、 .quit を使用して、シェルを終了します。 コマンド。

  sqlite> .tableDHT_datasqlite> .quit  

テーブルへのデータの挿入:

データベースに3セットのデータを入力してみましょう。各セットには、それぞれ3つのコンポーネント(タイムスタンプ、温度、ハム)が含まれます。コンポーネントのタイムスタンプ 組み込み関数「now」と temp を使用して、実際にシステムから取得されます とハム それぞれoCと%のダミーデータです。

時間は「UTC」であるということです。夏時間などの問題を心配する必要がないので、何が良いのでしょうか。ローカライズされた時間で日付を出力する場合は、後で適切なタイムゾーンに変換するだけです。

テーブルの作成で行われたのと同じ方法で、SQLiteシェルまたはPythonを介して手動でデータを挿入できます。シェルでは、次のようなSQLステートメントを使用してデータごとに実行します(この例では、3回実行します):

  sqlite> INSERT INTO DHT_data VALUES(datetime( 'now')、20.5、30);  

Pythonでは、同じことを一度に実行します。

  import sqlite3 as liteimport syscon =lite.connect( 'sensorsData.db')with con:cur =con.cursor()cur.execute( "INSERT INTO DHT_data VALUES (datetime( 'now')、20.5、30) ")cur.execute(" INSERT INTO DHT_data VALUES(datetime( 'now')、25.8、40) ")cur.execute(" INSERT INTO DHT_data VALUES(datetime( '今 ')、30.3、50) ") 

GitHubから上記のコードを開きます:insertTableDHT.py

Piターミナルで実行:

  python3 insertTableDHT.py  

上記のコードが機能したことを確認するには、SQLステートメントを使用してシェルを介してテーブル内のデータを確認できます。

  sqlite> SELECT * FROM DHT_DATA;  

上記のターミナル印刷画面は、テーブルの行がどのように表示されるかを示しています。

ステップ4:Pythonを使用したデータの挿入と検証

まず、以前と同じように(データの入力と取得)を行いますが、Pythonとデータの両方をターミナルに出力します:

  import sqlite3import sysconn =sqlite3.connect( 'sensorsData.db')curs =conn.cursor()#tabledefにデータを挿入する関数add_data(temp、hum) :curs.execute( "INSERT INTO DHT_data values(datetime( 'now')、(?)、(?))"、(temp、hum))conn.commit()#関数を呼び出してdataadd_data(20.5、30 )add_data(25.8、40)add_data(30.3、50)#print database contentprint( "\ nEntire database contents:\ n")for row in curs.execute( "SELECT * FROM DHT_data"):print(row)#close the useconn.close()後のデータベース 

上記のコードをGitHubから開きます:insertDataTableDHT.pyそしてそれをターミナルで実行します:

  python3 insertDataTableDHT.py  

上記のターミナル印刷画面に結果が表示されます。

ステップ5:DHT22温度および湿度センサー

これまでのところ、データベースにテーブルを作成しました。このテーブルには、センサーが読み取るすべてのデータが保存されます。そこにいくつかのダミーデータも入力しました。次に、実際のデータを使用して、テーブル、気温、相対湿度に保存します。そのために、古くて良いDHTxx(DHT11またはDHT22)を使用します。 ADAFRUITサイトは、これらのセンサーに関する優れた情報を提供します。ベロー、そこから取得した情報:

概要

低コストのDHT温度および湿度センサーは非常に基本的で低速ですが、基本的なデータロギングを行いたい愛好家には最適です。 DHTセンサーは、静電容量式湿度センサーとサーミスタの2つの部分で構成されています。内部には、アナログからデジタルへの変換を行い、温度と湿度でデジタル信号を吐き出す非常に基本的なチップもあります。デジタル信号は、どのマイクロコントローラーを使用してもかなり簡単に読み取ることができます。

DHT11とDHT22

DHTセンサーには2つのバージョンがあり、見た目は少し似ていてピン配置は同じですが、特性が異なります。仕様は次のとおりです。

DHT11(通常は青)

5%の精度で20〜80%の湿度の読み取りに適しています0〜50°Cの温度の読み取りに適しています±2°Cの精度1 Hz以下のサンプリングレート(1秒に1回)

DHT22(通常は白)

2〜5%の精度で0〜100%の湿度測定値に適しています-40〜125°Cの温度測定値に適しています±0.5°Cの精度0.5 Hz以下のサンプリングレート(2秒に1回)

ご覧のとおり、DHT22は少し広い範囲で少し正確で、優れています。どちらも1つのデジタルPINを使用しており、1秒に1回(DHT11)または2回(DHT22)しか照会できないという点で「遅い」です。

両方のセンサーが正常に機能して、屋内情報をデータベースに保存します。

DHTxxには4つのピンがあります(センサーに面しており、ピン1が一番左です):

プロジェクトではDHT22を使用します。

通常、20m未満の距離でセンサーを使用する場合は、4K7オームの抵抗をデータピンとVCCピンの間に接続する必要があります。 DHT22出力データピンはRaspberryGPIO16に接続されます。

以下のように、センサーをRPiピンに接続する上記の電気回路図を確認してください。

Vccピンとデータピンの間に4K7オームの抵抗を取り付けることを忘れないでください。センサーを接続したら、そのライブラリもRPiにインストールする必要があります。これは次のステップで行います。

ステップ6:DHTライブラリのインストール

Raspberryで、/ homeから始めて、/ Documents:

に移動します。
  cdドキュメント 

ライブラリをインストールしてそこに移動するディレクトリを作成します:

  mkdir DHT22_Sensorcd DHT22_Sensor  

ブラウザで、Adafruit GITHubにアクセスします:https://github.com/adafruit/Adafruit_Python_DHT

右側のダウンロードzipリンクをクリックしてライブラリをダウンロードし、最近作成したRaspberryPiフォルダーのアーカイブを解凍します。次に、ライブラリのディレクトリ(ファイルを解凍すると自動的に作成されるサブフォルダ)に移動し、次のコマンドを実行します。

  sudo python3 setup.py install  

GITHUBからテストプログラム(DHT22_test.py)を開きます:

  import Adafruit_DHTDHT22Sensor =Adafruit_DHT.DHT22DHTpin =16humidity、temperature =Adafruit_DHT.read_retry(DHT22Sensor、DHTpin)湿度がNoneでなく、温度がNoneでない場合:print( 'Temp ={0:0.1f} * C Humidity ={1:0.1f}% '。format(温度、湿度))else:print('読み取りに失敗しました。再試行してください! ') 

次のコマンドでプログラムを実行します:

  python3 DHT22_test.py  

上記のターミナル印刷画面に結果が表示されます。

ステップ7:実際のデータをキャプチャする

センサーとデータベースの両方がすべてインストールおよび構成されたので、実際のデータを読み取って保存します。

そのために、次のコードを使用します:

  import timeimport sqlite3import Adafruit_DHTdbname ='sensorsData.db' sampleFreq =2#時間(秒)#DHTからデータを取得sensordef getDHTdata():DHT22Sensor =Adafruit_DHT.DHT22 DHTpin =16 hum、temp =Adafruit_DHT.read_retry(DHT22Sensor、DHTpin)humがNoneでなく、tempがNoneでない場合:hum =round(hum)temp =round(temp、1)logData(temp、hum)#データベースのログセンサーデータdef logData (temp、hum):conn =sqlite3.connect(dbname)curs =conn.cursor()curs.execute( "INSERT INTO DHT_data values(datetime( 'now')、(?)、(?))"、(temp 、hum))conn.commit()conn.close()#display database datadef displayData():conn =sqlite3.connect(dbname)curs =conn.cursor()print( "\ nデータベースの内容全体:\ n")for curs.execute( "SELECT * FROM DHT_data")の行:print(row)conn.close()#main functiondef main():for i in range(0,3):getDHTdata()time.sleep(sampleFreq)displayData ()#プログラムmain()を実行します 

上記のファイルをGitHubから開きます:appDHT.pyそしてターミナルで実行します:

  python3 appDHT.py  

関数 getDHTdata() DHTセンサーの3つのサンプルをキャプチャし、エラーがないかテストし、問題がなければ、関数 logData(temp、hum)を使用してデータベースにデータを保存します。 。コードの最後の部分は、関数 displayData()を呼び出します。 これにより、テーブルのコンテンツ全体がターミナルに出力されます。

上記の印刷画面は結果を示しています。最後の3行(行)がこのプログラムでキャプチャされた実際のデータであり、前の3行が以前に手動で入力されたものであることに注意してください。

実際、appDHT.pyは適切な名前ではありません。一般に、「appSomething.py」は、このチュートリアルでさらに説明するように、Webサーバー上のPythonスクリプトで使用されます。もちろん、ここで使用できます。

ステップ8:データを自動的にキャプチャする

この時点で実装する必要があるのは、データベースのデータを自動的に読み取って挿入するメカニズムである「ロガー」です。

新しいターミナルウィンドウを開きます 次のPythonコードで入力します:

  import timeimport sqlite3import Adafruit_DHTdbname ='sensorsData.db'sampleFreq =1 * 60#秒単位の時間==> 1分ごとにサンプリング#DHTからデータを取得sensordef getDHTdata() :DHT22Sensor =Adafruit_DHT.DHT22 DHTpin =16 hum、temp =Adafruit_DHT.read_retry(DHT22Sensor、DHTpin)humがNoneでなく、tempがNoneでない場合:hum =round(hum)temp =round(temp、1)return temp、hum #databasedefにセンサーデータを記録するlogData(temp、hum):conn =sqlite3.connect(dbname)curs =conn.cursor()curs.execute( "INSERT INTO DHT_data values(datetime( 'now')、(?)、( ?)) "、(temp、hum))conn.commit()conn.close()#main functiondef main():while True:temp、hum =getDHTdata()logData(temp、hum)time.sleep(sampleFreq) #------------プログラムmain()を実行します 

または、GitHubから入手してください:logDHT.py。ターミナルで実行します:

  python3 logDHT.py  

main()関数の機能は次のとおりです。

関数 getDHTdata()を呼び出します 、DHT22センサーによってキャプチャされたデータを返します。これらのデータ(温度と湿度)を取得して、別の関数に渡します: logData(temp、hum) それらを実際の日付と時刻とともにテーブルに挿入します。そしてスリープ状態になり、次にスケジュールされた時間までデータをキャプチャします( sampleFreq で定義)。 、この例では1分です。

ターミナルウィンドウを開いたままにします。

たとえば、[Ctr + z]でプログラムを強制終了するまで、プログラムは継続的にデータをキャプチャし、データベースにフィードします。データベースにすばやくデータを入力するために、1分の頻度でしばらく実行したままにし、数時間後に頻度を10分に変更しました。

この種の「自動ロガー」を実行するには、「time.sleep」を使用するよりもはるかに効率的なメカニズムが他にもありますが、上記のコードはここでの目的には問題なく機能します。とにかく、より優れた「スケジューラ」を実装したい場合は、 Crontab を使用できます。 、これはジョブをスケジュールするための便利なUNIXツールです。 Crontabとは何かについての適切な説明は、このチュートリアル「Crontabを使用したLinuxでのタスクのスケジュール」(Kevin van Zonneveld著)にあります。

ステップ9:クエリ

データベースが自動的にフィードされるようになったので、これらすべてのデータを処理する方法を見つける必要があります。クエリで行います!

クエリとは何ですか?

データベース上でSQL言語を操作する際の最も重要な機能の1つは、「データベースクエリ」を作成する機能です。つまり、クエリはデータベースからデータを抽出し、読み取り可能な形式でフォーマットします。クエリは SQL言語で作成する必要があります 、 SELECT を使用します 特定のデータを選択するステートメント。

実際、最後のステップである「SELECT * FROMDHT_data」の「幅広い方法」で使用しています。

例:

すでに作成したテーブルのデータに対していくつかのクエリを作成しましょう。そのためには、以下のコードで入力してください:

  import sqlite3conn =sqlite3.connect( 'sensorsData.db')curs =conn.cursor()maxTemp =27.6print( "\ nデータベースの内容全体:\ n") curs.execute( "SELECT * FROM DHT_data")の行の場合:print(row)print( "\ n特定の湿度値のデータベースエントリ:\ n")curs.execute( "SELECT * FROM DHT_data WHERE hum ='29' "):print(row)print(" \ n温度が30oCを超えるデータベースエントリ:\ n ")for row in curs.execute(" SELECT * FROM DHT_data WHERE temp>
 30.0 "):print(row) print( "\ n温度がxを超えるデータベースエントリ:\ n")curs.execute( "SELECT * FROM DHT_data WHERE temp>
(?)"、(maxTemp、))の行:print(row)> 

または、GitHub:queryTableDHT.pyから取得して、ターミナルで実行します:

  python3 queryTableDHT.py  

結果は、上のターミナルの印刷画面で確認できます。これらは、クエリに関するアイデアを提供するための簡単な例です。上記のコードのSQLステートメントを理解するために時間をかけてください。

SQL言語について詳しく知りたい場合は、W3SchoolSQLチュートリアルが適しています。

ステップ10:テーブルに最後に入力されたデータ:

非常に重要なクエリは、最後に入力されたデータを取得するクエリです。 (またはログに記録された)テーブル。次のコマンドを使用して、SQLiteシェルで直接実行できます:

  sqlite> SELECT * FROM DHT_data ORDERBYタイムスタンプDESCLIMIT 1;  

または、以下のような単純なPythonコードを実行します:

  import sqlite3conn =sqlite3.connect( 'sensorsData.db')curs =conn.cursor()print( "\ nデータベースに最後に記録されたデータ:\ n")for curs.execute( "SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1")の行:print(行) 

結果は、上の最初のターミナル印刷画面で確認できます。

結果は「値のタプル」として表示されることに注意してください:(「タイムスタンプ」、一時、ハム)。

タプルは、テーブルの最後の行の内容を返しました。これは、3つの要素で構成されています。

したがって、コードをより適切に処理して、テーブルから「クリーンな」データを取得できます。例:

  import sqlite3conn =sqlite3.connect( 'sensorsData.db')curs =conn.cursor()print( "\ nデータベースに記録された最後の生データ:\ n") curs.execute( "SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1")の行の場合:print(str(row [0])+ "==> Temp =" + str(row [1])+ "Hum ="+ str(row [2])) 

GitHubからファイルを開きます:lastLogDataTableDHT.pyそしてターミナルで実行します:

  python3 lastLogDataTableDHT.py  

結果は上の2番目のターミナルの印刷画面で確認できます。

ステップ11:データ視覚化のためのWebフロントエンド

前回のチュートリアル:Python WebServerFlaskとRaspberryPiを使用して、センサーからデータをキャプチャし、ウェブページにステータスを表示するウェブサーバーを(Flaskを使用して)実装する方法を学びました。

これは私たちもここで達成したいことです。違いは、フロントエンドに送信されるデータにあります。データはデータベースから取得されます そのチュートリアルで行ったように、センサーから直接ではありません。

Webサーバー環境の作成:

最初に行うことは、RaspberryPiにFlaskをインストールすることです。お持ちでない場合は、ターミナルに移動して次のように入力してください:

  sudo apt-get install python3-flask  

新しいプロジェクトを開始するときの最良の方法は、ファイルを整理するためのフォルダーを作成することです。例:

自宅から、作業ディレクトリに移動します:

  cd Documents / Sensors_Database  

新しいフォルダを作成します。例:

  mkdir dhtWebServer  

上記のコマンドは、「dhtWebServer」という名前のフォルダーを作成します。このフォルダーに、Pythonスクリプトを保存します。

  / home / pi / Documents / Sensor_Database / rpiWebServer  

次に、このフォルダに2つのサブフォルダを作成しましょう: static CSS、最終的にはJavaScriptファイルとテンプレート HTMLファイルの場合 新しく作成したフォルダに移動します:

  cd dhtWebServer  

そして、2つの新しいサブフォルダを作成します:

  mkdir static  

および

  mkdirテンプレート 

最終的なディレクトリ「ツリー」は次のようになります。

 ├──Sensors_Database├──sensorsData.db├──logDHT.py├──dhtWebSensor├──templates└──static 

作成したデータベースは/ Sensor_Databaseディレクトリに残すため、SQLiteを「../sensorsData.db」に接続する必要があります。

わかった!環境が整ったら、パーツを組み立てて、 PythonWebサーバーアプリケーションを作成しましょう。 。上の図は、何をすべきかを示しています。

ステップ12:PythonWebサーバーアプリケーション

最後の図から始めて、Flaskを使用してPythonWebサーバーを作成しましょう。使用するIDEとして Geanyをお勧めします。 さまざまな種類のファイル(.py、.html、.css)を同時に操作できるようになったら

以下のコードは、最初のWebサーバーで使用されるPythonスクリプトです。

 フラスコからimportFlask、render_template、requestapp =Flask(__ name __)import sqlite3#databasedefからデータを取得getData():conn =sqlite3.connect( '../ SensorsData .db ')curs =conn.cursor()for row in curs.execute( "SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1"):time =str(row [0])temp =row [1] hum =row [2] conn.close()return time、temp、hum#main route @ app.route( "/")def index():time、temp、hum =getData()templateData ={'time':time、 ' temp ':temp、' hum ':hum} return render_template(' index.html '、** templateData)if __name__ =="__main __":app.run(host =' 0.0.0.0 '、port =80、debug =False) 

PythonスクリプトappDhtWebServer.pyは私のGitHubから入手できます。上記のコードの機能は次のとおりです。

このリクエストでは、コードで最初に行われるのは、関数 time、temp、hum =getData()を使用してデータベースからデータを取得することです。 この関数は基本的に、テーブルに格納されているデータを取得するために以前に使用されたものと同じクエリです。データが手元にあると、スクリプトはWebページ( index.html )に戻ります。 ):時間 temp ハム 前のリクエストへの応答として。

それでは、 index.html を見てみましょう。 および style.css フロントエンドの構築に使用されるファイル:

index.html

  <!DOCTYPE html>   DHTセンサーデータ    

DHTセンサーデータ

TEMPERATURE ==> {{tempLab}} oC

HUMIDITY(Rel。)==> { {humLab}}%


最後に読み取ったセンサー:{{time}} ==> 更新


@ 2018MJRoBot.orgによって開発されました

ファイルindex.htmlは私のGitHubから取得できます。

style.css

  body {background:blue;色:黄色; padding:1%}。button {フォント:太字の15px Arial;テキスト装飾:なし;背景色:#EEEEEE;色:#333333;パディング:2px 6px 2px 6px; border-top:1px solid #CCCCCC; border-right:1px solid#333333; border-bottom:1px solid#333333; border-left:1px solid #CCCCCC;}  

ファイルstyle.cssは私のGitHubから取得できます。ファイルは次のようにディレクトリに配置する必要があります:

 ├──Sensors_Database├──sensorsData.db├──logDHT.py├──dhtWebSensor├──appDhtWebSensor.py├──テンプレート│├──インデックス.html└──静的├──style.css 

次に、ターミナルでPythonスクリプトを実行します。

  sudo python3 appDhtWebServer.py  

ネットワーク内の任意のブラウザに移動し、 http:// YOUR_RPI_IP で入力します (たとえば、私の場合:http://10.0.1.27)

上記の印刷画面は、あなたが見なければならないものを示しています。注:RPi Ipアドレスがわからない場合は、端末で実行してください:

  ifconfig  

wlan0:セクションにあります。私の場合:10.0.1.27

ステップ13:Webフロントエンドファンシーを作成する!

より良い方法で実際の温度と湿度の値を提示するために、いくつかのゲージを紹介しましょう。 Pythonスクリプトは変更されませんが、html / cssファイルでJustGageを使用すると、データの表示方法が大幅に改善されることに注意してください。

JustGageとは何ですか?

JustGageは、すてきでクリーンなゲージを生成およびアニメーション化するための便利なJavaScriptプラグインです。ベクトル描画用のRaphaëlライブラリに基づいているため、完全に解像度に依存せず、自動調整され、ほとんどすべてのブラウザで機能します。

インストール:

justgage-1.2.2.zip

  <!doctype html>    DHTデータセンサー      

DHTセンサーデータ


最後のセンサー読み取り:{{time}} ==> 更新


@ 2018MJRoBot.orgによって開発

GitHubからファイルindex_gage.htmlをダウンロードし、名前をindex.htmlに変更します(以前のファイルを保持する場合は、index_txt.htmlなどの名前を変更することを忘れないでください)。

最終的なディレクトリツリーは次のようになります。

 ├──Sensors_Database├──sensorsData.db├──logDHT.py├──dhtWebServer├──appDhtWebServer.py├──テンプレート│├──インデックス.html└──static├──style.css├──justgage.js├──raphael-2.1.4.min.js 

ターミナルで[Crl-C]を押してappDhtWebServer.pyを終了し、再起動します。ブラウザを更新すると、上記の印刷画面が表示されます。

JustGageのWebサイトからダウンロードしたサンプルファイルを見てください。ゲージを変更してみてください。とても簡単です。

ステップ14:完全なプロセス

The above diagram resumes what we have accomplished so far:2 separate scripts running in parallel, doing their tasks independently:

Capturing data with sensor and load them into a database (logDHT.py )Look for data on the database and present them on a web front-end (appDhtWebServer.py

In general terms our project of capture data, saving them on a database and displaying those data on a webpage is finish. But make no sense to have a database with historical data and only use it for the last data captured. We must play with historical data and the most basic thing to do is presented them on a graph. Let’s go to it!

Step 15:Graphing the Historical Data

A very good library to graph data is Matplotlib that is a Python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms.

To install matplotlib , run the command below on your Terminal:

sudo apt-get install python3-matplotlib 

Before we start, let’s create a new environment, where we will save the new application to be developed: appDhtWebHist.py  and its correspondent index.html  and style.css

├── Sensors_Database ├── sensorsData.db ├── logDHT.py ├── dhtWebHist ├── appDhtWebHist.py ├── templates │ ├── index.html └── static ├── style.css  

Create the new 3 directories (dhtWebHist; /templates  and /static ) same as we did before and open from my GitHub the 3 files below:

1. appDhtWebHist.py

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvasfrom matplotlib.figure import Figureimport iofrom flask import Flask, render_template, send_file, make_response, requestapp =Flask(__name__)import sqlite3conn=sqlite3.connect('../sensorsData.db')curs=conn.cursor()# Retrieve LAST data from databasedef getLastData():for row in curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1"):time =str(row[0]) temp =row[1] hum =row[2] #conn.close() return time, temp, humdef getHistData (numSamples):curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT "+str(numSamples)) data =curs.fetchall() dates =[] temps =[] hums =[] for row in reversed(data):dates.append(row[0]) temps.append(row[1]) hums.append(row[2]) return dates, temps, humsdef maxRowsTable():for row in curs.execute("select COUNT(temp) from DHT_data"):maxNumberRows=row[0] return maxNumberRows# define and initialize global variablesglobal numSamplesnumSamples =maxRowsTable() if (numSamples> 101):numSamples =100# main [email protected]("/")def index():time, temp, hum =getLastData() templateData ={ 'time' :time, 'temp' :temp, 'hum' :hum, 'numSamples' :numSamples } return render_template('index.html', **templateData)@app.route('/', methods=['POST'])def my_form_post():global numSamples numSamples =int (request.form['numSamples']) numMaxSamples =maxRowsTable() if (numSamples> numMaxSamples):numSamples =(numMaxSamples-1) time, temp, hum =getLastData() templateData ={ 'time' :time, 'temp' :temp, 'hum' :hum, 'numSamples' :numSamples } return render_template('index.html', **templateData)@app.route('/plot/temp')def plot_temp():times, temps, hums =getHistData(numSamples) ys =temps fig =Figure() axis =fig.add_subplot(1, 1, 1) axis.set_title("Temperature [°C]") axis.set_xlabel("Samples") axis.grid(True) xs =range(numSamples) axis.plot(xs, ys) canvas =FigureCanvas(fig) output =io.BytesIO() canvas.print_png(output) response =make_response(output.getvalue()) response.mimetype ='image/png' return [email protected]('/plot/hum')def plot_hum():times, temps, hums =getHistData(numSamples) ys =hums fig =Figure() axis =fig.add_subplot(1, 1, 1) axis.set_title("Humidity [%]") axis.set_xlabel("Samples") axis.grid(True) xs =range(numSamples) axis.plot(xs, ys) canvas =FigureCanvas(fig) output =io.BytesIO() canvas.print_png(output) response =make_response(output.getvalue()) response.mimetype ='image/png' return responseif __name__ =="__main__":app.run(host='0.0.0.0', port=80, debug=False) 

A new function was created here: getHistData (numSamples) , that receives as a parameter the number of rows that should be taken from the database. Basically, it is very similar to getLastData(), where numSamples  was “1”. Of course, now we must “append” the return array for all required rows.

In fact, we could use only this last function for both tasks.

The number of samples is set by default as 100, at the beginning (if there are more them 100 rows into the database) and also received it as an input from the webpage, during normal operation. When we receive the number of samples to be retrieved, we must also check if it is lower than the maximum number of rows in the database (otherwise we will get an error). The function maxRowsTable() , returns this number.

With the historical data in hand: times, temps  and hums  that are arrays, we must build the graphs saving them as a .png ímage 。 Those images will be the return for the routes:

@app.route(‘/plot/temp’)  and @app.route(‘/plot/hum’).

The request for the images is done by index.html, by the IMG TAG.

2. index.html

  DHT Sensor data     

DHT Sensor Data

TEMPERATURE ==> {{ temp }} oC

HUMIDITY (Rel.) ==> {{ hum }} %


Last Sensors Reading:{{ time }} ==> REFRESH


HISTORICAL DATA

Enter number of samples to retrieve:


Image Placeholder Image Placeholder

@2018 Developed by MJRoBot.org

3. style.css

body{ background:blue; color:yellow; padding:1%}.button { font:bold 15px Arial;テキスト装飾:なし; background-color:#EEEEEE; color:#333333; padding:2px 6px 2px 6px; border-top:1px solid #CCCCCC; border-right:1px solid #333333; border-bottom:1px solid #333333; border-left:1px solid #CCCCCC;}img{ display:display:inline-block} 

The above print screen shows the result.

Step 16:Including Gage on History Webpage

If instead of text, you want also to include gages to display the actual data, you must have the 2 .js files that you have used before on /static and change the index.html file on /templates:

Below how the directory tree looks like:

├── Sensors_Database ├── sensorsData.db ├── logDHT.py ├── dhtWebHist ├── appDhtWebHist.py ├── templates │ ├── index.html └── static ├── style.css ├── justgage.js ├── raphael-2.1.4.min.js 

From my GitHub, open index_gage.html and rename it index.html. Replace the actual index.html (text version) and voilá! You will get a beautiful webpage, showing as gages the last captured data of temperature and humidity by the DHT22 and the historical graphs of those data.

Press[Crl-C] on your Terminal to Quit appDhtWebServer.py and just start it again. When you refresh your browser you must see the above print screen.

Step 17:Retrieving Data by Time Instead of Samples

So far we have build our graphics based on historical data, sending as a input parameter the numbers of samples to be retrieved from our database. Alternatively we could use as a parameter the number of past minutes that we want to show on a graph.

In order to do that, the first thing to know is the frequency of logged data on our database. Remember that this task is done for an independent program (in our case, logDHT.py )。 One simple way to finfd this frequency is to retrieve the last 2 data logged on database and subtracting their correspondent timeStamp data:

in general terms: frequency =timeStamp(1) – timeStamp(0)

The function below does the work for us, using “datetime.striptime()”:

# Get sample frequency in minutesdef freqSample():times, temps, hums =getHistData (2) fmt ='%Y-%m-%d %H:%M:%S' tstamp0 =datetime.strptime(times[0], fmt) tstamp1 =datetime.strptime(times[1], fmt) freq =tstamp1-tstamp0 freq =int(round(freq.total_seconds()/60)) return (freq) 

Once we we have this frequency parameter in minutes, we will show it on index.html and asking for a “rangeTime” number of minutes to be send back to our server ==> @app.route(‘/’, methods=[‘POST’]):

@app.route('/', methods=['POST'])def my_form_post():global numSamples global freqSamples global rangeTime rangeTime =int (request.form['rangeTime']) if (rangeTime  numMaxSamples):numSamples =(numMaxSamples-1) 

The picture shows the result:

Eliminating Possible errors when constructing the graphs:

Ocasionally, strange (or corrupted) data can be storaged on database, jeopardizing our analysis. Those data can be verified (or cleaneed) on several places (like during the time sensor are capturing the data, etc). But once the script that display data is independent of the one that logged the data, let’s “cap” the maximum and minimum values of our sensors, before using the data to buit the graphs. This can be achieved with the function testData(temps, hums) :

# Test data for cleanning possible "out of range" valuesdef testeData(temps, hums):n =len(temps) for i in range(0, n-1):if (temps[i] <-10 or temps[i]>50):temps[i] =temps[i-2] if (hums[i] <0 or hums[i]>100):hums[i] =temps[i-2] return temps, hums 

The scripts for this new version can be download from my GitHub: dhtWebHist_v2

Step 18:Conclusion

As always, I hope this project can help others find their way into the exciting world of electronics!

For details and final code, please visit my GitHub depository: RPI-Flask-SQLite

For more projects, please visit my blog: MJRoBot.org

Saludos from the south of the world!

See you at my next tutorial!

Thank you,

Source:From Data to Graph:A Web Journey With Flask and SQLite


製造プロセス

  1. シークレットマネージャーで機密データを保存および管理する
  2. マイクロチップ:最大153.6kSPSのデータレートを備えた24ビットおよび16ビットADC
  3. Webベースのチャートを備えたホーム(ルーム)温度および湿度モニター– Raspberry Pi
  4. RaspberryPiとPythonを使用したロボットの構築
  5. シスコとIBMのおかげで、IoTデータによるデジタルトランスフォーメーションの加速
  6. IoTデータをエッジからクラウドに、そしてその逆に活用する
  7. IIoTの旅は、リモートテレメトリから始まります
  8. TechDataとIBMPart2を使用してIOTを現実のものにする方法
  9. TechDataとIBMPart1を使用してIoTを現実のものにする方法
  10. ビッグデータプロジェクトとAIでビジネスの成果を推進
  11. エンタープライズリーダーがMLとAIで先を争う中、リアルタイムのニーズを解決する