파이썬(Python)/웹서버

아두이노에서 온도값 주면 db에서 저장한 값을 webGUI에서 그래프로 출력하기

끄적끄적아무거나 2020. 12. 29. 14:43
반응형

이번 프로젝트는 아두이노에서 온도값을 컴퓨터로 serial 통신을 사용해서 전달한다. (1초단위)

serial로 받은 값은 파이썬과 mongodb를 이용해서 db에 저장한다.

동시에 다른 파이썬 프로그램에서는 web GUI 를 flask를 이용해서 실행시키고 db에서 읽은 값을 웹브라우져를 통해 그래프로 표현하다.

여기서는 그래프로 출력하는 파이썬 flask와 html 코드를 설명하겠다.

코드 - flask python>>

from flask import Flask, Response, render_template
from pymongo import MongoClient 
from datetime import datetime
import json
import time
import random

app = Flask(__name__)

my_client = MongoClient("mongodb://localhost:27017/") 

db = my_client['Measurement'] 
db_col = db.data

@app.route('/')
def graph():
    return render_template('graph.html')

@app.route('/graph')
def chart_data():
    def generate_raw_data():
        while True:
            raw_data = db_col.find().sort("_id", -1).limit(1)[0]
            print(raw_data["Time"])
            print(raw_data["Temperature"])

            json_data = json.dumps({'time': raw_data["Time"], 'value': raw_data["Temperature"]})
            yield f"data:{json_data}\n\n"
            time.sleep(1)

    return Response(generate_raw_data(), mimetype='text/event-stream')


if __name__ == '__main__':
    app.run(debug=True, port=9999, threaded=True)

코드 - html>>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
</head>
<body>
<div class="container">
    <canvas id="canvas"></canvas>
</div>

<script>
    $(document).ready(function () {
        const config = {
            type: 'line',
            data: {
                labels: [],
                datasets: [{
                    label: "Temperature",
                    backgroundColor: 'rgb(255, 99, 132)',
                    borderColor: 'rgb(255, 99, 132)',
                    data: [],
                    fill: false,
                }],
            },
            options: {
                responsive: true,
                title: {
                    display: true,
                    text: 'Temperature Measurement'
                },
                scales: {
                    xAxes: [{
                        display: true,
                        scaleLabel: {
                            display: true,
                            labelString: 'Time'
                        }
                    }],
                    yAxes: [{
                        display: true,
                        scaleLabel: {
                            display: true,
                            labelString: 'Temp'
                        }
                    }]
                },
                tooltips: {
                    mode: 'index',
                    intersect: false,
                },
                hover: {
                    mode: 'nearest',
                    intersect: true
                }                
            }
        };

        const context = document.getElementById('canvas').getContext('2d');

        const lineChart = new Chart(context, config);

        const source = new EventSource("/graph");

        source.onmessage = function (event) {
            const data = JSON.parse(event.data);
            if (config.data.labels.length === 20) {
                config.data.labels.shift();
                config.data.datasets[0].data.shift();
            }
            config.data.labels.push(data.time);
            config.data.datasets[0].data.push(data.value);
            lineChart.update();
        }
    });
</script>
</body>
</html>

결과 >>

해당 온도 값은 실시간으로 업데이트 되고 있다.

주석>>

파이썬 부터 설명하겠다.

generate_raw_data 함수는 SSE (server sent event) 기법을 이용한 것으로 간단히 말해서 서버 push 기술입니다.

yield를 Response 와 묶어야지 실시간으로 반응합니다. (return을 사용해도 반응하지만 delay 현상이 발생함)

파이썬과 html 간에 데이터를 주고 받기 편하게 하기 위해서 json을 사용합니다.

json을 사용하지 않으면 string을 풀고 하는 등 추가 적인 코드가 많이 발생합니다.

html에 코드 부분은 그래프를 넣을 곳을 container로 묶었습니다. container는 bootstrap 디자인을 사용하는 함수입니다.

jquery를 사용해서 $(document).ready(function 문서가 로딩 될때까지 기다린 다음에 그래프에 들어갈 값과 설정을 넣는데 그래프는 Chart.min.css에서 가져왔습니다.

const source = new EventSource("/graph"); 에서 새롭게 json 값이 업데이트 될때 마다 source에 값을 받아서 업데이트 해줍니다.

 

 

 

 

반응형