diff options
author | Maximilien Cuony <maximilien@theglu.org> | 2016-09-11 03:02:00 +0200 |
---|---|---|
committer | Maximilien Cuony <maximilien@theglu.org> | 2016-09-11 03:02:00 +0200 |
commit | 007ea5571e2dca4d2ce6db7b3e7f98b86bf929ab (patch) | |
tree | 1485b4bb170f99cf5937bac13aef98b021160810 | |
parent | d381c117e8ac5986805ede5db2beca273b967e2f (diff) | |
download | glutte-serial-web-007ea5571e2dca4d2ce6db7b3e7f98b86bf929ab.tar.gz glutte-serial-web-007ea5571e2dca4d2ce6db7b3e7f98b86bf929ab.tar.bz2 glutte-serial-web-007ea5571e2dca4d2ce6db7b3e7f98b86bf929ab.zip |
Use websocket and add multiple-user at the same time
-rw-r--r-- | .gitignore | 2 | ||||
-rwxr-xr-x | glutte_serial_web.py | 58 | ||||
-rw-r--r-- | glutte_serial_web.unit.example | 2 | ||||
-rw-r--r-- | requirements.txt | 2 | ||||
-rw-r--r-- | serialrx.py | 44 | ||||
-rw-r--r-- | templates/index.html | 27 |
6 files changed, 88 insertions, 47 deletions
@@ -2,3 +2,5 @@ bin include lib pip-selfcheck.json +*.pyc +.ropeproject diff --git a/glutte_serial_web.py b/glutte_serial_web.py index bcb3261..016c8da 100755 --- a/glutte_serial_web.py +++ b/glutte_serial_web.py @@ -2,7 +2,7 @@ # # The MIT License (MIT) # -# Copyright (c) 2016 Matthias P. Braendli +# Copyright (c) 2016 Matthias P. Braendli, Maximilien Cuony # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,35 +22,57 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from gevent.wsgi import WSGIServer +from geventwebsocket.handler import WebSocketHandler +from gevent import pywsgi, Timeout from time import sleep from flask import Flask, render_template +from flask_sockets import Sockets import serialrx app = Flask(__name__) +sockets = Sockets(app) ser = serialrx.SerialRX() + @app.route('/') def index(): return render_template('index.html') -@app.route('/stream') -def stream(): - def generate(): - while True: - line = ser.get_line() - if line is not None: - yield line + +@sockets.route('/stream') +def stream(socket): + + try: + + queue = ser.register_client() + + while not socket.closed: + # Force to check if the client is still here + try: + with Timeout(0.1, False): + socket.receive() + except: + pass + try: + line = queue.popleft() + socket.send(line) + except IndexError: + pass sleep(0.1) + except: + raise + finally: + ser.unregister_client(queue) - return app.response_class(generate(), mimetype='text/plain') +ser.start() -try: - ser.start() - http_server = WSGIServer(('', 5000), app) - http_server.serve_forever() -except KeyboardInterrupt: - print("Ctrl-C received, quitting") -finally: - ser.stop() +if __name__ == "__main__": + print("You're running in dev mode, only one client at a time will works ! Please use gunicorn to fix this :)") + try: + http_server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler) + http_server.serve_forever() + except KeyboardInterrupt: + print("Ctrl-C received, quitting") + finally: + ser.stop() diff --git a/glutte_serial_web.unit.example b/glutte_serial_web.unit.example index cbc86db..5ee8b4b 100644 --- a/glutte_serial_web.unit.example +++ b/glutte_serial_web.unit.example @@ -6,5 +6,5 @@ After=syslog.target network.target Type=simple User=glutte WorkingDirectory=/home/glutte/glutte-serial-web -ExecStart=/home/glutte/glutte-serial-web/bin/python /home/glutte/glutte-serial-web/glutte_serial_web.py +ExecStart=/home/glutte/glutte-serial-web/bin/gunicorn -k flask_sockets.worker glutte_serial_web:app -b 0.0.0.0:5000 diff --git a/requirements.txt b/requirements.txt index 84f7820..e9ee31f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,5 @@ Jinja2==2.8 MarkupSafe==0.23 pyserial==3.1.1 Werkzeug==0.11.11 +Flask-Sockets==0.2.1 +gunicorn==19.6.0 diff --git a/serialrx.py b/serialrx.py index 66de50b..37855f6 100644 --- a/serialrx.py +++ b/serialrx.py @@ -2,7 +2,7 @@ # # The MIT License (MIT) # -# Copyright (c) 2016 Matthias P. Braendli +# Copyright (c) 2016 Matthias P. Braendli, Maximilien Cuony # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,16 +22,17 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from time import sleep import serial import threading import collections -SERIALPORT="/dev/ttyACM0" -BAUDRATE=9600 -LINES_TO_KEEP=200 +SERIALPORT = "/dev/ttyACM0" +BAUDRATE = 9600 +LINES_TO_KEEP = 200 + class SerialRX(threading.Thread): + def __init__(self): threading.Thread.__init__(self) @@ -41,7 +42,7 @@ class SerialRX(threading.Thread): self.event_stop = threading.Event() self.data_lock = threading.Lock() - self.data_queue = collections.deque() + self.clients = [] self.line_accumulator = [] @@ -56,24 +57,39 @@ class SerialRX(threading.Thread): if databyte == "\n": self.data_lock.acquire() try: - self.data_queue.append("".join(self.line_accumulator)) - if len(self.data_queue) > LINES_TO_KEEP: - self.data_queue.popleft() + for queue in self.clients: + queue.append("".join(self.line_accumulator)) + + if len(queue) > LINES_TO_KEEP: + queue.popleft() except: raise finally: self.data_lock.release() self.line_accumulator = [] - def stop(self): self.event_stop.set() self.join() - def get_line(self): + def register_client(self): + self.data_lock.acquire() try: - return self.data_queue.popleft() - except IndexError: - return None + new_queue = collections.deque() + self.clients.append(new_queue) + except: + raise + finally: + self.data_lock.release() + + return new_queue + def unregister_client(self, queue): + self.data_lock.acquire() + try: + self.clients.remove(queue) + except: + raise + finally: + self.data_lock.release() diff --git a/templates/index.html b/templates/index.html index 1b68ce2..038130d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -5,19 +5,18 @@ <title>Moniteur de Glutte</title> <link rel="stylesheet" href="static/style.css" type="text/css" media="screen" charset="utf-8"/> </head> -<body> - <h1>Ceci n'est pas une Glutte</h1> -<pre id="output"></pre> -<script> - var output = document.getElementById('output'); + <body> + <h1>Ceci n'est pas une Glutte</h1> + <pre id="output"></pre> + <script> + var output = document.getElementById('output'); - var xhr = new XMLHttpRequest(); - xhr.open('GET', '{{ url_for('stream') }}'); - xhr.send(); + var socket = new WebSocket("ws://" + window.location.host + "/stream"); - setInterval(function() { - output.textContent = xhr.responseText; - window.scrollTo(0, document.body.scrollHeight); - }, 1000); -</script> -</body></html> + socket.onmessage = function(data) { + output.textContent += data.data; + window.scrollTo(0, document.body.scrollHeight); + } + </script> + </body> +</html> |