Uses websockets to refresh the page when QR code scanned
This commit is contained in:
parent
912f84597d
commit
c5200805e1
17
README.md
17
README.md
@ -14,3 +14,20 @@ To create an empty `database.db` sqlite file with the table described in
|
|||||||
```bash
|
```bash
|
||||||
./init_db.py
|
./init_db.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Nginx reverse proxy configuration
|
||||||
|
|
||||||
|
Add this code to the nginx configuration file for the virtual host:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location /socket.io {
|
||||||
|
set $webapp http://attendance.lxd:5000;
|
||||||
|
include proxy_params;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_pass $webapp;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
27
main.py
27
main.py
@ -6,7 +6,10 @@ from datetime import datetime
|
|||||||
from flask import Flask, request, render_template
|
from flask import Flask, request, render_template
|
||||||
from flask_uuid import FlaskUUID
|
from flask_uuid import FlaskUUID
|
||||||
from flask_qrcode import QRcode
|
from flask_qrcode import QRcode
|
||||||
# TODO: use sockets to broadcast when a hit to the expected uuid has been
|
from flask_socketio import SocketIO
|
||||||
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
|
||||||
|
# WIP: use sockets to broadcast when a hit to the expected uuid has been
|
||||||
# received, so that connected clients (the Chromium public browser) can
|
# received, so that connected clients (the Chromium public browser) can
|
||||||
# refresh the qr code and update the list of users
|
# refresh the qr code and update the list of users
|
||||||
# https://flask-socketio.readthedocs.io
|
# https://flask-socketio.readthedocs.io
|
||||||
@ -14,6 +17,10 @@ from flask_qrcode import QRcode
|
|||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
FlaskUUID(app)
|
FlaskUUID(app)
|
||||||
QRcode(app)
|
QRcode(app)
|
||||||
|
app.config['SECRET_KEY'] = '53a8373e7ae652cd38beba15454b1dc4'
|
||||||
|
#app = ProxyFix(app, x_for=1, x_host=1)
|
||||||
|
app.wsgi_app = ProxyFix(app.wsgi_app)
|
||||||
|
socketio = SocketIO(app, async_mode=None)
|
||||||
|
|
||||||
def get_db_connection():
|
def get_db_connection():
|
||||||
conn = sqlite3.connect('database.db')
|
conn = sqlite3.connect('database.db')
|
||||||
@ -42,8 +49,9 @@ def catch_uuids(id):
|
|||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
existing = conn.execute(
|
existing = conn.execute(
|
||||||
'SELECT * FROM hits WHERE uuid = ?', (str(id),)).fetchone()
|
'SELECT * FROM hits WHERE uuid = ?', (str(id),)).fetchone()
|
||||||
# TODO: verify that the uuid was generated by us (otherwise any uuid,
|
existing = False # Temporary, for easier development
|
||||||
# like one generated by the user, would be accepted)
|
if id.fields[5] != uuid.getnode():
|
||||||
|
error = 'DIFFERENT_NODE'
|
||||||
if not ua:
|
if not ua:
|
||||||
error = 'NO_USERNAME'
|
error = 'NO_USERNAME'
|
||||||
elif existing:
|
elif existing:
|
||||||
@ -51,6 +59,8 @@ def catch_uuids(id):
|
|||||||
else:
|
else:
|
||||||
conn.execute("INSERT INTO hits (uuid, user) VALUES (?, ?)", (str(id), ua))
|
conn.execute("INSERT INTO hits (uuid, user) VALUES (?, ?)", (str(id), ua))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
socketio.emit('qr_used', {'data': (time, ua, str(id))})
|
||||||
|
|
||||||
data = conn.execute(
|
data = conn.execute(
|
||||||
'SELECT * FROM hits WHERE user = ? ORDER BY id DESC LIMIT 10', (ua,)
|
'SELECT * FROM hits WHERE user = ? ORDER BY id DESC LIMIT 10', (ua,)
|
||||||
).fetchall()
|
).fetchall()
|
||||||
@ -58,5 +68,14 @@ def catch_uuids(id):
|
|||||||
|
|
||||||
return render_template('thanks.html', user=ua, time=time, error=error, hits=data)
|
return render_template('thanks.html', user=ua, time=time, error=error, hits=data)
|
||||||
|
|
||||||
|
@socketio.on('message')
|
||||||
|
def handle_message(data):
|
||||||
|
print('received message: ' + data)
|
||||||
|
|
||||||
|
@socketio.on('my_event')
|
||||||
|
def handle_my_custom_event(json):
|
||||||
|
print('received json: ' + str(json))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='0.0.0.0')
|
#app.run(host='0.0.0.0')
|
||||||
|
socketio.run(app, host='0.0.0.0')
|
||||||
|
|||||||
@ -1,18 +1,38 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Example</title>
|
<script src="//code.jquery.com/jquery-1.12.4.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
$(document).ready(function() {
|
||||||
|
var socket = io();
|
||||||
|
socket.on('connect', function() {
|
||||||
|
socket.emit('my_event', {data: 'Connected to server'});
|
||||||
|
});
|
||||||
|
socket.on('qr_used', function(msg, cb) {
|
||||||
|
location.reload(true);
|
||||||
|
/*
|
||||||
|
$('#log').append('<li>' + msg.data[0] + ': ' + msg.data[1] + ' (' + msg.data[2] + ')</li>');
|
||||||
|
$('#qrcode').attr('src',src);
|
||||||
|
if (cb)
|
||||||
|
cb();
|
||||||
|
*/
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<title>Example</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>QR Code:</h1>
|
<h1>QR Code:</h1>
|
||||||
<p>For URL <a href="{{ request.url_root + next_uuid }}">{{ request.url_root + next_uuid }}</a></p>
|
<p>For URL <a href="{{ request.url_root + next_uuid }}">{{ request.url_root + next_uuid }}</a></p>
|
||||||
<img src="{{ qrcode(request.url_root + next_uuid, box_size=12, border=5) }}">
|
<img id="qrcode" src="{{ qrcode(request.url_root + next_uuid, box_size=12, border=5) }}">
|
||||||
<h1>Last 10 users:</h1>
|
<h1>Last 10 users:</h1>
|
||||||
<li>
|
<!-- div><ul id="log"></ul></div -->
|
||||||
|
<ul>
|
||||||
{% for hit in hits %}
|
{% for hit in hits %}
|
||||||
<ul>{{ hit['created'] }}, {{ hit['user'] }}</ul>
|
<li>{{ hit['created'] }}, {{ hit['user'] }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</li>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@ -10,16 +10,19 @@
|
|||||||
{% elif error == 'ALREADY_USED' %}
|
{% elif error == 'ALREADY_USED' %}
|
||||||
<h1>Error</h1>
|
<h1>Error</h1>
|
||||||
<p>Code has been used already.</p>
|
<p>Code has been used already.</p>
|
||||||
|
{% elif error == 'DIFFERENT_NODE' %}
|
||||||
|
<h1>Error</h1>
|
||||||
|
<p>Code was not generated by this system.</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h1>Thanks</h1>
|
<h1>Thanks</h1>
|
||||||
<p><strong>At {{ time }}</strong>,</p>
|
<p><strong>At {{ time }}</strong>,</p>
|
||||||
<p>Registered (entrance? exit?) for user {{ user }} .</p>
|
<p>Registered entrance or exit for user {{ user }} .</p>
|
||||||
<h2>Last 10 registers for {{ user }}:</h2>
|
<h2>Last 10 registers for {{ user }}:</h2>
|
||||||
<li>
|
<ul>
|
||||||
{% for hit in hits %}
|
{% for hit in hits %}
|
||||||
<ul>{{ hit['created'] }}</ul>
|
<li>{{ hit['created'] }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</li>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user