산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

데이터에서 그래프로:Flask 및 SQLite를 사용한 웹 여정

실제 데이터 캡처(RPi/DHT22), 데이터베이스에 저장(SQLite), 그래프 생성(Matplotlib) 및 웹 페이지에 표시(Flask).

소개:데이터에서 그래프로. Flask 및 SQLite를 사용한 웹 작업

이전 튜토리얼인 Python WebServer With Flask 및 Raspberry Pi에서 Flask로 구축된 웹 프런트엔드 페이지를 통해 실제 세계와 상호작용하는 방법을 배웠습니다. 따라서 다음 자연스러운 단계는 실제 세계에서 데이터를 수집하여 웹 페이지에서 사용할 수 있도록 하는 것입니다. 매우 간단합니다! 그러나 예를 들어 전날 상황을 알고 싶다면 어떻게 될까요? 아니면 그 데이터로 어떤 종류의 분석을 하시겠습니까? 이러한 경우 데이터베이스에도 데이터가 저장되어 있어야 합니다.

간단히 말해서, 이 새로운 튜토리얼에서 우리는:

실제 데이터 캡처 (대기 온도 및 상대 습도) DHT22 센서를 사용하여 해당 데이터 로드 로컬 데이터베이스에서 , SQLite로 구축됨 그래픽 만들기 이전 데이터 포함 Matplotlib; 사용 디스플레이 데이터 JustGage로 만든 애니메이션 '게이지' 포함 Python으로 만든 로컬 웹 서버를 통해 모든 것을 온라인에서 사용할 수 있도록 합니다. 및 플라스크

블록 다이어그램은 전체 프로젝트에 대한 아이디어를 제공합니다.

1단계:BoM – 재료 명세서

<울>
  • 라즈베리 파이 V3 – US$ 32.00
  • DHT22 온도 및 상대 습도 센서 - USD 9.95
  • 4K7 옴 저항기
  • 2단계:SQLite 설치

    좋습니다. 일반적인 아이디어는 센서에서 데이터를 수집하여 데이터베이스에 저장하는 것입니다.

    그러나 어떤 데이터베이스 "엔진"을 사용해야 합니까?

    시장에는 많은 옵션이 있으며 아마도 Raspberry Pi 및 센서와 함께 가장 많이 사용되는 두 가지 옵션은 MySQL과 SQLite일 것입니다. MySQL은 잘 알려져 있지만 간단한 Raspberry 기반 프로젝트에서 사용하기에는 약간 "무거워요"(오라클이 소유한 것 외에도!). SQLite가 아마도 가장 적합한 선택일 것입니다. 서버리스, 경량, 오픈 소스이고 대부분의 SQL 코드를 지원하기 때문입니다(라이센스는 "공개 도메인"). 또 다른 편리한 점은 SQLite가 데이터를 어디에나 저장할 수 있는 단일 파일에 저장한다는 것입니다.

    하지만 SQLite는 무엇입니까?

    SQLite는 C 프로그래밍 라이브러리에 포함된 관계형 데이터베이스 관리 시스템입니다. 다른 많은 데이터베이스 관리 시스템과 달리 SQLite는 클라이언트-서버 데이터베이스 엔진이 아닙니다. 오히려 최종 프로그램에 포함됩니다.

    SQLite는 인기 있는 공개 도메인입니다. 웹 브라우저와 같은 애플리케이션 소프트웨어에서 로컬/클라이언트 스토리지를 위한 임베디드 데이터베이스 소프트웨어로 선택. 오늘날 여러 브라우저, 운영 체제 및 임베디드 시스템(휴대폰과 같은)에서 사용되기 때문에 가장 널리 배포된 데이터베이스 엔진일 것입니다. SQLite에는 우리 프로젝트에서 사용되는 Python과 같은 많은 프로그래밍 언어에 대한 바인딩이 있습니다.

    (위키피디아에 대한 추가 정보)

    여기에 너무 많은 세부정보를 입력하지 않겠지만 전체 SQLite 설명서는 다음 링크에서 찾을 수 있습니다. https://www.sqlite.org/docs.html

    그러면 그렇게 해! Pi에 SQLite를 설치해 보겠습니다.

    설치:

    데이터베이스를 생성하려면 아래 단계를 따르십시오.

    1. 다음 명령을 사용하여 SQLite를 Raspberry Pi에 설치합니다.

    sudo apt-get install sqlite3 

    2. 프로젝트 개발을 위한 디렉토리 생성:

    mkdir 센서_데이터베이스 

    3. 이 디렉토리로 이동:

    cd mkdir 센서_데이터베이스/ 

    3. 이름을 지정하고 databaseName.db와 같은 데이터베이스를 만듭니다. (제 경우 "sensorsData.db"):

    sqlite3 sensorData.db 

    SQLite 명령으로 입력할 수 있는 "쉘"이 나타납니다. 나중에 다시 다루도록 하겠습니다.

    sqlite> 

    명령은 ".help", ".quit" 등과 같이 "."로 시작합니다.

    4. 쉘을 종료하여 터미널로 돌아갑니다:

    sqlite> .quit 

    위의 터미널 인쇄 화면은 설명된 내용을 보여줍니다.

    위의 "sqlite>"는 SQLite 셸이 어떻게 나타나는지 설명하기 위한 것입니다. 입력할 필요가 없습니다. 자동으로 나타납니다.

    3단계:테이블 생성 및 채우기

    DHT 센서 측정 데이터를 데이터베이스에 기록하려면 테이블을 생성해야 합니다. (데이터베이스는 여러 테이블을 포함할 수 있습니다). 테이블 이름은 "DHT_data"이며 3개의 열이 있으며 여기에 수집된 데이터가 기록됩니다. 날짜 및 시간(열 이름:timestamp ), 온도(열 이름:temp ) 및 습도(열 이름:hum ).

    표 만들기:

    표를 만들려면 다음과 같이 하십시오.

    <울>
  • SQLite 셸에서 직접 또는
  • Python 프로그램 사용.
  • 1. 쉘 사용:

    마지막 단계에서 생성된 데이터베이스를 엽니다.

    sqlite3 sensorData.db 

    그리고 SQL 문으로 입력:

    sqlite> BEGIN;sqlite> CREATE TABLE DHT_data(타임스탬프 DATETIME, 임시 숫자, 험 숫자);sqlite> COMMIT; 

    모든 SQL 문은 ";"으로 끝나야 합니다. 또한 일반적으로 이러한 진술은 대문자를 사용하여 작성됩니다. 필수 사항은 아니지만 좋은 습관입니다.

    2. 파이썬 사용

     sqlite3을 liteimport syscon =lite.connect('sensorsData.db') con으로 가져오기:cur =con.cursor() cur.execute("DROP TABLE IF EXISTS DHT_data") cur.execute("CREATE TABLE DHT_data(타임스탬프 DATETIME, 임시 숫자, 험 숫자)") 

    내 GitHub에서 위의 코드를 엽니다. createTableDHT.py

    터미널에서 실행:

    python3 createTableDHT.py 

    방법이 사용되는 곳마다 테이블이 생성되어야 합니다. ".table" 명령을 사용하여 SQLite Shell에서 확인할 수 있습니다. 데이터베이스 셸을 엽니다.

    sqlite3> sensorData.db 

    셸에서 .table을 사용하면 명령을 실행하면 생성된 테이블 이름이 표시됩니다(이 경우 "DHT_table" 하나만 표시됩니다. 이후에 셸을 종료하려면 .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에서는 같은 작업을 한 번에 수행할 수 있습니다.

     sqlite3을 liteimport syscon =lite.connect('sensorsData.db') con으로 가져오기:cur =con.cursor() cur.execute("INSERT INTO DHT_data VALUES (datetime('현재'), 20.5, 30)") cur.execute("INSERT INTO DHT_data VALUES(datetime('지금'), 25.8, 40)") cur.execute("INSERT INTO DHT_data VALUES(datetime(') 지금'), 30.3, 50)") 

    내 GitHub에서 위의 코드를 엽니다. insertTableDHT.py

    파이 터미널에서 실행:

    python3 insertTableDHT.py 

    위의 코드가 작동하는지 확인하려면 다음 SQL 문을 사용하여 셸을 통해 테이블의 데이터를 확인할 수 있습니다.

    sqlite> SELECT * FROM DHT_DATA; 

    위의 터미널 인쇄 화면은 테이블의 행이 어떻게 표시되는지 보여줍니다.

    4단계: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)# 데이터베이스 내용 인쇄("\n전체 데이터베이스 내용:\n")for row in curs.execute("SELECT * FROM DHT_data"):print (row)# 닫기 useconn.close() 이후의 데이터베이스 

    내 GitHub에서 위의 코드를 엽니다. insertDataTableDHT.py 그리고 터미널에서 실행합니다.

    python3 insertDataTableDHT.py 

    위의 터미널 인쇄 화면은 결과를 보여줍니다.

    5단계:DHT22 온도 및 습도 센서

    지금까지 데이터베이스에 센서가 읽을 모든 데이터를 저장할 테이블을 만들었습니다. 우리는 또한 거기에 일부 더미 데이터를 입력했습니다. 이제 실제 데이터를 사용하여 테이블, 기온 및 상대 습도에 저장할 시간입니다. 이를 위해 우리는 오래되고 좋은 DHTxx(DHT11 또는 DHT22)를 사용할 것입니다. ADAFRUIT 사이트는 이러한 센서에 대한 훌륭한 정보를 제공합니다. 아래에서 검색된 일부 정보:

    개요

    저렴한 DHT 온도 및 습도 센서는 매우 기본적이고 느리지만 기본적인 데이터 로깅을 원하는 애호가에게 적합합니다. DHT 센서는 용량성 습도 센서와 서미스터의 두 부분으로 구성됩니다. 또한 내부에 일부 아날로그에서 디지털로 변환을 수행하고 온도 및 습도와 함께 디지털 신호를 내보내는 매우 기본적인 칩이 있습니다. 디지털 신호는 모든 마이크로컨트롤러를 사용하여 상당히 읽기 쉽습니다.

    DHT11 대 DHT22

    우리는 DHT 센서의 두 가지 버전을 가지고 있습니다. 그것들은 약간 비슷해 보이고 같은 핀아웃을 가지고 있지만 다른 특성을 가지고 있습니다. 사양은 다음과 같습니다.

    DHT11(보통 파란색)

    5% 정확도로 20-80% 습도 판독에 적합 0-50°C 온도 판독에 적합 ±2°C 정확도 1Hz 이하 샘플링 속도(1초에 한 번)

    <울>
  • 초저가
  • 3~5V 전원 및 I/O
  • 변환 중 최대 2.5mA 전류 사용(데이터 요청 중)
  • 본체 크기 15.5mm x 12mm x 5.5mm
  • 0.1″ 간격의 핀 4개
  • DHT22(보통 흰색)

    2-5% 정확도로 0-100% 습도 판독에 적합 -40 ~ 125°C 온도 판독에 적합 ±0.5°C 정확도 0.5Hz 이하 샘플링 속도(2초에 한 번)

    <울>
  • 저비용
  • 3~5V 전원 및 I/O
  • 변환 중 최대 2.5mA 전류 사용(데이터 요청 중)
  • 본체 크기 15.1mm x 25mm x 7.7mm
  • 0.1″ 간격의 핀 4개
  • 보시다시피 DHT22는 약간 더 정확하고 약간 더 넓은 범위에서 좋습니다. 둘 다 단일 디지털 핀을 사용하며 초당 한 번(DHT11) 또는 두 번(DHT22) 이상 쿼리할 수 없다는 점에서 '느립니다'.

    두 센서 모두 실내 정보가 데이터베이스에 저장되도록 잘 작동합니다.

    DHTxx에는 4개의 핀이 있습니다(센서를 향하고 핀 1이 가장 왼쪽에 있음).

    <울>
  • VCC(외부 5V 또는 RPi에서 3.3V에 연결할 수 있음),
  • 데이터 출력
  • 연결되지 않음
  • 그라운드.
  • 우리는 프로젝트에서 DHT22를 사용할 것입니다.

    일반적으로 20m 미만의 거리에서 센서를 사용하게 되면 데이터와 VCC 핀 사이에 4K7 옴 저항을 연결해야 합니다. DHT22 출력 데이터 핀은 Raspberry GPIO 16에 연결됩니다.

    아래와 같이 센서를 RPi 핀에 연결하는 위의 전기 다이어그램을 확인하십시오.

    <울>
  • 핀 1 – Vcc ==> 3.3V
  • 핀 2 – 데이터 ==> GPIO 16
  • 핀 3 – 연결 안 됨
  • 핀 4 – 접지 ==> 접지
  • Vcc와 데이터 핀 사이에 4K7 옴 저항을 설치하는 것을 잊지 마십시오. 센서가 연결되면 RPi에 해당 라이브러리도 설치해야 합니다. 다음 단계에서 이 작업을 수행합니다.

    6단계:DHT 라이브러리 설치

    Raspberry에서 /home에서 시작하여 /Documents:

    로 이동합니다.
    cd 문서  

    라이브러리를 설치할 디렉토리를 만들고 그곳으로 이동하십시오:

    mkdir DHT22_Sensorcd DHT22_Sensor 

    브라우저에서 Adafruit GITHub로 이동합니다. https://github.com/adafruit/Adafruit_Python_DHT

    오른쪽에 있는 다운로드 zip 링크를 클릭하여 라이브러리를 다운로드하고 최근에 생성된 Raspberry Pi 폴더에 아카이브의 압축을 풉니다. 그런 다음 라이브러리의 디렉터리(파일의 압축을 풀면 자동으로 생성되는 하위 폴더)로 이동하여 다음 명령을 실행합니다.

    sudo python3 setup.py 설치 

    내 GITHUB에서 테스트 프로그램(DHT22_test.py)을 엽니다.

    가져오기 Adafruit_DHTDHT22Sensor =Adafruit_DHT.DHT22DHTpin =16humidity, temperature =Adafruit_DHT.read_retry(DHT22Sensor, DHTpin) 만약 습도가 None이 아니고 온도가 None이 아니라면:print('Temp={0:0.1f}*C 습도={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)# databasedef logData에 센서 데이터 기록 (temp, hum):conn=sqlite3.connect(dbname) curs=conn.cursor() curs.execute("INSERT INTO DHT_data values(datetime('현재'), (?), (?))", (temp , hum)) conn.commit() conn.close()# 데이터베이스 표시 datadef displayData():conn=sqlite3.connect(dbname) curs=conn.cursor() print("\n전체 데이터베이스 내용:\n") row in 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"는 웹 서버의 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 # 데이터베이스에 센서 데이터를 기록합니다. 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이 무엇인지에 대한 좋은 설명은 Kevin van Zonneveld의 'Schedule Tasks on Linux using Crontab' 튜토리얼에서 찾을 수 있습니다.

    9단계:쿼리

    이제 데이터베이스가 자동으로 제공되므로 모든 데이터로 작업할 방법을 찾아야 합니다. 쿼리로 처리합니다!

    쿼리란 무엇입니까?

    데이터베이스에 대한 SQL 언어 작업의 가장 중요한 기능 중 하나는 "데이터베이스 쿼리"를 생성하는 기능입니다. 즉, 쿼리는 읽을 수 있는 형식으로 형식을 지정하는 데이터베이스에서 데이터를 추출합니다. 쿼리는 SQL 언어로 작성해야 합니다. , SELECT 특정 데이터를 선택하는 문.

    실제로 마지막 단계인 "SELECT * FROM DHT_data"에서 "광범위한 방법"으로 사용했습니다.

    예:

    이미 생성한 테이블의 데이터에 대해 쿼리를 생성해 보겠습니다. 이를 위해 아래 코드로 입력하십시오:

    import sqlite3conn=sqlite3.connect('sensorsData.db')curs=conn.cursor()maxTemp =27.6print("\n전체 데이터베이스 내용:\n") for row in curs.execute("SELECT * FROM DHT_data"):print (row)print("\n특정 습도 값에 대한 데이터베이스 항목:\n")for row in curs.execute("SELECT * FROM DHT_data WHERE hum='29'"):인쇄(행) 인쇄("\n온도가 30oC 이상인 데이터베이스 항목:\n") for row in curs.execute("SELECT * FROM DHT_data WHERE temp>
    30.0"):인쇄(행) curs.execute("SELECT * FROM DHT_data WHERE temp>
    (?)", (maxTemp,))의 행에 대한 인쇄("\n온도가 x보다 높은 데이터베이스 항목:\n"):인쇄(행)  

    또는 내 GitHub(queryTableDHT.py)에서 다운로드하여 터미널에서 실행합니다.

    python3 queryTableDHT.py 

    위 터미널의 인쇄 화면에서 결과를 확인할 수 있습니다. 이는 쿼리에 대한 아이디어를 제공하는 간단한 예입니다. 시간을 내어 위 코드의 SQL 문을 이해하십시오.

    SQL 언어에 대해 더 알고 싶다면 W3School SQL Tutorial을 참조하세요.

    10단계:테이블에 마지막으로 입력한 데이터:

    매우 중요한 쿼리는 마지막으로 입력한 데이터를 검색하는 것입니다. (또는 기록) 테이블에. 다음 명령을 사용하여 SQLite 셸에서 직접 수행할 수 있습니다.

    sqlite> SELECT * FROM DHT_data ORDER BY 타임스탬프 DESC LIMIT 1; 

    또는 아래와 같이 간단한 파이썬 코드를 실행:

    import sqlite3conn =sqlite3.connect('sensorsData.db')curs=conn.cursor()print("\n데이터베이스에 로그온한 마지막 데이터:\n") curs.execute("SELECT * FROM DHT_data ORDER BY 타임스탬프 DESC LIMIT 1")의 행:인쇄(행) 

    위의 첫 번째 터미널 인쇄 화면에서 결과를 확인할 수 있습니다.

    결과는 "값의 튜플"('timestamp', temp, hum)로 나타납니다.

    튜플은 3개의 요소로 구성된 테이블의 마지막 행 내용을 반환했습니다.

    <울>
  • 행[0] =타임스탬프 [문자열]
  • row[1] =온도 [float]
  • row[2] =윙윙거림 [float]
  • 따라서 다음과 같이 테이블에서 "깨끗한" 데이터를 검색하기 위해 코드를 더 잘 사용할 수 있습니다.

    import sqlite3conn=sqlite3.connect('sensorsData.db')curs=conn.cursor()print("\n데이터베이스에 로그온한 마지막 원시 데이터:\n") for row in curs.execute("SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1"):print (str(row[0])+" ==> Temp ="+str(row[1])+" Hum ="+str(행[2])) 

    내 GitHub:lastLogDataTableDHT.py에서 파일을 열고 터미널에서 실행합니다.

    python3 lastLogDataTableDHT.py 

    위의 2nd Terminal 인쇄 화면에서 결과를 확인하실 수 있습니다.

    11단계:데이터 시각화를 위한 웹 프런트엔드

    지난 튜토리얼:Python WebServer With Flask 및 Raspberry Pi에서 웹 서버(Flask 사용)를 구현하여 센서에서 데이터를 캡처하고 웹페이지에 상태를 표시하는 방법을 배웠습니다.

    이것이 우리가 여기서 성취하고자 하는 것이기도 합니다. 차이점은 프런트 엔드로 보낼 데이터이며, 이는 데이터베이스에서 가져옵니다. 해당 튜토리얼에서 했던 것처럼 센서에서 직접적으로 발생하지 않습니다.

    웹 서버 환경 만들기:

    가장 먼저 할 일은 Raspberry Pi에 Flask를 설치하는 것입니다. 없는 경우 터미널로 이동하여 다음을 입력하십시오.

    sudo apt-get 설치 python3-flask 

    새 프로젝트를 시작할 때 가장 좋은 방법은 파일을 정리할 폴더를 만드는 것입니다. 예:

    집에서 작업 디렉토리로 이동하십시오.

    cd 문서/센서_데이터베이스 

    새 폴더를 만듭니다. 예:

    mkdir dhtWebServer 

    위의 명령은 "dhtWebServer"라는 이름의 폴더를 만들고 여기에 파이썬 스크립트를 저장할 것입니다.

    /home/pi/Documents/Sensor_Database/rpiWebServer 

    이제 이 폴더에 정적이라는 2개의 하위 폴더를 만들어 보겠습니다. CSS 및 궁극적으로는 JavaScript 파일 및 템플릿 용 HTML 파일용. 새로 만든 폴더로 이동:

    cd dhtWebServer 

    그리고 2개의 새 하위 폴더를 만듭니다.

    mkdir 정적 

    그리고

    mkdir 템플릿 

    최종 디렉토리 "tree"는 다음과 같습니다.

    ├── Sensors_Database ├── sensorData.db ├── logDHT.py ├── dhtWebSensor ├── 템플릿 └── 정적 

    생성된 데이터베이스는 /Sensor_Database 디렉토리에 남겨두므로 "../sensorsData.db"로 SQLite를 연결해야 합니다.

    확인! 환경이 마련되면 부품을 조합하고 Python WebServer 애플리케이션을 만들어 보겠습니다. . 위의 다이어그램은 무엇을 해야 하는지에 대한 아이디어를 제공합니다!

    12단계:Python 웹 서버 애플리케이션

    마지막 다이어그램부터 Flask를 사용하여 python WebServer를 생성해 보겠습니다. 저는 Geany를 사용할 IDE로 제안합니다. 다른 유형의 파일(.py, .html 및 .css)로 동시에 작업할 수 있습니다.

    아래 코드는 첫 번째 웹 서버에서 사용할 python 스크립트입니다.

    플라스크에서 가져오기 Flask, 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=거짓) 

    내 GitHub에서 python 스크립트 appDhtWebServer.py를 가져올 수 있습니다. 위 코드가 하는 일은:

    이 요청으로 코드에서 가장 먼저 수행되는 작업은 time, temp, hum =getData() 함수를 사용하여 데이터베이스에서 데이터를 가져오는 것입니다. 이 함수는 기본적으로 이전에 테이블에 저장된 데이터를 검색하는 데 사용된 것과 동일한 쿼리입니다. 데이터가 있는 상태에서 스크립트는 웹페이지(index.html ):시간 , 온도 그리고 이전 요청에 대한 응답으로.

    <울>
  • 누군가가 "/"를 "클릭"할 때마다, 그것은 우리 웹페이지의 메인 페이지(index.html)인 GET 요청이 생성됩니다.
  • 이제 index.html을 살펴보겠습니다. 및 style.css 프런트 엔드를 구축하는 데 사용할 파일:

    index.html

      DHT 센서 데이터     

    DHT 센서 데이터

    온도 ==> {{ tempLab }} oC

    습도(Rel.) ==> { { humLab }} %


    마지막 센서 판독값:{{ time }} ==> 새로 고침


    @2018 MJRoBot.org에서 개발

    내 GitHub에서 index.html 파일을 가져올 수 있습니다.

    style.css

    body{ 배경:파란색; 색상:노란색; 패딩:1%}.버튼 { 글꼴:굵게 15px Arial; 텍스트 장식:없음; 배경색:#EEEEEE; 색상:#333333; 패딩:2px 6px 2px 6px; border-top:1px 솔리드 #CCCCCC; border-right:1px 솔리드 #333333; border-bottom:1px 솔리드 #333333; border-left:1px 실선 #CCCCCC;} 

    내 GitHub에서 style.css 파일을 가져올 수 있습니다. 파일은 다음과 같이 디렉토리에 위치해야 합니다.

    ├── Sensors_Database ├── sensorData.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단계:웹 프론트엔드를 더 멋지게 만드세요!

    더 나은 방법으로 실제 온도 및 습도 값을 표시하기 위해 몇 가지 게이지를 소개하겠습니다. Python 스크립트는 변경되지 않지만 html/css 파일에서 JustGage를 사용하면 데이터가 표시되는 방식이 크게 향상됩니다.

    JustGage란 무엇입니까?

    JustGage는 멋지고 깨끗한 게이지를 생성하고 애니메이션화하기 위한 편리한 JavaScript 플러그인입니다. 벡터 드로잉을 위한 Raphaël 라이브러리를 기반으로 하므로 거의 모든 브라우저에서 작동하는 완전히 해상도 독립적이고 자체 조정됩니다.

    설치:

    <울>
  • JustGage 웹사이트에서 JustGage v1.2.2 + 예제 다운로드 ==> http://justgage.com/download/justgage-1.2.2.zip
  • /static/ 디렉토리에 2개의 .js 파일 저장
  • 아래의 새로운 index.html 사용:
  • justgage-1.2.2.zip

     DHT 데이터 센서    

    DHT 센서 데이터


    마지막 센서 판독값:{{ time }} ==> REFRESH


    @2018 MJRoBot.org에서 개발

    <스크립트 src="../static/raphael-2.1.4.min.js"> <스크립트 src="../static/justgage.js"> <스크립트> var g1, g2; document.addEventListener("DOMContentLoaded", function(event) { g1 =new JustGage({ id:"g1", 값:{{temp}}, valueFontColor:"노란색", 최소:-10, 최대:50, 제목:"온도", 레이블:"섭씨" }), g2 =new JustGage({ id:"g2", 값:{{hum}}, valueFontColor:"노란색", 최소:0, 최대:100, 제목:"습도 ", 레이블:"%" }); });

    내 GitHub에서 파일 index_gage.html을 다운로드하고 이름을 index.html로 바꿉니다(이전 파일을 유지하려면 index_txt.html과 같이 이전 이름을 다른 이름으로 바꾸는 것을 잊지 마십시오).

    최종 디렉토리 트리는 다음과 같아야 합니다.

    ├── Sensors_Database ├── sensorData.db ├── logDHT.py ├── dhtWebServer ├── appDhtWebServer.py ├── 템플릿 │ ├── 인덱스 .html └── 정적 ├── style.css ├── justgage.js ├── raphael-2.1.4.min.js 

    터미널에서 [Crl-C]를 눌러 appDhtWebServer.py를 종료하고 다시 시작하십시오. 브라우저를 새로고침하면 위의 인쇄 화면이 표시되어야 합니다.

    JustGage 웹사이트에서 다운로드한 예제 파일을 보십시오. 게이지를 변경해 보십시오. 매우 간단합니다.

    14단계:전체 프로세스

    위의 다이어그램은 지금까지 수행한 작업을 다시 시작합니다. 2개의 개별 스크립트가 병렬로 실행되고 독립적으로 작업을 수행합니다.

    센서로 데이터를 캡처하고 데이터베이스(logDHT.py)에 로드 )데이터베이스에서 데이터를 찾아 웹 프런트 엔드(appDhtWebServer.py)에 표시 ).

    일반적으로 데이터를 캡처하여 데이터베이스에 저장하고 해당 데이터를 웹페이지에 표시하는 프로젝트가 완료되었습니다. 그러나 과거 데이터가 있는 데이터베이스를 갖고 마지막으로 캡처한 데이터에만 사용하는 것은 의미가 없습니다. 우리는 과거 데이터를 가지고 놀아야 하며 가장 기본적인 것은 그래프로 제시하는 것입니다. 가자!

    15단계:과거 데이터 그래프화

    데이터를 그래프로 표시하는 데 아주 좋은 라이브러리는 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; text-decoration:none; 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. Secret Manager로 민감한 데이터 저장 및 관리
    2. Microchip:최대 153.6kSPS의 데이터 속도를 지원하는 24비트 및 16비트 ADC
    3. 웹 기반 차트가 포함된 가정(방) 온도 및 습도 모니터 – Raspberry Pi
    4. Raspberry Pi 및 Python으로 로봇 구축
    5. Cisco와 IBM 덕분에 IoT 데이터로 디지털 혁신 가속화
    6. 에지에서 클라우드 및 클라우드로 IoT 데이터 활용
    7. IIoT 여정은 원격 원격 측정으로 시작됩니다
    8. Tech Data 및 IBM Part 2로 IOT를 실현하는 방법
    9. Tech Data 및 IBM Part 1을 통해 IoT를 현실로 만드는 방법
    10. 빅 데이터 프로젝트 및 AI로 비즈니스 성과 창출