Mises à jour multiples à l'interface web : visu de photos, renommage des templates Jinja, nouvelle configuration, préparation graphe
This commit is contained in:
parent
4aa801634f
commit
2091c459be
@ -17,13 +17,23 @@ mqtt_pass = WaKaW9XMGUZ3rRJD
|
|||||||
mqtt_qos = 2
|
mqtt_qos = 2
|
||||||
mqtt_topic = huzzah0/#
|
mqtt_topic = huzzah0/#
|
||||||
|
|
||||||
|
[FLASK]
|
||||||
|
http_host = 0.0.0.0
|
||||||
|
http_listen_port = 5000
|
||||||
|
flask_debug = 1
|
||||||
|
flask_secret = 'blablabla'
|
||||||
|
|
||||||
|
flask_images_url = /urlsizer
|
||||||
|
flask_images_path = static/photos
|
||||||
|
flask_images_cache = cache/flask-images
|
||||||
|
|
||||||
[CAMERA]
|
[CAMERA]
|
||||||
camera_mqtt_topic = raspi0/camera
|
camera_mqtt_topic = raspi0/camera
|
||||||
camera_resolution_x=2592
|
camera_resolution_x=2592
|
||||||
camera_resolution_y=1944
|
camera_resolution_y=1944
|
||||||
camera_warmup_time=2
|
camera_warmup_time=2
|
||||||
camera_iso=0
|
camera_iso=0
|
||||||
camera_rotation=180
|
camera_rotation=0
|
||||||
camera_auto_white_balance=auto
|
camera_auto_white_balance=auto
|
||||||
camera_exposure_mode=auto
|
camera_exposure_mode=auto
|
||||||
camera_contrast=0
|
camera_contrast=0
|
||||||
|
@ -20,10 +20,17 @@ from flask_sqlalchemy import SQLAlchemy
|
|||||||
#####################
|
#####################
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
app.config['SERVER_NAME'] = hostname + ":" + http_listen_port
|
||||||
|
app.config['SECRET_KEY'] = flask_secret
|
||||||
|
app.config['DEBUG'] = flask_debug
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = sql_uri
|
app.config['SQLALCHEMY_DATABASE_URI'] = sql_uri
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
app.config['BOOTSTRAP_USE_MINIFIED'] = False
|
app.config['BOOTSTRAP_USE_MINIFIED'] = False
|
||||||
app.config['BOOTSTRAP_SERVE_LOCAL'] = True
|
app.config['BOOTSTRAP_SERVE_LOCAL'] = True
|
||||||
|
app.config['IMAGES_URL'] = flask_images_url
|
||||||
|
app.config['IMAGES_PATH'] = flask_images_path
|
||||||
|
app.config['IMAGES_CACHE'] = flask_images_cache
|
||||||
|
|
||||||
#app.config['SQLALCHEMY_POOL_RECYCLE'] = 600
|
#app.config['SQLALCHEMY_POOL_RECYCLE'] = 600
|
||||||
|
|
||||||
######################
|
######################
|
||||||
|
@ -13,12 +13,14 @@ Created on Fri Aug 18 21:35:59 2017
|
|||||||
|
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from configparser import SafeConfigParser
|
from configparser import SafeConfigParser
|
||||||
import os, sys
|
import os, sys, socket
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# CONFIGURATION #
|
# CONFIGURATION #
|
||||||
#################
|
#################
|
||||||
|
|
||||||
|
hostname = socket.gethostname() + ".local"
|
||||||
|
|
||||||
script_path = os.path.dirname(sys.argv[0])
|
script_path = os.path.dirname(sys.argv[0])
|
||||||
script_dir = os.path.abspath(script_path)
|
script_dir = os.path.abspath(script_path)
|
||||||
|
|
||||||
@ -50,6 +52,17 @@ mqtt_auth = {'username' : mqtt_user, 'password' : mqtt_pass}
|
|||||||
mqtt_qos = parser['MQTT'].get('mqtt_qos', fallback=0)
|
mqtt_qos = parser['MQTT'].get('mqtt_qos', fallback=0)
|
||||||
mqtt_topic = parser['MQTT'].get('mqtt_topic', fallback='sensors/#')
|
mqtt_topic = parser['MQTT'].get('mqtt_topic', fallback='sensors/#')
|
||||||
|
|
||||||
|
#HTTP FLASK
|
||||||
|
http_host = parser['FLASK'].get('http_host', fallback='127.0.0.1')
|
||||||
|
http_listen_port = parser['FLASK'].get('http_listen_port', fallback='5000')
|
||||||
|
|
||||||
|
flask_debug = bool(int(parser['FLASK'].get('flask_debug', fallback=1)))
|
||||||
|
flask_secret = parser['FLASK'].get('flask_secret', fallback='random')
|
||||||
|
|
||||||
|
flask_images_url = parser['FLASK'].get('flask_images_url', fallback='/urlsizer')
|
||||||
|
flask_images_path = parser['FLASK'].get('flask_images_path', fallback='static/photos')
|
||||||
|
flask_images_cache = parser['FLASK'].get('flask_images_cache', fallback='cache/flask-images')
|
||||||
|
|
||||||
#Camera
|
#Camera
|
||||||
camera_mqtt_topic = parser['CAMERA'].get('camera_mqtt_topic', fallback='raspi0/camera')
|
camera_mqtt_topic = parser['CAMERA'].get('camera_mqtt_topic', fallback='raspi0/camera')
|
||||||
camera_resolution_x = int(parser['CAMERA'].get('camera_resolution_x', fallback='800'))
|
camera_resolution_x = int(parser['CAMERA'].get('camera_resolution_x', fallback='800'))
|
||||||
@ -62,7 +75,7 @@ camera_expo_mode = parser['CAMERA'].get('camera_exposure_mode', fallback='aut
|
|||||||
camera_rotation = int(parser['CAMERA'].get('camera_rotation', fallback=0))
|
camera_rotation = int(parser['CAMERA'].get('camera_rotation', fallback=0))
|
||||||
camera_contrast = int(parser['CAMERA'].get('camera_contrast', fallback=0))
|
camera_contrast = int(parser['CAMERA'].get('camera_contrast', fallback=0))
|
||||||
|
|
||||||
photo_dir = parser['CAMERA'].get('photo_dir', fallback='/home/pi/photos/')
|
photo_dir = parser['CAMERA'].get('photo_dir', fallback='/home/pi/Cameteo/photos/')
|
||||||
photo_name = parser['CAMERA'].get('photo_name', fallback='%%Y%%m%%d_%%H%%M%%S')
|
photo_name = parser['CAMERA'].get('photo_name', fallback='%%Y%%m%%d_%%H%%M%%S')
|
||||||
photo_format = parser['CAMERA'].get('photo_format', fallback='jpg')
|
photo_format = parser['CAMERA'].get('photo_format', fallback='jpg')
|
||||||
photo_extensions = {'jpeg': 'jpg',
|
photo_extensions = {'jpeg': 'jpg',
|
||||||
|
@ -15,6 +15,11 @@ from flask_bootstrap import Bootstrap
|
|||||||
from flask_nav import Nav
|
from flask_nav import Nav
|
||||||
from flask_nav.elements import *
|
from flask_nav.elements import *
|
||||||
|
|
||||||
|
from bokeh.plotting import figure
|
||||||
|
from bokeh.embed import components
|
||||||
|
from bokeh.models import ColumnDataSource
|
||||||
|
from bokeh.resources import INLINE
|
||||||
|
|
||||||
########
|
########
|
||||||
# MAIN #
|
# MAIN #
|
||||||
########
|
########
|
||||||
@ -28,39 +33,81 @@ navbar = Navbar('Camétéo',
|
|||||||
View('Accueil', 'index'),
|
View('Accueil', 'index'),
|
||||||
View('Toutes les données', 'all_data'),
|
View('Toutes les données', 'all_data'),
|
||||||
Subgroup('Par données',
|
Subgroup('Par données',
|
||||||
View("Température de l'air", 'by_data_type', dt='TA'),
|
View("Température de l'air", 'by_data_type', dt='AT'),
|
||||||
View("Humidité relative", 'by_data_type', dt='HR'),
|
View("Humidité relative", 'by_data_type', dt='RH'),
|
||||||
View("Pression atmosphérique",'by_data_type', dt='PA'),
|
View("Pression atmosphérique (locale)", 'by_data_type', dt='AP'),
|
||||||
|
View("Pression atmosphérique (mer)", 'by_data_type', dt='MSLP'),
|
||||||
|
View("Altitude", 'by_data_type', dt='ALTI'),
|
||||||
),
|
),
|
||||||
Subgroup('Par capteur',
|
Subgroup('Par capteur',
|
||||||
View("Capteur BME280", 'by_sensor', sens = 'AdaBME280_1')
|
View("Capteur BME280", 'by_sensor', sens = 'AdaBME280_1')
|
||||||
),
|
),
|
||||||
|
Subgroup('Photos',
|
||||||
|
View('Dernière Photo', 'picture', num=0),
|
||||||
|
View('Première Photo', 'picture', num=999999999),
|
||||||
|
),
|
||||||
View('Configuration', 'config_page')
|
View('Configuration', 'config_page')
|
||||||
)
|
)
|
||||||
|
|
||||||
nav.register_element('top', navbar)
|
nav.register_element('top', navbar)
|
||||||
|
|
||||||
|
js_resources = INLINE.render_js()
|
||||||
|
css_resources = INLINE.render_css()
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html')
|
return render_template('index.tpl')
|
||||||
|
|
||||||
|
@app.route('/picture=<num>')
|
||||||
|
def picture(num):
|
||||||
|
num=int(num)
|
||||||
|
if num < 0 :
|
||||||
|
num = 0
|
||||||
|
pictures = Photo.query.order_by(Photo.file_date.desc())
|
||||||
|
if num > pictures.count()-1:
|
||||||
|
num = pictures.count()-1
|
||||||
|
pict = pictures[num]
|
||||||
|
return render_template('photos.tpl', picture_path = os.path.join("static/photos", pict.file_name), numero = num )
|
||||||
|
|
||||||
@app.route('/all_data')
|
@app.route('/all_data')
|
||||||
def all_data():
|
def all_data():
|
||||||
date_deb = datetime.utcnow()-timedelta(seconds=3600)
|
date_deb = datetime.utcnow()-timedelta(seconds=3600)
|
||||||
res = Data.query.filter(Data.dbdate >= date_deb)
|
res = Data.query.filter(Data.dbdate >= date_deb)
|
||||||
return render_template('data_viz.html', dat=res.order_by(Data.dbdate.desc()).paginate(per_page=15))
|
return render_template('data_viz.tpl', dat=res.order_by(Data.dbdate.desc()).paginate(per_page=15))
|
||||||
|
|
||||||
@app.route('/type_id=<dt>')
|
@app.route('/type_id=<dt>')
|
||||||
def by_data_type(dt):
|
def by_data_type(dt):
|
||||||
date_deb = datetime.utcnow()-timedelta(seconds=3600)
|
date_deb = datetime.utcnow()-timedelta(seconds=3600)
|
||||||
res = Data.query.filter(Data.type_id == dt).filter(Data.dbdate >= date_deb)
|
#Récupération des données à afficher
|
||||||
return render_template('data_viz.html', dat=res.order_by(Data.dbdate.desc()).paginate(per_page=15))
|
res = Data.query.filter(Data.type_id == dt).filter(Data.dbdate >= date_deb).order_by(Data.valdate)
|
||||||
|
|
||||||
|
plot_data = ColumnDataSource(data=dict(x = res.values('valdate'), y = res.values('value')))
|
||||||
|
|
||||||
|
#Préparation du graphique
|
||||||
|
data_plot = figure(tools = TOOLS,
|
||||||
|
title = dt,
|
||||||
|
x_axis_label = 'Date',
|
||||||
|
x_axis_type = 'datetime',
|
||||||
|
y_axis_label = dt,
|
||||||
|
plot_height = 400,
|
||||||
|
plot_width = 800,
|
||||||
|
)
|
||||||
|
data_plot.line('x', 'y', source=plot_data, line_width=2)
|
||||||
|
|
||||||
|
script, div = components(data_plot)
|
||||||
|
|
||||||
|
return render_template('data_graph.tpl', dat=res.order_by(Data.dbdate.desc()).paginate(per_page=15),
|
||||||
|
plot_script=script,
|
||||||
|
plot_div=div,
|
||||||
|
js_resources=js_resources,
|
||||||
|
css_resources=css_resources,
|
||||||
|
)
|
||||||
|
|
||||||
@app.route('/sensor_id=<sens>')
|
@app.route('/sensor_id=<sens>')
|
||||||
def by_sensor(sens):
|
def by_sensor(sens):
|
||||||
date_deb = datetime.utcnow()-timedelta(seconds=3600)
|
date_deb = datetime.utcnow()-timedelta(seconds=3600)
|
||||||
res = Data.query.filter(Data.sensor_id == sens).filter(Data.dbdate >= date_deb)
|
res = Data.query.filter(Data.sensor_id == sens).filter(Data.dbdate >= date_deb)
|
||||||
return render_template('data_viz.html', dat=res.order_by(Data.dbdate.desc()).paginate(per_page=15))
|
return render_template('data_viz.tpl', dat=res.order_by(Data.dbdate.desc()).paginate(per_page=15))
|
||||||
|
|
||||||
@app.route('/configuration', methods=['GET', 'POST'])
|
@app.route('/configuration', methods=['GET', 'POST'])
|
||||||
def config_page():
|
def config_page():
|
||||||
@ -70,7 +117,7 @@ def config_page():
|
|||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return render_template('config_page.html')
|
return render_template('config_page.tpl')
|
||||||
|
|
||||||
if __name__=="__main__":
|
if __name__=="__main__":
|
||||||
app.run(host="0.0.0.0", debug=True)
|
app.run(host="0.0.0.0")
|
1
cameteo-interface/static/photos
Symbolic link
1
cameteo-interface/static/photos
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../photos
|
Loading…
Reference in New Issue
Block a user