用 flask 和 bokeh 绘制实时数据
Plotting realtime data with flask and bokeh
我正在使用 MongoDB 来存储传感器数据(1 次测量/秒),我想使用 flask 和 bokeh 在网络浏览器中实时绘制数据。不幸的是,我对 web-frameworks 的了解不是那么好。
到目前为止,我设法创建了一个从数据库中读取数据的静态图(请参见下面的示例)
实时更新情节的最佳方式是什么?
from flask import Flask
import datetime
from pymongo import MongoClient
from bokeh.templates import RESOURCES
from bokeh.plotting import figure
from bokeh.resources import CDN
from bokeh.embed import file_html
app = Flask(__name__)
@app.route('/')
def index():
client = MongoClient()
db = client.test
sdata = db.sensordata
output = list(sdata.find())
temp = [x['temperature'] for x in output]
get_time = lambda x: datetime.datetime.strptime(x['time'], '%Y-%m-%d %H:%M:%S')
time = [get_time(x) for x in output]
humidity = [x['humidity'] for x in output]
plot = figure(x_axis_type = "datetime")
plot.line(time, temp)
plot.line(time, humidity)
html = file_html(plot, CDN, "my plot")
return html
if __name__=='__main__':
app.run(host='localhost', debug=True)
编辑:
我认为 flask-socketio 的解决方案会很好,但我还不确定该怎么做。要嵌入情节,我需要创建一个脚本和 div 以及 script, div = components(plot)
参见 (http://docs.bokeh.org/en/latest/docs/user_guide/embed.html)
所以脚本被放入 html header 而 div 被放入 body。我看不到如何更新数据,因为它存储在 header 而不是 div 中的脚本文件中。
我的想法是将 div 中的 html 更改为:
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
//connect to the socket server.
var socket = io.connect('http://' + document.domain + ':' + location.port + '/');
socket.on('plotupdate', function(msg) {
$('#plot').html(msg.plot);
});
});
</script>
但这在这种情况下不起作用。
您可以使用 javascript 的 setInterval 和 ajax 调用来仅刷新包含绘图的 div。将您的路线更改为“/plotIt”之类的内容。显示代码使用 jQuery 重复 ajax 调用刷新具有 id="myPlot" 属性的 div:
setInterval(function() {
$.ajax({
url: "/plotit",
type: "GET",
dataType: "html",
success: function (data) {$('#myPlot').html(data);},
});
}, 60*1000); // Repeat interval is in milliseconds
尚未测试此代码,但它应该可以正常工作或稍作调整。
我通常不太喜欢这样重复的工作,更喜欢事件驱动的方法。即,对新传感器数据使用事件侦听器(侦听 mongodb)并在生成新图时推送新图(使用例如 flask-socketio)。选择适合您的方法。上面的代码至少应该让你开始。
我正在使用 MongoDB 来存储传感器数据(1 次测量/秒),我想使用 flask 和 bokeh 在网络浏览器中实时绘制数据。不幸的是,我对 web-frameworks 的了解不是那么好。 到目前为止,我设法创建了一个从数据库中读取数据的静态图(请参见下面的示例) 实时更新情节的最佳方式是什么?
from flask import Flask
import datetime
from pymongo import MongoClient
from bokeh.templates import RESOURCES
from bokeh.plotting import figure
from bokeh.resources import CDN
from bokeh.embed import file_html
app = Flask(__name__)
@app.route('/')
def index():
client = MongoClient()
db = client.test
sdata = db.sensordata
output = list(sdata.find())
temp = [x['temperature'] for x in output]
get_time = lambda x: datetime.datetime.strptime(x['time'], '%Y-%m-%d %H:%M:%S')
time = [get_time(x) for x in output]
humidity = [x['humidity'] for x in output]
plot = figure(x_axis_type = "datetime")
plot.line(time, temp)
plot.line(time, humidity)
html = file_html(plot, CDN, "my plot")
return html
if __name__=='__main__':
app.run(host='localhost', debug=True)
编辑:
我认为 flask-socketio 的解决方案会很好,但我还不确定该怎么做。要嵌入情节,我需要创建一个脚本和 div 以及 script, div = components(plot)
参见 (http://docs.bokeh.org/en/latest/docs/user_guide/embed.html)
所以脚本被放入 html header 而 div 被放入 body。我看不到如何更新数据,因为它存储在 header 而不是 div 中的脚本文件中。
我的想法是将 div 中的 html 更改为:
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
//connect to the socket server.
var socket = io.connect('http://' + document.domain + ':' + location.port + '/');
socket.on('plotupdate', function(msg) {
$('#plot').html(msg.plot);
});
});
</script>
但这在这种情况下不起作用。
您可以使用 javascript 的 setInterval 和 ajax 调用来仅刷新包含绘图的 div。将您的路线更改为“/plotIt”之类的内容。显示代码使用 jQuery 重复 ajax 调用刷新具有 id="myPlot" 属性的 div:
setInterval(function() {
$.ajax({
url: "/plotit",
type: "GET",
dataType: "html",
success: function (data) {$('#myPlot').html(data);},
});
}, 60*1000); // Repeat interval is in milliseconds
尚未测试此代码,但它应该可以正常工作或稍作调整。
我通常不太喜欢这样重复的工作,更喜欢事件驱动的方法。即,对新传感器数据使用事件侦听器(侦听 mongodb)并在生成新图时推送新图(使用例如 flask-socketio)。选择适合您的方法。上面的代码至少应该让你开始。