I'm improving a system for controlling a telescope remotely. A Raspberry Pi runs flask, and provides a video stream for a camera attached to the telescope. The telescope's focuser is actuated by a stepper motor controlled with an Arduino.The server provides a website that shows the video stream, and offers two buttons to move the focuser in and out.
When either button is clicked, the client sends a POST to the RasPi, and then the RasPi tells the Arduino to move the focuser. But crucially I did not want the page to refresh while refocusing. Hence, I used jQuery and Ajax to suppress the page refresh.
The relevant code snippets are here:
Python/Flask code:
@app.route('/stream/<wcam>', methods=['GET'])
def stream_get(wcam):
class FocuserForm(FlaskForm):
nsteps = IntegerField('# steps: ', default=1)
focuser_in = SubmitField('Focuser in')
focuser_out = SubmitField('Focuser out')
form = FocuserForm()
return render_template('stream.html', wcam=wcam, form=form)
@app.route('/stream/<wcam>', methods=['POST'])
def stream_post(wcam):
results = request.form
arduino_serial = SerialFocuser()
if results['caller'] == "focuser_in":
command = "MVD" + results['steps'] + "\n"
arduino_serial.send_command(command)
elif results['caller'] == "focuser_out":
command = "MVU" + results['steps'] + "\n"
arduino_serial.send_command(command)
return ''
Web (stream.html):
<html>
<head>
<title>Video Streaming</title>
<style>
...
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {});
</script>
</head>
<body>
<h1>Streaming camera {{ wcam }}</h1>
<br>
<img id="bg" src="{{ url_for('video_feed', wcam=wcam) }}", height="480" width="640">
<a href="{{ url_for('index') }}">Back</a>
<br>
<!--######################################################-->
<!--# Focuser handling -->
<!--######################################################-->
<br>
<form id="flaskform" method="POST">
<p>
{{ form.nsteps.label }} {{ form.nsteps() }}
{{ form.focuser_in() }}
{{ form.focuser_out() }}
</p>
</form>
<script>
// $(document).ready(function() { // Moved to header
var form = document.getElementById('flaskform');
function onSubmit(event) {
console.log('onSubmit function');
var objectID = event.explicitOriginalTarget.id;
var nsteps = form.nsteps.value;
var return_data = {caller: "", steps: nsteps};
if (objectID == "focuser_in") {
return_data.caller = objectID;
console.log("Focuser_in detected");
} else if (objectID == "focuser_out") {
return_data.caller = objectID;
console.log("Focuser_out detected");
} else if (objectID == "nsteps") {
console.log("nsteps detected");
event.preventDefault();
return;
} else {
console.log("No matches");
return;
}
console.log("About to run Ajax");
$.ajax({
url: "stream.html",
type: "post",
data: return_data,
success: function(response) {
console.log('It worked!');
},
error: function(xhr, status, text) {
console.log('An error occurred:', status,"; ", text);
},
timeout: 1000 // 1s
}); // Ajax
console.log("After running Ajax");
if (event) { event.preventDefault(); }
}
// prevent when a submit button is clicked
form.addEventListener('submit', onSubmit, false);
//<!--form.addEventListener('submit', onSubmit, false);-->
// prevent submit() calls by overwriting the method
form.submit = onSubmit;
//}); // Moved to header
</script>
</body>
</html>
The problem is as follows:
If I refresh the page on the client's browser and then click a button, ajax does POST, but flask does not seem to receive it. The request times out.
If I now restart the server (I'm developing this with PyCharm, so I just click re-run) without refreshing the page in the client, and then click a button, flask does get the POST, and the focuser works like a charm.
If I refresh the page again, then the buttons stop working until I reset the server.
Why does this happen? Obviously the code works in its main purpose, but somehow the page refresh is breaking something.