diff --git a/sorteerhoed/central_management.py b/sorteerhoed/central_management.py
index 5cbb425..8c788b0 100644
--- a/sorteerhoed/central_management.py
+++ b/sorteerhoed/central_management.py
@@ -295,6 +295,17 @@ class CentralManagement():
self.currentHit.open_page_at = datetime.datetime.utcnow()
self.store.saveHIT(self.currentHit)
self.setLight(True)
+ elif signal.name == 'server.close':
+ if not signal.params['abandoned']:
+ continue
+ a = self.currentHit.getLastAssignment()
+ if a.assignment_id != signal.params['assignment_id']:
+ self.logger.info(f"Close of older assignment_id: {signal}")
+ continue
+ self.logger.critical(f"Websocket closed of active assignment_id: {signal}")
+ a.abandoned_at = datetime.datetime.utcnow()
+ self.store.saveAssignment(a)
+ self.plotter.park()
elif signal.name == 'assignment.submit':
a = self.currentHit.getLastAssignment()
if a.assignment_id != signal.params['assignment_id']:
diff --git a/sorteerhoed/webserver.py b/sorteerhoed/webserver.py
index 20de705..14b691d 100644
--- a/sorteerhoed/webserver.py
+++ b/sorteerhoed/webserver.py
@@ -56,6 +56,8 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
self.plotterQ = plotterQ
self.eventQ = eventQ
self.store = store
+ self.assignment_id = None
+ self.abandoned = False
def check_origin(self, origin):
parsed_origin = urlparse(origin)
@@ -79,7 +81,8 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
if self.assignment.assignment_id != self.assignment_id:
raise Exception(f"Opening websocket for invalid assignment {self.assignment_id}")
- self.timeout = datetime.datetime.now() + datetime.timedelta(seconds=self.store.getHitTimeout())
+ self.timeout = self.assignment.created_at + datetime.timedelta(seconds=self.store.getHitTimeout())
+# timeLeft = (self.timeout - datetime.datetime.utcnow()).total_seconds()
if self.hit.isSubmitted():
raise Exception("Opening websocket for already submitted hit")
@@ -87,7 +90,8 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
#logger.info(f"New client connected: {self.request.remote_ip} for {self.hit.id}/{self.hit.hit_id}")
self.eventQ.put(Signal('server.open', dict(assignment_id=self.assignment_id)))
self.strokes = []
-
+
+
# the client sent the message
def on_message(self, message):
@@ -97,7 +101,7 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
logger.critical(f"Skip message for non-last assignment {message}")
return
- if datetime.datetime.now() > self.timeout:
+ if datetime.datetime.utcnow() > self.timeout:
logger.critical("Close websocket after timeout (abandon?)")
self.close()
return
@@ -164,6 +168,9 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
# client disconnected
def on_close(self):
self.__class__.rmConnection(self)
+ if self.assignment_id:
+ self.eventQ.put(Signal('server.close', dict(assignment_id=self.assignment_id, abandoned=self.abandoned)))
+
logger.info(f"Client disconnected: {self.request.remote_ip}")
# TODO: abandon assignment??
@@ -206,6 +213,20 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
if client not in cls.connections:
return
cls.connections.remove(client)
+
+ @classmethod
+ def hasConnection(cls, client):
+ return client in cls.connections
+
+
+ @classmethod
+ def timeoutConnectionForAssignment(cls, assignment_id):
+ logger.warn(f"Check timeout for {assignment_id}")
+ for client in cls.connections:
+ logger.info(client.assignment_id)
+ if client.assignment_id == assignment_id:
+ client.abandoned = True
+ client.close()
class StatusWebSocketHandler(tornado.websocket.WebSocketHandler):
@@ -311,6 +332,8 @@ class DrawPageHandler(tornado.web.RequestHandler):
logger.warning(f"Create new assignment {assignmentId}")
assignment = self.store.newAssignment(self.store.currentHit, assignmentId)
self.store.saveAssignment(assignment)
+ logger.info(f"Set close timeout for {self.store.getHitTimeout()}")
+ Server.loop.asyncio_loop.call_later(self.store.getHitTimeout(), WebSocketHandler.timeoutConnectionForAssignment, assignment.assignment_id)
previous_hit = self.store.getLastSubmittedHit()
if not previous_hit:
@@ -432,7 +455,6 @@ class StatusPage():
return [hit.toDict() for hit in hits]
-
class Server:
"""
Server for HIT -> plotter events
diff --git a/www/basic.svg b/www/basic.svg
index 315d9e1..2e5c7a4 100644
--- a/www/basic.svg
+++ b/www/basic.svg
@@ -5,11 +5,11 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
- id="svg8"
- version="1.1"
- viewBox="0 0 210 210"
+ width="210mm"
height="210mm"
- width="210mm">
+ viewBox="0 0 210 210"
+ version="1.1"
+ id="svg8">
+ style="stroke-width:1.52441633"
+ id="layer1"
+ transform="matrix(0.65598879,0,0,0.65598879,44.11553,-86.509667)">
+ width="107.34524"
+ height="107.34524"
+ x="51.327381"
+ y="138.32738" />
diff --git a/www/basic_square.svg b/www/basic_square.svg
index 20c8df1..a300851 100644
--- a/www/basic_square.svg
+++ b/www/basic_square.svg
@@ -13,7 +13,7 @@
height="180mm"
preserveAspectRatio="none"
id="svg3"
- sodipodi:docname="000139.svg"
+ sodipodi:docname="basic_square.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
@@ -37,22 +37,23 @@
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:window-width="3836"
- inkscape:window-height="2126"
+ inkscape:window-width="3840"
+ inkscape:window-height="2160"
id="namedview5"
showgrid="false"
inkscape:zoom="1.3875926"
- inkscape:cx="311.32047"
+ inkscape:cx="-14.783892"
inkscape:cy="589.76197"
- inkscape:window-x="2"
- inkscape:window-y="32"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
inkscape:window-maximized="1"
- inkscape:current-layer="svg3" />
+ inkscape:current-layer="svg3"
+ showguides="false" />
+ y="165.88982" />