Plotting real time monitoring with Flask and Vuejs.
Data and it’s visualization, it’s some of my favorite things to work on. In this tutorial I will talk about how to plot in real time data from the server side, this data could easily come from any database engine, but for the for the sake of simplicity it will come from a CSV.
I will be using Flask with Pandas on the server side, and Vuejs with charjs on client side.
So let’s start by generating our dummy data with Python with the help of Pandas library:
This dataframe will have 10000 rows and looks something like this:
X Y1 Y2 Y3
0 2020-12-30 11:04:54 78 309 485
1 2020-12-30 11:04:55 214 199 484
2 2020-12-30 11:04:56 101 377 18
3 2020-12-30 11:04:57 149 365 134
4 2020-12-30 11:04:58 243 177 203
5 2020-12-30 11:04:59 48 125 57
....
Now we are all setted up and we can simply start coding, I will not be using vue cli, but I can later add the link to Github repository with it.
Client side implementation.
Let’s set up the HTML, let’s call this file client.html:
Note: I will not declare a Doctype or header for the sake of this tutorial, just exactly the things we need.
Our container with acceptable dimensions, and adding the line-chart component prepared to receive our dynamic property chartData:
Let’s import the libraries:
- Vuejs
- Charjs Library
- Our Chartjs wrapper for Vuejs
- Vue Resource
Now let’s start by import our line-chart component and it’s options:
Now it’s time for our main Vue instance:
PS: This could be done with web sockets as well, instead of AJAX.
For the first request the response will have 20 values for each dataset (data) and 20 labels (X axis).
It will look something like:
{
"chart_data": {
"datasets": [
{
"backgroundColor": "#483D8B",
"borderColor": "#483D8B",
"borderWidth": 2,
"data": [
32,
112,
102,
...
],
"fill": false,
"label": "name_Y1",
"lineTension": 0,
"pointBorderColor": "#000000",
"pointBorderWidth": 1,
"pointRadius": 2
},
{
"backgroundColor": "#f87979",
"borderColor": "#f87979",
"borderWidth": 2,
"data": [
153,
2,
335,
...
],
"fill": false,
"label": "name_Y2",
"lineTension": 0.23,
"pointBorderColor": "#000000",
"pointBorderWidth": 1,
"pointRadius": 2
},
{
"backgroundColor": "#00BFFF",
"borderColor": "#00BFFF",
"borderWidth": 2,
"data": [
267,
262,
232,
...
],
"fill": false,
"label": "name_Y3",
"lineTension": 0.46,
"pointBorderColor": "#000000",
"pointBorderWidth": 1,
"pointRadius": 2
}
],
"labels": [
"21:33:26",
"21:33:27",
"21:33:28",
...
]
}
}
But for the next n requests the response will have just 1 value for each dataset and one label:
{
"chart_data": {
"datasets": [
{
"backgroundColor": "#483D8B",
"borderColor": "#483D8B",
"borderWidth": 2,
"data": [
114
],
"fill": false,
"label": "name_Y1",
"lineTension": 0,
"pointBorderColor": "#000000",
"pointBorderWidth": 1,
"pointRadius": 2
},
{
"backgroundColor": "#f87979",
"borderColor": "#f87979",
"borderWidth": 2,
"data": [
430
],
"fill": false,
"label": "name_Y2",
"lineTension": 0.23,
"pointBorderColor": "#000000",
"pointBorderWidth": 1,
"pointRadius": 2
},
{
"backgroundColor": "#00BFFF",
"borderColor": "#00BFFF",
"borderWidth": 2,
"data": [
368
],
"fill": false,
"label": "name_Y3",
"lineTension": 0.46,
"pointBorderColor": "#000000",
"pointBorderWidth": 1,
"pointRadius": 2
}
],
"labels": [
"21:33:46"
]
}
}
I did this way because we want to avoid send the same data we already have plotted, we want to get just one new row of data each second after the first one.
This logic it’s implemented directly in read_csv function below, I will explain it on the comments.
Server side implementation.
Since most of the work’s logic is being executed on the client side, the server side will be less confusing and more straightforward.
Let’s call this file server.py and start importing the libraries we need:
from flask import Flask, request, jsonify
from flask_cors import CORS
import pandas as pd
- Flask
- Cors, in this case because our domains are diferrent we need to allow CORS
- Pandas
Let’s start by setting up our app:
app = Flask(__name__)
CORS(app)
Now our route and logic:
And we are all set:
Just run:
$ python3 server.py
By default it should start the server on http://127.0.0.1:5000, if not just adjust the endpoint on the Ajax request in the client side.
Then double click on the client.html file, it should open a web browser.
Anyway, I know the code here can be a little confusing, so here it is the Github project.