diff --git a/cameteo-interface/cameteo.conf b/cameteo-interface/cameteo.conf index 5da1079..c5b4424 100644 --- a/cameteo-interface/cameteo.conf +++ b/cameteo-interface/cameteo.conf @@ -17,13 +17,23 @@ mqtt_pass = WaKaW9XMGUZ3rRJD mqtt_qos = 2 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_mqtt_topic = raspi0/camera camera_resolution_x=2592 camera_resolution_y=1944 camera_warmup_time=2 camera_iso=0 -camera_rotation=180 +camera_rotation=0 camera_auto_white_balance=auto camera_exposure_mode=auto camera_contrast=0 diff --git a/cameteo-interface/cameteo.py b/cameteo-interface/cameteo.py index 0664a02..3f0f843 100644 --- a/cameteo-interface/cameteo.py +++ b/cameteo-interface/cameteo.py @@ -20,10 +20,17 @@ from flask_sqlalchemy import SQLAlchemy ##################### 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_TRACK_MODIFICATIONS'] = False app.config['BOOTSTRAP_USE_MINIFIED'] = False 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 ###################### diff --git a/cameteo-interface/cameteo_conf.py b/cameteo-interface/cameteo_conf.py index bea4fb8..b297da8 100644 --- a/cameteo-interface/cameteo_conf.py +++ b/cameteo-interface/cameteo_conf.py @@ -13,12 +13,14 @@ Created on Fri Aug 18 21:35:59 2017 from datetime import datetime, timedelta, timezone from configparser import SafeConfigParser -import os, sys +import os, sys, socket ################# # CONFIGURATION # ################# +hostname = socket.gethostname() + ".local" + script_path = os.path.dirname(sys.argv[0]) 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_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_mqtt_topic = parser['CAMERA'].get('camera_mqtt_topic', fallback='raspi0/camera') 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_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_format = parser['CAMERA'].get('photo_format', fallback='jpg') photo_extensions = {'jpeg': 'jpg', diff --git a/cameteo-interface/interface.py b/cameteo-interface/interface.py index 52b30db..074797f 100755 --- a/cameteo-interface/interface.py +++ b/cameteo-interface/interface.py @@ -15,6 +15,11 @@ from flask_bootstrap import Bootstrap from flask_nav import Nav 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 # ######## @@ -28,39 +33,81 @@ navbar = Navbar('Camétéo', View('Accueil', 'index'), View('Toutes les données', 'all_data'), Subgroup('Par données', - View("Température de l'air", 'by_data_type', dt='TA'), - View("Humidité relative", 'by_data_type', dt='HR'), - View("Pression atmosphérique",'by_data_type', dt='PA'), + View("Température de l'air", 'by_data_type', dt='AT'), + View("Humidité relative", 'by_data_type', dt='RH'), + 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', 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') ) nav.register_element('top', navbar) +js_resources = INLINE.render_js() +css_resources = INLINE.render_css() + @app.route('/') def index(): - return render_template('index.html') + return render_template('index.tpl') + +@app.route('/picture=') +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') def all_data(): date_deb = datetime.utcnow()-timedelta(seconds=3600) 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=
') def by_data_type(dt): date_deb = datetime.utcnow()-timedelta(seconds=3600) - res = Data.query.filter(Data.type_id == dt).filter(Data.dbdate >= date_deb) - return render_template('data_viz.html', dat=res.order_by(Data.dbdate.desc()).paginate(per_page=15)) + #Récupération des données à afficher + 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=') def by_sensor(sens): date_deb = datetime.utcnow()-timedelta(seconds=3600) 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']) def config_page(): @@ -70,7 +117,7 @@ def config_page(): else: pass - return render_template('config_page.html') + return render_template('config_page.tpl') if __name__=="__main__": - app.run(host="0.0.0.0", debug=True) \ No newline at end of file + app.run(host="0.0.0.0") \ No newline at end of file diff --git a/cameteo-interface/static/photos b/cameteo-interface/static/photos new file mode 120000 index 0000000..43ed8a0 --- /dev/null +++ b/cameteo-interface/static/photos @@ -0,0 +1 @@ +../../photos \ No newline at end of file