Issue
I am trying to read in data from a load sensor using a raspberry pi. I can successfully get the data from the python file but when I try and pass it to a html file using flask it wont update the data correctly. it acts like its not getting current data just loading the same data over and over.
*SEE BOTTOM FOR UPDATE
here is my main.py file -
#! /usr/bin/python3
import time
import sys
from flask import Flask, render_template
import datetime
app = Flask(__name__)
@app.route("/main")
def main():
EMULATE_HX711=False
referenceUnit = 1
if not EMULATE_HX711:
import RPi.GPIO as GPIO
from hx711 import HX711
else:
from emulated_hx711 import HX711
hx = HX711(5, 6)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit(-23000)
#this clears the data on startup
hx.reset()
hx.tare()
#this is the only data I would like to refresh and stream into html
while True:
try:
val = hx.get_weight(5)
lbs = val * 2.2046
templateData = {
'data' : lbs
}
return render_template('index.html', **templateData)
hx.power_down()
hx.power_up()
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
cleanAndExit()
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80, debug=True)
I am trying to pass lbs as data into index.html -
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Flask App</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
<div id='test'></div>
<script>
function loadlink(){
$('#test').load('/main',function () {
$(this).unwrap();
$('#test').replaceWith('{{ data }}');
});
}
loadlink();
setInterval(function(){
loadlink()
}, 1000);
</script>
</body>
</html>
UPDATE I have figured out that the data is being reset with each refresh because of the -
hx.reset()
hx.tare()
Which is needed to start the sensor at zero, but once started I want it to stream the sensor data as it changes. How could I accomplish this without refreshing the page?
Solution
Your python code return the entire page of index.html upon receiving each request from the browser, what you should do is instead of return render_template('index.html', **templateData)
, you only return the data with something like return jsonify(templateData), 200
. In order to do this, create a separate route for handling the request.
#! /usr/bin/python3
from flask import Flask, render_template, jsonify
app = Flask(__name__)
EMULATE_HX711=False
referenceUnit = 1
if not EMULATE_HX711:
import RPi.GPIO as GPIO
from hx711 import HX711
else:
from emulated_hx711 import HX711
hx = HX711(5, 6)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit(-23000)
#this clears the data on startup
hx.reset()
hx.tare()
# this route only handle the rendering of index.html
@app.route("/main")
def main():
return render_template('index.html')
# this route handling the request send to the /update uri
@app.route("/update")
def update():
val = hx.get_weight(5)
lbs = val * 2.2046
templateData = {'data' : lbs}
return jsonify(templateData), 200
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80, debug=True)
Modify the JavaScript accordingly to send the request to the new route /update
, as I have not used the jQuery for ages, so I used my own pure JavaScript here:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Flask App</title>
</head>
<body>
<div id='test'></div>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
const getSensorReading = function() {
fetch(`http://${location.host}/update`) // send request to route /update
.then((resp) => resp.json())
.then(function(response) {
document.getElementById('test').innerHTML =response.data.toFixed(2);
});
}
getSensorReading();
setInterval(getSensorReading, 1000); //request for update every 1 second
});
</script>
</body>
</html>
Please test the code yourself as I did not test the code. This is mostly copy-and-pasted from my project which offers more sophisticated usage cases on sensor reading and web development that you might find beneficial.
Answered By - hcheung Answer Checked By - Willingham (WPSolving Volunteer)