I am having an odd behavior in my FLASK project and I am not really sure what is going on here, basically it works OK while the developer tools of the browser is open (tested in firefox/chrome) but it stops updating as soon as I close it.
I have a Thread in FLASK that is emitting current date and pH values (read from a pH probe) and also appending the data to a csv file that i later read in the js to make a graph and refresh it every time I have a new pH reading. In python:
....
#Inside the thread. Running every 5 seconds.
socketio.emit('new_pH', {'pH': pH[0],'date': date})
with open("static/data.csv", "a") as myfile:
myfile.write("{},{}\n".format(date,pH[0]))
print("pH: {}".format(pH[0]))
....
and on the js side:
var socket = io.connect('http://' + document.domain + ':' + location.port,{'multiplex': false});
socket.on('new_pH', function(msg){
....
console.log("Received pH: ", msg.pH)
console.log("Received date: ", msg.date)
d3.csv("static/data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
....
});
On my terminal I see that when the dev tools are open I have a GET request for the data:
pH: 7.64666214035
127.0.0.1 - - [22/Nov/2017 18:11:39] "GET /static/data.csv HTTP/1.1" 200 4950 0.000831
and as soon as I close the devel tools I only see the pH values.
It happens with the FLASK server and also with gunicorn gunicorn --worker-class eventlet -w 1 pHMon:app -b 0.0.0.0:5000 --reload
Any hint would be appreciated! Thanks!
Python code:
from flask import Flask, render_template, g, redirect
from flask_socketio import SocketIO, emit
import numpy as np
import threading
import eventlet
import datetime
import sqlite3
import time
from models import db
eventlet.monkey_patch()
class rand_pH(object):
def __init__(self, interval, exp_id):
self.interval = interval
self.exp_id = exp_id
thread = threading.Thread(target=self.run, args=())
thread.daemon = True
thread.start()
# Initialice the textfile
with open("static/data.csv", "w") as myfile:
myfile.write("date,close\n")
def run(self):
"""
Runs forever in the backround
Used to emit the state of the system
Now it just send a new pH every 5 seconds
But will be replaced by the actual reading
"""
global pH
global current_status_loop
current_status_loop = get_current_status()
while current_status_loop==1:
s = np.random.normal(0, 0.5, 1)
pH=pH+s
date=datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")
socketio.emit('new_pH', {'pH': pH[0],'date': date})
# Update the database
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute('''INSERT INTO experiment_data(date, value, exp_id) VALUES(?,?,?)''', (date,pH[0],self.exp_id))
conn.commit()
with open("static/data.csv", "a") as myfile:
myfile.write("{},{}\n".format(date,pH[0]))
time.sleep(self.interval)
current_status_loop = get_current_status()
@app.route('/')
def index():
'''Main access point'''
# Get the status of the last experiment
cursor = get_db().cursor()
cursor.execute(''' SELECT status FROM exp ORDER BY exp_id DESC LIMIT 1 ''')
current_status = cursor.fetchall()[0][0]
# if current_status_loop is not defined it means that
# the thread was not started (ie. previous enexpected server shutownd
# or not an expement runnin).
try:
current_status_loop
except NameError:
stop()
return render_template('start_new.html')
else:
print "sure, it was defined."
if current_status == 0:
return render_template('start_new.html')
if current_status == 1:
return render_template('view_running.html')
JS
var socket = io.connect('http://' + document.domain + ':' + location.port,{'multiplex': false});
socket.on('new_pH', function(msg){
console.log("Recived pH: ", msg.pH)
console.log("Recived date: ", msg.date)
// Get the data
d3.csv("static/data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(2);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(2);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
});