Realtime Data Plotting
Following on from my earlier post trying to use smoothiecharts with flask-socketio for realtime data i managed to get an alternative with a pillion onboardwith a pillion onboardworking this time using charts https://www.chartjs.org/ Using this i am now able to generate random data (in lieu of external input values) and have them graphed in realtime on a line chart created using the api. The main part of the flask-python element consists of the data creation routine
python code snippet start
@application.route('/')
def index():
return render_template('data_acq.html')
@application.route('/chart-data')
def chart_data():
def generate_random_data():
while True:
timestamp = datetime.now().strftime('%H:%M:%S')
tc1 = round(random.random() * 100)
json_data = json.dumps(
{'time': timestamp, 'value0': tc1})
yield f"data:{json_data}\n\n"
values = (timestamp,tc1)
header = ['timestamp','tc1']
time.sleep(1)
print(values)
return Response(generate_random_data(), mimetype='text/event-stream')
python code snippet end
and then inside the appropriate html file we have'
- the link to the charting library
html code snippet start
<head>
<meta charset="UTF-8">
<title>realtime chart demo</title>
<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">
</head>
html code snippet end
- then the body contains the div element for the line chart
html code snippet start
<div class="container">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<canvas id="canvas"></canvas>
</div>
</div>
</div>
</div>
</div>
html code snippet end
- and the javascript to receive the data from the flask app
javascript code snippet start
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<!--suppress JSUnresolvedLibraryURL -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<!--suppress JSUnresolvedLibraryURL -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<script>
$(document).ready(function () {
const config = {
type: 'line',
data: {
labels: [],
datasets: [{
label: "TC1",
backgroundColor: 'rgb(255, 179, 179)',
borderColor: 'rgb(255, 179, 179)',
data: [],
fill: false,
}
],
},
options: {
responsive: true,
title: {
display: true,
text: 'Random value'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Time'
}
}],
yAxes: [{
display: true,
ticks: {
suggestedMin: 50,
suggestedMax: 200},
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
};
const context = document.getElementById('canvas').getContext('2d');
const lineChart = new Chart(context, config);
const source = new EventSource("/chart-data");
source.onmessage = function (event) {
const data = JSON.parse(event.data);
if (config.data.labels.length === 100) {
config.data.labels.shift();
config.data.datasets[0].data.shift();
}
document.getElementById('time').innerHTML = data.time;
document.getElementById('tc1').innerHTML = data.value0;
config.data.labels.push(data.time);
config.data.datasets[0].data.push(data.value0);
lineChart.update();
}
});
</script>
javascript code snippet end
Adding all this together results in a line graph that is updated every second looking like

with a simple table underneath that also shows the last value received. Currently it shows 100 values on the chart before each one is “lost” like a FIFO system but we can change this by altering the value in the HTML file
javascript code snippet start
if (config.data.labels.length === 100) {
config.data.labels.shift();
config.data.datasets[0].data.shift();
}
javascript code snippet end
So changing the value seen above dictates how many values are plotted on the chart before being moved off it, following the above it should easily be possible for anyone to build a chart with multiple realtime values shown.